mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 05:47:59 -05:00
Compare commits
162 Commits
epbs-propo
...
migrate-rp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f3056ac84 | ||
|
|
4ab86838b8 | ||
|
|
203ac12216 | ||
|
|
2e0d4ac184 | ||
|
|
9c598ea9aa | ||
|
|
2cfc204e9a | ||
|
|
e859fc4e09 | ||
|
|
c0021f91c2 | ||
|
|
877d9ee948 | ||
|
|
785fefa3f1 | ||
|
|
0c22d91a55 | ||
|
|
fb60456116 | ||
|
|
be56711892 | ||
|
|
370ae9a12c | ||
|
|
96f1ebf706 | ||
|
|
fb755c7f3b | ||
|
|
bdb12c7d2f | ||
|
|
83cf0f8658 | ||
|
|
762594a368 | ||
|
|
c1fc812a38 | ||
|
|
340935af9c | ||
|
|
17d0082c5c | ||
|
|
e998b5ec97 | ||
|
|
5d0eb3168c | ||
|
|
e0c2aa71d4 | ||
|
|
6eff474042 | ||
|
|
70c31949ba | ||
|
|
e38fdb09a4 | ||
|
|
a50e981c74 | ||
|
|
8be205cf3d | ||
|
|
1b65e00096 | ||
|
|
e3fb4e86ec | ||
|
|
70aaad1904 | ||
|
|
e42611ec72 | ||
|
|
a3e61275a3 | ||
|
|
e82f9ccca3 | ||
|
|
38a6a7a4ea | ||
|
|
1295c987e8 | ||
|
|
6a27c41aad | ||
|
|
98b13ea144 | ||
|
|
c735ed2e32 | ||
|
|
bd17779231 | ||
|
|
e08ed0d823 | ||
|
|
2b4d8a09ff | ||
|
|
21e1f7883b | ||
|
|
bfa24606c3 | ||
|
|
d7628bab37 | ||
|
|
8e2c9313e9 | ||
|
|
fea441d889 | ||
|
|
2351064e8d | ||
|
|
d2699761ed | ||
|
|
c73473b59d | ||
|
|
2aa52fb56a | ||
|
|
16d5abd21b | ||
|
|
08bfaca42d | ||
|
|
179cedd4a0 | ||
|
|
0f39857653 | ||
|
|
645328bb9e | ||
|
|
9d2273c514 | ||
|
|
34429368fe | ||
|
|
629568c796 | ||
|
|
5c24978702 | ||
|
|
4e44999207 | ||
|
|
15ae71c0da | ||
|
|
1caea86152 | ||
|
|
7cef3b0491 | ||
|
|
15462844f9 | ||
|
|
863eee7b40 | ||
|
|
6d89373583 | ||
|
|
9a421a2feb | ||
|
|
4e41d5c610 | ||
|
|
0b6bea43a8 | ||
|
|
f89afb0fbd | ||
|
|
3cd2973c92 | ||
|
|
d3e5710a63 | ||
|
|
f40b4f16c2 | ||
|
|
7fd4f746d6 | ||
|
|
2362d9f3c2 | ||
|
|
6b84f8c6b1 | ||
|
|
997a9112d1 | ||
|
|
d46ca97680 | ||
|
|
417bbf8a9e | ||
|
|
a7b016c954 | ||
|
|
6015493de9 | ||
|
|
c718bdbe2b | ||
|
|
0a8f947169 | ||
|
|
d7efccf6a5 | ||
|
|
334920bc9e | ||
|
|
6e00db433c | ||
|
|
c6344e7c3e | ||
|
|
2131254722 | ||
|
|
b6d1866deb | ||
|
|
e56f489d06 | ||
|
|
bf62afb27c | ||
|
|
8369056027 | ||
|
|
09499a732f | ||
|
|
2ee015452c | ||
|
|
ffc1bf8bbe | ||
|
|
014dbd5c3a | ||
|
|
9bceaa59d2 | ||
|
|
832ebb3f39 | ||
|
|
8345c271cc | ||
|
|
56208aa84d | ||
|
|
b866a2c744 | ||
|
|
a77234e637 | ||
|
|
e0e7354708 | ||
|
|
0f86a16915 | ||
|
|
972c22b02f | ||
|
|
93c27340e4 | ||
|
|
c3edb32558 | ||
|
|
3baaa732df | ||
|
|
8ceb7e76ea | ||
|
|
4d5dddd302 | ||
|
|
55efccb07f | ||
|
|
961d8e1481 | ||
|
|
d396a9931e | ||
|
|
e3f8f121f4 | ||
|
|
80f29e9eda | ||
|
|
8995d8133a | ||
|
|
31044206b8 | ||
|
|
3a1702e56f | ||
|
|
501ec74a48 | ||
|
|
c248fe0bb3 | ||
|
|
215fbcb2e4 | ||
|
|
e39f44b529 | ||
|
|
9eff6ae476 | ||
|
|
3eec5a5cb6 | ||
|
|
66878deb2c | ||
|
|
0b6e1711e4 | ||
|
|
15025837bb | ||
|
|
0229a2055e | ||
|
|
eb9af15c7a | ||
|
|
0584746815 | ||
|
|
8c4ea850ba | ||
|
|
4b43f13e65 | ||
|
|
26d35474e9 | ||
|
|
9fbe3564df | ||
|
|
bed5547890 | ||
|
|
47922fe7d8 | ||
|
|
dcd25d1d97 | ||
|
|
81a2a17c5f | ||
|
|
6b3f1de19d | ||
|
|
7c17af2a41 | ||
|
|
ecf5a368d7 | ||
|
|
557c5be433 | ||
|
|
49405c3afd | ||
|
|
3439122629 | ||
|
|
f6e5da6723 | ||
|
|
842f241cb9 | ||
|
|
41daac1b04 | ||
|
|
2a7fc84044 | ||
|
|
44ff0b1a14 | ||
|
|
91cdd318a8 | ||
|
|
3dc00816fb | ||
|
|
e331d5b371 | ||
|
|
8d5090ce54 | ||
|
|
25244d906d | ||
|
|
aa445713ac | ||
|
|
177769a1ce | ||
|
|
967e9255a2 | ||
|
|
910609a75f | ||
|
|
f9c202190a |
2
.github/actions/gomodtidy/Dockerfile
vendored
2
.github/actions/gomodtidy/Dockerfile
vendored
@@ -1,4 +1,4 @@
|
||||
FROM golang:1.23-alpine
|
||||
FROM golang:1.24-alpine
|
||||
|
||||
COPY entrypoint.sh /entrypoint.sh
|
||||
|
||||
|
||||
4
.github/workflows/changelog.yml
vendored
4
.github/workflows/changelog.yml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout source code
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
|
||||
|
||||
- name: Download unclog binary
|
||||
uses: dsaltares/fetch-gh-release-asset@aa2ab1243d6e0d5b405b973c89fa4d06a2d0fff7 # 1.1.2
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
|
||||
- name: Get new changelog files
|
||||
id: new-changelog-files
|
||||
uses: tj-actions/changed-files@v45
|
||||
uses: OffchainLabs/gh-action-changed-files@9200e69727eb73eb060652b19946b8a2fdfb654b # v4.0.8
|
||||
with:
|
||||
files: |
|
||||
changelog/**.md
|
||||
|
||||
16
.github/workflows/go.yml
vendored
16
.github/workflows/go.yml
vendored
@@ -28,15 +28,15 @@ jobs:
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Go 1.23
|
||||
- name: Set up Go 1.24
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.23.5'
|
||||
go-version: '1.24.0'
|
||||
- name: Run Gosec Security Scanner
|
||||
run: | # https://github.com/securego/gosec/issues/469
|
||||
export PATH=$PATH:$(go env GOPATH)/bin
|
||||
go install github.com/securego/gosec/v2/cmd/gosec@v2.19.0
|
||||
gosec -exclude-generated -exclude=G307 -exclude-dir=crypto/bls/herumi ./...
|
||||
go install github.com/securego/gosec/v2/cmd/gosec@v2.22.1
|
||||
gosec -exclude-generated -exclude=G307,G115 -exclude-dir=crypto/bls/herumi ./...
|
||||
|
||||
lint:
|
||||
name: Lint
|
||||
@@ -45,16 +45,16 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Set up Go 1.23
|
||||
- name: Set up Go 1.24
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.23.5'
|
||||
go-version: '1.24.0'
|
||||
id: go
|
||||
|
||||
- name: Golangci-lint
|
||||
uses: golangci/golangci-lint-action@v5
|
||||
with:
|
||||
version: v1.63.4
|
||||
version: v1.64.5
|
||||
args: --config=.golangci.yml --out-${NO_FUTURE}format colored-line-number
|
||||
|
||||
build:
|
||||
@@ -64,7 +64,7 @@ jobs:
|
||||
- name: Set up Go 1.x
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.23.5'
|
||||
go-version: '1.24.0'
|
||||
id: go
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
|
||||
@@ -75,6 +75,7 @@ linters:
|
||||
- tagliatelle
|
||||
- thelper
|
||||
- unparam
|
||||
- usetesting
|
||||
- varnamelen
|
||||
- wrapcheck
|
||||
- wsl
|
||||
|
||||
@@ -165,7 +165,7 @@ STATICCHECK_ANALYZERS = [
|
||||
"sa6006",
|
||||
"sa9001",
|
||||
"sa9002",
|
||||
#"sa9003", # Doesn't build. See https://github.com/dominikh/go-tools/pull/1483
|
||||
"sa9003",
|
||||
"sa9004",
|
||||
"sa9005",
|
||||
"sa9006",
|
||||
@@ -197,6 +197,7 @@ nogo(
|
||||
"//tools/analyzers/logruswitherror:go_default_library",
|
||||
"//tools/analyzers/maligned:go_default_library",
|
||||
"//tools/analyzers/nop:go_default_library",
|
||||
"//tools/analyzers/nopanic:go_default_library",
|
||||
"//tools/analyzers/properpermissions:go_default_library",
|
||||
"//tools/analyzers/recursivelock:go_default_library",
|
||||
"//tools/analyzers/shadowpredecl:go_default_library",
|
||||
|
||||
268
CHANGELOG.md
268
CHANGELOG.md
@@ -4,6 +4,274 @@ 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.2](https://github.com/prysmaticlabs/prysm/compare/v5.3.1...v5.3.2) - 2025-03-25
|
||||
|
||||
This release introduces support for the `Hoodi` testnet.
|
||||
|
||||
Release highlights:
|
||||
|
||||
- Ability to run the node on the `Hoodi` tesnet. See https://blog.ethereum.org/2025/03/18/hoodi-holesky for more information about `Hoodi`.
|
||||
- A new feature that allows treat certain blocks as invalid. This is especially useful when the network is split, allowing the node to discontinue following unwanted forks.
|
||||
|
||||
Testnet operators are required to update to this release. Without this release you will be unable to run the node on the `Hoodi` testnet.
|
||||
|
||||
Mainnet operators are recommended to update to this release at their regular cadence.
|
||||
|
||||
### Added
|
||||
|
||||
- enable SSZ for builder API calls. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14976)
|
||||
- Add Hoodi testnet flag `--hoodi` to specify Hoodi testnet config and bootnodes. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15057)
|
||||
- block_gossip topic support to the beacon api event stream. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15038)
|
||||
- Added a static analyzer to discourage use of panic() in Prysm. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15075)
|
||||
- Add a feature flag `--blacklist-roots` to allow the node to specify blocks that will be treated as invalid. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15030)
|
||||
|
||||
### Changed
|
||||
|
||||
- changed request object for `POST /eth/v1/beacon/states/head/validators` to omit the field if empty for satisfying other clients. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15031)
|
||||
- Update spec test to v1.5.0-beta.3. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15050)
|
||||
- Update Gossip and RPC message limits to comply with the spec. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14799)
|
||||
- Return 404 instead of 500 from API when when a blob for a requested index is not found. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14845)
|
||||
- Save Electra orphaned attestations into attestations pool's block attestations. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15060)
|
||||
- Removed redundant string conversion in `BeaconDbStater.State` to improve code clarity and maintainability. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15081)
|
||||
|
||||
### Fixed
|
||||
|
||||
- Update seen unaggregated att cache to properly handle Electra attestations. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15034)
|
||||
- cosmetic fix for calling `/prysm/validators/performance` when connecting to non prysm beacon nodes and removing the 404 error log. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15062)
|
||||
- Tracked validator cache: Make sure no to loose the reference. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15077)
|
||||
- Fixed proposing at genesis when starting post Bellatrix. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15084)
|
||||
|
||||
## [v5.3.1](https://github.com/prysmaticlabs/prysm/compare/v5.3.0...v5.3.1) - 2025-03-13
|
||||
|
||||
This release is packed with critical fixes for **Electra** and some important fixes for mainnet too.
|
||||
|
||||
The release highlights include:
|
||||
|
||||
- Ensure that deleting a block from the database clears its entry in the slot->root db index. This issue was causing some operators to have a bricked database, requiring a full resync. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15011)
|
||||
- Updated go to go1.24.0. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14969)
|
||||
- Added a feature flag to sync from an arbitrary beacon block root at startup. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15000)
|
||||
- Updated default gas limit from 30M to 36M. Override this with `--suggested-gas-limit=` in the validator client. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14858)
|
||||
|
||||
Known issues in **Electra**:
|
||||
|
||||
- Duplicate attestations are needlessly processed. This is being addressed in [[PR]](https://github.com/prysmaticlabs/prysm/pull/15034).
|
||||
|
||||
Testnet operators are strongly encouraged to update to this release. There are many fixes and improvements from the Holesky upgrade incident.
|
||||
|
||||
Mainnet operators are recommended to update to this release at their regular cadence.
|
||||
|
||||
### Added
|
||||
|
||||
- enable E2E for minimal and mainnet tests. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14842)
|
||||
- enable web3signer E2E for electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14936)
|
||||
- Enable multiclient E2E for electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14946)
|
||||
- Enable Scenario E2E tests with electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14946)
|
||||
- Add endpoint for getting pending deposits. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14941)
|
||||
- Add request hash to header for builder: executable data to block. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14955)
|
||||
- Log execution requests in each block. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14956)
|
||||
- Add endpoint for getting pending partial withdrawals. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14949)
|
||||
- Tracked validators cache: Added the `ItemCount` method. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14957)
|
||||
- Tracked validators cache: Added the `Indices` method. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14957)
|
||||
- Added deposit request testing for electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14964)
|
||||
- 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`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14972)
|
||||
- Add SSZ support to light client finality and optimistic APIs. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14836)
|
||||
- add log to committee index when committeebits are not the expected length of 1. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14993)
|
||||
- Add acceptable address types for static peers. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14886)
|
||||
- Added a feature flag to sync from an arbitrary beacon block root at startup. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15000)
|
||||
|
||||
### Changed
|
||||
|
||||
- updates geth to 1.15.0. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14842)
|
||||
- Updates blst to v3.14.0 and fixes the references in our deps.bzl file. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14921)
|
||||
- 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. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14928)
|
||||
- Don't use MaxCover for Electra on-chain attestations. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14925)
|
||||
- Tracked validators cache: Remove validators from the cache if not seen after 1 hour. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14957)
|
||||
- execution requests errors on ssz length have been improved. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14962)
|
||||
- deprecate beacon api endpoints based on [3.0.0 release](https://github.com/ethereum/beacon-APIs/pull/506) for electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14967)
|
||||
- Use go-cmp for printing better diffs for assertions.DeepEqual. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14978)
|
||||
- Reorganized beacon chain flags in `--help` text into logical sections. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14959)
|
||||
- `--validators-registration-batch-size`: Change default value from `0` to `200`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14981)
|
||||
- Updated go to go1.24.0. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14969)
|
||||
- Updated gosec to v2.22.1 and golangci to v1.64.5. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14969)
|
||||
- Updated github.com/trailofbits/go-mutexasserts. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14969)
|
||||
- Updated rules_go to cf3c3af34bd869b864f5f2b98e2f41c2b220d6c9 to support go1.24.0. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14969)
|
||||
- Validate blob sidecar re-order signature and bad parent block. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15013)
|
||||
- Updated default gas limit from 30M to 36M. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14858)
|
||||
- Ignore errors from `hasSeenBit` and don't pack unaggregated attestations. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15018)
|
||||
|
||||
### Removed
|
||||
|
||||
- Remove Fulu state and block. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14905)
|
||||
- Removed the log summarizing all started services. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14958)
|
||||
|
||||
### Fixed
|
||||
|
||||
- fixed max and target blob per block from static to dynamic values. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14911)
|
||||
- refactored publish block and block ssz functions to fix gocognit. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14913)
|
||||
- refactored publish blinded block and blinded block ssz to correctly deal with version headers and sent blocks. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14913)
|
||||
- Only check for electra related engine methods if electra is active. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14924)
|
||||
- Fixed bug that breaks new blob storage layout code on Windows, caused by accidental use of platform-dependent path parsing package. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14931)
|
||||
- Fix E2E Process Deposit Evaluator for Electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14933)
|
||||
- Fixed the `bazel run //:gazelle` command in `DEPENDENCIES.md`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14934)
|
||||
- Fix E2E Deposit Activation Evaluator for Electra. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14938)
|
||||
- Dedicated processing of `SingleAttestation` in the monitor service. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14965)
|
||||
- adding in content type and accept headers for builder API call on registration. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14961)
|
||||
- fixed gocognit in block conversions between json and proto types. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14953)
|
||||
- Lint: Fix violations of S1009: should omit nil check; len() for nil slices is defined as zero. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14973)
|
||||
- Lint: Fix violations of non-constant format string in call. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14974)
|
||||
- Fixed violations of gosec G301. This is a check that created files and directories have file permissions 0750 and 0600 respectively. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14980)
|
||||
- Check for the correct attester slashing type during gossip validation. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14985)
|
||||
- cosmetic fix for post electra validator logs displaying attestation committee information correctly. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14992)
|
||||
- fix inserting the wrong committee index into the seen cache for electra attestations. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14998)
|
||||
- Allow any block type to be unmarshaled rather than only phase0 blocks in `slotByBlockRoot`. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15008)
|
||||
- Fixed pruner to not block while pruning large database by introducing batchSize. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14929)
|
||||
- Decompose Electra block attestations to prevent redundant packing. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14896)
|
||||
- Fixed use of deprecated rand.Seed. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14969)
|
||||
- Fixed build issue with SszGen where the go binary was not present in the $PATH. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14969)
|
||||
- fixed /eth/v1/config/spec displays BLOB_SIDECAR_SUBNET_COUNT,BLOB_SIDECAR_SUBNET_COUNT_ELECTRA. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15016)
|
||||
- Ensure that deleting a block from the database clears its entry in the slot->root db index. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15011)
|
||||
- Broadcasting BLS to execution changes should not use the request context in a go routine. Use context.Background() for the broadcasting go routine. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15019)
|
||||
- /eth/v1/validator/sync_committee_contribution should check for optimistic status and return a 503 if it's optimistic. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15022)
|
||||
- Fixes printing superfluous response.WriteHeader call from error in builder. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15025)
|
||||
- Fixes e2e run with builder having wrong gaslimit header due to not being set on eth1 nodes. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15025)
|
||||
- Fixed a bug in the event stream handler when processing payload attribute events where the timestamp and slot of the event would be based on the head rather than the current slot. [[PR]](https://github.com/prysmaticlabs/prysm/pull/14963)
|
||||
- Handle unaggregated attestations when decomposing Electra block attestations. [[PR]](https://github.com/prysmaticlabs/prysm/pull/15027)
|
||||
|
||||
## [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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
|
||||
63
README.md
63
README.md
@@ -1,5 +1,7 @@
|
||||
# Prysm: An Ethereum Consensus Implementation Written in Go
|
||||
<h1 align="left">Prysm: An Ethereum Consensus Implementation Written in Go</h1>
|
||||
|
||||
<div align="left">
|
||||
|
||||
[](https://buildkite.com/prysmatic-labs/prysm)
|
||||
[](https://goreportcard.com/report/github.com/prysmaticlabs/prysm)
|
||||
[](https://github.com/ethereum/consensus-specs/tree/v1.4.0)
|
||||
@@ -7,31 +9,60 @@
|
||||
[](https://discord.gg/prysmaticlabs)
|
||||
[](https://www.gitpoap.io/gh/prysmaticlabs/prysm)
|
||||
|
||||
This is the core repository for Prysm, a [Golang](https://golang.org/) implementation of the [Ethereum Consensus](https://ethereum.org/en/developers/docs/consensus-mechanisms/#proof-of-stake) [specification](https://github.com/ethereum/consensus-specs), developed by [Offchain Labs](https://www.offchainlabs.com). See the [Changelog](https://github.com/prysmaticlabs/prysm/releases) for details of the latest releases and upcoming breaking changes.
|
||||
</div>
|
||||
|
||||
### Getting Started
|
||||
---
|
||||
|
||||
A detailed set of installation and usage instructions as well as breakdowns of each individual component are available in the [official documentation portal](https://docs.prylabs.network). If you still have questions, feel free to stop by our [Discord](https://discord.gg/prysmaticlabs).
|
||||
## 📖 Overview
|
||||
|
||||
### Staking on Mainnet
|
||||
This is the core repository for Prysm, a [Golang](https://golang.org/) implementation of the [Ethereum Consensus](https://ethereum.org/en/developers/docs/consensus-mechanisms/#proof-of-stake) [specification](https://github.com/ethereum/consensus-specs), developed by [Offchain Labs](https://www.offchainlabs.com).
|
||||
|
||||
To participate in staking, you can join the [official eth2 launchpad](https://launchpad.ethereum.org). The launchpad is the only recommended way to become a validator on mainnet. You can explore validator rewards/penalties via Bitfly's block explorer: [beaconcha.in](https://beaconcha.in), and follow the latest blocks added to the chain on [beaconscan](https://beaconscan.com).
|
||||
See the [Changelog](https://github.com/prysmaticlabs/prysm/releases) for details of the latest releases and upcoming breaking changes.
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Getting Started
|
||||
|
||||
A detailed set of installation and usage instructions as well as breakdowns of each individual component are available in the **[official documentation portal](https://docs.prylabs.network)**.
|
||||
|
||||
💬 **Need help?** Join our **[Discord Community](https://discord.gg/prysmaticlabs)** for support.
|
||||
|
||||
---
|
||||
|
||||
## 🏆 Staking on Mainnet
|
||||
|
||||
To participate in staking, you can join the **[official Ethereum launchpad](https://launchpad.ethereum.org)**. The launchpad is the **only recommended** way to become a validator on mainnet.
|
||||
|
||||
🔍 Explore validator rewards/penalties:
|
||||
|
||||
- **[beaconcha.in](https://beaconcha.in)**
|
||||
- **[beaconscan](https://beaconscan.com)**
|
||||
|
||||
---
|
||||
|
||||
## 🤝 Contributing
|
||||
|
||||
### 🔥 Branches
|
||||
|
||||
## Contributing
|
||||
### Branches
|
||||
Prysm maintains two permanent branches:
|
||||
|
||||
* [master](https://github.com/prysmaticlabs/prysm/tree/master): This points to the latest stable release. It is ideal for most users.
|
||||
* [develop](https://github.com/prysmaticlabs/prysm/tree/develop): This is used for development, it contains the latest PRs. Developers should base their PRs on this branch.
|
||||
- **[`master`](https://github.com/prysmaticlabs/prysm/tree/master)** - This points to the latest stable release. It is ideal for most users.
|
||||
- **[`develop`](https://github.com/prysmaticlabs/prysm/tree/develop)** - This is used for development and contains the latest PRs. Developers should base their PRs on this branch.
|
||||
|
||||
### Guide
|
||||
Want to get involved? Check out our [Contribution Guide](https://docs.prylabs.network/docs/contribute/contribution-guidelines/) to learn more!
|
||||
### 🛠 Contribution Guide
|
||||
|
||||
## License
|
||||
Want to get involved? Check out our **[Contribution Guide](https://docs.prylabs.network/docs/contribute/contribution-guidelines/)** to learn more!
|
||||
|
||||
[GNU General Public License v3.0](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||
---
|
||||
|
||||
## Legal Disclaimer
|
||||
## 📜 License
|
||||
|
||||
[Terms of Use](/TERMS_OF_SERVICE.md)
|
||||
[](https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||
|
||||
This project is licensed under the **GNU General Public License v3.0**.
|
||||
|
||||
---
|
||||
|
||||
## ⚖️ Legal Disclaimer
|
||||
|
||||
📜 [Terms of Use](/TERMS_OF_SERVICE.md)
|
||||
|
||||
48
WORKSPACE
48
WORKSPACE
@@ -160,15 +160,15 @@ oci_register_toolchains(
|
||||
|
||||
http_archive(
|
||||
name = "io_bazel_rules_go",
|
||||
integrity = "sha256-JD8o94crTb2DFiJJR8nMAGdBAW95zIENB4cbI+JnrI4=",
|
||||
patch_args = ["-p1"],
|
||||
patches = [
|
||||
# Expose internals of go_test for custom build transitions.
|
||||
"//third_party:io_bazel_rules_go_test.patch",
|
||||
],
|
||||
sha256 = "b2038e2de2cace18f032249cb4bb0048abf583a36369fa98f687af1b3f880b26",
|
||||
strip_prefix = "rules_go-cf3c3af34bd869b864f5f2b98e2f41c2b220d6c9",
|
||||
urls = [
|
||||
"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",
|
||||
"https://github.com/bazel-contrib/rules_go/archive/cf3c3af34bd869b864f5f2b98e2f41c2b220d6c9.tar.gz",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -210,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.23.5",
|
||||
go_version = "1.24.0",
|
||||
nogo = "@//:nogo",
|
||||
)
|
||||
|
||||
@@ -255,7 +255,7 @@ filegroup(
|
||||
url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz",
|
||||
)
|
||||
|
||||
consensus_spec_version = "v1.5.0-beta.1"
|
||||
consensus_spec_version = "v1.5.0-beta.4"
|
||||
|
||||
bls_test_version = "v0.1.1"
|
||||
|
||||
@@ -271,7 +271,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-R6r60geCfEjMaB1Ag3svaMFXFIgaJvkTJhfKsf76rFE=",
|
||||
integrity = "sha256-QG0NUqaCvP5lKaKKwF/fmeICZVjONMlb7EE+MtYl0C0=",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -287,7 +287,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-2Pem2gMHxW/6bBhZ2BaqkQruQSd/dTS3WMaMQO8rZ/o=",
|
||||
integrity = "sha256-8NQngTSSqzW/j3tOUi3r5h+94ChRbLNWTt7BOGqr4+E=",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -303,7 +303,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-5yP05JTV1MhcUZ2kSh+T+kXjG+uW3A5877veC5c1mD4=",
|
||||
integrity = "sha256-gFqxbaBnJ7dtdoj0zFbVrtlHv/bLNuWjrTHkyCAjFjI=",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -318,7 +318,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-O6Rg6h19T0RsJs0sBDZ9O1k4LnCJ/gu2ilHijFBVfME=",
|
||||
integrity = "sha256-9paalF0POULpP2ga+4ouHSETKYrWNCUCZoJHPuFw06E=",
|
||||
strip_prefix = "consensus-specs-" + consensus_spec_version[1:],
|
||||
url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
@@ -365,9 +365,9 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-b7ZTT+olF+VXEJYNTV5jggNtCkt9dOejm1i2VE+zy+0=",
|
||||
strip_prefix = "holesky-874c199423ccd180607320c38cbaca05d9a1573a",
|
||||
url = "https://github.com/eth-clients/holesky/archive/874c199423ccd180607320c38cbaca05d9a1573a.tar.gz", # 2024-06-18
|
||||
integrity = "sha256-YVFFrCmjoGZ3fXMWpsCpSsYbANy1grnqYwOLKIg2SsA=",
|
||||
strip_prefix = "holesky-32a72e21c6e53c262f27d50dd540cb654517d03a",
|
||||
url = "https://github.com/eth-clients/holesky/archive/32a72e21c6e53c262f27d50dd540cb654517d03a.tar.gz", # 2025-03-17
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -381,9 +381,25 @@ filegroup(
|
||||
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
|
||||
integrity = "sha256-b5F7Wg9LLMqGRIpP2uqb/YsSFVn2ynzlV7g/Nb1EFLk=",
|
||||
strip_prefix = "sepolia-562d9938f08675e9ba490a1dfba21fb05843f39f",
|
||||
url = "https://github.com/eth-clients/sepolia/archive/562d9938f08675e9ba490a1dfba21fb05843f39f.tar.gz", # 2025-03-17
|
||||
)
|
||||
|
||||
http_archive(
|
||||
name = "hoodi_testnet",
|
||||
build_file_content = """
|
||||
filegroup(
|
||||
name = "configs",
|
||||
srcs = [
|
||||
"metadata/config.yaml",
|
||||
],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
integrity = "sha256-dPiEWUd8QvbYGwGtIm0QtCekitVLOLsW5rpQIGzz8PU=",
|
||||
strip_prefix = "hoodi-828c2c940e1141092bd4bb979cef547ea926d272",
|
||||
url = "https://github.com/eth-clients/hoodi/archive/828c2c940e1141092bd4bb979cef547ea926d272.tar.gz",
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -431,7 +447,7 @@ gometalinter_dependencies()
|
||||
|
||||
load("@bazel_gazelle//:deps.bzl", "gazelle_dependencies")
|
||||
|
||||
gazelle_dependencies()
|
||||
gazelle_dependencies(go_sdk = "go_sdk")
|
||||
|
||||
load("@com_google_protobuf//:protobuf_deps.bzl", "protobuf_deps")
|
||||
|
||||
|
||||
9
api/apiutil/BUILD.bazel
Normal file
9
api/apiutil/BUILD.bazel
Normal file
@@ -0,0 +1,9 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["common.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/apiutil",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["//consensus-types/primitives:go_default_library"],
|
||||
)
|
||||
30
api/apiutil/common.go
Normal file
30
api/apiutil/common.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package apiutil
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
neturl "net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
)
|
||||
|
||||
func ValidRoot(root string) bool {
|
||||
matchesRegex, err := regexp.MatchString("^0x[a-fA-F0-9]{64}$", root)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return matchesRegex
|
||||
}
|
||||
|
||||
func Uint64ToString[T uint64 | primitives.Slot | primitives.ValidatorIndex | primitives.CommitteeIndex | primitives.Epoch](val T) string {
|
||||
return strconv.FormatUint(uint64(val), 10)
|
||||
}
|
||||
|
||||
func BuildURL(path string, queryParams ...neturl.Values) string {
|
||||
if len(queryParams) == 0 {
|
||||
return path
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s?%s", path, queryParams[0].Encode())
|
||||
}
|
||||
@@ -5,16 +5,31 @@ go_library(
|
||||
srcs = [
|
||||
"client.go",
|
||||
"errors.go",
|
||||
"json_rest_handler.go",
|
||||
"options.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["@com_github_pkg_errors//:go_default_library"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//network/httputil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["client_test.go"],
|
||||
srcs = [
|
||||
"client_test.go",
|
||||
"json_rest_handler_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = ["//testing/require:go_default_library"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//network/httputil:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -3,61 +3,34 @@ 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",
|
||||
"log.go",
|
||||
"structs.go",
|
||||
"template.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client:go_default_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",
|
||||
],
|
||||
srcs = ["client_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
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",
|
||||
],
|
||||
)
|
||||
|
||||
45
api/client/beacon/chain/BUILD.bazel
Normal file
45
api/client/beacon/chain/BUILD.bazel
Normal file
@@ -0,0 +1,45 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"client.go",
|
||||
"grpc_client.go",
|
||||
"interfaces.go",
|
||||
"rest_client.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/chain",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/beacon/shared_providers:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"//validator/helpers:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["rest_client_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/client/beacon/mock:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//consensus-types/primitives: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_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
31
api/client/beacon/chain/client.go
Normal file
31
api/client/beacon/chain/client.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package chain
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
validatorHelpers "github.com/prysmaticlabs/prysm/v5/validator/helpers"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func NewClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandler client.JsonRestHandler) Client {
|
||||
grpcClient := NewGrpcChainClient(validatorConn.GetGrpcClientConn())
|
||||
if features.Get().EnableBeaconRESTApi {
|
||||
return NewBeaconApiChainClientWithFallback(jsonRestHandler, grpcClient)
|
||||
} else {
|
||||
return grpcClient
|
||||
}
|
||||
}
|
||||
|
||||
func NewGrpcChainClient(cc grpc.ClientConnInterface) Client {
|
||||
return &grpcChainClient{ethpb.NewBeaconChainClient(cc)}
|
||||
}
|
||||
|
||||
func NewBeaconApiChainClientWithFallback(jsonRestHandler client.JsonRestHandler, fallbackClient Client) Client {
|
||||
return &beaconApiChainClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
fallbackClient: fallbackClient,
|
||||
stateValidatorsProvider: shared_providers.NewStateValidators(jsonRestHandler),
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,10 @@
|
||||
package grpc_api
|
||||
package chain
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type grpcChainClient struct {
|
||||
@@ -36,7 +34,3 @@ func (c *grpcChainClient) ValidatorPerformance(ctx context.Context, in *ethpb.Va
|
||||
func (c *grpcChainClient) ValidatorParticipation(ctx context.Context, in *ethpb.GetValidatorParticipationRequest) (*ethpb.ValidatorParticipationResponse, error) {
|
||||
return c.beaconChainClient.GetValidatorParticipation(ctx, in)
|
||||
}
|
||||
|
||||
func NewGrpcChainClient(cc grpc.ClientConnInterface) iface.ChainClient {
|
||||
return &grpcChainClient{ethpb.NewBeaconChainClient(cc)}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package iface
|
||||
package chain
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,11 +7,11 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type ChainClient interface {
|
||||
type Client interface {
|
||||
ChainHead(ctx context.Context, in *empty.Empty) (*ethpb.ChainHead, error)
|
||||
ValidatorBalances(ctx context.Context, in *ethpb.ListValidatorBalancesRequest) (*ethpb.ValidatorBalances, error)
|
||||
Validators(ctx context.Context, in *ethpb.ListValidatorsRequest) (*ethpb.Validators, error)
|
||||
ValidatorQueue(ctx context.Context, in *empty.Empty) (*ethpb.ValidatorQueue, error)
|
||||
ValidatorPerformance(ctx context.Context, in *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error)
|
||||
ValidatorParticipation(ctx context.Context, in *ethpb.GetValidatorParticipationRequest) (*ethpb.ValidatorParticipationResponse, error)
|
||||
ValidatorPerformance(context.Context, *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error)
|
||||
}
|
||||
@@ -1,30 +1,27 @@
|
||||
package beacon_api
|
||||
package chain
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
)
|
||||
|
||||
type beaconApiChainClient struct {
|
||||
fallbackClient iface.ChainClient
|
||||
jsonRestHandler JsonRestHandler
|
||||
stateValidatorsProvider StateValidatorsProvider
|
||||
fallbackClient Client
|
||||
jsonRestHandler client.JsonRestHandler
|
||||
stateValidatorsProvider shared_providers.StateValidators
|
||||
}
|
||||
|
||||
const getValidatorPerformanceEndpoint = "/prysm/validators/performance"
|
||||
|
||||
func (c beaconApiChainClient) headBlockHeaders(ctx context.Context) (*structs.GetBlockHeaderResponse, error) {
|
||||
blockHeader := structs.GetBlockHeaderResponse{}
|
||||
err := c.jsonRestHandler.Get(ctx, "/eth/v1/beacon/headers/head", &blockHeader)
|
||||
@@ -152,7 +149,7 @@ func (c beaconApiChainClient) ValidatorBalances(ctx context.Context, in *ethpb.L
|
||||
}
|
||||
|
||||
// TODO: Implement me
|
||||
panic("beaconApiChainClient.ValidatorBalances is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
|
||||
return nil, errors.New("beaconApiChainClient.ValidatorBalances is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
|
||||
}
|
||||
|
||||
func (c beaconApiChainClient) Validators(ctx context.Context, in *ethpb.ListValidatorsRequest) (*ethpb.Validators, error) {
|
||||
@@ -316,33 +313,16 @@ func (c beaconApiChainClient) ValidatorQueue(ctx context.Context, in *empty.Empt
|
||||
}
|
||||
|
||||
// TODO: Implement me
|
||||
panic("beaconApiChainClient.ValidatorQueue is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
|
||||
return nil, errors.New("beaconApiChainClient.ValidatorQueue is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
|
||||
}
|
||||
|
||||
func (c beaconApiChainClient) ValidatorPerformance(ctx context.Context, in *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error) {
|
||||
request, err := json.Marshal(structs.GetValidatorPerformanceRequest{
|
||||
PublicKeys: in.PublicKeys,
|
||||
Indices: in.Indices,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to marshal request")
|
||||
}
|
||||
resp := &structs.GetValidatorPerformanceResponse{}
|
||||
if err = c.jsonRestHandler.Post(ctx, getValidatorPerformanceEndpoint, nil, bytes.NewBuffer(request), resp); err != nil {
|
||||
return nil, err
|
||||
if c.fallbackClient != nil {
|
||||
return c.fallbackClient.ValidatorPerformance(ctx, in)
|
||||
}
|
||||
|
||||
return ðpb.ValidatorPerformanceResponse{
|
||||
CurrentEffectiveBalances: resp.CurrentEffectiveBalances,
|
||||
CorrectlyVotedSource: resp.CorrectlyVotedSource,
|
||||
CorrectlyVotedTarget: resp.CorrectlyVotedTarget,
|
||||
CorrectlyVotedHead: resp.CorrectlyVotedHead,
|
||||
BalancesBeforeEpochTransition: resp.BalancesBeforeEpochTransition,
|
||||
BalancesAfterEpochTransition: resp.BalancesAfterEpochTransition,
|
||||
MissingValidators: resp.MissingValidators,
|
||||
PublicKeys: resp.PublicKeys,
|
||||
InactivityScores: resp.InactivityScores,
|
||||
}, nil
|
||||
// TODO: Implement me
|
||||
return nil, errors.New("beaconApiChainClient.ValidatorPerformance is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
|
||||
}
|
||||
|
||||
func (c beaconApiChainClient) ValidatorParticipation(ctx context.Context, in *ethpb.GetValidatorParticipationRequest) (*ethpb.ValidatorParticipationResponse, error) {
|
||||
@@ -351,13 +331,5 @@ func (c beaconApiChainClient) ValidatorParticipation(ctx context.Context, in *et
|
||||
}
|
||||
|
||||
// TODO: Implement me
|
||||
panic("beaconApiChainClient.ValidatorParticipation is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
|
||||
}
|
||||
|
||||
func NewBeaconApiChainClientWithFallback(jsonRestHandler JsonRestHandler, fallbackClient iface.ChainClient) iface.ChainClient {
|
||||
return &beaconApiChainClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
fallbackClient: fallbackClient,
|
||||
stateValidatorsProvider: beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler},
|
||||
}
|
||||
return nil, errors.New("beaconApiChainClient.ValidatorParticipation is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
package beacon_api
|
||||
package chain
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
@@ -11,14 +9,13 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"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/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"go.uber.org/mock/gomock"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
@@ -919,43 +916,3 @@ func TestGetChainHead(t *testing.T) {
|
||||
assert.DeepEqual(t, expectedChainHead, chainHead)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_beaconApiBeaconChainClient_GetValidatorPerformance(t *testing.T) {
|
||||
publicKeys := [][48]byte{
|
||||
bytesutil.ToBytes48([]byte{1}),
|
||||
bytesutil.ToBytes48([]byte{2}),
|
||||
bytesutil.ToBytes48([]byte{3}),
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
request, err := json.Marshal(structs.GetValidatorPerformanceRequest{
|
||||
PublicKeys: [][]byte{publicKeys[0][:], publicKeys[2][:], publicKeys[1][:]},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
wantResponse := &structs.GetValidatorPerformanceResponse{}
|
||||
want := ðpb.ValidatorPerformanceResponse{}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
getValidatorPerformanceEndpoint,
|
||||
nil,
|
||||
bytes.NewBuffer(request),
|
||||
wantResponse,
|
||||
).Return(
|
||||
nil,
|
||||
)
|
||||
|
||||
c := beaconApiChainClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
|
||||
got, err := c.ValidatorPerformance(ctx, ðpb.ValidatorPerformanceRequest{
|
||||
PublicKeys: [][]byte{publicKeys[0][:], publicKeys[2][:], publicKeys[1][:]},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, want.PublicKeys, got.PublicKeys)
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"regexp"
|
||||
"sort"
|
||||
"strconv"
|
||||
"text/template"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
@@ -29,12 +28,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.
|
||||
@@ -63,24 +63,8 @@ func IdFromSlot(s primitives.Slot) StateOrBlockId {
|
||||
return StateOrBlockId(strconv.FormatUint(uint64(s), 10))
|
||||
}
|
||||
|
||||
// idTemplate is used to create template functions that can interpolate StateOrBlockId values.
|
||||
func idTemplate(ts string) func(StateOrBlockId) string {
|
||||
t := template.Must(template.New("").Parse(ts))
|
||||
f := func(id StateOrBlockId) string {
|
||||
b := bytes.NewBuffer(nil)
|
||||
err := t.Execute(b, struct{ Id string }{Id: string(id)})
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("invalid idTemplate: %s", ts))
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
// run the template to ensure that it is valid
|
||||
// this should happen load time (using package scoped vars) to ensure runtime errors aren't possible
|
||||
_ = f(IdGenesis)
|
||||
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 +88,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)
|
||||
@@ -112,8 +96,6 @@ func (c *Client) GetBlock(ctx context.Context, blockId StateOrBlockId) ([]byte,
|
||||
return b, nil
|
||||
}
|
||||
|
||||
var getBlockRootTpl = idTemplate(getBlockRootPath)
|
||||
|
||||
// GetBlockRoot retrieves the hash_tree_root of the BeaconBlock for the given block id.
|
||||
// Block identifier can be one of: "head" (canonical head in node's view), "genesis", "finalized",
|
||||
// <slot>, <hex encoded blockRoot with 0x prefix>. Variables of type StateOrBlockId are exported by this package
|
||||
@@ -136,8 +118,6 @@ func (c *Client) GetBlockRoot(ctx context.Context, blockId StateOrBlockId) ([32]
|
||||
return bytesutil.ToBytes32(rs), nil
|
||||
}
|
||||
|
||||
var getForkTpl = idTemplate(getForkForStatePath)
|
||||
|
||||
// GetFork queries the Beacon Node API for the Fork from the state identified by stateId.
|
||||
// Block identifier can be one of: "head" (canonical head in node's view), "genesis", "finalized",
|
||||
// <slot>, <hex encoded blockRoot with 0x prefix>. Variables of type StateOrBlockId are exported by this package
|
||||
@@ -195,6 +175,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 +196,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 +212,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 +231,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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
},
|
||||
}
|
||||
|
||||
20
api/client/beacon/health/BUILD.bazel
Normal file
20
api/client/beacon/health/BUILD.bazel
Normal file
@@ -0,0 +1,20 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"health_mock.go",
|
||||
"interfaces.go",
|
||||
"tracker.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/health",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = ["@org_uber_go_mock//gomock:go_default_library"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["tracker_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = ["@org_uber_go_mock//gomock:go_default_library"],
|
||||
)
|
||||
@@ -1,22 +1,25 @@
|
||||
package testing
|
||||
package health
|
||||
|
||||
import (
|
||||
"context"
|
||||
"reflect"
|
||||
"sync"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/iface"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = iface.HealthNode(&MockHealthClient{})
|
||||
)
|
||||
// NewMockHealthClient creates a new mock instance.
|
||||
func NewMockHealthClient(ctrl *gomock.Controller) *MockHealthClient {
|
||||
mock := &MockHealthClient{ctrl: ctrl}
|
||||
mock.recorder = &MockHealthClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
|
||||
// MockHealthClient is a mock of HealthClient interface.
|
||||
type MockHealthClient struct {
|
||||
ctrl *gomock.Controller
|
||||
recorder *MockHealthClientMockRecorder
|
||||
Health bool
|
||||
sync.Mutex
|
||||
}
|
||||
|
||||
@@ -38,6 +41,16 @@ func (m *MockHealthClient) IsHealthy(arg0 context.Context) bool {
|
||||
return ret0
|
||||
}
|
||||
|
||||
func (m *MockHealthClient) HealthUpdates() <-chan bool {
|
||||
ch := make(chan bool, 2)
|
||||
ch <- m.Health
|
||||
return ch
|
||||
}
|
||||
|
||||
func (m *MockHealthClient) CheckHealth(_ context.Context) bool {
|
||||
return m.Health
|
||||
}
|
||||
|
||||
// EXPECT returns an object that allows the caller to indicate expected use.
|
||||
func (m *MockHealthClient) EXPECT() *MockHealthClientMockRecorder {
|
||||
return m.recorder
|
||||
@@ -50,10 +63,3 @@ func (mr *MockHealthClientMockRecorder) IsHealthy(arg0 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "IsHealthy", reflect.TypeOf((*MockHealthClient)(nil).IsHealthy), arg0)
|
||||
}
|
||||
|
||||
// NewMockHealthClient creates a new mock instance.
|
||||
func NewMockHealthClient(ctrl *gomock.Controller) *MockHealthClient {
|
||||
mock := &MockHealthClient{ctrl: ctrl}
|
||||
mock.recorder = &MockHealthClientMockRecorder{mock}
|
||||
return mock
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
package iface
|
||||
package health
|
||||
|
||||
import "context"
|
||||
|
||||
type HealthTracker interface {
|
||||
HealthUpdates() <-chan bool
|
||||
IsHealthy() bool
|
||||
IsHealthy(ctx context.Context) bool
|
||||
CheckHealth(ctx context.Context) bool
|
||||
}
|
||||
|
||||
@@ -1,32 +1,30 @@
|
||||
package beacon
|
||||
package health
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/iface"
|
||||
)
|
||||
|
||||
type NodeHealthTracker struct {
|
||||
type healthTracker struct {
|
||||
isHealthy *bool
|
||||
healthChan chan bool
|
||||
node iface.HealthNode
|
||||
node HealthNode
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
func NewNodeHealthTracker(node iface.HealthNode) *NodeHealthTracker {
|
||||
return &NodeHealthTracker{
|
||||
func NewTracker(node HealthNode) HealthTracker {
|
||||
return &healthTracker{
|
||||
node: node,
|
||||
healthChan: make(chan bool, 1),
|
||||
}
|
||||
}
|
||||
|
||||
// HealthUpdates provides a read-only channel for health updates.
|
||||
func (n *NodeHealthTracker) HealthUpdates() <-chan bool {
|
||||
func (n *healthTracker) HealthUpdates() <-chan bool {
|
||||
return n.healthChan
|
||||
}
|
||||
|
||||
func (n *NodeHealthTracker) IsHealthy() bool {
|
||||
func (n *healthTracker) IsHealthy(_ context.Context) bool {
|
||||
n.RLock()
|
||||
defer n.RUnlock()
|
||||
if n.isHealthy == nil {
|
||||
@@ -35,7 +33,7 @@ func (n *NodeHealthTracker) IsHealthy() bool {
|
||||
return *n.isHealthy
|
||||
}
|
||||
|
||||
func (n *NodeHealthTracker) CheckHealth(ctx context.Context) bool {
|
||||
func (n *healthTracker) CheckHealth(ctx context.Context) bool {
|
||||
n.Lock()
|
||||
defer n.Unlock()
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
package beacon
|
||||
package health
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
healthTesting "github.com/prysmaticlabs/prysm/v5/api/client/beacon/testing"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = HealthTracker(&MockHealthClient{})
|
||||
)
|
||||
|
||||
func TestNodeHealth_IsHealthy(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -20,11 +23,11 @@ func TestNodeHealth_IsHealthy(t *testing.T) {
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
n := &NodeHealthTracker{
|
||||
n := &healthTracker{
|
||||
isHealthy: &tt.isHealthy,
|
||||
healthChan: make(chan bool, 1),
|
||||
}
|
||||
if got := n.IsHealthy(); got != tt.want {
|
||||
if got := n.IsHealthy(context.Background()); got != tt.want {
|
||||
t.Errorf("IsHealthy() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
@@ -47,9 +50,9 @@ func TestNodeHealth_UpdateNodeHealth(t *testing.T) {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
client := healthTesting.NewMockHealthClient(ctrl)
|
||||
client := NewMockHealthClient(ctrl)
|
||||
client.EXPECT().IsHealthy(gomock.Any()).Return(tt.newStatus)
|
||||
n := &NodeHealthTracker{
|
||||
n := &healthTracker{
|
||||
isHealthy: &tt.initial,
|
||||
node: client,
|
||||
healthChan: make(chan bool, 1),
|
||||
@@ -80,8 +83,8 @@ func TestNodeHealth_UpdateNodeHealth(t *testing.T) {
|
||||
func TestNodeHealth_Concurrency(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
client := healthTesting.NewMockHealthClient(ctrl)
|
||||
n := NewNodeHealthTracker(client)
|
||||
client := NewMockHealthClient(ctrl)
|
||||
n := NewTracker(client)
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// Number of goroutines to spawn for both reading and writing
|
||||
@@ -104,7 +107,7 @@ func TestNodeHealth_Concurrency(t *testing.T) {
|
||||
for i := 0; i < numGoroutines; i++ {
|
||||
go func() {
|
||||
defer wg.Done()
|
||||
_ = n.IsHealthy() // Just read the value
|
||||
_ = n.IsHealthy(context.Background()) // Just read the value
|
||||
}()
|
||||
}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["health.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/iface",
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
@@ -1,24 +1,28 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
package(default_testonly = True)
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"beacon_block_converter_mock.go",
|
||||
"chain_client_mock.go",
|
||||
"duties_mock.go",
|
||||
"genesis_mock.go",
|
||||
"json_rest_handler_mock.go",
|
||||
"node_client_mock.go",
|
||||
"prysm_chain_client_mock.go",
|
||||
"state_validators_mock.go",
|
||||
"validator_client_mock.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/testing/validator-mock",
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client/beacon:go_default_library",
|
||||
"//api/client/beacon/health:go_default_library",
|
||||
"//api/client/event:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
// Package validator_mock is a generated GoMock package.
|
||||
package validator_mock
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
@@ -1,5 +1,3 @@
|
||||
// Code generated by MockGen. DO NOT EDIT.
|
||||
// Source: github.com/prysmaticlabs/prysm/v5/validator/client/iface (interfaces: NodeClient)
|
||||
//
|
||||
// Generated by this command:
|
||||
//
|
||||
@@ -7,13 +5,13 @@
|
||||
//
|
||||
|
||||
// Package validator_mock is a generated GoMock package.
|
||||
package validator_mock
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
beacon "github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/health"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||
@@ -58,10 +56,10 @@ func (mr *MockNodeClientMockRecorder) Genesis(arg0, arg1 any) *gomock.Call {
|
||||
}
|
||||
|
||||
// HealthTracker mocks base method.
|
||||
func (m *MockNodeClient) HealthTracker() *beacon.NodeHealthTracker {
|
||||
func (m *MockNodeClient) HealthTracker() health.HealthTracker {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "HealthTracker")
|
||||
ret0, _ := ret[0].(*beacon.NodeHealthTracker)
|
||||
ret0, _ := ret[0].(health.HealthTracker)
|
||||
return ret0
|
||||
}
|
||||
|
||||
@@ -7,14 +7,15 @@
|
||||
//
|
||||
|
||||
// Package validator_mock is a generated GoMock package.
|
||||
package validator_mock
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
validator "github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
iface "github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -42,10 +43,10 @@ func (m *MockPrysmChainClient) EXPECT() *MockPrysmChainClientMockRecorder {
|
||||
}
|
||||
|
||||
// ValidatorCount mocks base method.
|
||||
func (m *MockPrysmChainClient) ValidatorCount(arg0 context.Context, arg1 string, arg2 []validator.Status) ([]iface.ValidatorCount, error) {
|
||||
func (m *MockPrysmChainClient) ValidatorCount(arg0 context.Context, arg1 string, arg2 []validator.Status) ([]beacon.ValidatorCount, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidatorCount", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].([]iface.ValidatorCount)
|
||||
ret0, _ := ret[0].([]beacon.ValidatorCount)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
@@ -55,3 +56,18 @@ func (mr *MockPrysmChainClientMockRecorder) ValidatorCount(arg0, arg1, arg2 any)
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorCount", reflect.TypeOf((*MockPrysmChainClient)(nil).ValidatorCount), arg0, arg1, arg2)
|
||||
}
|
||||
|
||||
// ValidatorPerformance mocks base method.
|
||||
func (m *MockPrysmChainClient) ValidatorPerformance(arg0 context.Context, arg1 *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "ValidatorPerformance", arg0, arg1)
|
||||
ret0, _ := ret[0].(*ethpb.ValidatorPerformanceResponse)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
|
||||
// ValidatorPerformance indicates an expected call of ValidatorPerformance.
|
||||
func (mr *MockPrysmChainClientMockRecorder) ValidatorPerformance(arg0, arg1 any) *gomock.Call {
|
||||
mr.mock.ctrl.T.Helper()
|
||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ValidatorCount", reflect.TypeOf((*MockPrysmChainClient)(nil).ValidatorPerformance), arg0, arg1)
|
||||
}
|
||||
@@ -7,16 +7,16 @@
|
||||
//
|
||||
|
||||
// Package validator_mock is a generated GoMock package.
|
||||
package validator_mock
|
||||
package mock
|
||||
|
||||
import (
|
||||
context "context"
|
||||
reflect "reflect"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
event "github.com/prysmaticlabs/prysm/v5/api/client/event"
|
||||
primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
iface "github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
emptypb "google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
@@ -45,10 +45,10 @@ func (m *MockValidatorClient) EXPECT() *MockValidatorClientMockRecorder {
|
||||
}
|
||||
|
||||
// AggregatedSelections mocks base method.
|
||||
func (m *MockValidatorClient) AggregatedSelections(arg0 context.Context, arg1 []iface.BeaconCommitteeSelection) ([]iface.BeaconCommitteeSelection, error) {
|
||||
func (m *MockValidatorClient) AggregatedSelections(arg0 context.Context, arg1 []beacon.BeaconCommitteeSelection) ([]beacon.BeaconCommitteeSelection, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AggregatedSelections", arg0, arg1)
|
||||
ret0, _ := ret[0].([]iface.BeaconCommitteeSelection)
|
||||
ret0, _ := ret[0].([]beacon.BeaconCommitteeSelection)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
@@ -60,10 +60,10 @@ func (mr *MockValidatorClientMockRecorder) AggregatedSelections(arg0, arg1 any)
|
||||
}
|
||||
|
||||
// AggregatedSyncSelections mocks base method.
|
||||
func (m *MockValidatorClient) AggregatedSyncSelections(arg0 context.Context, arg1 []iface.SyncCommitteeSelection) ([]iface.SyncCommitteeSelection, error) {
|
||||
func (m *MockValidatorClient) AggregatedSyncSelections(arg0 context.Context, arg1 []beacon.SyncCommitteeSelection) ([]beacon.SyncCommitteeSelection, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "AggregatedSyncSelections", arg0, arg1)
|
||||
ret0, _ := ret[0].([]iface.SyncCommitteeSelection)
|
||||
ret0, _ := ret[0].([]beacon.SyncCommitteeSelection)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
@@ -135,10 +135,10 @@ func (mr *MockValidatorClientMockRecorder) DomainData(arg0, arg1 any) *gomock.Ca
|
||||
}
|
||||
|
||||
// Duties mocks base method.
|
||||
func (m *MockValidatorClient) Duties(arg0 context.Context, arg1 *eth.DutiesRequest) (*eth.DutiesResponse, error) {
|
||||
func (m *MockValidatorClient) Duties(arg0 context.Context, arg1 *eth.DutiesRequest) (*eth.ValidatorDutiesContainer, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "Duties", arg0, arg1)
|
||||
ret0, _ := ret[0].(*eth.DutiesResponse)
|
||||
ret0, _ := ret[0].(*eth.ValidatorDutiesContainer)
|
||||
ret1, _ := ret[1].(error)
|
||||
return ret0, ret1
|
||||
}
|
||||
@@ -412,7 +412,7 @@ func (mr *MockValidatorClientMockRecorder) SubmitValidatorRegistrations(arg0, ar
|
||||
}
|
||||
|
||||
// SubscribeCommitteeSubnets mocks base method.
|
||||
func (m *MockValidatorClient) SubscribeCommitteeSubnets(arg0 context.Context, arg1 *eth.CommitteeSubnetsSubscribeRequest, arg2 []*eth.DutiesResponse_Duty) (*emptypb.Empty, error) {
|
||||
func (m *MockValidatorClient) SubscribeCommitteeSubnets(arg0 context.Context, arg1 *eth.CommitteeSubnetsSubscribeRequest, arg2 []*eth.ValidatorDuty) (*emptypb.Empty, error) {
|
||||
m.ctrl.T.Helper()
|
||||
ret := m.ctrl.Call(m, "SubscribeCommitteeSubnets", arg0, arg1, arg2)
|
||||
ret0, _ := ret[0].(*emptypb.Empty)
|
||||
44
api/client/beacon/node/BUILD.bazel
Normal file
44
api/client/beacon/node/BUILD.bazel
Normal file
@@ -0,0 +1,44 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"client.go",
|
||||
"grpc_node_client.go",
|
||||
"interfaces.go",
|
||||
"rest_client.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/node",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/beacon/health:go_default_library",
|
||||
"//api/client/beacon/shared_providers:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//validator/helpers:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["rest_client_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/client/beacon/mock:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
28
api/client/beacon/node/client.go
Normal file
28
api/client/beacon/node/client.go
Normal file
@@ -0,0 +1,28 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/health"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
validatorHelpers "github.com/prysmaticlabs/prysm/v5/validator/helpers"
|
||||
)
|
||||
|
||||
func NewClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandler client.JsonRestHandler) Client {
|
||||
grpcClient := NewNodeClient(validatorConn.GetGrpcClientConn())
|
||||
if features.Get().EnableBeaconRESTApi {
|
||||
return NewNodeClientWithFallback(jsonRestHandler, grpcClient)
|
||||
} else {
|
||||
return grpcClient
|
||||
}
|
||||
}
|
||||
|
||||
func NewNodeClientWithFallback(jsonRestHandler client.JsonRestHandler, fallbackClient Client) Client {
|
||||
b := &beaconapiNodeClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
fallbackClient: fallbackClient,
|
||||
genesisProvider: shared_providers.NewGenesis(jsonRestHandler),
|
||||
}
|
||||
b.healthTracker = health.NewTracker(b)
|
||||
return b
|
||||
}
|
||||
@@ -1,23 +1,22 @@
|
||||
package grpc_api
|
||||
package node
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/health"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = iface.NodeClient(&grpcNodeClient{})
|
||||
_ = Client(&grpcNodeClient{})
|
||||
)
|
||||
|
||||
type grpcNodeClient struct {
|
||||
nodeClient ethpb.NodeClient
|
||||
healthTracker *beacon.NodeHealthTracker
|
||||
healthTracker health.HealthTracker
|
||||
}
|
||||
|
||||
func (c *grpcNodeClient) SyncStatus(ctx context.Context, in *empty.Empty) (*ethpb.SyncStatus, error) {
|
||||
@@ -45,12 +44,12 @@ func (c *grpcNodeClient) IsHealthy(ctx context.Context) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (c *grpcNodeClient) HealthTracker() *beacon.NodeHealthTracker {
|
||||
func (c *grpcNodeClient) HealthTracker() health.HealthTracker {
|
||||
return c.healthTracker
|
||||
}
|
||||
|
||||
func NewNodeClient(cc grpc.ClientConnInterface) iface.NodeClient {
|
||||
func NewNodeClient(cc grpc.ClientConnInterface) Client {
|
||||
g := &grpcNodeClient{nodeClient: ethpb.NewNodeClient(cc)}
|
||||
g.healthTracker = beacon.NewNodeHealthTracker(g)
|
||||
g.healthTracker = health.NewTracker(g)
|
||||
return g
|
||||
}
|
||||
@@ -1,17 +1,17 @@
|
||||
package iface
|
||||
package node
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/health"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type NodeClient interface {
|
||||
type Client interface {
|
||||
SyncStatus(ctx context.Context, in *empty.Empty) (*ethpb.SyncStatus, error)
|
||||
Genesis(ctx context.Context, in *empty.Empty) (*ethpb.Genesis, error)
|
||||
Version(ctx context.Context, in *empty.Empty) (*ethpb.Version, error)
|
||||
Peers(ctx context.Context, in *empty.Empty) (*ethpb.Peers, error)
|
||||
HealthTracker() *beacon.NodeHealthTracker
|
||||
HealthTracker() health.HealthTracker
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package node
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,25 +7,26 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/health"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
)
|
||||
|
||||
var (
|
||||
_ = iface.NodeClient(&beaconApiNodeClient{})
|
||||
_ = Client(&beaconapiNodeClient{})
|
||||
)
|
||||
|
||||
type beaconApiNodeClient struct {
|
||||
fallbackClient iface.NodeClient
|
||||
jsonRestHandler JsonRestHandler
|
||||
genesisProvider GenesisProvider
|
||||
healthTracker *beacon.NodeHealthTracker
|
||||
type beaconapiNodeClient struct {
|
||||
fallbackClient Client
|
||||
jsonRestHandler client.JsonRestHandler
|
||||
genesisProvider shared_providers.Genesis
|
||||
healthTracker health.HealthTracker
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) SyncStatus(ctx context.Context, _ *empty.Empty) (*ethpb.SyncStatus, error) {
|
||||
func (c *beaconapiNodeClient) SyncStatus(ctx context.Context, _ *empty.Empty) (*ethpb.SyncStatus, error) {
|
||||
syncingResponse := structs.SyncStatusResponse{}
|
||||
if err := c.jsonRestHandler.Get(ctx, "/eth/v1/node/syncing", &syncingResponse); err != nil {
|
||||
return nil, err
|
||||
@@ -40,7 +41,7 @@ func (c *beaconApiNodeClient) SyncStatus(ctx context.Context, _ *empty.Empty) (*
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) Genesis(ctx context.Context, _ *empty.Empty) (*ethpb.Genesis, error) {
|
||||
func (c *beaconapiNodeClient) Genesis(ctx context.Context, _ *empty.Empty) (*ethpb.Genesis, error) {
|
||||
genesisJson, err := c.genesisProvider.Genesis(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get genesis")
|
||||
@@ -79,7 +80,7 @@ func (c *beaconApiNodeClient) Genesis(ctx context.Context, _ *empty.Empty) (*eth
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) Version(ctx context.Context, _ *empty.Empty) (*ethpb.Version, error) {
|
||||
func (c *beaconapiNodeClient) Version(ctx context.Context, _ *empty.Empty) (*ethpb.Version, error) {
|
||||
var versionResponse structs.GetVersionResponse
|
||||
if err := c.jsonRestHandler.Get(ctx, "/eth/v1/node/version", &versionResponse); err != nil {
|
||||
return nil, err
|
||||
@@ -94,29 +95,19 @@ func (c *beaconApiNodeClient) Version(ctx context.Context, _ *empty.Empty) (*eth
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) Peers(ctx context.Context, in *empty.Empty) (*ethpb.Peers, error) {
|
||||
func (c *beaconapiNodeClient) Peers(ctx context.Context, in *empty.Empty) (*ethpb.Peers, error) {
|
||||
if c.fallbackClient != nil {
|
||||
return c.fallbackClient.Peers(ctx, in)
|
||||
}
|
||||
|
||||
// TODO: Implement me
|
||||
panic("beaconApiNodeClient.Peers is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiNodeClientWithFallback.")
|
||||
return nil, errors.New("beaconapiNodeClient.Peers is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiNodeClientWithFallback.")
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) IsHealthy(ctx context.Context) bool {
|
||||
func (c *beaconapiNodeClient) IsHealthy(ctx context.Context) bool {
|
||||
return c.jsonRestHandler.Get(ctx, "/eth/v1/node/health", nil) == nil
|
||||
}
|
||||
|
||||
func (c *beaconApiNodeClient) HealthTracker() *beacon.NodeHealthTracker {
|
||||
func (c *beaconapiNodeClient) HealthTracker() health.HealthTracker {
|
||||
return c.healthTracker
|
||||
}
|
||||
|
||||
func NewNodeClientWithFallback(jsonRestHandler JsonRestHandler, fallbackClient iface.NodeClient) iface.NodeClient {
|
||||
b := &beaconApiNodeClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
fallbackClient: fallbackClient,
|
||||
genesisProvider: &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler},
|
||||
}
|
||||
b.healthTracker = beacon.NewNodeHealthTracker(b)
|
||||
return b
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package node
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,10 +6,10 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"go.uber.org/mock/gomock"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
@@ -135,7 +135,7 @@ func TestGetGenesis(t *testing.T) {
|
||||
)
|
||||
}
|
||||
|
||||
nodeClient := &beaconApiNodeClient{
|
||||
nodeClient := &beaconapiNodeClient{
|
||||
genesisProvider: genesisProvider,
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
@@ -213,7 +213,7 @@ func TestGetSyncStatus(t *testing.T) {
|
||||
testCase.restEndpointResponse,
|
||||
)
|
||||
|
||||
nodeClient := &beaconApiNodeClient{jsonRestHandler: jsonRestHandler}
|
||||
nodeClient := &beaconapiNodeClient{jsonRestHandler: jsonRestHandler}
|
||||
syncStatus, err := nodeClient.SyncStatus(ctx, &emptypb.Empty{})
|
||||
|
||||
if testCase.expectedResponse == nil {
|
||||
@@ -277,7 +277,7 @@ func TestGetVersion(t *testing.T) {
|
||||
testCase.restEndpointResponse,
|
||||
)
|
||||
|
||||
nodeClient := &beaconApiNodeClient{jsonRestHandler: jsonRestHandler}
|
||||
nodeClient := &beaconapiNodeClient{jsonRestHandler: jsonRestHandler}
|
||||
version, err := nodeClient.Version(ctx, &emptypb.Empty{})
|
||||
|
||||
if testCase.expectedResponse == nil {
|
||||
@@ -3,56 +3,53 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"grpc_beacon_chain_client.go",
|
||||
"grpc_node_client.go",
|
||||
"grpc_prysm_beacon_chain_client.go",
|
||||
"grpc_validator_client.go",
|
||||
"client.go",
|
||||
"grpc_client.go",
|
||||
"interfaces.go",
|
||||
"rest_client.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/validator/client/grpc-api",
|
||||
visibility = ["//validator:__subpackages__"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/prysm_api",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/apiutil:go_default_library",
|
||||
"//api/client/beacon:go_default_library",
|
||||
"//api/client/event:go_default_library",
|
||||
"//api/client/beacon/chain:go_default_library",
|
||||
"//api/client/beacon/node:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//beacon-chain/rpc/eth/helpers:go_default_library",
|
||||
"//beacon-chain/state/state-native:go_default_library",
|
||||
"//config/features: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",
|
||||
"//validator/helpers:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"grpc_prysm_beacon_chain_client_test.go",
|
||||
"grpc_validator_client_test.go",
|
||||
"grpc_client_test.go",
|
||||
"rest_client_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/client/event:go_default_library",
|
||||
"//api/client/beacon:go_default_library",
|
||||
"//api/client/beacon/mock:go_default_library",
|
||||
"//api/client/beacon/node:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//proto/prysm/v1alpha1: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",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
30
api/client/beacon/prysm_api/client.go
Normal file
30
api/client/beacon/prysm_api/client.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package prysm_api
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/chain"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/node"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
validatorHelpers "github.com/prysmaticlabs/prysm/v5/validator/helpers"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func NewClient(validatorConn validatorHelpers.NodeConnection, jsonRestHandler client.JsonRestHandler) Client {
|
||||
if features.Get().EnableBeaconRESTApi {
|
||||
return NewPrysmChainRestClient(jsonRestHandler, node.NewClient(validatorConn, jsonRestHandler))
|
||||
} else {
|
||||
return NewGrpcPrysmChainClient(validatorConn.GetGrpcClientConn())
|
||||
}
|
||||
}
|
||||
|
||||
// NewPrysmChainClient returns implementation of Client.
|
||||
func NewPrysmChainRestClient(jsonRestHandler client.JsonRestHandler, nodeClient node.Client) Client {
|
||||
return prysmChainClient{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
nodeClient: nodeClient,
|
||||
}
|
||||
}
|
||||
|
||||
func NewGrpcPrysmChainClient(cc grpc.ClientConnInterface) Client {
|
||||
return &grpcPrysmChainClient{chainClient: chain.NewGrpcChainClient(cc)}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package grpc_api
|
||||
package prysm_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,21 +7,21 @@ import (
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/chain"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/rpc/eth/helpers"
|
||||
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"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/eth/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
type grpcPrysmChainClient struct {
|
||||
chainClient iface.ChainClient
|
||||
chainClient chain.Client
|
||||
}
|
||||
|
||||
func (g grpcPrysmChainClient) ValidatorCount(ctx context.Context, _ string, statuses []validator.Status) ([]iface.ValidatorCount, error) {
|
||||
func (g grpcPrysmChainClient) ValidatorCount(ctx context.Context, _ string, statuses []validator.Status) ([]beacon.ValidatorCount, error) {
|
||||
resp, err := g.chainClient.Validators(ctx, ðpb.ListValidatorsRequest{PageSize: 0})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "list validators failed")
|
||||
@@ -52,7 +52,7 @@ func (g grpcPrysmChainClient) ValidatorCount(ctx context.Context, _ string, stat
|
||||
}
|
||||
|
||||
// validatorCountByStatus returns a slice of validator count for each status in the given epoch.
|
||||
func validatorCountByStatus(validators []*ethpb.Validator, statuses []validator.Status, epoch primitives.Epoch) ([]iface.ValidatorCount, error) {
|
||||
func validatorCountByStatus(validators []*ethpb.Validator, statuses []validator.Status, epoch primitives.Epoch) ([]beacon.ValidatorCount, error) {
|
||||
countByStatus := make(map[validator.Status]uint64)
|
||||
for _, val := range validators {
|
||||
readOnlyVal, err := statenative.NewValidator(val)
|
||||
@@ -75,9 +75,9 @@ func validatorCountByStatus(validators []*ethpb.Validator, statuses []validator.
|
||||
}
|
||||
}
|
||||
|
||||
var resp []iface.ValidatorCount
|
||||
var resp []beacon.ValidatorCount
|
||||
for status, count := range countByStatus {
|
||||
resp = append(resp, iface.ValidatorCount{
|
||||
resp = append(resp, beacon.ValidatorCount{
|
||||
Status: status.String(),
|
||||
Count: count,
|
||||
})
|
||||
@@ -91,6 +91,6 @@ func validatorCountByStatus(validators []*ethpb.Validator, statuses []validator.
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func NewGrpcPrysmChainClient(cc grpc.ClientConnInterface) iface.PrysmChainClient {
|
||||
return &grpcPrysmChainClient{chainClient: &grpcChainClient{ethpb.NewBeaconChainClient(cc)}}
|
||||
func (c *grpcPrysmChainClient) ValidatorPerformance(ctx context.Context, in *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error) {
|
||||
return c.chainClient.ValidatorPerformance(ctx, in)
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
package grpc_api
|
||||
package prysm_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
mock "github.com/prysmaticlabs/prysm/v5/testing/validator-mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
func TestGetValidatorCount(t *testing.T) {
|
||||
func TestGRPC_GetValidatorCount(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisState(t, 10)
|
||||
farFutureEpoch := params.BeaconConfig().FarFutureEpoch
|
||||
validators := []*ethpb.Validator{
|
||||
@@ -92,12 +92,12 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name string
|
||||
statuses []string
|
||||
currentEpoch int
|
||||
expectedResponse []iface.ValidatorCount
|
||||
expectedResponse []beacon.ValidatorCount
|
||||
}{
|
||||
{
|
||||
name: "Head count active validators",
|
||||
statuses: []string{"active"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: 13,
|
||||
@@ -107,7 +107,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count active ongoing validators",
|
||||
statuses: []string{"active_ongoing"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active_ongoing",
|
||||
Count: 11,
|
||||
@@ -117,7 +117,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count active exiting validators",
|
||||
statuses: []string{"active_exiting"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active_exiting",
|
||||
Count: 1,
|
||||
@@ -127,7 +127,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count active slashed validators",
|
||||
statuses: []string{"active_slashed"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active_slashed",
|
||||
Count: 1,
|
||||
@@ -137,7 +137,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count pending validators",
|
||||
statuses: []string{"pending"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "pending",
|
||||
Count: 6,
|
||||
@@ -147,7 +147,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count pending initialized validators",
|
||||
statuses: []string{"pending_initialized"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "pending_initialized",
|
||||
Count: 1,
|
||||
@@ -157,7 +157,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count pending queued validators",
|
||||
statuses: []string{"pending_queued"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "pending_queued",
|
||||
Count: 5,
|
||||
@@ -168,7 +168,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name: "Head count exited validators",
|
||||
statuses: []string{"exited"},
|
||||
currentEpoch: 35,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "exited",
|
||||
Count: 6,
|
||||
@@ -179,7 +179,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name: "Head count exited slashed validators",
|
||||
statuses: []string{"exited_slashed"},
|
||||
currentEpoch: 35,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "exited_slashed",
|
||||
Count: 2,
|
||||
@@ -190,7 +190,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name: "Head count exited unslashed validators",
|
||||
statuses: []string{"exited_unslashed"},
|
||||
currentEpoch: 35,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "exited_unslashed",
|
||||
Count: 4,
|
||||
@@ -201,7 +201,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name: "Head count withdrawal validators",
|
||||
statuses: []string{"withdrawal"},
|
||||
currentEpoch: 45,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "withdrawal",
|
||||
Count: 2,
|
||||
@@ -212,7 +212,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name: "Head count withdrawal possible validators",
|
||||
statuses: []string{"withdrawal_possible"},
|
||||
currentEpoch: 45,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "withdrawal_possible",
|
||||
Count: 1,
|
||||
@@ -223,7 +223,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
name: "Head count withdrawal done validators",
|
||||
statuses: []string{"withdrawal_done"},
|
||||
currentEpoch: 45,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "withdrawal_done",
|
||||
Count: 1,
|
||||
@@ -233,7 +233,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
{
|
||||
name: "Head count active and pending validators",
|
||||
statuses: []string{"active", "pending"},
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: 13,
|
||||
@@ -246,7 +246,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
},
|
||||
{
|
||||
name: "Head count of ALL validators",
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: 13,
|
||||
15
api/client/beacon/prysm_api/interfaces.go
Normal file
15
api/client/beacon/prysm_api/interfaces.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package prysm_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// Client defines an interface required to implement all the prysm specific custom endpoints.
|
||||
type Client interface {
|
||||
ValidatorCount(context.Context, string, []validator.Status) ([]beacon.ValidatorCount, error)
|
||||
ValidatorPerformance(context.Context, *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error)
|
||||
}
|
||||
108
api/client/beacon/prysm_api/rest_client.go
Normal file
108
api/client/beacon/prysm_api/rest_client.go
Normal file
@@ -0,0 +1,108 @@
|
||||
package prysm_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
neturl "net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/node"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
validator2 "github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type prysmChainClient struct {
|
||||
jsonRestHandler client.JsonRestHandler
|
||||
nodeClient node.Client
|
||||
}
|
||||
|
||||
func (c prysmChainClient) ValidatorCount(ctx context.Context, stateID string, statuses []validator2.Status) ([]beacon.ValidatorCount, error) {
|
||||
// Check node version for prysm beacon node as it is a custom endpoint for prysm beacon node.
|
||||
nodeVersion, err := c.nodeClient.Version(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get node version")
|
||||
}
|
||||
|
||||
if !strings.Contains(strings.ToLower(nodeVersion.Version), "prysm") {
|
||||
return nil, client.ErrNotSupported
|
||||
}
|
||||
|
||||
queryParams := neturl.Values{}
|
||||
for _, status := range statuses {
|
||||
queryParams.Add("status", status.String())
|
||||
}
|
||||
|
||||
queryUrl := apiutil.BuildURL(fmt.Sprintf("/eth/v1/beacon/states/%s/validator_count", stateID), queryParams)
|
||||
|
||||
var validatorCountResponse structs.GetValidatorCountResponse
|
||||
if err = c.jsonRestHandler.Get(ctx, queryUrl, &validatorCountResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if validatorCountResponse.Data == nil {
|
||||
return nil, errors.New("validator count data is nil")
|
||||
}
|
||||
|
||||
if len(statuses) != 0 && len(statuses) != len(validatorCountResponse.Data) {
|
||||
return nil, errors.New("mismatch between validator count data and the number of statuses provided")
|
||||
}
|
||||
|
||||
var resp []beacon.ValidatorCount
|
||||
for _, vc := range validatorCountResponse.Data {
|
||||
count, err := strconv.ParseUint(vc.Count, 10, 64)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse validator count %s", vc.Count)
|
||||
}
|
||||
|
||||
resp = append(resp, beacon.ValidatorCount{
|
||||
Status: vc.Status,
|
||||
Count: count,
|
||||
})
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (c prysmChainClient) ValidatorPerformance(ctx context.Context, in *ethpb.ValidatorPerformanceRequest) (*ethpb.ValidatorPerformanceResponse, error) {
|
||||
// Check node version for prysm beacon node as it is a custom endpoint for prysm beacon node.
|
||||
nodeVersion, err := c.nodeClient.Version(ctx, nil)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get node version")
|
||||
}
|
||||
|
||||
if !strings.Contains(strings.ToLower(nodeVersion.Version), "prysm") {
|
||||
return nil, client.ErrNotSupported
|
||||
}
|
||||
|
||||
request, err := json.Marshal(structs.GetValidatorPerformanceRequest{
|
||||
PublicKeys: in.PublicKeys,
|
||||
Indices: in.Indices,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to marshal request")
|
||||
}
|
||||
resp := &structs.GetValidatorPerformanceResponse{}
|
||||
if err = c.jsonRestHandler.Post(ctx, "/prysm/validators/performance", nil, bytes.NewBuffer(request), resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ðpb.ValidatorPerformanceResponse{
|
||||
CurrentEffectiveBalances: resp.CurrentEffectiveBalances,
|
||||
CorrectlyVotedSource: resp.CorrectlyVotedSource,
|
||||
CorrectlyVotedTarget: resp.CorrectlyVotedTarget,
|
||||
CorrectlyVotedHead: resp.CorrectlyVotedHead,
|
||||
BalancesBeforeEpochTransition: resp.BalancesBeforeEpochTransition,
|
||||
BalancesAfterEpochTransition: resp.BalancesAfterEpochTransition,
|
||||
MissingValidators: resp.MissingValidators,
|
||||
PublicKeys: resp.PublicKeys,
|
||||
InactivityScores: resp.InactivityScores,
|
||||
}, nil
|
||||
}
|
||||
@@ -1,15 +1,20 @@
|
||||
package beacon_api
|
||||
package prysm_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/node"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
"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/validator/client/beacon-api/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/iface"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -23,7 +28,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
versionResponse structs.GetVersionResponse
|
||||
validatorCountResponse structs.GetValidatorCountResponse
|
||||
validatorCountCalled int
|
||||
expectedResponse []iface.ValidatorCount
|
||||
expectedResponse []beacon.ValidatorCount
|
||||
expectedError string
|
||||
}{
|
||||
{
|
||||
@@ -42,7 +47,7 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
},
|
||||
},
|
||||
validatorCountCalled: 1,
|
||||
expectedResponse: []iface.ValidatorCount{
|
||||
expectedResponse: []beacon.ValidatorCount{
|
||||
{
|
||||
Status: "active",
|
||||
Count: 10,
|
||||
@@ -141,8 +146,8 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
).Times(test.validatorCountCalled)
|
||||
|
||||
// Type assertion.
|
||||
var client iface.PrysmChainClient = &prysmChainClient{
|
||||
nodeClient: &beaconApiNodeClient{jsonRestHandler: jsonRestHandler},
|
||||
var client Client = &prysmChainClient{
|
||||
nodeClient: node.NewNodeClientWithFallback(jsonRestHandler, nil),
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
|
||||
@@ -156,5 +161,61 @@ func TestGetValidatorCount(t *testing.T) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func Test_beaconApiBeaconChainClient_GetValidatorPerformance(t *testing.T) {
|
||||
const nodeVersion = "prysm/v0.0.1"
|
||||
publicKeys := [][48]byte{
|
||||
bytesutil.ToBytes48([]byte{1}),
|
||||
bytesutil.ToBytes48([]byte{2}),
|
||||
bytesutil.ToBytes48([]byte{3}),
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
request, err := json.Marshal(structs.GetValidatorPerformanceRequest{
|
||||
PublicKeys: [][]byte{publicKeys[0][:], publicKeys[2][:], publicKeys[1][:]},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
// Expect node version endpoint call.
|
||||
var nodeVersionResponse structs.GetVersionResponse
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
"/eth/v1/node/version",
|
||||
&nodeVersionResponse,
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetVersionResponse{
|
||||
Data: &structs.Version{Version: nodeVersion},
|
||||
},
|
||||
)
|
||||
|
||||
wantResponse := &structs.GetValidatorPerformanceResponse{}
|
||||
want := ðpb.ValidatorPerformanceResponse{}
|
||||
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
"/prysm/validators/performance",
|
||||
nil,
|
||||
bytes.NewBuffer(request),
|
||||
wantResponse,
|
||||
).Return(
|
||||
nil,
|
||||
)
|
||||
|
||||
var client Client = &prysmChainClient{
|
||||
nodeClient: node.NewNodeClientWithFallback(jsonRestHandler, nil),
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
}
|
||||
|
||||
got, err := client.ValidatorPerformance(ctx, ðpb.ValidatorPerformanceRequest{
|
||||
PublicKeys: [][]byte{publicKeys[0][:], publicKeys[2][:], publicKeys[1][:]},
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, want.PublicKeys, got.PublicKeys)
|
||||
}
|
||||
42
api/client/beacon/shared_providers/BUILD.bazel
Normal file
42
api/client/beacon/shared_providers/BUILD.bazel
Normal file
@@ -0,0 +1,42 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"duties.go",
|
||||
"genesis.go",
|
||||
"interfaces.go",
|
||||
"providers.go",
|
||||
"state_validators.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/apiutil:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"duties_test.go",
|
||||
"genesis_test.go",
|
||||
"state_validators_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api/client/apiutil:go_default_library",
|
||||
"//api/client/beacon/mock:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
132
api/client/beacon/shared_providers/duties.go
Normal file
132
api/client/beacon/shared_providers/duties.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
)
|
||||
|
||||
type dutiesProvider struct {
|
||||
jsonRestHandler client.JsonRestHandler
|
||||
}
|
||||
|
||||
// Committees retrieves the committees for the given epoch
|
||||
func (c dutiesProvider) Committees(ctx context.Context, epoch primitives.Epoch) ([]*structs.Committee, error) {
|
||||
committeeParams := url.Values{}
|
||||
committeeParams.Add("epoch", strconv.FormatUint(uint64(epoch), 10))
|
||||
committeesRequest := apiutil.BuildURL("/eth/v1/beacon/states/head/committees", committeeParams)
|
||||
|
||||
var stateCommittees structs.GetCommitteesResponse
|
||||
if err := c.jsonRestHandler.Get(ctx, committeesRequest, &stateCommittees); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if stateCommittees.Data == nil {
|
||||
return nil, errors.New("state committees data is nil")
|
||||
}
|
||||
|
||||
for index, committee := range stateCommittees.Data {
|
||||
if committee == nil {
|
||||
return nil, errors.Errorf("committee at index `%d` is nil", index)
|
||||
}
|
||||
}
|
||||
|
||||
return stateCommittees.Data, nil
|
||||
}
|
||||
|
||||
// AttesterDuties retrieves the attester duties for the given epoch and validatorIndices
|
||||
func (c dutiesProvider) AttesterDuties(ctx context.Context, epoch primitives.Epoch, validatorIndices []primitives.ValidatorIndex) ([]*structs.AttesterDuty, error) {
|
||||
jsonValidatorIndices := make([]string, len(validatorIndices))
|
||||
for index, validatorIndex := range validatorIndices {
|
||||
jsonValidatorIndices[index] = strconv.FormatUint(uint64(validatorIndex), 10)
|
||||
}
|
||||
|
||||
validatorIndicesBytes, err := json.Marshal(jsonValidatorIndices)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to marshal validator indices")
|
||||
}
|
||||
|
||||
attesterDuties := &structs.GetAttesterDutiesResponse{}
|
||||
if err = c.jsonRestHandler.Post(
|
||||
ctx,
|
||||
fmt.Sprintf("/eth/v1/validator/duties/attester/%d", epoch),
|
||||
nil,
|
||||
bytes.NewBuffer(validatorIndicesBytes),
|
||||
attesterDuties,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for index, attesterDuty := range attesterDuties.Data {
|
||||
if attesterDuty == nil {
|
||||
return nil, errors.Errorf("attester duty at index `%d` is nil", index)
|
||||
}
|
||||
}
|
||||
|
||||
return attesterDuties.Data, nil
|
||||
}
|
||||
|
||||
// ProposerDuties retrieves the proposer duties for the given epoch
|
||||
func (c dutiesProvider) ProposerDuties(ctx context.Context, epoch primitives.Epoch) ([]*structs.ProposerDuty, error) {
|
||||
proposerDuties := structs.GetProposerDutiesResponse{}
|
||||
if err := c.jsonRestHandler.Get(ctx, fmt.Sprintf("/eth/v1/validator/duties/proposer/%d", epoch), &proposerDuties); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if proposerDuties.Data == nil {
|
||||
return nil, errors.New("proposer duties data is nil")
|
||||
}
|
||||
|
||||
for index, proposerDuty := range proposerDuties.Data {
|
||||
if proposerDuty == nil {
|
||||
return nil, errors.Errorf("proposer duty at index `%d` is nil", index)
|
||||
}
|
||||
}
|
||||
|
||||
return proposerDuties.Data, nil
|
||||
}
|
||||
|
||||
// SyncDuties retrieves the sync committee duties for the given epoch and validatorIndices
|
||||
func (c dutiesProvider) SyncDuties(ctx context.Context, epoch primitives.Epoch, validatorIndices []primitives.ValidatorIndex) ([]*structs.SyncCommitteeDuty, error) {
|
||||
jsonValidatorIndices := make([]string, len(validatorIndices))
|
||||
for index, validatorIndex := range validatorIndices {
|
||||
jsonValidatorIndices[index] = strconv.FormatUint(uint64(validatorIndex), 10)
|
||||
}
|
||||
|
||||
validatorIndicesBytes, err := json.Marshal(jsonValidatorIndices)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to marshal validator indices")
|
||||
}
|
||||
|
||||
syncDuties := structs.GetSyncCommitteeDutiesResponse{}
|
||||
if err = c.jsonRestHandler.Post(
|
||||
ctx,
|
||||
fmt.Sprintf("/eth/v1/validator/duties/sync/%d", epoch),
|
||||
nil,
|
||||
bytes.NewBuffer(validatorIndicesBytes),
|
||||
&syncDuties,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if syncDuties.Data == nil {
|
||||
return nil, errors.New("sync duties data is nil")
|
||||
}
|
||||
|
||||
for index, syncDuty := range syncDuties.Data {
|
||||
if syncDuty == nil {
|
||||
return nil, errors.Errorf("sync duty at index `%d` is nil", index)
|
||||
}
|
||||
}
|
||||
|
||||
return syncDuties.Data, nil
|
||||
}
|
||||
508
api/client/beacon/shared_providers/duties_test.go
Normal file
508
api/client/beacon/shared_providers/duties_test.go
Normal file
@@ -0,0 +1,508 @@
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
const getAttesterDutiesTestEndpoint = "/eth/v1/validator/duties/attester"
|
||||
const getProposerDutiesTestEndpoint = "/eth/v1/validator/duties/proposer"
|
||||
const getSyncDutiesTestEndpoint = "/eth/v1/validator/duties/sync"
|
||||
const getCommitteesTestEndpoint = "/eth/v1/beacon/states/head/committees"
|
||||
|
||||
func TestGetAttesterDuties_Valid(t *testing.T) {
|
||||
stringValidatorIndices := []string{"2", "9"}
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
validatorIndicesBytes, err := json.Marshal(stringValidatorIndices)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedAttesterDuties := structs.GetAttesterDutiesResponse{
|
||||
Data: []*structs.AttesterDuty{
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{1}),
|
||||
ValidatorIndex: "2",
|
||||
CommitteeIndex: "3",
|
||||
CommitteeLength: "4",
|
||||
CommitteesAtSlot: "5",
|
||||
ValidatorCommitteeIndex: "6",
|
||||
Slot: "7",
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{8}),
|
||||
ValidatorIndex: "9",
|
||||
CommitteeIndex: "10",
|
||||
CommitteeLength: "11",
|
||||
CommitteesAtSlot: "12",
|
||||
ValidatorCommitteeIndex: "13",
|
||||
Slot: "14",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
validatorIndices := []primitives.ValidatorIndex{2, 9}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getAttesterDutiesTestEndpoint, epoch),
|
||||
nil,
|
||||
bytes.NewBuffer(validatorIndicesBytes),
|
||||
&structs.GetAttesterDutiesResponse{},
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
expectedAttesterDuties,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
attesterDuties, err := dutiesProvider.AttesterDuties(ctx, epoch, validatorIndices)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedAttesterDuties.Data, attesterDuties)
|
||||
}
|
||||
|
||||
func TestGetAttesterDuties_HttpError(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getAttesterDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.AttesterDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func TestGetAttesterDuties_NilAttesterDuty(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getAttesterDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
structs.GetAttesterDutiesResponse{
|
||||
Data: []*structs.AttesterDuty{nil},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.AttesterDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "attester duty at index `0` is nil", err)
|
||||
}
|
||||
|
||||
func TestGetProposerDuties_Valid(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
expectedProposerDuties := structs.GetProposerDutiesResponse{
|
||||
Data: []*structs.ProposerDuty{
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{1}),
|
||||
ValidatorIndex: "2",
|
||||
Slot: "3",
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{4}),
|
||||
ValidatorIndex: "5",
|
||||
Slot: "6",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
|
||||
&structs.GetProposerDutiesResponse{},
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
expectedProposerDuties,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
proposerDuties, err := dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedProposerDuties.Data, proposerDuties)
|
||||
}
|
||||
|
||||
func TestGetProposerDuties_HttpError(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func TestGetProposerDuties_NilData(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetProposerDutiesResponse{
|
||||
Data: nil,
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
assert.ErrorContains(t, "proposer duties data is nil", err)
|
||||
}
|
||||
|
||||
func TestGetProposerDuties_NilProposerDuty(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetProposerDutiesResponse{
|
||||
Data: []*structs.ProposerDuty{nil},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
assert.ErrorContains(t, "proposer duty at index `0` is nil", err)
|
||||
}
|
||||
|
||||
func TestGetSyncDuties_Valid(t *testing.T) {
|
||||
stringValidatorIndices := []string{"2", "6"}
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
validatorIndicesBytes, err := json.Marshal(stringValidatorIndices)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedSyncDuties := structs.GetSyncCommitteeDutiesResponse{
|
||||
Data: []*structs.SyncCommitteeDuty{
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{1}),
|
||||
ValidatorIndex: "2",
|
||||
ValidatorSyncCommitteeIndices: []string{
|
||||
"3",
|
||||
"4",
|
||||
},
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{5}),
|
||||
ValidatorIndex: "6",
|
||||
ValidatorSyncCommitteeIndices: []string{
|
||||
"7",
|
||||
"8",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
validatorIndices := []primitives.ValidatorIndex{2, 6}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
|
||||
nil,
|
||||
bytes.NewBuffer(validatorIndicesBytes),
|
||||
&structs.GetSyncCommitteeDutiesResponse{},
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
expectedSyncDuties,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
syncDuties, err := dutiesProvider.SyncDuties(ctx, epoch, validatorIndices)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedSyncDuties.Data, syncDuties)
|
||||
}
|
||||
|
||||
func TestGetSyncDuties_HttpError(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.SyncDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func TestGetSyncDuties_NilData(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
structs.GetSyncCommitteeDutiesResponse{
|
||||
Data: nil,
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.SyncDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "sync duties data is nil", err)
|
||||
}
|
||||
|
||||
func TestGetSyncDuties_NilSyncDuty(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
structs.GetSyncCommitteeDutiesResponse{
|
||||
Data: []*structs.SyncCommitteeDuty{nil},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.SyncDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "sync duty at index `0` is nil", err)
|
||||
}
|
||||
|
||||
func TestGetCommittees_Valid(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
expectedCommittees := structs.GetCommitteesResponse{
|
||||
Data: []*structs.Committee{
|
||||
{
|
||||
Index: "1",
|
||||
Slot: "2",
|
||||
Validators: []string{
|
||||
"3",
|
||||
"4",
|
||||
},
|
||||
},
|
||||
{
|
||||
Index: "5",
|
||||
Slot: "6",
|
||||
Validators: []string{
|
||||
"7",
|
||||
"8",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
|
||||
&structs.GetCommitteesResponse{},
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
expectedCommittees,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
committees, err := dutiesProvider.Committees(ctx, epoch)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedCommittees.Data, committees)
|
||||
}
|
||||
|
||||
func TestGetCommittees_HttpError(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.Committees(ctx, epoch)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func TestGetCommittees_NilData(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetCommitteesResponse{
|
||||
Data: nil,
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.Committees(ctx, epoch)
|
||||
assert.ErrorContains(t, "state committees data is nil", err)
|
||||
}
|
||||
|
||||
func TestGetCommittees_NilCommittee(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetCommitteesResponse{
|
||||
Data: []*structs.Committee{nil},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.Committees(ctx, epoch)
|
||||
assert.ErrorContains(t, "committee at index `0` is nil", err)
|
||||
}
|
||||
38
api/client/beacon/shared_providers/genesis.go
Normal file
38
api/client/beacon/shared_providers/genesis.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"sync"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
)
|
||||
|
||||
type genesisProvider struct {
|
||||
jsonRestHandler client.JsonRestHandler
|
||||
genesis *structs.Genesis
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
// GetGenesis gets the genesis information from the beacon node via the /eth/v1/beacon/genesis endpoint
|
||||
func (c *genesisProvider) Genesis(ctx context.Context) (*structs.Genesis, error) {
|
||||
genesisJson := &structs.GetGenesisResponse{}
|
||||
var doErr error
|
||||
c.once.Do(func() {
|
||||
if err := c.jsonRestHandler.Get(ctx, "/eth/v1/beacon/genesis", genesisJson); err != nil {
|
||||
doErr = err
|
||||
return
|
||||
}
|
||||
if genesisJson.Data == nil {
|
||||
doErr = errors.New("genesis data is nil")
|
||||
return
|
||||
}
|
||||
c.genesis = genesisJson.Data
|
||||
})
|
||||
if doErr != nil {
|
||||
// Allow another call because the current one returned an error
|
||||
c.once = sync.Once{}
|
||||
}
|
||||
return c.genesis, doErr
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
package beacon_api
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -36,7 +36,7 @@ func TestGetGenesis_ValidGenesis(t *testing.T) {
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
genesisProvider := &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
genesisProvider := &genesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
resp, err := genesisProvider.Genesis(ctx)
|
||||
assert.NoError(t, err)
|
||||
require.NotNil(t, resp)
|
||||
@@ -63,7 +63,7 @@ func TestGetGenesis_NilData(t *testing.T) {
|
||||
structs.GetGenesisResponse{Data: nil},
|
||||
).Times(1)
|
||||
|
||||
genesisProvider := &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
genesisProvider := &genesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := genesisProvider.Genesis(ctx)
|
||||
assert.ErrorContains(t, "genesis data is nil", err)
|
||||
}
|
||||
@@ -92,7 +92,7 @@ func TestGetGenesis_EndpointCalledOnlyOnce(t *testing.T) {
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
genesisProvider := &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
genesisProvider := &genesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := genesisProvider.Genesis(ctx)
|
||||
assert.NoError(t, err)
|
||||
resp, err := genesisProvider.Genesis(ctx)
|
||||
@@ -133,7 +133,7 @@ func TestGetGenesis_EndpointCanBeCalledAgainAfterError(t *testing.T) {
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
genesisProvider := &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
genesisProvider := &genesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := genesisProvider.Genesis(ctx)
|
||||
require.ErrorContains(t, "foo", err)
|
||||
resp, err := genesisProvider.Genesis(ctx)
|
||||
25
api/client/beacon/shared_providers/interfaces.go
Normal file
25
api/client/beacon/shared_providers/interfaces.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
)
|
||||
|
||||
type Genesis interface {
|
||||
Genesis(ctx context.Context) (*structs.Genesis, error)
|
||||
}
|
||||
|
||||
type StateValidators interface {
|
||||
StateValidators(context.Context, []string, []primitives.ValidatorIndex, []string) (*structs.GetValidatorsResponse, error)
|
||||
StateValidatorsForSlot(context.Context, primitives.Slot, []string, []primitives.ValidatorIndex, []string) (*structs.GetValidatorsResponse, error)
|
||||
StateValidatorsForHead(context.Context, []string, []primitives.ValidatorIndex, []string) (*structs.GetValidatorsResponse, error)
|
||||
}
|
||||
|
||||
type Duties interface {
|
||||
AttesterDuties(ctx context.Context, epoch primitives.Epoch, validatorIndices []primitives.ValidatorIndex) ([]*structs.AttesterDuty, error)
|
||||
ProposerDuties(ctx context.Context, epoch primitives.Epoch) ([]*structs.ProposerDuty, error)
|
||||
SyncDuties(ctx context.Context, epoch primitives.Epoch, validatorIndices []primitives.ValidatorIndex) ([]*structs.SyncCommitteeDuty, error)
|
||||
Committees(ctx context.Context, epoch primitives.Epoch) ([]*structs.Committee, error)
|
||||
}
|
||||
17
api/client/beacon/shared_providers/providers.go
Normal file
17
api/client/beacon/shared_providers/providers.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
)
|
||||
|
||||
func NewStateValidators(jsonRestHandler client.JsonRestHandler) StateValidators {
|
||||
return &stateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
}
|
||||
|
||||
func NewDuties(jsonRestHandler client.JsonRestHandler) Duties {
|
||||
return &dutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
}
|
||||
|
||||
func NewGenesis(jsonRestHandler client.JsonRestHandler) Genesis {
|
||||
return &genesisProvider{jsonRestHandler: jsonRestHandler}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -9,21 +9,17 @@ import (
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
)
|
||||
|
||||
type StateValidatorsProvider interface {
|
||||
StateValidators(context.Context, []string, []primitives.ValidatorIndex, []string) (*structs.GetValidatorsResponse, error)
|
||||
StateValidatorsForSlot(context.Context, primitives.Slot, []string, []primitives.ValidatorIndex, []string) (*structs.GetValidatorsResponse, error)
|
||||
StateValidatorsForHead(context.Context, []string, []primitives.ValidatorIndex, []string) (*structs.GetValidatorsResponse, error)
|
||||
type stateValidatorsProvider struct {
|
||||
jsonRestHandler client.JsonRestHandler
|
||||
}
|
||||
|
||||
type beaconApiStateValidatorsProvider struct {
|
||||
jsonRestHandler JsonRestHandler
|
||||
}
|
||||
|
||||
func (c beaconApiStateValidatorsProvider) StateValidators(
|
||||
func (c stateValidatorsProvider) StateValidators(
|
||||
ctx context.Context,
|
||||
stringPubkeys []string,
|
||||
indexes []primitives.ValidatorIndex,
|
||||
@@ -33,7 +29,7 @@ func (c beaconApiStateValidatorsProvider) StateValidators(
|
||||
return c.getStateValidatorsHelper(ctx, "/eth/v1/beacon/states/head/validators", append(stringIndices, stringPubkeys...), statuses)
|
||||
}
|
||||
|
||||
func (c beaconApiStateValidatorsProvider) StateValidatorsForSlot(
|
||||
func (c stateValidatorsProvider) StateValidatorsForSlot(
|
||||
ctx context.Context,
|
||||
slot primitives.Slot,
|
||||
stringPubkeys []string,
|
||||
@@ -44,7 +40,7 @@ func (c beaconApiStateValidatorsProvider) StateValidatorsForSlot(
|
||||
return c.getStateValidatorsHelper(ctx, fmt.Sprintf("/eth/v1/beacon/states/%d/validators", slot), append(stringIndices, stringPubkeys...), statuses)
|
||||
}
|
||||
|
||||
func (c beaconApiStateValidatorsProvider) StateValidatorsForHead(
|
||||
func (c stateValidatorsProvider) StateValidatorsForHead(
|
||||
ctx context.Context,
|
||||
stringPubkeys []string,
|
||||
indices []primitives.ValidatorIndex,
|
||||
@@ -66,7 +62,7 @@ func convertValidatorIndicesToStrings(indices []primitives.ValidatorIndex) []str
|
||||
return result
|
||||
}
|
||||
|
||||
func (c beaconApiStateValidatorsProvider) getStateValidatorsHelper(
|
||||
func (c stateValidatorsProvider) getStateValidatorsHelper(
|
||||
ctx context.Context,
|
||||
endpoint string,
|
||||
vals []string,
|
||||
@@ -112,7 +108,7 @@ func (c beaconApiStateValidatorsProvider) getStateValidatorsHelper(
|
||||
queryParams.Add("status", st)
|
||||
}
|
||||
|
||||
query := buildURL(endpoint, queryParams)
|
||||
query := apiutil.BuildURL(endpoint, queryParams)
|
||||
|
||||
err = c.jsonRestHandler.Get(ctx, query, stateValidatorsJson)
|
||||
if err != nil {
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package shared_providers
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -8,11 +8,12 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -84,7 +85,7 @@ func TestGetStateValidators_Nominal_POST(t *testing.T) {
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
stateValidatorsProvider := beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
stateValidatorsProvider := stateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
actual, err := stateValidatorsProvider.StateValidators(ctx, []string{
|
||||
"0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13", // active_ongoing
|
||||
"0x80000e851c0f53c3246ff726d7ff7766661ca5e12a07c45c114d208d54f0f8233d4380b2e9aff759d69795d1df905526", // active_exiting
|
||||
@@ -175,7 +176,7 @@ func TestGetStateValidators_Nominal_GET(t *testing.T) {
|
||||
queryParams.Add("status", st)
|
||||
}
|
||||
|
||||
query := buildURL("/eth/v1/beacon/states/head/validators", queryParams)
|
||||
query := apiutil.BuildURL("/eth/v1/beacon/states/head/validators", queryParams)
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
@@ -190,7 +191,7 @@ func TestGetStateValidators_Nominal_GET(t *testing.T) {
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
stateValidatorsProvider := beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
stateValidatorsProvider := stateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
actual, err := stateValidatorsProvider.StateValidators(ctx, []string{
|
||||
"0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13", // active_ongoing
|
||||
"0x80000e851c0f53c3246ff726d7ff7766661ca5e12a07c45c114d208d54f0f8233d4380b2e9aff759d69795d1df905526", // active_exiting
|
||||
@@ -244,7 +245,7 @@ func TestGetStateValidators_GetRestJsonResponseOnError(t *testing.T) {
|
||||
queryParams.Add("status", st)
|
||||
}
|
||||
|
||||
query := buildURL("/eth/v1/beacon/states/head/validators", queryParams)
|
||||
query := apiutil.BuildURL("/eth/v1/beacon/states/head/validators", queryParams)
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
@@ -254,7 +255,7 @@ func TestGetStateValidators_GetRestJsonResponseOnError(t *testing.T) {
|
||||
errors.New("an error"),
|
||||
).Times(1)
|
||||
|
||||
stateValidatorsProvider := beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
stateValidatorsProvider := stateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err = stateValidatorsProvider.StateValidators(ctx, []string{
|
||||
"0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13", // active_ongoing
|
||||
},
|
||||
@@ -293,7 +294,7 @@ func TestGetStateValidators_DataIsNil_POST(t *testing.T) {
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
stateValidatorsProvider := beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
stateValidatorsProvider := stateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err = stateValidatorsProvider.StateValidators(ctx, []string{
|
||||
"0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13", // active_ongoing
|
||||
},
|
||||
@@ -338,7 +339,7 @@ func TestGetStateValidators_DataIsNil_GET(t *testing.T) {
|
||||
queryParams.Add("status", st)
|
||||
}
|
||||
|
||||
query := buildURL("/eth/v1/beacon/states/head/validators", queryParams)
|
||||
query := apiutil.BuildURL("/eth/v1/beacon/states/head/validators", queryParams)
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
@@ -353,7 +354,7 @@ func TestGetStateValidators_DataIsNil_GET(t *testing.T) {
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
stateValidatorsProvider := beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
stateValidatorsProvider := stateValidatorsProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err = stateValidatorsProvider.StateValidators(ctx, []string{
|
||||
"0x8000091c2ae64ee414a54c1cc1fc67dec663408bc636cb86756e0200e41a75c8f86603f104f02c856983d2783116be13", // active_ongoing
|
||||
},
|
||||
145
api/client/beacon/structs.go
Normal file
145
api/client/beacon/structs.go
Normal file
@@ -0,0 +1,145 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type BeaconCommitteeSelection struct {
|
||||
SelectionProof []byte
|
||||
Slot primitives.Slot
|
||||
ValidatorIndex primitives.ValidatorIndex
|
||||
}
|
||||
|
||||
type beaconCommitteeSelectionJson struct {
|
||||
SelectionProof string `json:"selection_proof"`
|
||||
Slot string `json:"slot"`
|
||||
ValidatorIndex string `json:"validator_index"`
|
||||
}
|
||||
|
||||
func (b *BeaconCommitteeSelection) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(beaconCommitteeSelectionJson{
|
||||
SelectionProof: hexutil.Encode(b.SelectionProof),
|
||||
Slot: strconv.FormatUint(uint64(b.Slot), 10),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(b.ValidatorIndex), 10),
|
||||
})
|
||||
}
|
||||
|
||||
func (b *BeaconCommitteeSelection) UnmarshalJSON(input []byte) error {
|
||||
var bjson beaconCommitteeSelectionJson
|
||||
err := json.Unmarshal(input, &bjson)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal beacon committee selection")
|
||||
}
|
||||
|
||||
slot, err := strconv.ParseUint(bjson.Slot, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse slot")
|
||||
}
|
||||
|
||||
vIdx, err := strconv.ParseUint(bjson.ValidatorIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse validator index")
|
||||
}
|
||||
|
||||
selectionProof, err := hexutil.Decode(bjson.SelectionProof)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse selection proof")
|
||||
}
|
||||
|
||||
b.Slot = primitives.Slot(slot)
|
||||
b.SelectionProof = selectionProof
|
||||
b.ValidatorIndex = primitives.ValidatorIndex(vIdx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type SyncCommitteeSelection struct {
|
||||
SelectionProof []byte
|
||||
Slot primitives.Slot
|
||||
SubcommitteeIndex primitives.CommitteeIndex
|
||||
ValidatorIndex primitives.ValidatorIndex
|
||||
}
|
||||
|
||||
type syncCommitteeSelectionJson struct {
|
||||
SelectionProof string `json:"selection_proof"`
|
||||
Slot string `json:"slot"`
|
||||
SubcommitteeIndex string `json:"subcommittee_index"`
|
||||
ValidatorIndex string `json:"validator_index"`
|
||||
}
|
||||
|
||||
func (s *SyncCommitteeSelection) MarshalJSON() ([]byte, error) {
|
||||
return json.Marshal(syncCommitteeSelectionJson{
|
||||
SelectionProof: hexutil.Encode(s.SelectionProof),
|
||||
Slot: strconv.FormatUint(uint64(s.Slot), 10),
|
||||
SubcommitteeIndex: strconv.FormatUint(uint64(s.SubcommitteeIndex), 10),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(s.ValidatorIndex), 10),
|
||||
})
|
||||
}
|
||||
|
||||
func (s *SyncCommitteeSelection) UnmarshalJSON(input []byte) error {
|
||||
var resJson syncCommitteeSelectionJson
|
||||
err := json.Unmarshal(input, &resJson)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to unmarshal sync committee selection")
|
||||
}
|
||||
|
||||
slot, err := strconv.ParseUint(resJson.Slot, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse slot")
|
||||
}
|
||||
|
||||
vIdx, err := strconv.ParseUint(resJson.ValidatorIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse validator index")
|
||||
}
|
||||
|
||||
subcommIdx, err := strconv.ParseUint(resJson.SubcommitteeIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse subcommittee index")
|
||||
}
|
||||
|
||||
selectionProof, err := hexutil.Decode(resJson.SelectionProof)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to parse selection proof")
|
||||
}
|
||||
|
||||
s.Slot = primitives.Slot(slot)
|
||||
s.SelectionProof = selectionProof
|
||||
s.ValidatorIndex = primitives.ValidatorIndex(vIdx)
|
||||
s.SubcommitteeIndex = primitives.CommitteeIndex(subcommIdx)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type AggregatedSelectionResponse struct {
|
||||
Data []BeaconCommitteeSelection `json:"data"`
|
||||
}
|
||||
|
||||
type AggregatedSyncSelectionResponse struct {
|
||||
Data []SyncCommitteeSelection `json:"data"`
|
||||
}
|
||||
|
||||
type AttesterDuty struct {
|
||||
CommitteeIndex primitives.CommitteeIndex
|
||||
Slot primitives.Slot
|
||||
CommitteeLength uint64
|
||||
ValidatorCommitteeIndex uint64
|
||||
CommitteesAtSlot uint64
|
||||
}
|
||||
|
||||
type ValidatorForDuty struct {
|
||||
Pubkey []byte
|
||||
Index primitives.ValidatorIndex
|
||||
Status ethpb.ValidatorStatus
|
||||
}
|
||||
|
||||
type ValidatorCount struct {
|
||||
Status string
|
||||
Count uint64
|
||||
}
|
||||
34
api/client/beacon/template.go
Normal file
34
api/client/beacon/template.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package beacon
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type templateFn func(StateOrBlockId) string
|
||||
|
||||
var getBlockRootTpl templateFn
|
||||
var getForkTpl templateFn
|
||||
|
||||
func init() {
|
||||
// idTemplate is used to create template functions that can interpolate StateOrBlockId values.
|
||||
idTemplate := func(ts string) func(StateOrBlockId) string {
|
||||
t := template.Must(template.New("").Parse(ts))
|
||||
f := func(id StateOrBlockId) string {
|
||||
b := bytes.NewBuffer(nil)
|
||||
err := t.Execute(b, struct{ Id string }{Id: string(id)})
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("invalid idTemplate: %s", ts))
|
||||
}
|
||||
return b.String()
|
||||
}
|
||||
// run the template to ensure that it is valid
|
||||
// this should happen load time (using package scoped vars) to ensure runtime errors aren't possible
|
||||
_ = f(IdGenesis)
|
||||
return f
|
||||
}
|
||||
|
||||
getBlockRootTpl = idTemplate(getBlockRootPath)
|
||||
getForkTpl = idTemplate(getForkForStatePath)
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["mock.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/testing",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api/client/beacon/iface:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -4,30 +4,26 @@ go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"attestation_data.go",
|
||||
"beacon_api_beacon_chain_client.go",
|
||||
"beacon_api_helpers.go",
|
||||
"beacon_api_node_client.go",
|
||||
"beacon_api_validator_client.go",
|
||||
"beacon_block_converter.go",
|
||||
"beacon_block_json_helpers.go",
|
||||
"beacon_block_proto_helpers.go",
|
||||
"beacon_committee_selections.go",
|
||||
"client.go",
|
||||
"domain_data.go",
|
||||
"doppelganger.go",
|
||||
"duties.go",
|
||||
"genesis.go",
|
||||
"get_beacon_block.go",
|
||||
"grpc_client.go",
|
||||
"index.go",
|
||||
"json_rest_handler.go",
|
||||
"interfaces.go",
|
||||
"log.go",
|
||||
"metrics.go",
|
||||
"prepare_beacon_proposer.go",
|
||||
"propose_attestation.go",
|
||||
"propose_beacon_block.go",
|
||||
"propose_exit.go",
|
||||
"prysm_beacon_chain_client.go",
|
||||
"registration.go",
|
||||
"state_validators.go",
|
||||
"rest_client.go",
|
||||
"status.go",
|
||||
"stream_blocks.go",
|
||||
"submit_aggregate_selection_proof.go",
|
||||
@@ -37,15 +33,20 @@ go_library(
|
||||
"sync_committee.go",
|
||||
"sync_committee_selections.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api",
|
||||
visibility = ["//validator:__subpackages__"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/api/client/beacon/validator_api",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/apiutil:go_default_library",
|
||||
"//api/client/beacon:go_default_library",
|
||||
"//api/client/beacon/node:go_default_library",
|
||||
"//api/client/beacon/prysm_api:go_default_library",
|
||||
"//api/client/beacon/shared_providers:go_default_library",
|
||||
"//api/client/event:go_default_library",
|
||||
"//api/server/structs:go_default_library",
|
||||
"//beacon-chain/core/helpers:go_default_library",
|
||||
"//beacon-chain/core/signing:go_default_library",
|
||||
"//config/features:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
@@ -57,7 +58,7 @@ go_library(
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"//validator/helpers:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
@@ -65,39 +66,32 @@ go_library(
|
||||
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",
|
||||
"@com_github_sirupsen_logrus//: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",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
size = "small",
|
||||
srcs = [
|
||||
"attestation_data_test.go",
|
||||
"beacon_api_beacon_chain_client_test.go",
|
||||
"beacon_api_helpers_test.go",
|
||||
"beacon_api_node_client_test.go",
|
||||
"beacon_api_validator_client_test.go",
|
||||
"beacon_block_converter_test.go",
|
||||
"beacon_block_json_helpers_test.go",
|
||||
"beacon_block_proto_helpers_test.go",
|
||||
"beacon_committee_selections_test.go",
|
||||
"domain_data_test.go",
|
||||
"doppelganger_test.go",
|
||||
"duties_test.go",
|
||||
"genesis_test.go",
|
||||
"get_beacon_block_test.go",
|
||||
"grpc_client_test.go",
|
||||
"index_test.go",
|
||||
"json_rest_handler_test.go",
|
||||
"prepare_beacon_proposer_test.go",
|
||||
"propose_attestation_test.go",
|
||||
"propose_beacon_block_altair_test.go",
|
||||
"propose_beacon_block_bellatrix_test.go",
|
||||
"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",
|
||||
@@ -106,7 +100,7 @@ go_test(
|
||||
"propose_beacon_block_test.go",
|
||||
"propose_exit_test.go",
|
||||
"registration_test.go",
|
||||
"state_validators_test.go",
|
||||
"rest_client_test.go",
|
||||
"status_test.go",
|
||||
"stream_blocks_test.go",
|
||||
"submit_aggregate_selection_proof_test.go",
|
||||
@@ -115,34 +109,38 @@ go_test(
|
||||
"subscribe_committee_subnets_test.go",
|
||||
"sync_committee_selections_test.go",
|
||||
"sync_committee_test.go",
|
||||
"validator_count_test.go",
|
||||
"wait_for_chain_start_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//api:go_default_library",
|
||||
"//api/client:go_default_library",
|
||||
"//api/client/apiutil:go_default_library",
|
||||
"//api/client/beacon:go_default_library",
|
||||
"//api/client/beacon/mock:go_default_library",
|
||||
"//api/client/beacon/node:go_default_library",
|
||||
"//api/client/beacon/prysm_api:go_default_library",
|
||||
"//api/client/beacon/shared_providers:go_default_library",
|
||||
"//api/client/beacon/validator_api/test_helpers:go_default_library",
|
||||
"//api/client/event: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",
|
||||
"//consensus-types/validator:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//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/mock:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"//validator/client/beacon-api/mock:go_default_library",
|
||||
"//validator/client/beacon-api/test-helpers:go_default_library",
|
||||
"//validator/client/iface:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_golang_protobuf//ptypes/empty",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||
"@org_uber_go_mock//gomock:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
@@ -21,7 +22,7 @@ func (c *beaconApiValidatorClient) attestationData(
|
||||
params.Add("slot", strconv.FormatUint(uint64(reqSlot), 10))
|
||||
params.Add("committee_index", strconv.FormatUint(uint64(reqCommitteeIndex), 10))
|
||||
|
||||
query := buildURL("/eth/v1/validator/attestation_data", params)
|
||||
query := apiutil.BuildURL("/eth/v1/validator/attestation_data", params)
|
||||
produceAttestationDataResponseJson := structs.GetAttestationDataResponse{}
|
||||
|
||||
if err := c.jsonRestHandler.Get(ctx, query, &produceAttestationDataResponseJson); err != nil {
|
||||
@@ -38,7 +39,7 @@ func (c *beaconApiValidatorClient) attestationData(
|
||||
return nil, errors.Wrapf(err, "failed to parse attestation committee index: %s", attestationData.CommitteeIndex)
|
||||
}
|
||||
|
||||
if !validRoot(attestationData.BeaconBlockRoot) {
|
||||
if !apiutil.ValidRoot(attestationData.BeaconBlockRoot) {
|
||||
return nil, errors.Errorf("invalid beacon block root: %s", attestationData.BeaconBlockRoot)
|
||||
}
|
||||
|
||||
@@ -61,7 +62,7 @@ func (c *beaconApiValidatorClient) attestationData(
|
||||
return nil, errors.Wrapf(err, "failed to parse attestation source epoch: %s", attestationData.Source.Epoch)
|
||||
}
|
||||
|
||||
if !validRoot(attestationData.Source.Root) {
|
||||
if !apiutil.ValidRoot(attestationData.Source.Root) {
|
||||
return nil, errors.Errorf("invalid attestation source root: %s", attestationData.Source.Root)
|
||||
}
|
||||
|
||||
@@ -79,7 +80,7 @@ func (c *beaconApiValidatorClient) attestationData(
|
||||
return nil, errors.Wrapf(err, "failed to parse attestation target epoch: %s", attestationData.Target.Epoch)
|
||||
}
|
||||
|
||||
if !validRoot(attestationData.Target.Root) {
|
||||
if !apiutil.ValidRoot(attestationData.Target.Root) {
|
||||
return nil, errors.Errorf("invalid attestation target root: %s", attestationData.Target.Root)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -1,12 +1,9 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
neturl "net/url"
|
||||
"regexp"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@@ -27,26 +24,6 @@ var beaconAPITogRPCValidatorStatus = map[string]ethpb.ValidatorStatus{
|
||||
"withdrawal_done": ethpb.ValidatorStatus_EXITED,
|
||||
}
|
||||
|
||||
func validRoot(root string) bool {
|
||||
matchesRegex, err := regexp.MatchString("^0x[a-fA-F0-9]{64}$", root)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return matchesRegex
|
||||
}
|
||||
|
||||
func uint64ToString[T uint64 | primitives.Slot | primitives.ValidatorIndex | primitives.CommitteeIndex | primitives.Epoch](val T) string {
|
||||
return strconv.FormatUint(uint64(val), 10)
|
||||
}
|
||||
|
||||
func buildURL(path string, queryParams ...neturl.Values) string {
|
||||
if len(queryParams) == 0 {
|
||||
return path
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s?%s", path, queryParams[0].Encode())
|
||||
}
|
||||
|
||||
func (c *beaconApiValidatorClient) fork(ctx context.Context) (*structs.GetStateForkResponse, error) {
|
||||
const endpoint = "/eth/v1/beacon/states/head/fork"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -8,11 +8,12 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -56,7 +57,7 @@ func TestBeaconApiHelpers(t *testing.T) {
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.valid, validRoot(tt.input))
|
||||
assert.Equal(t, tt.valid, apiutil.ValidRoot(tt.input))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -65,16 +66,16 @@ func TestBeaconApiHelpers_TestUint64ToString(t *testing.T) {
|
||||
const expectedResult = "1234"
|
||||
const val = uint64(1234)
|
||||
|
||||
assert.Equal(t, expectedResult, uint64ToString(val))
|
||||
assert.Equal(t, expectedResult, uint64ToString(primitives.Slot(val)))
|
||||
assert.Equal(t, expectedResult, uint64ToString(primitives.ValidatorIndex(val)))
|
||||
assert.Equal(t, expectedResult, uint64ToString(primitives.CommitteeIndex(val)))
|
||||
assert.Equal(t, expectedResult, uint64ToString(primitives.Epoch(val)))
|
||||
assert.Equal(t, expectedResult, apiutil.Uint64ToString(val))
|
||||
assert.Equal(t, expectedResult, apiutil.Uint64ToString(primitives.Slot(val)))
|
||||
assert.Equal(t, expectedResult, apiutil.Uint64ToString(primitives.ValidatorIndex(val)))
|
||||
assert.Equal(t, expectedResult, apiutil.Uint64ToString(primitives.CommitteeIndex(val)))
|
||||
assert.Equal(t, expectedResult, apiutil.Uint64ToString(primitives.Epoch(val)))
|
||||
}
|
||||
|
||||
func TestBuildURL_NoParams(t *testing.T) {
|
||||
wanted := "/aaa/bbb/ccc"
|
||||
actual := buildURL("/aaa/bbb/ccc")
|
||||
actual := apiutil.BuildURL("/aaa/bbb/ccc")
|
||||
assert.Equal(t, wanted, actual)
|
||||
}
|
||||
|
||||
@@ -85,7 +86,7 @@ func TestBuildURL_WithParams(t *testing.T) {
|
||||
params.Add("zzzz", "3")
|
||||
|
||||
wanted := "/aaa/bbb/ccc?xxxx=1&yyyy=2&zzzz=3"
|
||||
actual := buildURL("/aaa/bbb/ccc", params)
|
||||
actual := apiutil.BuildURL("/aaa/bbb/ccc", params)
|
||||
assert.Equal(t, wanted, actual)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
@@ -1,18 +1,18 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/validator_api/test_helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
testhelpers "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/test-helpers"
|
||||
)
|
||||
|
||||
func TestGetBeaconBlockConverter_Phase0Valid(t *testing.T) {
|
||||
expectedBeaconBlock := testhelpers.GenerateProtoPhase0BeaconBlock()
|
||||
expectedBeaconBlock := test_helpers.GenerateProtoPhase0BeaconBlock()
|
||||
beaconBlockConverter := &beaconApiBeaconBlockConverter{}
|
||||
beaconBlock, err := beaconBlockConverter.ConvertRESTPhase0BlockToProto(testhelpers.GenerateJsonPhase0BeaconBlock())
|
||||
beaconBlock, err := beaconBlockConverter.ConvertRESTPhase0BlockToProto(test_helpers.GenerateJsonPhase0BeaconBlock())
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
|
||||
}
|
||||
@@ -27,7 +27,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "nil body",
|
||||
expectedErrorMessage: "block body is nil",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Body = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -36,7 +36,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "nil eth1 data",
|
||||
expectedErrorMessage: "eth1 data is nil",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Body.Eth1Data = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -45,7 +45,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad slot",
|
||||
expectedErrorMessage: "failed to parse slot `foo`",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Slot = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -54,7 +54,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad proposer index",
|
||||
expectedErrorMessage: "failed to parse proposer index `bar`",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.ProposerIndex = "bar"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -63,7 +63,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad parent root",
|
||||
expectedErrorMessage: "failed to decode parent root `foo`",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.ParentRoot = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -72,7 +72,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad state root",
|
||||
expectedErrorMessage: "failed to decode state root `bar`",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.StateRoot = "bar"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -81,7 +81,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad randao reveal",
|
||||
expectedErrorMessage: "failed to decode randao reveal `foo`",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Body.RandaoReveal = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -90,7 +90,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad deposit root",
|
||||
expectedErrorMessage: "failed to decode deposit root `bar`",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Body.Eth1Data.DepositRoot = "bar"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -99,7 +99,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad deposit count",
|
||||
expectedErrorMessage: "failed to parse deposit count `foo`",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Body.Eth1Data.DepositCount = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -108,7 +108,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad block hash",
|
||||
expectedErrorMessage: "failed to decode block hash `bar`",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Body.Eth1Data.BlockHash = "bar"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -117,7 +117,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad graffiti",
|
||||
expectedErrorMessage: "failed to decode graffiti `foo`",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Body.Graffiti = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -126,7 +126,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad proposer slashings",
|
||||
expectedErrorMessage: "failed to get proposer slashings",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Body.ProposerSlashings[0] = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -135,7 +135,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad attester slashings",
|
||||
expectedErrorMessage: "failed to get attester slashings",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Body.AttesterSlashings[0] = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -144,7 +144,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad attestations",
|
||||
expectedErrorMessage: "failed to get attestations",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Body.Attestations[0] = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -153,7 +153,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad deposits",
|
||||
expectedErrorMessage: "failed to get deposits",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Body.Deposits[0] = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -162,7 +162,7 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
name: "bad voluntary exits",
|
||||
expectedErrorMessage: "failed to get voluntary exits",
|
||||
generateData: func() *structs.BeaconBlock {
|
||||
beaconBlock := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
beaconBlock.Body.VoluntaryExits[0] = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -181,9 +181,9 @@ func TestGetBeaconBlockConverter_Phase0Error(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetBeaconBlockConverter_AltairValid(t *testing.T) {
|
||||
expectedBeaconBlock := testhelpers.GenerateProtoAltairBeaconBlock()
|
||||
expectedBeaconBlock := test_helpers.GenerateProtoAltairBeaconBlock()
|
||||
beaconBlockConverter := &beaconApiBeaconBlockConverter{}
|
||||
beaconBlock, err := beaconBlockConverter.ConvertRESTAltairBlockToProto(testhelpers.GenerateJsonAltairBeaconBlock())
|
||||
beaconBlock, err := beaconBlockConverter.ConvertRESTAltairBlockToProto(test_helpers.GenerateJsonAltairBeaconBlock())
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
|
||||
}
|
||||
@@ -198,7 +198,7 @@ func TestGetBeaconBlockConverter_AltairError(t *testing.T) {
|
||||
name: "nil body",
|
||||
expectedErrorMessage: "block body is nil",
|
||||
generateData: func() *structs.BeaconBlockAltair {
|
||||
beaconBlock := testhelpers.GenerateJsonAltairBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonAltairBeaconBlock()
|
||||
beaconBlock.Body = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -207,7 +207,7 @@ func TestGetBeaconBlockConverter_AltairError(t *testing.T) {
|
||||
name: "nil sync aggregate",
|
||||
expectedErrorMessage: "sync aggregate is nil",
|
||||
generateData: func() *structs.BeaconBlockAltair {
|
||||
beaconBlock := testhelpers.GenerateJsonAltairBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonAltairBeaconBlock()
|
||||
beaconBlock.Body.SyncAggregate = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -216,7 +216,7 @@ func TestGetBeaconBlockConverter_AltairError(t *testing.T) {
|
||||
name: "bad phase0 fields",
|
||||
expectedErrorMessage: "failed to get the phase0 fields of the altair block",
|
||||
generateData: func() *structs.BeaconBlockAltair {
|
||||
beaconBlock := testhelpers.GenerateJsonAltairBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonAltairBeaconBlock()
|
||||
beaconBlock.Body.Eth1Data = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -225,7 +225,7 @@ func TestGetBeaconBlockConverter_AltairError(t *testing.T) {
|
||||
name: "bad sync committee bits",
|
||||
expectedErrorMessage: "failed to decode sync committee bits `foo`",
|
||||
generateData: func() *structs.BeaconBlockAltair {
|
||||
beaconBlock := testhelpers.GenerateJsonAltairBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonAltairBeaconBlock()
|
||||
beaconBlock.Body.SyncAggregate.SyncCommitteeBits = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -234,7 +234,7 @@ func TestGetBeaconBlockConverter_AltairError(t *testing.T) {
|
||||
name: "bad sync committee signature",
|
||||
expectedErrorMessage: "failed to decode sync committee signature `bar`",
|
||||
generateData: func() *structs.BeaconBlockAltair {
|
||||
beaconBlock := testhelpers.GenerateJsonAltairBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonAltairBeaconBlock()
|
||||
beaconBlock.Body.SyncAggregate.SyncCommitteeSignature = "bar"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -253,9 +253,9 @@ func TestGetBeaconBlockConverter_AltairError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetBeaconBlockConverter_BellatrixValid(t *testing.T) {
|
||||
expectedBeaconBlock := testhelpers.GenerateProtoBellatrixBeaconBlock()
|
||||
expectedBeaconBlock := test_helpers.GenerateProtoBellatrixBeaconBlock()
|
||||
beaconBlockConverter := &beaconApiBeaconBlockConverter{}
|
||||
beaconBlock, err := beaconBlockConverter.ConvertRESTBellatrixBlockToProto(testhelpers.GenerateJsonBellatrixBeaconBlock())
|
||||
beaconBlock, err := beaconBlockConverter.ConvertRESTBellatrixBlockToProto(test_helpers.GenerateJsonBellatrixBeaconBlock())
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
|
||||
}
|
||||
@@ -270,7 +270,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "nil body",
|
||||
expectedErrorMessage: "block body is nil",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -279,7 +279,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "nil execution payload",
|
||||
expectedErrorMessage: "execution payload is nil",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -288,7 +288,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad altair fields",
|
||||
expectedErrorMessage: "failed to get the altair fields of the bellatrix block",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.Eth1Data = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -297,7 +297,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad parent hash",
|
||||
expectedErrorMessage: "failed to decode execution payload parent hash `foo`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.ParentHash = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -306,7 +306,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad fee recipient",
|
||||
expectedErrorMessage: "failed to decode execution payload fee recipient `bar`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.FeeRecipient = "bar"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -315,7 +315,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad state root",
|
||||
expectedErrorMessage: "failed to decode execution payload state root `foo`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.StateRoot = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -324,7 +324,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad receipts root",
|
||||
expectedErrorMessage: "failed to decode execution payload receipts root `bar`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.ReceiptsRoot = "bar"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -333,7 +333,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad logs bloom",
|
||||
expectedErrorMessage: "failed to decode execution payload logs bloom `foo`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.LogsBloom = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -342,7 +342,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad prev randao",
|
||||
expectedErrorMessage: "failed to decode execution payload prev randao `bar`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.PrevRandao = "bar"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -351,7 +351,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad block number",
|
||||
expectedErrorMessage: "failed to parse execution payload block number `foo`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.BlockNumber = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -360,7 +360,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad gas limit",
|
||||
expectedErrorMessage: "failed to parse execution payload gas limit `bar`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.GasLimit = "bar"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -369,7 +369,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad gas used",
|
||||
expectedErrorMessage: "failed to parse execution payload gas used `foo`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.GasUsed = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -378,7 +378,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad timestamp",
|
||||
expectedErrorMessage: "failed to parse execution payload timestamp `bar`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.Timestamp = "bar"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -387,7 +387,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad extra data",
|
||||
expectedErrorMessage: "failed to decode execution payload extra data `foo`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.ExtraData = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -396,7 +396,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad base fee per gas",
|
||||
expectedErrorMessage: "failed to parse execution payload base fee per gas `bar`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.BaseFeePerGas = "bar"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -405,7 +405,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad block hash",
|
||||
expectedErrorMessage: "failed to decode execution payload block hash `foo`",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.BlockHash = "foo"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -414,7 +414,7 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
name: "bad transactions",
|
||||
expectedErrorMessage: "failed to get execution payload transactions",
|
||||
generateData: func() *structs.BeaconBlockBellatrix {
|
||||
beaconBlock := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.Transactions[0] = "bar"
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -433,9 +433,9 @@ func TestGetBeaconBlockConverter_BellatrixError(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestGetBeaconBlockConverter_CapellaValid(t *testing.T) {
|
||||
expectedBeaconBlock := testhelpers.GenerateProtoCapellaBeaconBlock()
|
||||
expectedBeaconBlock := test_helpers.GenerateProtoCapellaBeaconBlock()
|
||||
beaconBlockConverter := &beaconApiBeaconBlockConverter{}
|
||||
beaconBlock, err := beaconBlockConverter.ConvertRESTCapellaBlockToProto(testhelpers.GenerateJsonCapellaBeaconBlock())
|
||||
beaconBlock, err := beaconBlockConverter.ConvertRESTCapellaBlockToProto(test_helpers.GenerateJsonCapellaBeaconBlock())
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedBeaconBlock, beaconBlock)
|
||||
}
|
||||
@@ -450,7 +450,7 @@ func TestGetBeaconBlockConverter_CapellaError(t *testing.T) {
|
||||
name: "nil body",
|
||||
expectedErrorMessage: "block body is nil",
|
||||
generateData: func() *structs.BeaconBlockCapella {
|
||||
beaconBlock := testhelpers.GenerateJsonCapellaBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonCapellaBeaconBlock()
|
||||
beaconBlock.Body = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -459,7 +459,7 @@ func TestGetBeaconBlockConverter_CapellaError(t *testing.T) {
|
||||
name: "nil execution payload",
|
||||
expectedErrorMessage: "execution payload is nil",
|
||||
generateData: func() *structs.BeaconBlockCapella {
|
||||
beaconBlock := testhelpers.GenerateJsonCapellaBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonCapellaBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -468,7 +468,7 @@ func TestGetBeaconBlockConverter_CapellaError(t *testing.T) {
|
||||
name: "bad bellatrix fields",
|
||||
expectedErrorMessage: "failed to get the bellatrix fields of the capella block",
|
||||
generateData: func() *structs.BeaconBlockCapella {
|
||||
beaconBlock := testhelpers.GenerateJsonCapellaBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonCapellaBeaconBlock()
|
||||
beaconBlock.Body.Eth1Data = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -477,7 +477,7 @@ func TestGetBeaconBlockConverter_CapellaError(t *testing.T) {
|
||||
name: "bad withdrawals",
|
||||
expectedErrorMessage: "failed to get withdrawals",
|
||||
generateData: func() *structs.BeaconBlockCapella {
|
||||
beaconBlock := testhelpers.GenerateJsonCapellaBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonCapellaBeaconBlock()
|
||||
beaconBlock.Body.ExecutionPayload.Withdrawals[0] = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -486,7 +486,7 @@ func TestGetBeaconBlockConverter_CapellaError(t *testing.T) {
|
||||
name: "bad bls execution changes",
|
||||
expectedErrorMessage: "failed to get bls to execution changes",
|
||||
generateData: func() *structs.BeaconBlockCapella {
|
||||
beaconBlock := testhelpers.GenerateJsonCapellaBeaconBlock()
|
||||
beaconBlock := test_helpers.GenerateJsonCapellaBeaconBlock()
|
||||
beaconBlock.Body.BLSToExecutionChanges[0] = nil
|
||||
return beaconBlock
|
||||
},
|
||||
@@ -1,9 +1,10 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
@@ -22,7 +23,7 @@ func jsonifyBlsToExecutionChanges(blsToExecutionChanges []*ethpb.SignedBLSToExec
|
||||
jsonBlsToExecutionChanges := make([]*structs.SignedBLSToExecutionChange, len(blsToExecutionChanges))
|
||||
for index, signedBlsToExecutionChange := range blsToExecutionChanges {
|
||||
blsToExecutionChangeJson := &structs.BLSToExecutionChange{
|
||||
ValidatorIndex: uint64ToString(signedBlsToExecutionChange.Message.ValidatorIndex),
|
||||
ValidatorIndex: apiutil.Uint64ToString(signedBlsToExecutionChange.Message.ValidatorIndex),
|
||||
FromBLSPubkey: hexutil.Encode(signedBlsToExecutionChange.Message.FromBlsPubkey),
|
||||
ToExecutionAddress: hexutil.Encode(signedBlsToExecutionChange.Message.ToExecutionAddress),
|
||||
}
|
||||
@@ -38,7 +39,7 @@ func jsonifyBlsToExecutionChanges(blsToExecutionChanges []*ethpb.SignedBLSToExec
|
||||
func jsonifyEth1Data(eth1Data *ethpb.Eth1Data) *structs.Eth1Data {
|
||||
return &structs.Eth1Data{
|
||||
BlockHash: hexutil.Encode(eth1Data.BlockHash),
|
||||
DepositCount: uint64ToString(eth1Data.DepositCount),
|
||||
DepositCount: apiutil.Uint64ToString(eth1Data.DepositCount),
|
||||
DepositRoot: hexutil.Encode(eth1Data.DepositRoot),
|
||||
}
|
||||
}
|
||||
@@ -81,7 +82,7 @@ func jsonifyDeposits(deposits []*ethpb.Deposit) []*structs.Deposit {
|
||||
|
||||
jsonDeposit := &structs.Deposit{
|
||||
Data: &structs.DepositData{
|
||||
Amount: uint64ToString(deposit.Data.Amount),
|
||||
Amount: apiutil.Uint64ToString(deposit.Data.Amount),
|
||||
Pubkey: hexutil.Encode(deposit.Data.PublicKey),
|
||||
Signature: hexutil.Encode(deposit.Data.Signature),
|
||||
WithdrawalCredentials: hexutil.Encode(deposit.Data.WithdrawalCredentials),
|
||||
@@ -111,8 +112,8 @@ func JsonifySignedVoluntaryExits(voluntaryExits []*ethpb.SignedVoluntaryExit) []
|
||||
for index, signedVoluntaryExit := range voluntaryExits {
|
||||
jsonSignedVoluntaryExit := &structs.SignedVoluntaryExit{
|
||||
Message: &structs.VoluntaryExit{
|
||||
Epoch: uint64ToString(signedVoluntaryExit.Exit.Epoch),
|
||||
ValidatorIndex: uint64ToString(signedVoluntaryExit.Exit.ValidatorIndex),
|
||||
Epoch: apiutil.Uint64ToString(signedVoluntaryExit.Exit.Epoch),
|
||||
ValidatorIndex: apiutil.Uint64ToString(signedVoluntaryExit.Exit.ValidatorIndex),
|
||||
},
|
||||
Signature: hexutil.Encode(signedVoluntaryExit.Signature),
|
||||
}
|
||||
@@ -126,8 +127,8 @@ func jsonifySignedBeaconBlockHeader(signedBeaconBlockHeader *ethpb.SignedBeaconB
|
||||
Message: &structs.BeaconBlockHeader{
|
||||
BodyRoot: hexutil.Encode(signedBeaconBlockHeader.Header.BodyRoot),
|
||||
ParentRoot: hexutil.Encode(signedBeaconBlockHeader.Header.ParentRoot),
|
||||
ProposerIndex: uint64ToString(signedBeaconBlockHeader.Header.ProposerIndex),
|
||||
Slot: uint64ToString(signedBeaconBlockHeader.Header.Slot),
|
||||
ProposerIndex: apiutil.Uint64ToString(signedBeaconBlockHeader.Header.ProposerIndex),
|
||||
Slot: apiutil.Uint64ToString(signedBeaconBlockHeader.Header.Slot),
|
||||
StateRoot: hexutil.Encode(signedBeaconBlockHeader.Header.StateRoot),
|
||||
},
|
||||
Signature: hexutil.Encode(signedBeaconBlockHeader.Signature),
|
||||
@@ -137,7 +138,7 @@ func jsonifySignedBeaconBlockHeader(signedBeaconBlockHeader *ethpb.SignedBeaconB
|
||||
func jsonifyIndexedAttestation(indexedAttestation *ethpb.IndexedAttestation) *structs.IndexedAttestation {
|
||||
attestingIndices := make([]string, len(indexedAttestation.AttestingIndices))
|
||||
for index, attestingIndex := range indexedAttestation.AttestingIndices {
|
||||
attestingIndex := uint64ToString(attestingIndex)
|
||||
attestingIndex := apiutil.Uint64ToString(attestingIndex)
|
||||
attestingIndices[index] = attestingIndex
|
||||
}
|
||||
|
||||
@@ -151,14 +152,14 @@ func jsonifyIndexedAttestation(indexedAttestation *ethpb.IndexedAttestation) *st
|
||||
func jsonifyAttestationData(attestationData *ethpb.AttestationData) *structs.AttestationData {
|
||||
return &structs.AttestationData{
|
||||
BeaconBlockRoot: hexutil.Encode(attestationData.BeaconBlockRoot),
|
||||
CommitteeIndex: uint64ToString(attestationData.CommitteeIndex),
|
||||
Slot: uint64ToString(attestationData.Slot),
|
||||
CommitteeIndex: apiutil.Uint64ToString(attestationData.CommitteeIndex),
|
||||
Slot: apiutil.Uint64ToString(attestationData.Slot),
|
||||
Source: &structs.Checkpoint{
|
||||
Epoch: uint64ToString(attestationData.Source.Epoch),
|
||||
Epoch: apiutil.Uint64ToString(attestationData.Source.Epoch),
|
||||
Root: hexutil.Encode(attestationData.Source.Root),
|
||||
},
|
||||
Target: &structs.Checkpoint{
|
||||
Epoch: uint64ToString(attestationData.Target.Epoch),
|
||||
Epoch: apiutil.Uint64ToString(attestationData.Target.Epoch),
|
||||
Root: hexutil.Encode(attestationData.Target.Root),
|
||||
},
|
||||
}
|
||||
@@ -183,8 +184,8 @@ func jsonifyAttestationElectra(attestation *ethpb.AttestationElectra) *structs.A
|
||||
|
||||
func jsonifySingleAttestation(attestation *ethpb.SingleAttestation) *structs.SingleAttestation {
|
||||
return &structs.SingleAttestation{
|
||||
CommitteeIndex: uint64ToString(attestation.CommitteeId),
|
||||
AttesterIndex: uint64ToString(attestation.AttesterIndex),
|
||||
CommitteeIndex: apiutil.Uint64ToString(attestation.CommitteeId),
|
||||
AttesterIndex: apiutil.Uint64ToString(attestation.AttesterIndex),
|
||||
Data: jsonifyAttestationData(attestation.Data),
|
||||
Signature: hexutil.Encode(attestation.Signature),
|
||||
}
|
||||
@@ -193,7 +194,7 @@ func jsonifySingleAttestation(attestation *ethpb.SingleAttestation) *structs.Sin
|
||||
func jsonifySignedAggregateAndProof(signedAggregateAndProof *ethpb.SignedAggregateAttestationAndProof) *structs.SignedAggregateAttestationAndProof {
|
||||
return &structs.SignedAggregateAttestationAndProof{
|
||||
Message: &structs.AggregateAttestationAndProof{
|
||||
AggregatorIndex: uint64ToString(signedAggregateAndProof.Message.AggregatorIndex),
|
||||
AggregatorIndex: apiutil.Uint64ToString(signedAggregateAndProof.Message.AggregatorIndex),
|
||||
Aggregate: jsonifyAttestation(signedAggregateAndProof.Message.Aggregate),
|
||||
SelectionProof: hexutil.Encode(signedAggregateAndProof.Message.SelectionProof),
|
||||
},
|
||||
@@ -204,7 +205,7 @@ func jsonifySignedAggregateAndProof(signedAggregateAndProof *ethpb.SignedAggrega
|
||||
func jsonifySignedAggregateAndProofElectra(signedAggregateAndProof *ethpb.SignedAggregateAttestationAndProofElectra) *structs.SignedAggregateAttestationAndProofElectra {
|
||||
return &structs.SignedAggregateAttestationAndProofElectra{
|
||||
Message: &structs.AggregateAttestationAndProofElectra{
|
||||
AggregatorIndex: uint64ToString(signedAggregateAndProof.Message.AggregatorIndex),
|
||||
AggregatorIndex: apiutil.Uint64ToString(signedAggregateAndProof.Message.AggregatorIndex),
|
||||
Aggregate: jsonifyAttestationElectra(signedAggregateAndProof.Message.Aggregate),
|
||||
SelectionProof: hexutil.Encode(signedAggregateAndProof.Message.SelectionProof),
|
||||
},
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
38
api/client/beacon/validator_api/client.go
Normal file
38
api/client/beacon/validator_api/client.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/node"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/prysm_api"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
validatorHelpers "github.com/prysmaticlabs/prysm/v5/validator/helpers"
|
||||
)
|
||||
|
||||
func NewClient(
|
||||
validatorConn validatorHelpers.NodeConnection,
|
||||
jsonRestHandler client.JsonRestHandler,
|
||||
opt ...ValidatorClientOpt,
|
||||
) Client {
|
||||
if features.Get().EnableBeaconRESTApi {
|
||||
return NewBeaconApiValidatorClient(jsonRestHandler, opt...)
|
||||
} else {
|
||||
return NewGrpcValidatorClient(validatorConn.GetGrpcClientConn())
|
||||
}
|
||||
}
|
||||
|
||||
func NewBeaconApiValidatorClient(jsonRestHandler client.JsonRestHandler, opts ...ValidatorClientOpt) Client {
|
||||
c := &beaconApiValidatorClient{
|
||||
genesisProvider: shared_providers.NewGenesis(jsonRestHandler),
|
||||
dutiesProvider: shared_providers.NewDuties(jsonRestHandler),
|
||||
stateValidatorsProvider: shared_providers.NewStateValidators(jsonRestHandler),
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
beaconBlockConverter: beaconApiBeaconBlockConverter{},
|
||||
prysmChainClient: prysm_api.NewPrysmChainRestClient(jsonRestHandler, node.NewNodeClientWithFallback(jsonRestHandler, nil)), //TODO: this is really bad design...
|
||||
isEventStreamRunning: false,
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/network/forks"
|
||||
@@ -24,7 +25,7 @@ func (c *beaconApiValidatorClient) domainData(ctx context.Context, epoch primiti
|
||||
return nil, errors.Wrapf(err, "failed to get genesis info")
|
||||
}
|
||||
|
||||
if !validRoot(genesis.GenesisValidatorsRoot) {
|
||||
if !apiutil.ValidRoot(genesis.GenesisValidatorsRoot) {
|
||||
return nil, errors.Errorf("invalid genesis validators root: %s", genesis.GenesisValidatorsRoot)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,12 +6,12 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -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))
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
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"
|
||||
)
|
||||
|
||||
228
api/client/beacon/validator_api/duties.go
Normal file
228
api/client/beacon/validator_api/duties.go
Normal file
@@ -0,0 +1,228 @@
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/validator"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"golang.org/x/sync/errgroup"
|
||||
)
|
||||
|
||||
func (c *beaconApiValidatorClient) duties(ctx context.Context, in *ethpb.DutiesRequest) (*ethpb.ValidatorDutiesContainer, error) {
|
||||
vals, err := c.validatorsForDuties(ctx, in.PublicKeys)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get validators for duties")
|
||||
}
|
||||
|
||||
// Sync committees are an Altair feature
|
||||
fetchSyncDuties := in.Epoch >= params.BeaconConfig().AltairForkEpoch
|
||||
|
||||
errCh := make(chan error, 1)
|
||||
|
||||
var currentEpochDuties []*ethpb.ValidatorDuty
|
||||
go func() {
|
||||
currentEpochDuties, err = c.dutiesForEpoch(ctx, in.Epoch, vals, fetchSyncDuties)
|
||||
if err != nil {
|
||||
errCh <- errors.Wrapf(err, "failed to get duties for current epoch `%d`", in.Epoch)
|
||||
return
|
||||
}
|
||||
errCh <- nil
|
||||
}()
|
||||
|
||||
nextEpochDuties, err := c.dutiesForEpoch(ctx, in.Epoch+1, vals, fetchSyncDuties)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get duties for next epoch `%d`", in.Epoch+1)
|
||||
}
|
||||
|
||||
if err = <-errCh; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return ðpb.ValidatorDutiesContainer{
|
||||
CurrentEpochDuties: currentEpochDuties,
|
||||
NextEpochDuties: nextEpochDuties,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiValidatorClient) dutiesForEpoch(
|
||||
ctx context.Context,
|
||||
epoch primitives.Epoch,
|
||||
vals []beacon.ValidatorForDuty,
|
||||
fetchSyncDuties bool,
|
||||
) ([]*ethpb.ValidatorDuty, error) {
|
||||
indices := make([]primitives.ValidatorIndex, len(vals))
|
||||
for i, v := range vals {
|
||||
indices[i] = v.Index
|
||||
}
|
||||
|
||||
// Below variables MUST NOT be used in the main function before wg.Wait().
|
||||
// This is because they are populated in goroutines and wg.Wait()
|
||||
// will return only once all goroutines finish their execution.
|
||||
|
||||
// Mapping from a validator index to its attesting committee's index and slot
|
||||
attesterDutiesMapping := make(map[primitives.ValidatorIndex]beacon.AttesterDuty)
|
||||
// Set containing all validator indices that are part of a sync committee for this epoch
|
||||
syncDutiesMapping := make(map[primitives.ValidatorIndex]bool)
|
||||
// Mapping from a validator index to its proposal slot
|
||||
proposerDutySlots := make(map[primitives.ValidatorIndex][]primitives.Slot)
|
||||
|
||||
var wg errgroup.Group
|
||||
|
||||
wg.Go(func() error {
|
||||
attesterDuties, err := c.dutiesProvider.AttesterDuties(ctx, epoch, indices)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get attester duties for epoch `%d`", epoch)
|
||||
}
|
||||
|
||||
for _, duty := range attesterDuties {
|
||||
validatorIndex, err := strconv.ParseUint(duty.ValidatorIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse attester validator index `%s`", duty.ValidatorIndex)
|
||||
}
|
||||
slot, err := strconv.ParseUint(duty.Slot, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse attester slot `%s`", duty.Slot)
|
||||
}
|
||||
committeeIndex, err := strconv.ParseUint(duty.CommitteeIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse attester committee index `%s`", duty.CommitteeIndex)
|
||||
}
|
||||
committeeLength, err := strconv.ParseUint(duty.CommitteeLength, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse attester committee length `%s`", duty.CommitteeLength)
|
||||
}
|
||||
validatorCommitteeIndex, err := strconv.ParseUint(duty.ValidatorCommitteeIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse attester validator committee index `%s`", duty.ValidatorCommitteeIndex)
|
||||
}
|
||||
committeesAtSlot, err := strconv.ParseUint(duty.CommitteesAtSlot, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse attester committees at slot `%s`", duty.CommitteesAtSlot)
|
||||
}
|
||||
attesterDutiesMapping[primitives.ValidatorIndex(validatorIndex)] = beacon.AttesterDuty{
|
||||
Slot: primitives.Slot(slot),
|
||||
CommitteeIndex: primitives.CommitteeIndex(committeeIndex),
|
||||
CommitteeLength: committeeLength,
|
||||
ValidatorCommitteeIndex: validatorCommitteeIndex,
|
||||
CommitteesAtSlot: committeesAtSlot,
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if fetchSyncDuties {
|
||||
wg.Go(func() error {
|
||||
syncDuties, err := c.dutiesProvider.SyncDuties(ctx, epoch, indices)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get sync duties for epoch `%d`", epoch)
|
||||
}
|
||||
for _, syncDuty := range syncDuties {
|
||||
validatorIndex, err := strconv.ParseUint(syncDuty.ValidatorIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse sync validator index `%s`", syncDuty.ValidatorIndex)
|
||||
}
|
||||
syncDutiesMapping[primitives.ValidatorIndex(validatorIndex)] = true
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
wg.Go(func() error {
|
||||
proposerDuties, err := c.dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to get proposer duties for epoch `%d`", epoch)
|
||||
}
|
||||
|
||||
for _, proposerDuty := range proposerDuties {
|
||||
validatorIndex, err := strconv.ParseUint(proposerDuty.ValidatorIndex, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse proposer validator index `%s`", proposerDuty.ValidatorIndex)
|
||||
}
|
||||
slot, err := strconv.ParseUint(proposerDuty.Slot, 10, 64)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to parse proposer slot `%s`", proposerDuty.Slot)
|
||||
}
|
||||
proposerDutySlots[primitives.ValidatorIndex(validatorIndex)] =
|
||||
append(proposerDutySlots[primitives.ValidatorIndex(validatorIndex)], primitives.Slot(slot))
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err := wg.Wait(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
duties := make([]*ethpb.ValidatorDuty, len(vals))
|
||||
for i, v := range vals {
|
||||
att, ok := attesterDutiesMapping[v.Index]
|
||||
if !ok {
|
||||
log.Debugf("failed to find attester duty for validator `%d`", v.Index)
|
||||
}
|
||||
|
||||
duties[i] = ðpb.ValidatorDuty{
|
||||
ValidatorCommitteeIndex: att.ValidatorCommitteeIndex,
|
||||
CommitteeLength: att.CommitteeLength,
|
||||
CommitteeIndex: att.CommitteeIndex,
|
||||
AttesterSlot: att.Slot,
|
||||
CommitteesAtSlot: att.CommitteesAtSlot,
|
||||
ProposerSlots: proposerDutySlots[v.Index],
|
||||
PublicKey: v.Pubkey,
|
||||
Status: v.Status,
|
||||
ValidatorIndex: v.Index,
|
||||
IsSyncCommittee: syncDutiesMapping[v.Index],
|
||||
}
|
||||
}
|
||||
|
||||
return duties, nil
|
||||
}
|
||||
|
||||
func (c *beaconApiValidatorClient) validatorsForDuties(ctx context.Context, pubkeys [][]byte) ([]beacon.ValidatorForDuty, error) {
|
||||
vals := make([]beacon.ValidatorForDuty, 0, len(pubkeys))
|
||||
stringPubkeysToPubkeys := make(map[string][]byte, len(pubkeys))
|
||||
stringPubkeys := make([]string, len(pubkeys))
|
||||
|
||||
for i, pk := range pubkeys {
|
||||
stringPk := hexutil.Encode(pk)
|
||||
stringPubkeysToPubkeys[stringPk] = pk
|
||||
stringPubkeys[i] = stringPk
|
||||
}
|
||||
|
||||
statusesWithDuties := []string{validator.ActiveOngoing.String(), validator.ActiveExiting.String()}
|
||||
stateValidatorsResponse, err := c.stateValidatorsProvider.StateValidators(ctx, stringPubkeys, nil, statusesWithDuties)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to get state validators")
|
||||
}
|
||||
|
||||
for _, validatorContainer := range stateValidatorsResponse.Data {
|
||||
val := beacon.ValidatorForDuty{}
|
||||
|
||||
validatorIndex, err := strconv.ParseUint(validatorContainer.Index, 10, 64)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse validator index %s", validatorContainer.Index)
|
||||
}
|
||||
val.Index = primitives.ValidatorIndex(validatorIndex)
|
||||
|
||||
stringPubkey := validatorContainer.Validator.Pubkey
|
||||
pubkey, ok := stringPubkeysToPubkeys[stringPubkey]
|
||||
if !ok {
|
||||
return nil, errors.Wrapf(err, "returned public key %s not requested", stringPubkey)
|
||||
}
|
||||
val.Pubkey = pubkey
|
||||
|
||||
status, ok := beaconAPITogRPCValidatorStatus[validatorContainer.Status]
|
||||
if !ok {
|
||||
return nil, errors.New("invalid validator status " + validatorContainer.Status)
|
||||
}
|
||||
val.Status = status
|
||||
|
||||
vals = append(vals, val)
|
||||
}
|
||||
|
||||
return vals, nil
|
||||
}
|
||||
@@ -1,515 +1,24 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"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"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
const getAttesterDutiesTestEndpoint = "/eth/v1/validator/duties/attester"
|
||||
const getProposerDutiesTestEndpoint = "/eth/v1/validator/duties/proposer"
|
||||
const getSyncDutiesTestEndpoint = "/eth/v1/validator/duties/sync"
|
||||
const getCommitteesTestEndpoint = "/eth/v1/beacon/states/head/committees"
|
||||
|
||||
func TestGetAttesterDuties_Valid(t *testing.T) {
|
||||
stringValidatorIndices := []string{"2", "9"}
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
validatorIndicesBytes, err := json.Marshal(stringValidatorIndices)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedAttesterDuties := structs.GetAttesterDutiesResponse{
|
||||
Data: []*structs.AttesterDuty{
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{1}),
|
||||
ValidatorIndex: "2",
|
||||
CommitteeIndex: "3",
|
||||
CommitteeLength: "4",
|
||||
CommitteesAtSlot: "5",
|
||||
ValidatorCommitteeIndex: "6",
|
||||
Slot: "7",
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{8}),
|
||||
ValidatorIndex: "9",
|
||||
CommitteeIndex: "10",
|
||||
CommitteeLength: "11",
|
||||
CommitteesAtSlot: "12",
|
||||
ValidatorCommitteeIndex: "13",
|
||||
Slot: "14",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
validatorIndices := []primitives.ValidatorIndex{2, 9}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getAttesterDutiesTestEndpoint, epoch),
|
||||
nil,
|
||||
bytes.NewBuffer(validatorIndicesBytes),
|
||||
&structs.GetAttesterDutiesResponse{},
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
expectedAttesterDuties,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
attesterDuties, err := dutiesProvider.AttesterDuties(ctx, epoch, validatorIndices)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedAttesterDuties.Data, attesterDuties)
|
||||
}
|
||||
|
||||
func TestGetAttesterDuties_HttpError(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getAttesterDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.AttesterDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func TestGetAttesterDuties_NilAttesterDuty(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getAttesterDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
structs.GetAttesterDutiesResponse{
|
||||
Data: []*structs.AttesterDuty{nil},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.AttesterDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "attester duty at index `0` is nil", err)
|
||||
}
|
||||
|
||||
func TestGetProposerDuties_Valid(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
expectedProposerDuties := structs.GetProposerDutiesResponse{
|
||||
Data: []*structs.ProposerDuty{
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{1}),
|
||||
ValidatorIndex: "2",
|
||||
Slot: "3",
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{4}),
|
||||
ValidatorIndex: "5",
|
||||
Slot: "6",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
|
||||
&structs.GetProposerDutiesResponse{},
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
expectedProposerDuties,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
proposerDuties, err := dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedProposerDuties.Data, proposerDuties)
|
||||
}
|
||||
|
||||
func TestGetProposerDuties_HttpError(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func TestGetProposerDuties_NilData(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetProposerDutiesResponse{
|
||||
Data: nil,
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
assert.ErrorContains(t, "proposer duties data is nil", err)
|
||||
}
|
||||
|
||||
func TestGetProposerDuties_NilProposerDuty(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetProposerDutiesResponse{
|
||||
Data: []*structs.ProposerDuty{nil},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.ProposerDuties(ctx, epoch)
|
||||
assert.ErrorContains(t, "proposer duty at index `0` is nil", err)
|
||||
}
|
||||
|
||||
func TestGetSyncDuties_Valid(t *testing.T) {
|
||||
stringValidatorIndices := []string{"2", "6"}
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
validatorIndicesBytes, err := json.Marshal(stringValidatorIndices)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedSyncDuties := structs.GetSyncCommitteeDutiesResponse{
|
||||
Data: []*structs.SyncCommitteeDuty{
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{1}),
|
||||
ValidatorIndex: "2",
|
||||
ValidatorSyncCommitteeIndices: []string{
|
||||
"3",
|
||||
"4",
|
||||
},
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode([]byte{5}),
|
||||
ValidatorIndex: "6",
|
||||
ValidatorSyncCommitteeIndices: []string{
|
||||
"7",
|
||||
"8",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
validatorIndices := []primitives.ValidatorIndex{2, 6}
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
|
||||
nil,
|
||||
bytes.NewBuffer(validatorIndicesBytes),
|
||||
&structs.GetSyncCommitteeDutiesResponse{},
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
expectedSyncDuties,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
syncDuties, err := dutiesProvider.SyncDuties(ctx, epoch, validatorIndices)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedSyncDuties.Data, syncDuties)
|
||||
}
|
||||
|
||||
func TestGetSyncDuties_HttpError(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.SyncDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func TestGetSyncDuties_NilData(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
structs.GetSyncCommitteeDutiesResponse{
|
||||
Data: nil,
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.SyncDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "sync duties data is nil", err)
|
||||
}
|
||||
|
||||
func TestGetSyncDuties_NilSyncDuty(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
4,
|
||||
structs.GetSyncCommitteeDutiesResponse{
|
||||
Data: []*structs.SyncCommitteeDuty{nil},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.SyncDuties(ctx, epoch, nil)
|
||||
assert.ErrorContains(t, "sync duty at index `0` is nil", err)
|
||||
}
|
||||
|
||||
func TestGetCommittees_Valid(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
expectedCommittees := structs.GetCommitteesResponse{
|
||||
Data: []*structs.Committee{
|
||||
{
|
||||
Index: "1",
|
||||
Slot: "2",
|
||||
Validators: []string{
|
||||
"3",
|
||||
"4",
|
||||
},
|
||||
},
|
||||
{
|
||||
Index: "5",
|
||||
Slot: "6",
|
||||
Validators: []string{
|
||||
"7",
|
||||
"8",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
|
||||
&structs.GetCommitteesResponse{},
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
expectedCommittees,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
committees, err := dutiesProvider.Committees(ctx, epoch)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedCommittees.Data, committees)
|
||||
}
|
||||
|
||||
func TestGetCommittees_HttpError(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.Committees(ctx, epoch)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func TestGetCommittees_NilData(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetCommitteesResponse{
|
||||
Data: nil,
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.Committees(ctx, epoch)
|
||||
assert.ErrorContains(t, "state committees data is nil", err)
|
||||
}
|
||||
|
||||
func TestGetCommittees_NilCommittee(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
ctx := context.Background()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
|
||||
gomock.Any(),
|
||||
).Return(
|
||||
nil,
|
||||
).SetArg(
|
||||
2,
|
||||
structs.GetCommitteesResponse{
|
||||
Data: []*structs.Committee{nil},
|
||||
},
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
|
||||
_, err := dutiesProvider.Committees(ctx, epoch)
|
||||
assert.ErrorContains(t, "committee at index `0` is nil", err)
|
||||
}
|
||||
|
||||
func TestGetDutiesForEpoch_Error(t *testing.T) {
|
||||
const epoch = primitives.Epoch(1)
|
||||
pubkeys := [][]byte{{1}, {2}, {3}, {4}, {5}, {6}, {7}, {8}, {9}, {10}, {11}, {12}}
|
||||
@@ -527,8 +36,6 @@ func TestGetDutiesForEpoch_Error(t *testing.T) {
|
||||
fetchProposerDutiesError error
|
||||
generateSyncDuties func() []*structs.SyncCommitteeDuty
|
||||
fetchSyncDutiesError error
|
||||
generateCommittees func() []*structs.Committee
|
||||
fetchCommitteesError error
|
||||
}{
|
||||
{
|
||||
name: "get attester duties failed",
|
||||
@@ -545,11 +52,6 @@ func TestGetDutiesForEpoch_Error(t *testing.T) {
|
||||
expectedError: "failed to get sync duties for epoch `1`: foo error",
|
||||
fetchSyncDutiesError: errors.New("foo error"),
|
||||
},
|
||||
{
|
||||
name: "get committees failed",
|
||||
expectedError: "failed to get committees for epoch `1`: foo error",
|
||||
fetchCommitteesError: errors.New("foo error"),
|
||||
},
|
||||
{
|
||||
name: "bad attester validator index",
|
||||
expectedError: "failed to parse attester validator index `foo`",
|
||||
@@ -604,46 +106,6 @@ func TestGetDutiesForEpoch_Error(t *testing.T) {
|
||||
return syncDuties
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bad committee index",
|
||||
expectedError: "failed to parse committee index `foo`",
|
||||
generateCommittees: func() []*structs.Committee {
|
||||
committees := generateValidCommittees(committeeIndices, committeeSlots, validatorIndices)
|
||||
committees[0].Index = "foo"
|
||||
return committees
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bad committee slot",
|
||||
expectedError: "failed to parse slot `foo`",
|
||||
generateCommittees: func() []*structs.Committee {
|
||||
committees := generateValidCommittees(committeeIndices, committeeSlots, validatorIndices)
|
||||
committees[0].Slot = "foo"
|
||||
return committees
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "bad committee validator index",
|
||||
expectedError: "failed to parse committee validator index `foo`",
|
||||
generateCommittees: func() []*structs.Committee {
|
||||
committees := generateValidCommittees(committeeIndices, committeeSlots, validatorIndices)
|
||||
committees[0].Validators[0] = "foo"
|
||||
return committees
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "committee index and slot not found in committees mapping",
|
||||
expectedError: "failed to find validators for committee index `1` and slot `2`",
|
||||
generateAttesterDuties: func() []*structs.AttesterDuty {
|
||||
attesterDuties := generateValidAttesterDuties(pubkeys, validatorIndices, committeeIndices, committeeSlots)
|
||||
attesterDuties[0].CommitteeIndex = "1"
|
||||
attesterDuties[0].Slot = "2"
|
||||
return attesterDuties
|
||||
},
|
||||
generateCommittees: func() []*structs.Committee {
|
||||
return []*structs.Committee{}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, testCase := range testCases {
|
||||
@@ -674,13 +136,6 @@ func TestGetDutiesForEpoch_Error(t *testing.T) {
|
||||
syncDuties = testCase.generateSyncDuties()
|
||||
}
|
||||
|
||||
var committees []*structs.Committee
|
||||
if testCase.generateCommittees == nil {
|
||||
committees = generateValidCommittees(committeeIndices, committeeSlots, validatorIndices)
|
||||
} else {
|
||||
committees = testCase.generateCommittees()
|
||||
}
|
||||
|
||||
dutiesProvider := mock.NewMockdutiesProvider(ctrl)
|
||||
dutiesProvider.EXPECT().AttesterDuties(
|
||||
ctx,
|
||||
@@ -708,20 +163,12 @@ func TestGetDutiesForEpoch_Error(t *testing.T) {
|
||||
testCase.fetchSyncDutiesError,
|
||||
).AnyTimes()
|
||||
|
||||
dutiesProvider.EXPECT().Committees(
|
||||
ctx,
|
||||
epoch,
|
||||
).Return(
|
||||
committees,
|
||||
testCase.fetchCommitteesError,
|
||||
).AnyTimes()
|
||||
|
||||
vals := make([]validatorForDuty, len(pubkeys))
|
||||
vals := make([]beacon.ValidatorForDuty, len(pubkeys))
|
||||
for i := 0; i < len(pubkeys); i++ {
|
||||
vals[i] = validatorForDuty{
|
||||
pubkey: pubkeys[i],
|
||||
index: validatorIndices[i],
|
||||
status: ethpb.ValidatorStatus_ACTIVE,
|
||||
vals[i] = beacon.ValidatorForDuty{
|
||||
Pubkey: pubkeys[i],
|
||||
Index: validatorIndices[i],
|
||||
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -767,13 +214,6 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
dutiesProvider := mock.NewMockdutiesProvider(ctrl)
|
||||
dutiesProvider.EXPECT().Committees(
|
||||
ctx,
|
||||
epoch,
|
||||
).Return(
|
||||
generateValidCommittees(committeeIndices, committeeSlots, validatorIndices),
|
||||
nil,
|
||||
).Times(1)
|
||||
|
||||
dutiesProvider.EXPECT().AttesterDuties(
|
||||
ctx,
|
||||
@@ -943,12 +383,12 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
||||
}
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{dutiesProvider: dutiesProvider}
|
||||
vals := make([]validatorForDuty, len(pubkeys))
|
||||
vals := make([]beacon.ValidatorForDuty, len(pubkeys))
|
||||
for i := 0; i < len(pubkeys); i++ {
|
||||
vals[i] = validatorForDuty{
|
||||
pubkey: pubkeys[i],
|
||||
index: validatorIndices[i],
|
||||
status: ethpb.ValidatorStatus_ACTIVE,
|
||||
vals[i] = beacon.ValidatorForDuty{
|
||||
Pubkey: pubkeys[i],
|
||||
Index: validatorIndices[i],
|
||||
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||
}
|
||||
}
|
||||
duties, err := validatorClient.dutiesForEpoch(
|
||||
@@ -958,7 +398,14 @@ func TestGetDutiesForEpoch_Valid(t *testing.T) {
|
||||
testCase.fetchSyncDuties,
|
||||
)
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedDuties, duties)
|
||||
require.Equal(t, len(expectedDuties), len(duties))
|
||||
for i, duty := range expectedDuties {
|
||||
assert.Equal(t, duty.CommitteeIndex, duties[i].CommitteeIndex)
|
||||
assert.DeepEqual(t, duty.ProposerSlots, duties[i].ProposerSlots)
|
||||
assert.Equal(t, duty.ValidatorIndex, duties[i].ValidatorIndex)
|
||||
assert.Equal(t, duty.IsSyncCommittee, duties[i].IsSyncCommittee)
|
||||
assert.Equal(t, duty.Status, duties[i].Status)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -983,14 +430,14 @@ func TestGetDuties_Valid(t *testing.T) {
|
||||
valCount := 12
|
||||
pubkeys := make([][]byte, valCount)
|
||||
validatorIndices := make([]primitives.ValidatorIndex, valCount)
|
||||
vals := make([]validatorForDuty, valCount)
|
||||
vals := make([]beacon.ValidatorForDuty, valCount)
|
||||
for i := 0; i < valCount; i++ {
|
||||
pubkeys[i] = []byte(strconv.Itoa(i))
|
||||
validatorIndices[i] = primitives.ValidatorIndex(i)
|
||||
vals[i] = validatorForDuty{
|
||||
pubkey: pubkeys[i],
|
||||
index: validatorIndices[i],
|
||||
status: ethpb.ValidatorStatus_ACTIVE,
|
||||
vals[i] = beacon.ValidatorForDuty{
|
||||
Pubkey: pubkeys[i],
|
||||
Index: validatorIndices[i],
|
||||
Status: ethpb.ValidatorStatus_ACTIVE,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1004,13 +451,6 @@ func TestGetDuties_Valid(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
|
||||
dutiesProvider := mock.NewMockdutiesProvider(ctrl)
|
||||
dutiesProvider.EXPECT().Committees(
|
||||
ctx,
|
||||
testCase.epoch,
|
||||
).Return(
|
||||
generateValidCommittees(committeeIndices, committeeSlots, validatorIndices),
|
||||
nil,
|
||||
).Times(2)
|
||||
|
||||
dutiesProvider.EXPECT().AttesterDuties(
|
||||
ctx,
|
||||
@@ -1041,14 +481,6 @@ func TestGetDuties_Valid(t *testing.T) {
|
||||
).Times(2)
|
||||
}
|
||||
|
||||
dutiesProvider.EXPECT().Committees(
|
||||
ctx,
|
||||
testCase.epoch+1,
|
||||
).Return(
|
||||
reverseSlice(generateValidCommittees(committeeIndices, committeeSlots, validatorIndices)),
|
||||
nil,
|
||||
).Times(2)
|
||||
|
||||
dutiesProvider.EXPECT().AttesterDuties(
|
||||
ctx,
|
||||
testCase.epoch+1,
|
||||
@@ -1209,7 +641,7 @@ func TestGetDuties_Valid(t *testing.T) {
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
expectedDuties := ðpb.DutiesResponse{
|
||||
expectedDuties := ðpb.ValidatorDutiesContainer{
|
||||
CurrentEpochDuties: expectedCurrentEpochDuties,
|
||||
NextEpochDuties: expectedNextEpochDuties,
|
||||
}
|
||||
@@ -1298,10 +730,6 @@ func TestGetDuties_GetDutiesForEpochFailed(t *testing.T) {
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
).Times(2)
|
||||
dutiesProvider.EXPECT().Committees(
|
||||
ctx,
|
||||
gomock.Any(),
|
||||
).Times(2)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{
|
||||
stateValidatorsProvider: stateValidatorsProvider,
|
||||
@@ -1316,72 +744,61 @@ func TestGetDuties_GetDutiesForEpochFailed(t *testing.T) {
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
func generateValidCommittees(committeeIndices []primitives.CommitteeIndex, slots []primitives.Slot, validatorIndices []primitives.ValidatorIndex) []*structs.Committee {
|
||||
return []*structs.Committee{
|
||||
{
|
||||
Index: strconv.FormatUint(uint64(committeeIndices[0]), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[0]), 10),
|
||||
Validators: []string{
|
||||
strconv.FormatUint(uint64(validatorIndices[0]), 10),
|
||||
strconv.FormatUint(uint64(validatorIndices[1]), 10),
|
||||
},
|
||||
},
|
||||
{
|
||||
Index: strconv.FormatUint(uint64(committeeIndices[1]), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[1]), 10),
|
||||
Validators: []string{
|
||||
strconv.FormatUint(uint64(validatorIndices[2]), 10),
|
||||
strconv.FormatUint(uint64(validatorIndices[3]), 10),
|
||||
},
|
||||
},
|
||||
{
|
||||
Index: strconv.FormatUint(uint64(committeeIndices[2]), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[2]), 10),
|
||||
Validators: []string{
|
||||
strconv.FormatUint(uint64(validatorIndices[4]), 10),
|
||||
strconv.FormatUint(uint64(validatorIndices[5]), 10),
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func generateValidAttesterDuties(pubkeys [][]byte, validatorIndices []primitives.ValidatorIndex, committeeIndices []primitives.CommitteeIndex, slots []primitives.Slot) []*structs.AttesterDuty {
|
||||
return []*structs.AttesterDuty{
|
||||
{
|
||||
Pubkey: hexutil.Encode(pubkeys[0]),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(validatorIndices[0]), 10),
|
||||
CommitteeIndex: strconv.FormatUint(uint64(committeeIndices[0]), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[0]), 10),
|
||||
Pubkey: hexutil.Encode(pubkeys[0]),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(validatorIndices[0]), 10),
|
||||
CommitteeIndex: strconv.FormatUint(uint64(committeeIndices[0]), 10),
|
||||
CommitteeLength: fmt.Sprintf("%d", len(committeeIndices)),
|
||||
ValidatorCommitteeIndex: strconv.FormatUint(uint64(0), 10),
|
||||
CommitteesAtSlot: strconv.FormatUint(uint64(10), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[0]), 10),
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode(pubkeys[1]),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(validatorIndices[1]), 10),
|
||||
CommitteeIndex: strconv.FormatUint(uint64(committeeIndices[0]), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[0]), 10),
|
||||
Pubkey: hexutil.Encode(pubkeys[1]),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(validatorIndices[1]), 10),
|
||||
CommitteeIndex: strconv.FormatUint(uint64(committeeIndices[0]), 10),
|
||||
CommitteeLength: fmt.Sprintf("%d", len(committeeIndices)),
|
||||
ValidatorCommitteeIndex: strconv.FormatUint(uint64(0), 10),
|
||||
CommitteesAtSlot: strconv.FormatUint(uint64(10), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[0]), 10),
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode(pubkeys[2]),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(validatorIndices[2]), 10),
|
||||
CommitteeIndex: strconv.FormatUint(uint64(committeeIndices[1]), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[1]), 10),
|
||||
Pubkey: hexutil.Encode(pubkeys[2]),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(validatorIndices[2]), 10),
|
||||
CommitteeIndex: strconv.FormatUint(uint64(committeeIndices[1]), 10),
|
||||
CommitteeLength: fmt.Sprintf("%d", len(committeeIndices)),
|
||||
ValidatorCommitteeIndex: strconv.FormatUint(uint64(0), 10),
|
||||
CommitteesAtSlot: strconv.FormatUint(uint64(10), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[1]), 10),
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode(pubkeys[3]),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(validatorIndices[3]), 10),
|
||||
CommitteeIndex: strconv.FormatUint(uint64(committeeIndices[1]), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[1]), 10),
|
||||
Pubkey: hexutil.Encode(pubkeys[3]),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(validatorIndices[3]), 10),
|
||||
CommitteeIndex: strconv.FormatUint(uint64(committeeIndices[1]), 10),
|
||||
CommitteeLength: fmt.Sprintf("%d", len(committeeIndices)),
|
||||
ValidatorCommitteeIndex: strconv.FormatUint(uint64(0), 10),
|
||||
CommitteesAtSlot: strconv.FormatUint(uint64(10), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[1]), 10),
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode(pubkeys[4]),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(validatorIndices[4]), 10),
|
||||
CommitteeIndex: strconv.FormatUint(uint64(committeeIndices[2]), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[2]), 10),
|
||||
Pubkey: hexutil.Encode(pubkeys[4]),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(validatorIndices[4]), 10),
|
||||
CommitteeIndex: strconv.FormatUint(uint64(committeeIndices[2]), 10),
|
||||
CommitteeLength: fmt.Sprintf("%d", len(committeeIndices)),
|
||||
ValidatorCommitteeIndex: strconv.FormatUint(uint64(0), 10),
|
||||
CommitteesAtSlot: strconv.FormatUint(uint64(10), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[2]), 10),
|
||||
},
|
||||
{
|
||||
Pubkey: hexutil.Encode(pubkeys[5]),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(validatorIndices[5]), 10),
|
||||
CommitteeIndex: strconv.FormatUint(uint64(committeeIndices[2]), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[2]), 10),
|
||||
Pubkey: hexutil.Encode(pubkeys[5]),
|
||||
ValidatorIndex: strconv.FormatUint(uint64(validatorIndices[5]), 10),
|
||||
CommitteeIndex: strconv.FormatUint(uint64(committeeIndices[2]), 10),
|
||||
CommitteeLength: fmt.Sprintf("%d", len(committeeIndices)),
|
||||
ValidatorCommitteeIndex: strconv.FormatUint(uint64(0), 10),
|
||||
CommitteesAtSlot: strconv.FormatUint(uint64(10), 10),
|
||||
Slot: strconv.FormatUint(uint64(slots[2]), 10),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/network/httputil"
|
||||
@@ -35,7 +36,7 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti
|
||||
|
||||
// Try v3 endpoint first. If it's not supported, then we fall back to older endpoints.
|
||||
// We try the blinded block endpoint first. If it fails, we assume that we got a full block and try the full block endpoint.
|
||||
queryUrl := buildURL(fmt.Sprintf("/eth/v3/validator/blocks/%d", slot), queryParams)
|
||||
queryUrl := apiutil.BuildURL(fmt.Sprintf("/eth/v3/validator/blocks/%d", slot), queryParams)
|
||||
produceBlockV3ResponseJson := structs.ProduceBlockV3Response{}
|
||||
err := c.jsonRestHandler.Get(ctx, queryUrl, &produceBlockV3ResponseJson)
|
||||
errJson := &httputil.DefaultJsonError{}
|
||||
@@ -221,7 +222,7 @@ func (c *beaconApiValidatorClient) fallBackToBlinded(
|
||||
queryParams neturl.Values,
|
||||
) (*abstractProduceBlockResponseJson, error) {
|
||||
resp := &abstractProduceBlockResponseJson{}
|
||||
url := buildURL(fmt.Sprintf("/eth/v1/validator/blinded_blocks/%d", slot), queryParams)
|
||||
url := apiutil.BuildURL(fmt.Sprintf("/eth/v1/validator/blinded_blocks/%d", slot), queryParams)
|
||||
if err := c.jsonRestHandler.Get(ctx, url, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -234,7 +235,7 @@ func (c *beaconApiValidatorClient) fallBackToFull(
|
||||
queryParams neturl.Values,
|
||||
) (*abstractProduceBlockResponseJson, error) {
|
||||
resp := &abstractProduceBlockResponseJson{}
|
||||
url := buildURL(fmt.Sprintf("/eth/v2/validator/blocks/%d", slot), queryParams)
|
||||
url := apiutil.BuildURL(fmt.Sprintf("/eth/v2/validator/blocks/%d", slot), queryParams)
|
||||
if err := c.jsonRestHandler.Get(ctx, url, resp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -9,14 +9,14 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/validator_api/test_helpers"
|
||||
"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"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
testhelpers "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/test-helpers"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -149,8 +149,8 @@ func TestGetBeaconBlock_Phase0Valid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := testhelpers.GenerateProtoPhase0BeaconBlock()
|
||||
block := testhelpers.GenerateJsonPhase0BeaconBlock()
|
||||
proto := test_helpers.GenerateProtoPhase0BeaconBlock()
|
||||
block := test_helpers.GenerateJsonPhase0BeaconBlock()
|
||||
bytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -191,8 +191,8 @@ func TestGetBeaconBlock_AltairValid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := testhelpers.GenerateProtoAltairBeaconBlock()
|
||||
block := testhelpers.GenerateJsonAltairBeaconBlock()
|
||||
proto := test_helpers.GenerateProtoAltairBeaconBlock()
|
||||
block := test_helpers.GenerateJsonAltairBeaconBlock()
|
||||
bytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -234,8 +234,8 @@ func TestGetBeaconBlock_BellatrixValid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := testhelpers.GenerateProtoBellatrixBeaconBlock()
|
||||
block := testhelpers.GenerateJsonBellatrixBeaconBlock()
|
||||
proto := test_helpers.GenerateProtoBellatrixBeaconBlock()
|
||||
block := test_helpers.GenerateJsonBellatrixBeaconBlock()
|
||||
bytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -279,8 +279,8 @@ func TestGetBeaconBlock_BlindedBellatrixValid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := testhelpers.GenerateProtoBlindedBellatrixBeaconBlock()
|
||||
block := testhelpers.GenerateJsonBlindedBellatrixBeaconBlock()
|
||||
proto := test_helpers.GenerateProtoBlindedBellatrixBeaconBlock()
|
||||
block := test_helpers.GenerateJsonBlindedBellatrixBeaconBlock()
|
||||
bytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -324,8 +324,8 @@ func TestGetBeaconBlock_CapellaValid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := testhelpers.GenerateProtoCapellaBeaconBlock()
|
||||
block := testhelpers.GenerateJsonCapellaBeaconBlock()
|
||||
proto := test_helpers.GenerateProtoCapellaBeaconBlock()
|
||||
block := test_helpers.GenerateJsonCapellaBeaconBlock()
|
||||
bytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -369,8 +369,8 @@ func TestGetBeaconBlock_BlindedCapellaValid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := testhelpers.GenerateProtoBlindedCapellaBeaconBlock()
|
||||
block := testhelpers.GenerateJsonBlindedCapellaBeaconBlock()
|
||||
proto := test_helpers.GenerateProtoBlindedCapellaBeaconBlock()
|
||||
block := test_helpers.GenerateJsonBlindedCapellaBeaconBlock()
|
||||
bytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -414,8 +414,8 @@ func TestGetBeaconBlock_DenebValid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := testhelpers.GenerateProtoDenebBeaconBlockContents()
|
||||
block := testhelpers.GenerateJsonDenebBeaconBlockContents()
|
||||
proto := test_helpers.GenerateProtoDenebBeaconBlockContents()
|
||||
block := test_helpers.GenerateJsonDenebBeaconBlockContents()
|
||||
bytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -459,8 +459,8 @@ func TestGetBeaconBlock_BlindedDenebValid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := testhelpers.GenerateProtoBlindedDenebBeaconBlock()
|
||||
block := testhelpers.GenerateJsonBlindedDenebBeaconBlock()
|
||||
proto := test_helpers.GenerateProtoBlindedDenebBeaconBlock()
|
||||
block := test_helpers.GenerateJsonBlindedDenebBeaconBlock()
|
||||
bytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -504,8 +504,8 @@ func TestGetBeaconBlock_ElectraValid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := testhelpers.GenerateProtoElectraBeaconBlockContents()
|
||||
block := testhelpers.GenerateJsonElectraBeaconBlockContents()
|
||||
proto := test_helpers.GenerateProtoElectraBeaconBlockContents()
|
||||
block := test_helpers.GenerateJsonElectraBeaconBlockContents()
|
||||
bytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -549,8 +549,8 @@ func TestGetBeaconBlock_BlindedElectraValid(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := testhelpers.GenerateProtoBlindedElectraBeaconBlock()
|
||||
block := testhelpers.GenerateJsonBlindedElectraBeaconBlock()
|
||||
proto := test_helpers.GenerateProtoBlindedElectraBeaconBlock()
|
||||
block := test_helpers.GenerateJsonBlindedElectraBeaconBlock()
|
||||
bytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -594,8 +594,8 @@ func TestGetBeaconBlock_FallbackToBlindedBlock(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := testhelpers.GenerateProtoBlindedDenebBeaconBlock()
|
||||
block := testhelpers.GenerateJsonBlindedDenebBeaconBlock()
|
||||
proto := test_helpers.GenerateProtoBlindedDenebBeaconBlock()
|
||||
block := test_helpers.GenerateJsonBlindedDenebBeaconBlock()
|
||||
blockBytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -645,8 +645,8 @@ func TestGetBeaconBlock_FallbackToFullBlock(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
|
||||
proto := testhelpers.GenerateProtoDenebBeaconBlockContents()
|
||||
block := testhelpers.GenerateJsonDenebBeaconBlockContents()
|
||||
proto := test_helpers.GenerateProtoDenebBeaconBlockContents()
|
||||
block := test_helpers.GenerateJsonDenebBeaconBlockContents()
|
||||
blockBytes, err := json.Marshal(block)
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package grpc_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,13 +8,13 @@ import (
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
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/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"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
@@ -23,8 +23,59 @@ type grpcValidatorClient struct {
|
||||
isEventStreamRunning bool
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) Duties(ctx context.Context, in *ethpb.DutiesRequest) (*ethpb.DutiesResponse, error) {
|
||||
return c.beaconNodeValidatorClient.GetDuties(ctx, in)
|
||||
func (c *grpcValidatorClient) Duties(ctx context.Context, in *ethpb.DutiesRequest) (*ethpb.ValidatorDutiesContainer, error) {
|
||||
dutiesResponse, err := c.beaconNodeValidatorClient.GetDuties(ctx, in)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return toValidatorDutiesContainer(dutiesResponse)
|
||||
}
|
||||
|
||||
func toValidatorDutiesContainer(dutiesResponse *ethpb.DutiesResponse) (*ethpb.ValidatorDutiesContainer, error) {
|
||||
currentDuties := make([]*ethpb.ValidatorDuty, len(dutiesResponse.CurrentEpochDuties))
|
||||
for i, cd := range dutiesResponse.CurrentEpochDuties {
|
||||
duty, err := toValidatorDuty(cd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
currentDuties[i] = duty
|
||||
}
|
||||
nextDuties := make([]*ethpb.ValidatorDuty, len(dutiesResponse.NextEpochDuties))
|
||||
for i, nd := range dutiesResponse.NextEpochDuties {
|
||||
duty, err := toValidatorDuty(nd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
nextDuties[i] = duty
|
||||
}
|
||||
return ðpb.ValidatorDutiesContainer{
|
||||
CurrentEpochDuties: currentDuties,
|
||||
NextEpochDuties: nextDuties,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func toValidatorDuty(duty *ethpb.DutiesResponse_Duty) (*ethpb.ValidatorDuty, error) {
|
||||
var valIndexInCommittee uint64
|
||||
// valIndexInCommittee will be 0 in case we don't get a match. This is a potential false positive,
|
||||
// however it's an impossible condition because every validator must be assigned to a committee.
|
||||
for cIndex, vIndex := range duty.Committee {
|
||||
if vIndex == duty.ValidatorIndex {
|
||||
valIndexInCommittee = uint64(cIndex)
|
||||
break
|
||||
}
|
||||
}
|
||||
return ðpb.ValidatorDuty{
|
||||
CommitteeLength: uint64(len(duty.Committee)),
|
||||
CommitteeIndex: duty.CommitteeIndex,
|
||||
CommitteesAtSlot: duty.CommitteesAtSlot, // GRPC doesn't use this value though
|
||||
ValidatorCommitteeIndex: valIndexInCommittee,
|
||||
AttesterSlot: duty.AttesterSlot,
|
||||
ProposerSlots: duty.ProposerSlots,
|
||||
PublicKey: bytesutil.SafeCopyBytes(duty.PublicKey),
|
||||
Status: duty.Status,
|
||||
ValidatorIndex: duty.ValidatorIndex,
|
||||
IsSyncCommittee: duty.IsSyncCommittee,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) CheckDoppelGanger(ctx context.Context, in *ethpb.DoppelGangerRequest) (*ethpb.DoppelGangerResponse, error) {
|
||||
@@ -115,7 +166,7 @@ func (c *grpcValidatorClient) SubmitValidatorRegistrations(ctx context.Context,
|
||||
return c.beaconNodeValidatorClient.SubmitValidatorRegistrations(ctx, in)
|
||||
}
|
||||
|
||||
func (c *grpcValidatorClient) SubscribeCommitteeSubnets(ctx context.Context, in *ethpb.CommitteeSubnetsSubscribeRequest, _ []*ethpb.DutiesResponse_Duty) (*empty.Empty, error) {
|
||||
func (c *grpcValidatorClient) SubscribeCommitteeSubnets(ctx context.Context, in *ethpb.CommitteeSubnetsSubscribeRequest, _ []*ethpb.ValidatorDuty) (*empty.Empty, error) {
|
||||
return c.beaconNodeValidatorClient.SubscribeCommitteeSubnets(ctx, in)
|
||||
}
|
||||
|
||||
@@ -150,15 +201,15 @@ func (c *grpcValidatorClient) AggregatedSigAndAggregationBits(
|
||||
return c.beaconNodeValidatorClient.AggregatedSigAndAggregationBits(ctx, in)
|
||||
}
|
||||
|
||||
func (*grpcValidatorClient) AggregatedSelections(context.Context, []iface.BeaconCommitteeSelection) ([]iface.BeaconCommitteeSelection, error) {
|
||||
return nil, iface.ErrNotSupported
|
||||
func (*grpcValidatorClient) AggregatedSelections(context.Context, []beacon.BeaconCommitteeSelection) ([]beacon.BeaconCommitteeSelection, error) {
|
||||
return nil, client.ErrNotSupported
|
||||
}
|
||||
|
||||
func (*grpcValidatorClient) AggregatedSyncSelections(context.Context, []iface.SyncCommitteeSelection) ([]iface.SyncCommitteeSelection, error) {
|
||||
return nil, iface.ErrNotSupported
|
||||
func (*grpcValidatorClient) AggregatedSyncSelections(context.Context, []beacon.SyncCommitteeSelection) ([]beacon.SyncCommitteeSelection, error) {
|
||||
return nil, client.ErrNotSupported
|
||||
}
|
||||
|
||||
func NewGrpcValidatorClient(cc grpc.ClientConnInterface) iface.ValidatorClient {
|
||||
func NewGrpcValidatorClient(cc grpc.ClientConnInterface) Client {
|
||||
return &grpcValidatorClient{ethpb.NewBeaconNodeValidatorClient(cc), false}
|
||||
}
|
||||
|
||||
@@ -255,10 +306,10 @@ func (c *grpcValidatorClient) EventStreamIsRunning() bool {
|
||||
}
|
||||
|
||||
func (*grpcValidatorClient) Host() string {
|
||||
log.Warn(iface.ErrNotSupported)
|
||||
log.Warn(client.ErrNotSupported)
|
||||
return ""
|
||||
}
|
||||
|
||||
func (*grpcValidatorClient) SetHost(_ string) {
|
||||
log.Warn(iface.ErrNotSupported)
|
||||
log.Warn(client.ErrNotSupported)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package grpc_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -9,6 +9,7 @@ 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"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
mock2 "github.com/prysmaticlabs/prysm/v5/testing/mock"
|
||||
@@ -18,6 +19,58 @@ import (
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
// toValidatorDutiesContainer is assumed to be available from your package, returning a *v1alpha1.ValidatorDutiesContainer.
|
||||
func TestToValidatorDutiesContainer_HappyPath(t *testing.T) {
|
||||
// Create a mock DutiesResponse with current and next duties.
|
||||
dutiesResp := ð.DutiesResponse{
|
||||
CurrentEpochDuties: []*eth.DutiesResponse_Duty{
|
||||
{
|
||||
Committee: []primitives.ValidatorIndex{100, 101},
|
||||
CommitteeIndex: 4,
|
||||
AttesterSlot: 200,
|
||||
ProposerSlots: []primitives.Slot{400},
|
||||
PublicKey: []byte{0xAA, 0xBB},
|
||||
Status: eth.ValidatorStatus_ACTIVE,
|
||||
ValidatorIndex: 101,
|
||||
IsSyncCommittee: false,
|
||||
CommitteesAtSlot: 2,
|
||||
},
|
||||
},
|
||||
NextEpochDuties: []*eth.DutiesResponse_Duty{
|
||||
{
|
||||
Committee: []primitives.ValidatorIndex{300, 301},
|
||||
CommitteeIndex: 8,
|
||||
AttesterSlot: 600,
|
||||
ProposerSlots: []primitives.Slot{700, 701},
|
||||
PublicKey: []byte{0xCC, 0xDD},
|
||||
Status: eth.ValidatorStatus_ACTIVE,
|
||||
ValidatorIndex: 301,
|
||||
IsSyncCommittee: true,
|
||||
CommitteesAtSlot: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
gotContainer, err := toValidatorDutiesContainer(dutiesResp)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Validate we have the correct number of duties in current and next epochs.
|
||||
assert.Equal(t, len(gotContainer.CurrentEpochDuties), len(dutiesResp.CurrentEpochDuties))
|
||||
assert.Equal(t, len(gotContainer.NextEpochDuties), len(dutiesResp.NextEpochDuties))
|
||||
|
||||
firstCurrentDuty := gotContainer.CurrentEpochDuties[0]
|
||||
expectedCurrentDuty := dutiesResp.CurrentEpochDuties[0]
|
||||
assert.DeepEqual(t, firstCurrentDuty.PublicKey, expectedCurrentDuty.PublicKey)
|
||||
assert.Equal(t, firstCurrentDuty.ValidatorIndex, expectedCurrentDuty.ValidatorIndex)
|
||||
assert.DeepEqual(t, firstCurrentDuty.ProposerSlots, expectedCurrentDuty.ProposerSlots)
|
||||
|
||||
firstNextDuty := gotContainer.NextEpochDuties[0]
|
||||
expectedNextDuty := dutiesResp.NextEpochDuties[0]
|
||||
assert.DeepEqual(t, firstNextDuty.PublicKey, expectedNextDuty.PublicKey)
|
||||
assert.Equal(t, firstNextDuty.ValidatorIndex, expectedNextDuty.ValidatorIndex)
|
||||
assert.DeepEqual(t, firstNextDuty.ProposerSlots, expectedNextDuty.ProposerSlots)
|
||||
}
|
||||
|
||||
func TestWaitForChainStart_StreamSetupFails(t *testing.T) {
|
||||
ctrl := gomock.NewController(t)
|
||||
defer ctrl.Finish()
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -9,12 +9,14 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/shared_providers"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"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"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -67,9 +69,7 @@ func TestIndex_Nominal(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: beaconApiStateValidatorsProvider{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
stateValidatorsProvider: shared_providers.NewStateValidators(jsonRestHandler),
|
||||
}
|
||||
|
||||
validatorIndex, err := validatorClient.ValidatorIndex(
|
||||
@@ -109,9 +109,7 @@ func TestIndex_UnexistingValidator(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: beaconApiStateValidatorsProvider{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
stateValidatorsProvider: shared_providers.NewStateValidators(jsonRestHandler),
|
||||
}
|
||||
|
||||
_, err := validatorClient.ValidatorIndex(
|
||||
@@ -159,9 +157,7 @@ func TestIndex_BadIndexError(t *testing.T) {
|
||||
).Times(1)
|
||||
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: beaconApiStateValidatorsProvider{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
stateValidatorsProvider: shared_providers.NewStateValidators(jsonRestHandler),
|
||||
}
|
||||
|
||||
_, err := validatorClient.ValidatorIndex(
|
||||
@@ -209,16 +205,14 @@ func TestIndex_JsonResponseError(t *testing.T) {
|
||||
|
||||
jsonRestHandler.EXPECT().Get(
|
||||
gomock.Any(),
|
||||
buildURL("/eth/v1/beacon/states/head/validators", queryParams),
|
||||
apiutil.BuildURL("/eth/v1/beacon/states/head/validators", queryParams),
|
||||
&stateValidatorsResponseJson,
|
||||
).Return(
|
||||
errors.New("some specific json error"),
|
||||
).Times(1)
|
||||
|
||||
validatorClient := beaconApiValidatorClient{
|
||||
stateValidatorsProvider: beaconApiStateValidatorsProvider{
|
||||
jsonRestHandler: jsonRestHandler,
|
||||
},
|
||||
stateValidatorsProvider: shared_providers.NewStateValidators(jsonRestHandler),
|
||||
}
|
||||
|
||||
_, err := validatorClient.ValidatorIndex(
|
||||
46
api/client/beacon/validator_api/interfaces.go
Normal file
46
api/client/beacon/validator_api/interfaces.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/event"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
type Client interface {
|
||||
Duties(ctx context.Context, in *ethpb.DutiesRequest) (*ethpb.ValidatorDutiesContainer, error)
|
||||
DomainData(ctx context.Context, in *ethpb.DomainRequest) (*ethpb.DomainResponse, error)
|
||||
WaitForChainStart(ctx context.Context, in *empty.Empty) (*ethpb.ChainStartResponse, 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)
|
||||
BeaconBlock(ctx context.Context, in *ethpb.BlockRequest) (*ethpb.GenericBeaconBlock, error)
|
||||
ProposeBeaconBlock(ctx context.Context, in *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error)
|
||||
PrepareBeaconProposer(ctx context.Context, in *ethpb.PrepareBeaconProposerRequest) (*empty.Empty, error)
|
||||
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.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)
|
||||
SubmitSignedAggregateSelectionProofElectra(ctx context.Context, in *ethpb.SignedAggregateSubmitElectraRequest) (*ethpb.SignedAggregateSubmitResponse, error)
|
||||
ProposeExit(ctx context.Context, in *ethpb.SignedVoluntaryExit) (*ethpb.ProposeExitResponse, error)
|
||||
SubscribeCommitteeSubnets(ctx context.Context, in *ethpb.CommitteeSubnetsSubscribeRequest, duties []*ethpb.ValidatorDuty) (*empty.Empty, error)
|
||||
CheckDoppelGanger(ctx context.Context, in *ethpb.DoppelGangerRequest) (*ethpb.DoppelGangerResponse, error)
|
||||
SyncMessageBlockRoot(ctx context.Context, in *empty.Empty) (*ethpb.SyncMessageBlockRootResponse, error)
|
||||
SubmitSyncMessage(ctx context.Context, in *ethpb.SyncCommitteeMessage) (*empty.Empty, error)
|
||||
SyncSubcommitteeIndex(ctx context.Context, in *ethpb.SyncSubcommitteeIndexRequest) (*ethpb.SyncSubcommitteeIndexResponse, error)
|
||||
SyncCommitteeContribution(ctx context.Context, in *ethpb.SyncCommitteeContributionRequest) (*ethpb.SyncCommitteeContribution, error)
|
||||
SubmitSignedContributionAndProof(ctx context.Context, in *ethpb.SignedContributionAndProof) (*empty.Empty, error)
|
||||
SubmitValidatorRegistrations(ctx context.Context, in *ethpb.SignedValidatorRegistrationsV1) (*empty.Empty, error)
|
||||
StartEventStream(ctx context.Context, topics []string, eventsChannel chan<- *event.Event)
|
||||
EventStreamIsRunning() bool
|
||||
AggregatedSelections(ctx context.Context, selections []beacon.BeaconCommitteeSelection) ([]beacon.BeaconCommitteeSelection, error)
|
||||
AggregatedSyncSelections(ctx context.Context, selections []beacon.SyncCommitteeSelection) ([]beacon.SyncCommitteeSelection, error)
|
||||
Host() string
|
||||
SetHost(host string)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import "github.com/sirupsen/logrus"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -8,11 +8,11 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
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"
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -8,34 +8,34 @@ import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/validator_api/test_helpers"
|
||||
"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"
|
||||
testhelpers "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/test-helpers"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
func TestProposeAttestation(t *testing.T) {
|
||||
attestation := ðpb.Attestation{
|
||||
AggregationBits: testhelpers.FillByteSlice(4, 74),
|
||||
AggregationBits: test_helpers.FillByteSlice(4, 74),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 75,
|
||||
CommitteeIndex: 76,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 78,
|
||||
Root: testhelpers.FillByteSlice(32, 79),
|
||||
Root: test_helpers.FillByteSlice(32, 79),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 80,
|
||||
Root: testhelpers.FillByteSlice(32, 81),
|
||||
Root: test_helpers.FillByteSlice(32, 81),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
Signature: test_helpers.FillByteSlice(96, 82),
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
@@ -57,30 +57,30 @@ func TestProposeAttestation(t *testing.T) {
|
||||
{
|
||||
name: "nil attestation data",
|
||||
attestation: ðpb.Attestation{
|
||||
AggregationBits: testhelpers.FillByteSlice(4, 74),
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
AggregationBits: test_helpers.FillByteSlice(4, 74),
|
||||
Signature: test_helpers.FillByteSlice(96, 82),
|
||||
},
|
||||
expectedErrorMessage: "attestation is nil",
|
||||
},
|
||||
{
|
||||
name: "nil source checkpoint",
|
||||
attestation: ðpb.Attestation{
|
||||
AggregationBits: testhelpers.FillByteSlice(4, 74),
|
||||
AggregationBits: test_helpers.FillByteSlice(4, 74),
|
||||
Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
Signature: test_helpers.FillByteSlice(96, 82),
|
||||
},
|
||||
expectedErrorMessage: "attestation's source can't be nil",
|
||||
},
|
||||
{
|
||||
name: "nil target checkpoint",
|
||||
attestation: ðpb.Attestation{
|
||||
AggregationBits: testhelpers.FillByteSlice(4, 74),
|
||||
AggregationBits: test_helpers.FillByteSlice(4, 74),
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
Signature: test_helpers.FillByteSlice(96, 82),
|
||||
},
|
||||
expectedErrorMessage: "attestation's target can't be nil",
|
||||
},
|
||||
@@ -91,7 +91,7 @@ func TestProposeAttestation(t *testing.T) {
|
||||
Source: ðpb.Checkpoint{},
|
||||
Target: ðpb.Checkpoint{},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
Signature: test_helpers.FillByteSlice(96, 82),
|
||||
},
|
||||
expectedErrorMessage: "attestation's bitfield can't be nil",
|
||||
},
|
||||
@@ -150,21 +150,21 @@ func TestProposeAttestation(t *testing.T) {
|
||||
|
||||
func TestProposeAttestationFallBack(t *testing.T) {
|
||||
attestation := ðpb.Attestation{
|
||||
AggregationBits: testhelpers.FillByteSlice(4, 74),
|
||||
AggregationBits: test_helpers.FillByteSlice(4, 74),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 75,
|
||||
CommitteeIndex: 76,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 78,
|
||||
Root: testhelpers.FillByteSlice(32, 79),
|
||||
Root: test_helpers.FillByteSlice(32, 79),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 80,
|
||||
Root: testhelpers.FillByteSlice(32, 81),
|
||||
Root: test_helpers.FillByteSlice(32, 81),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
Signature: test_helpers.FillByteSlice(96, 82),
|
||||
}
|
||||
|
||||
ctrl := gomock.NewController(t)
|
||||
@@ -220,17 +220,17 @@ func TestProposeAttestationElectra(t *testing.T) {
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 75,
|
||||
CommitteeIndex: 76,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 78,
|
||||
Root: testhelpers.FillByteSlice(32, 79),
|
||||
Root: test_helpers.FillByteSlice(32, 79),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 80,
|
||||
Root: testhelpers.FillByteSlice(32, 81),
|
||||
Root: test_helpers.FillByteSlice(32, 81),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
Signature: test_helpers.FillByteSlice(96, 82),
|
||||
CommitteeId: 83,
|
||||
}
|
||||
|
||||
@@ -254,7 +254,7 @@ func TestProposeAttestationElectra(t *testing.T) {
|
||||
name: "nil attestation data",
|
||||
attestation: ðpb.SingleAttestation{
|
||||
AttesterIndex: 74,
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
Signature: test_helpers.FillByteSlice(96, 82),
|
||||
CommitteeId: 83,
|
||||
},
|
||||
expectedErrorMessage: "attestation is nil",
|
||||
@@ -266,7 +266,7 @@ func TestProposeAttestationElectra(t *testing.T) {
|
||||
Data: ðpb.AttestationData{
|
||||
Target: ðpb.Checkpoint{},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
Signature: test_helpers.FillByteSlice(96, 82),
|
||||
CommitteeId: 83,
|
||||
},
|
||||
expectedErrorMessage: "attestation's source can't be nil",
|
||||
@@ -278,7 +278,7 @@ func TestProposeAttestationElectra(t *testing.T) {
|
||||
Data: ðpb.AttestationData{
|
||||
Source: ðpb.Checkpoint{},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
Signature: test_helpers.FillByteSlice(96, 82),
|
||||
CommitteeId: 83,
|
||||
},
|
||||
expectedErrorMessage: "attestation's target can't be nil",
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/network/httputil"
|
||||
@@ -221,8 +222,8 @@ func marshallBeaconBlockPhase0(block *ethpb.SignedBeaconBlock) ([]byte, error) {
|
||||
VoluntaryExits: JsonifySignedVoluntaryExits(block.Block.Body.VoluntaryExits),
|
||||
},
|
||||
ParentRoot: hexutil.Encode(block.Block.ParentRoot),
|
||||
ProposerIndex: uint64ToString(block.Block.ProposerIndex),
|
||||
Slot: uint64ToString(block.Block.Slot),
|
||||
ProposerIndex: apiutil.Uint64ToString(block.Block.ProposerIndex),
|
||||
Slot: apiutil.Uint64ToString(block.Block.Slot),
|
||||
StateRoot: hexutil.Encode(block.Block.StateRoot),
|
||||
},
|
||||
}
|
||||
@@ -235,8 +236,8 @@ func marshallBeaconBlockAltair(block *ethpb.SignedBeaconBlockAltair) ([]byte, er
|
||||
Signature: hexutil.Encode(block.Signature),
|
||||
Message: &structs.BeaconBlockAltair{
|
||||
ParentRoot: hexutil.Encode(block.Block.ParentRoot),
|
||||
ProposerIndex: uint64ToString(block.Block.ProposerIndex),
|
||||
Slot: uint64ToString(block.Block.Slot),
|
||||
ProposerIndex: apiutil.Uint64ToString(block.Block.ProposerIndex),
|
||||
Slot: apiutil.Uint64ToString(block.Block.Slot),
|
||||
StateRoot: hexutil.Encode(block.Block.StateRoot),
|
||||
Body: &structs.BeaconBlockBodyAltair{
|
||||
Attestations: jsonifyAttestations(block.Block.Body.Attestations),
|
||||
@@ -263,8 +264,8 @@ func marshallBeaconBlockBellatrix(block *ethpb.SignedBeaconBlockBellatrix) ([]by
|
||||
Signature: hexutil.Encode(block.Signature),
|
||||
Message: &structs.BeaconBlockBellatrix{
|
||||
ParentRoot: hexutil.Encode(block.Block.ParentRoot),
|
||||
ProposerIndex: uint64ToString(block.Block.ProposerIndex),
|
||||
Slot: uint64ToString(block.Block.Slot),
|
||||
ProposerIndex: apiutil.Uint64ToString(block.Block.ProposerIndex),
|
||||
Slot: apiutil.Uint64ToString(block.Block.Slot),
|
||||
StateRoot: hexutil.Encode(block.Block.StateRoot),
|
||||
Body: &structs.BeaconBlockBodyBellatrix{
|
||||
Attestations: jsonifyAttestations(block.Block.Body.Attestations),
|
||||
@@ -286,10 +287,10 @@ func marshallBeaconBlockBellatrix(block *ethpb.SignedBeaconBlockBellatrix) ([]by
|
||||
ReceiptsRoot: hexutil.Encode(block.Block.Body.ExecutionPayload.ReceiptsRoot),
|
||||
LogsBloom: hexutil.Encode(block.Block.Body.ExecutionPayload.LogsBloom),
|
||||
PrevRandao: hexutil.Encode(block.Block.Body.ExecutionPayload.PrevRandao),
|
||||
BlockNumber: uint64ToString(block.Block.Body.ExecutionPayload.BlockNumber),
|
||||
GasLimit: uint64ToString(block.Block.Body.ExecutionPayload.GasLimit),
|
||||
GasUsed: uint64ToString(block.Block.Body.ExecutionPayload.GasUsed),
|
||||
Timestamp: uint64ToString(block.Block.Body.ExecutionPayload.Timestamp),
|
||||
BlockNumber: apiutil.Uint64ToString(block.Block.Body.ExecutionPayload.BlockNumber),
|
||||
GasLimit: apiutil.Uint64ToString(block.Block.Body.ExecutionPayload.GasLimit),
|
||||
GasUsed: apiutil.Uint64ToString(block.Block.Body.ExecutionPayload.GasUsed),
|
||||
Timestamp: apiutil.Uint64ToString(block.Block.Body.ExecutionPayload.Timestamp),
|
||||
ExtraData: hexutil.Encode(block.Block.Body.ExecutionPayload.ExtraData),
|
||||
BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(block.Block.Body.ExecutionPayload.BaseFeePerGas).String(),
|
||||
BlockHash: hexutil.Encode(block.Block.Body.ExecutionPayload.BlockHash),
|
||||
@@ -307,8 +308,8 @@ func marshallBeaconBlockBlindedBellatrix(block *ethpb.SignedBlindedBeaconBlockBe
|
||||
Signature: hexutil.Encode(block.Signature),
|
||||
Message: &structs.BlindedBeaconBlockBellatrix{
|
||||
ParentRoot: hexutil.Encode(block.Block.ParentRoot),
|
||||
ProposerIndex: uint64ToString(block.Block.ProposerIndex),
|
||||
Slot: uint64ToString(block.Block.Slot),
|
||||
ProposerIndex: apiutil.Uint64ToString(block.Block.ProposerIndex),
|
||||
Slot: apiutil.Uint64ToString(block.Block.Slot),
|
||||
StateRoot: hexutil.Encode(block.Block.StateRoot),
|
||||
Body: &structs.BlindedBeaconBlockBodyBellatrix{
|
||||
Attestations: jsonifyAttestations(block.Block.Body.Attestations),
|
||||
@@ -330,10 +331,10 @@ func marshallBeaconBlockBlindedBellatrix(block *ethpb.SignedBlindedBeaconBlockBe
|
||||
ReceiptsRoot: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.ReceiptsRoot),
|
||||
LogsBloom: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.LogsBloom),
|
||||
PrevRandao: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.PrevRandao),
|
||||
BlockNumber: uint64ToString(block.Block.Body.ExecutionPayloadHeader.BlockNumber),
|
||||
GasLimit: uint64ToString(block.Block.Body.ExecutionPayloadHeader.GasLimit),
|
||||
GasUsed: uint64ToString(block.Block.Body.ExecutionPayloadHeader.GasUsed),
|
||||
Timestamp: uint64ToString(block.Block.Body.ExecutionPayloadHeader.Timestamp),
|
||||
BlockNumber: apiutil.Uint64ToString(block.Block.Body.ExecutionPayloadHeader.BlockNumber),
|
||||
GasLimit: apiutil.Uint64ToString(block.Block.Body.ExecutionPayloadHeader.GasLimit),
|
||||
GasUsed: apiutil.Uint64ToString(block.Block.Body.ExecutionPayloadHeader.GasUsed),
|
||||
Timestamp: apiutil.Uint64ToString(block.Block.Body.ExecutionPayloadHeader.Timestamp),
|
||||
ExtraData: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.ExtraData),
|
||||
BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(block.Block.Body.ExecutionPayloadHeader.BaseFeePerGas).String(),
|
||||
BlockHash: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.BlockHash),
|
||||
@@ -351,8 +352,8 @@ func marshallBeaconBlockCapella(block *ethpb.SignedBeaconBlockCapella) ([]byte,
|
||||
Signature: hexutil.Encode(block.Signature),
|
||||
Message: &structs.BeaconBlockCapella{
|
||||
ParentRoot: hexutil.Encode(block.Block.ParentRoot),
|
||||
ProposerIndex: uint64ToString(block.Block.ProposerIndex),
|
||||
Slot: uint64ToString(block.Block.Slot),
|
||||
ProposerIndex: apiutil.Uint64ToString(block.Block.ProposerIndex),
|
||||
Slot: apiutil.Uint64ToString(block.Block.Slot),
|
||||
StateRoot: hexutil.Encode(block.Block.StateRoot),
|
||||
Body: &structs.BeaconBlockBodyCapella{
|
||||
Attestations: jsonifyAttestations(block.Block.Body.Attestations),
|
||||
@@ -374,10 +375,10 @@ func marshallBeaconBlockCapella(block *ethpb.SignedBeaconBlockCapella) ([]byte,
|
||||
ReceiptsRoot: hexutil.Encode(block.Block.Body.ExecutionPayload.ReceiptsRoot),
|
||||
LogsBloom: hexutil.Encode(block.Block.Body.ExecutionPayload.LogsBloom),
|
||||
PrevRandao: hexutil.Encode(block.Block.Body.ExecutionPayload.PrevRandao),
|
||||
BlockNumber: uint64ToString(block.Block.Body.ExecutionPayload.BlockNumber),
|
||||
GasLimit: uint64ToString(block.Block.Body.ExecutionPayload.GasLimit),
|
||||
GasUsed: uint64ToString(block.Block.Body.ExecutionPayload.GasUsed),
|
||||
Timestamp: uint64ToString(block.Block.Body.ExecutionPayload.Timestamp),
|
||||
BlockNumber: apiutil.Uint64ToString(block.Block.Body.ExecutionPayload.BlockNumber),
|
||||
GasLimit: apiutil.Uint64ToString(block.Block.Body.ExecutionPayload.GasLimit),
|
||||
GasUsed: apiutil.Uint64ToString(block.Block.Body.ExecutionPayload.GasUsed),
|
||||
Timestamp: apiutil.Uint64ToString(block.Block.Body.ExecutionPayload.Timestamp),
|
||||
ExtraData: hexutil.Encode(block.Block.Body.ExecutionPayload.ExtraData),
|
||||
BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(block.Block.Body.ExecutionPayload.BaseFeePerGas).String(),
|
||||
BlockHash: hexutil.Encode(block.Block.Body.ExecutionPayload.BlockHash),
|
||||
@@ -397,8 +398,8 @@ func marshallBeaconBlockBlindedCapella(block *ethpb.SignedBlindedBeaconBlockCape
|
||||
Signature: hexutil.Encode(block.Signature),
|
||||
Message: &structs.BlindedBeaconBlockCapella{
|
||||
ParentRoot: hexutil.Encode(block.Block.ParentRoot),
|
||||
ProposerIndex: uint64ToString(block.Block.ProposerIndex),
|
||||
Slot: uint64ToString(block.Block.Slot),
|
||||
ProposerIndex: apiutil.Uint64ToString(block.Block.ProposerIndex),
|
||||
Slot: apiutil.Uint64ToString(block.Block.Slot),
|
||||
StateRoot: hexutil.Encode(block.Block.StateRoot),
|
||||
Body: &structs.BlindedBeaconBlockBodyCapella{
|
||||
Attestations: jsonifyAttestations(block.Block.Body.Attestations),
|
||||
@@ -420,10 +421,10 @@ func marshallBeaconBlockBlindedCapella(block *ethpb.SignedBlindedBeaconBlockCape
|
||||
ReceiptsRoot: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.ReceiptsRoot),
|
||||
LogsBloom: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.LogsBloom),
|
||||
PrevRandao: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.PrevRandao),
|
||||
BlockNumber: uint64ToString(block.Block.Body.ExecutionPayloadHeader.BlockNumber),
|
||||
GasLimit: uint64ToString(block.Block.Body.ExecutionPayloadHeader.GasLimit),
|
||||
GasUsed: uint64ToString(block.Block.Body.ExecutionPayloadHeader.GasUsed),
|
||||
Timestamp: uint64ToString(block.Block.Body.ExecutionPayloadHeader.Timestamp),
|
||||
BlockNumber: apiutil.Uint64ToString(block.Block.Body.ExecutionPayloadHeader.BlockNumber),
|
||||
GasLimit: apiutil.Uint64ToString(block.Block.Body.ExecutionPayloadHeader.GasLimit),
|
||||
GasUsed: apiutil.Uint64ToString(block.Block.Body.ExecutionPayloadHeader.GasUsed),
|
||||
Timestamp: apiutil.Uint64ToString(block.Block.Body.ExecutionPayloadHeader.Timestamp),
|
||||
ExtraData: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.ExtraData),
|
||||
BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(block.Block.Body.ExecutionPayloadHeader.BaseFeePerGas).String(),
|
||||
BlockHash: hexutil.Encode(block.Block.Body.ExecutionPayloadHeader.BlockHash),
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -7,12 +7,13 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/validator_api/test_helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/server/structs"
|
||||
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"
|
||||
testhelpers "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/test-helpers"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -30,8 +31,8 @@ func TestProposeBeaconBlock_Altair(t *testing.T) {
|
||||
Signature: hexutil.Encode(altairBlock.Altair.Signature),
|
||||
Message: &structs.BeaconBlockAltair{
|
||||
ParentRoot: hexutil.Encode(altairBlock.Altair.Block.ParentRoot),
|
||||
ProposerIndex: uint64ToString(altairBlock.Altair.Block.ProposerIndex),
|
||||
Slot: uint64ToString(altairBlock.Altair.Block.Slot),
|
||||
ProposerIndex: apiutil.Uint64ToString(altairBlock.Altair.Block.ProposerIndex),
|
||||
Slot: apiutil.Uint64ToString(altairBlock.Altair.Block.Slot),
|
||||
StateRoot: hexutil.Encode(altairBlock.Altair.Block.StateRoot),
|
||||
Body: &structs.BeaconBlockBodyAltair{
|
||||
Attestations: jsonifyAttestations(altairBlock.Altair.Block.Body.Attestations),
|
||||
@@ -80,8 +81,8 @@ func TestProposeBeaconBlock_Altair(t *testing.T) {
|
||||
func generateSignedAltairBlock() *ethpb.GenericSignedBeaconBlock_Altair {
|
||||
return ðpb.GenericSignedBeaconBlock_Altair{
|
||||
Altair: ðpb.SignedBeaconBlockAltair{
|
||||
Block: testhelpers.GenerateProtoAltairBeaconBlock(),
|
||||
Signature: testhelpers.FillByteSlice(96, 112),
|
||||
Block: test_helpers.GenerateProtoAltairBeaconBlock(),
|
||||
Signature: test_helpers.FillByteSlice(96, 112),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -7,14 +7,15 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/validator_api/test_helpers"
|
||||
"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"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
testhelpers "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/test-helpers"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -32,8 +33,8 @@ func TestProposeBeaconBlock_BlindedBellatrix(t *testing.T) {
|
||||
Signature: hexutil.Encode(blindedBellatrixBlock.BlindedBellatrix.Signature),
|
||||
Message: &structs.BlindedBeaconBlockBellatrix{
|
||||
ParentRoot: hexutil.Encode(blindedBellatrixBlock.BlindedBellatrix.Block.ParentRoot),
|
||||
ProposerIndex: uint64ToString(blindedBellatrixBlock.BlindedBellatrix.Block.ProposerIndex),
|
||||
Slot: uint64ToString(blindedBellatrixBlock.BlindedBellatrix.Block.Slot),
|
||||
ProposerIndex: apiutil.Uint64ToString(blindedBellatrixBlock.BlindedBellatrix.Block.ProposerIndex),
|
||||
Slot: apiutil.Uint64ToString(blindedBellatrixBlock.BlindedBellatrix.Block.Slot),
|
||||
StateRoot: hexutil.Encode(blindedBellatrixBlock.BlindedBellatrix.Block.StateRoot),
|
||||
Body: &structs.BlindedBeaconBlockBodyBellatrix{
|
||||
Attestations: jsonifyAttestations(blindedBellatrixBlock.BlindedBellatrix.Block.Body.Attestations),
|
||||
@@ -51,17 +52,17 @@ func TestProposeBeaconBlock_BlindedBellatrix(t *testing.T) {
|
||||
ExecutionPayloadHeader: &structs.ExecutionPayloadHeader{
|
||||
BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.BaseFeePerGas).String(),
|
||||
BlockHash: hexutil.Encode(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.BlockHash),
|
||||
BlockNumber: uint64ToString(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.BlockNumber),
|
||||
BlockNumber: apiutil.Uint64ToString(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.BlockNumber),
|
||||
ExtraData: hexutil.Encode(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.ExtraData),
|
||||
FeeRecipient: hexutil.Encode(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.FeeRecipient),
|
||||
GasLimit: uint64ToString(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.GasLimit),
|
||||
GasUsed: uint64ToString(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.GasUsed),
|
||||
GasLimit: apiutil.Uint64ToString(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.GasLimit),
|
||||
GasUsed: apiutil.Uint64ToString(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.GasUsed),
|
||||
LogsBloom: hexutil.Encode(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.LogsBloom),
|
||||
ParentHash: hexutil.Encode(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.ParentHash),
|
||||
PrevRandao: hexutil.Encode(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.PrevRandao),
|
||||
ReceiptsRoot: hexutil.Encode(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.ReceiptsRoot),
|
||||
StateRoot: hexutil.Encode(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.StateRoot),
|
||||
Timestamp: uint64ToString(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.Timestamp),
|
||||
Timestamp: apiutil.Uint64ToString(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.Timestamp),
|
||||
TransactionsRoot: hexutil.Encode(blindedBellatrixBlock.BlindedBellatrix.Block.Body.ExecutionPayloadHeader.TransactionsRoot),
|
||||
},
|
||||
},
|
||||
@@ -101,37 +102,37 @@ func generateSignedBlindedBellatrixBlock() *ethpb.GenericSignedBeaconBlock_Blind
|
||||
Block: ðpb.BlindedBeaconBlockBellatrix{
|
||||
Slot: 1,
|
||||
ProposerIndex: 2,
|
||||
ParentRoot: testhelpers.FillByteSlice(32, 3),
|
||||
StateRoot: testhelpers.FillByteSlice(32, 4),
|
||||
ParentRoot: test_helpers.FillByteSlice(32, 3),
|
||||
StateRoot: test_helpers.FillByteSlice(32, 4),
|
||||
Body: ðpb.BlindedBeaconBlockBodyBellatrix{
|
||||
RandaoReveal: testhelpers.FillByteSlice(96, 5),
|
||||
RandaoReveal: test_helpers.FillByteSlice(96, 5),
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
DepositRoot: testhelpers.FillByteSlice(32, 6),
|
||||
DepositRoot: test_helpers.FillByteSlice(32, 6),
|
||||
DepositCount: 7,
|
||||
BlockHash: testhelpers.FillByteSlice(32, 8),
|
||||
BlockHash: test_helpers.FillByteSlice(32, 8),
|
||||
},
|
||||
Graffiti: testhelpers.FillByteSlice(32, 9),
|
||||
Graffiti: test_helpers.FillByteSlice(32, 9),
|
||||
ProposerSlashings: []*ethpb.ProposerSlashing{
|
||||
{
|
||||
Header_1: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 10,
|
||||
ProposerIndex: 11,
|
||||
ParentRoot: testhelpers.FillByteSlice(32, 12),
|
||||
StateRoot: testhelpers.FillByteSlice(32, 13),
|
||||
BodyRoot: testhelpers.FillByteSlice(32, 14),
|
||||
ParentRoot: test_helpers.FillByteSlice(32, 12),
|
||||
StateRoot: test_helpers.FillByteSlice(32, 13),
|
||||
BodyRoot: test_helpers.FillByteSlice(32, 14),
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 15),
|
||||
Signature: test_helpers.FillByteSlice(96, 15),
|
||||
},
|
||||
Header_2: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 16,
|
||||
ProposerIndex: 17,
|
||||
ParentRoot: testhelpers.FillByteSlice(32, 18),
|
||||
StateRoot: testhelpers.FillByteSlice(32, 19),
|
||||
BodyRoot: testhelpers.FillByteSlice(32, 20),
|
||||
ParentRoot: test_helpers.FillByteSlice(32, 18),
|
||||
StateRoot: test_helpers.FillByteSlice(32, 19),
|
||||
BodyRoot: test_helpers.FillByteSlice(32, 20),
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 21),
|
||||
Signature: test_helpers.FillByteSlice(96, 21),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -139,21 +140,21 @@ func generateSignedBlindedBellatrixBlock() *ethpb.GenericSignedBeaconBlock_Blind
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 22,
|
||||
ProposerIndex: 23,
|
||||
ParentRoot: testhelpers.FillByteSlice(32, 24),
|
||||
StateRoot: testhelpers.FillByteSlice(32, 25),
|
||||
BodyRoot: testhelpers.FillByteSlice(32, 26),
|
||||
ParentRoot: test_helpers.FillByteSlice(32, 24),
|
||||
StateRoot: test_helpers.FillByteSlice(32, 25),
|
||||
BodyRoot: test_helpers.FillByteSlice(32, 26),
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 27),
|
||||
Signature: test_helpers.FillByteSlice(96, 27),
|
||||
},
|
||||
Header_2: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 28,
|
||||
ProposerIndex: 29,
|
||||
ParentRoot: testhelpers.FillByteSlice(32, 30),
|
||||
StateRoot: testhelpers.FillByteSlice(32, 31),
|
||||
BodyRoot: testhelpers.FillByteSlice(32, 32),
|
||||
ParentRoot: test_helpers.FillByteSlice(32, 30),
|
||||
StateRoot: test_helpers.FillByteSlice(32, 31),
|
||||
BodyRoot: test_helpers.FillByteSlice(32, 32),
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 33),
|
||||
Signature: test_helpers.FillByteSlice(96, 33),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -164,34 +165,34 @@ func generateSignedBlindedBellatrixBlock() *ethpb.GenericSignedBeaconBlock_Blind
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 36,
|
||||
CommitteeIndex: 37,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 39,
|
||||
Root: testhelpers.FillByteSlice(32, 40),
|
||||
Root: test_helpers.FillByteSlice(32, 40),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 41,
|
||||
Root: testhelpers.FillByteSlice(32, 42),
|
||||
Root: test_helpers.FillByteSlice(32, 42),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 43),
|
||||
Signature: test_helpers.FillByteSlice(96, 43),
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{44, 45},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 46,
|
||||
CommitteeIndex: 47,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 49,
|
||||
Root: testhelpers.FillByteSlice(32, 50),
|
||||
Root: test_helpers.FillByteSlice(32, 50),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 51,
|
||||
Root: testhelpers.FillByteSlice(32, 52),
|
||||
Root: test_helpers.FillByteSlice(32, 52),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 53),
|
||||
Signature: test_helpers.FillByteSlice(96, 53),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -200,90 +201,90 @@ func generateSignedBlindedBellatrixBlock() *ethpb.GenericSignedBeaconBlock_Blind
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 56,
|
||||
CommitteeIndex: 57,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 59,
|
||||
Root: testhelpers.FillByteSlice(32, 60),
|
||||
Root: test_helpers.FillByteSlice(32, 60),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 61,
|
||||
Root: testhelpers.FillByteSlice(32, 62),
|
||||
Root: test_helpers.FillByteSlice(32, 62),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 63),
|
||||
Signature: test_helpers.FillByteSlice(96, 63),
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{64, 65},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 66,
|
||||
CommitteeIndex: 67,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 69,
|
||||
Root: testhelpers.FillByteSlice(32, 70),
|
||||
Root: test_helpers.FillByteSlice(32, 70),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 71,
|
||||
Root: testhelpers.FillByteSlice(32, 72),
|
||||
Root: test_helpers.FillByteSlice(32, 72),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 73),
|
||||
Signature: test_helpers.FillByteSlice(96, 73),
|
||||
},
|
||||
},
|
||||
},
|
||||
Attestations: []*ethpb.Attestation{
|
||||
{
|
||||
AggregationBits: testhelpers.FillByteSlice(4, 74),
|
||||
AggregationBits: test_helpers.FillByteSlice(4, 74),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 75,
|
||||
CommitteeIndex: 76,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 78,
|
||||
Root: testhelpers.FillByteSlice(32, 79),
|
||||
Root: test_helpers.FillByteSlice(32, 79),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 80,
|
||||
Root: testhelpers.FillByteSlice(32, 81),
|
||||
Root: test_helpers.FillByteSlice(32, 81),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
Signature: test_helpers.FillByteSlice(96, 82),
|
||||
},
|
||||
{
|
||||
AggregationBits: testhelpers.FillByteSlice(4, 83),
|
||||
AggregationBits: test_helpers.FillByteSlice(4, 83),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 84,
|
||||
CommitteeIndex: 85,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 87,
|
||||
Root: testhelpers.FillByteSlice(32, 88),
|
||||
Root: test_helpers.FillByteSlice(32, 88),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 89,
|
||||
Root: testhelpers.FillByteSlice(32, 90),
|
||||
Root: test_helpers.FillByteSlice(32, 90),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 91),
|
||||
Signature: test_helpers.FillByteSlice(96, 91),
|
||||
},
|
||||
},
|
||||
Deposits: []*ethpb.Deposit{
|
||||
{
|
||||
Proof: testhelpers.FillByteArraySlice(33, testhelpers.FillByteSlice(32, 92)),
|
||||
Proof: test_helpers.FillByteArraySlice(33, test_helpers.FillByteSlice(32, 92)),
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: testhelpers.FillByteSlice(48, 94),
|
||||
WithdrawalCredentials: testhelpers.FillByteSlice(32, 95),
|
||||
PublicKey: test_helpers.FillByteSlice(48, 94),
|
||||
WithdrawalCredentials: test_helpers.FillByteSlice(32, 95),
|
||||
Amount: 96,
|
||||
Signature: testhelpers.FillByteSlice(96, 97),
|
||||
Signature: test_helpers.FillByteSlice(96, 97),
|
||||
},
|
||||
},
|
||||
{
|
||||
Proof: testhelpers.FillByteArraySlice(33, testhelpers.FillByteSlice(32, 98)),
|
||||
Proof: test_helpers.FillByteArraySlice(33, test_helpers.FillByteSlice(32, 98)),
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: testhelpers.FillByteSlice(48, 100),
|
||||
WithdrawalCredentials: testhelpers.FillByteSlice(32, 101),
|
||||
PublicKey: test_helpers.FillByteSlice(48, 100),
|
||||
WithdrawalCredentials: test_helpers.FillByteSlice(32, 101),
|
||||
Amount: 102,
|
||||
Signature: testhelpers.FillByteSlice(96, 103),
|
||||
Signature: test_helpers.FillByteSlice(96, 103),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -293,39 +294,48 @@ func generateSignedBlindedBellatrixBlock() *ethpb.GenericSignedBeaconBlock_Blind
|
||||
Epoch: 104,
|
||||
ValidatorIndex: 105,
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 106),
|
||||
Signature: test_helpers.FillByteSlice(96, 106),
|
||||
},
|
||||
{
|
||||
Exit: ðpb.VoluntaryExit{
|
||||
Epoch: 107,
|
||||
ValidatorIndex: 108,
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 109),
|
||||
Signature: test_helpers.FillByteSlice(96, 109),
|
||||
},
|
||||
},
|
||||
SyncAggregate: ðpb.SyncAggregate{
|
||||
SyncCommitteeBits: testhelpers.FillByteSlice(64, 110),
|
||||
SyncCommitteeSignature: testhelpers.FillByteSlice(96, 111),
|
||||
SyncCommitteeBits: test_helpers.FillByteSlice(64, 110),
|
||||
SyncCommitteeSignature: test_helpers.FillByteSlice(96, 111),
|
||||
},
|
||||
ExecutionPayloadHeader: &enginev1.ExecutionPayloadHeader{
|
||||
ParentHash: testhelpers.FillByteSlice(32, 112),
|
||||
FeeRecipient: testhelpers.FillByteSlice(20, 113),
|
||||
StateRoot: testhelpers.FillByteSlice(32, 114),
|
||||
ReceiptsRoot: testhelpers.FillByteSlice(32, 115),
|
||||
LogsBloom: testhelpers.FillByteSlice(256, 116),
|
||||
PrevRandao: testhelpers.FillByteSlice(32, 117),
|
||||
ParentHash: test_helpers.FillByteSlice(32, 112),
|
||||
FeeRecipient: test_helpers.FillByteSlice(20, 113),
|
||||
StateRoot: test_helpers.FillByteSlice(32, 114),
|
||||
ReceiptsRoot: test_helpers.FillByteSlice(32, 115),
|
||||
LogsBloom: test_helpers.FillByteSlice(256, 116),
|
||||
PrevRandao: test_helpers.FillByteSlice(32, 117),
|
||||
BlockNumber: 118,
|
||||
GasLimit: 119,
|
||||
GasUsed: 120,
|
||||
Timestamp: 121,
|
||||
ExtraData: testhelpers.FillByteSlice(32, 122),
|
||||
BaseFeePerGas: testhelpers.FillByteSlice(32, 123),
|
||||
BlockHash: testhelpers.FillByteSlice(32, 124),
|
||||
TransactionsRoot: testhelpers.FillByteSlice(32, 125),
|
||||
ExtraData: test_helpers.FillByteSlice(32, 122),
|
||||
BaseFeePerGas: test_helpers.FillByteSlice(32, 123),
|
||||
BlockHash: test_helpers.FillByteSlice(32, 124),
|
||||
TransactionsRoot: test_helpers.FillByteSlice(32, 125),
|
||||
},
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 126),
|
||||
Signature: test_helpers.FillByteSlice(96, 126),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func generateSignedBellatrixBlock() *ethpb.GenericSignedBeaconBlock_Bellatrix {
|
||||
return ðpb.GenericSignedBeaconBlock_Bellatrix{
|
||||
Bellatrix: ðpb.SignedBeaconBlockBellatrix{
|
||||
Block: test_helpers.GenerateProtoBellatrixBeaconBlock(),
|
||||
Signature: test_helpers.FillByteSlice(96, 127),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -7,14 +7,15 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/apiutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/validator_api/test_helpers"
|
||||
"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"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/mock"
|
||||
testhelpers "github.com/prysmaticlabs/prysm/v5/validator/client/beacon-api/test-helpers"
|
||||
"go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -32,8 +33,8 @@ func TestProposeBeaconBlock_BlindedCapella(t *testing.T) {
|
||||
Signature: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Signature),
|
||||
Message: &structs.BlindedBeaconBlockCapella{
|
||||
ParentRoot: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Block.ParentRoot),
|
||||
ProposerIndex: uint64ToString(blindedCapellaBlock.BlindedCapella.Block.ProposerIndex),
|
||||
Slot: uint64ToString(blindedCapellaBlock.BlindedCapella.Block.Slot),
|
||||
ProposerIndex: apiutil.Uint64ToString(blindedCapellaBlock.BlindedCapella.Block.ProposerIndex),
|
||||
Slot: apiutil.Uint64ToString(blindedCapellaBlock.BlindedCapella.Block.Slot),
|
||||
StateRoot: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Block.StateRoot),
|
||||
Body: &structs.BlindedBeaconBlockBodyCapella{
|
||||
Attestations: jsonifyAttestations(blindedCapellaBlock.BlindedCapella.Block.Body.Attestations),
|
||||
@@ -51,17 +52,17 @@ func TestProposeBeaconBlock_BlindedCapella(t *testing.T) {
|
||||
ExecutionPayloadHeader: &structs.ExecutionPayloadHeaderCapella{
|
||||
BaseFeePerGas: bytesutil.LittleEndianBytesToBigInt(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.BaseFeePerGas).String(),
|
||||
BlockHash: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.BlockHash),
|
||||
BlockNumber: uint64ToString(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.BlockNumber),
|
||||
BlockNumber: apiutil.Uint64ToString(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.BlockNumber),
|
||||
ExtraData: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.ExtraData),
|
||||
FeeRecipient: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.FeeRecipient),
|
||||
GasLimit: uint64ToString(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.GasLimit),
|
||||
GasUsed: uint64ToString(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.GasUsed),
|
||||
GasLimit: apiutil.Uint64ToString(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.GasLimit),
|
||||
GasUsed: apiutil.Uint64ToString(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.GasUsed),
|
||||
LogsBloom: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.LogsBloom),
|
||||
ParentHash: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.ParentHash),
|
||||
PrevRandao: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.PrevRandao),
|
||||
ReceiptsRoot: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.ReceiptsRoot),
|
||||
StateRoot: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.StateRoot),
|
||||
Timestamp: uint64ToString(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.Timestamp),
|
||||
Timestamp: apiutil.Uint64ToString(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.Timestamp),
|
||||
TransactionsRoot: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.TransactionsRoot),
|
||||
WithdrawalsRoot: hexutil.Encode(blindedCapellaBlock.BlindedCapella.Block.Body.ExecutionPayloadHeader.WithdrawalsRoot),
|
||||
},
|
||||
@@ -103,37 +104,37 @@ func generateSignedBlindedCapellaBlock() *ethpb.GenericSignedBeaconBlock_Blinded
|
||||
Block: ðpb.BlindedBeaconBlockCapella{
|
||||
Slot: 1,
|
||||
ProposerIndex: 2,
|
||||
ParentRoot: testhelpers.FillByteSlice(32, 3),
|
||||
StateRoot: testhelpers.FillByteSlice(32, 4),
|
||||
ParentRoot: test_helpers.FillByteSlice(32, 3),
|
||||
StateRoot: test_helpers.FillByteSlice(32, 4),
|
||||
Body: ðpb.BlindedBeaconBlockBodyCapella{
|
||||
RandaoReveal: testhelpers.FillByteSlice(96, 5),
|
||||
RandaoReveal: test_helpers.FillByteSlice(96, 5),
|
||||
Eth1Data: ðpb.Eth1Data{
|
||||
DepositRoot: testhelpers.FillByteSlice(32, 6),
|
||||
DepositRoot: test_helpers.FillByteSlice(32, 6),
|
||||
DepositCount: 7,
|
||||
BlockHash: testhelpers.FillByteSlice(32, 8),
|
||||
BlockHash: test_helpers.FillByteSlice(32, 8),
|
||||
},
|
||||
Graffiti: testhelpers.FillByteSlice(32, 9),
|
||||
Graffiti: test_helpers.FillByteSlice(32, 9),
|
||||
ProposerSlashings: []*ethpb.ProposerSlashing{
|
||||
{
|
||||
Header_1: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 10,
|
||||
ProposerIndex: 11,
|
||||
ParentRoot: testhelpers.FillByteSlice(32, 12),
|
||||
StateRoot: testhelpers.FillByteSlice(32, 13),
|
||||
BodyRoot: testhelpers.FillByteSlice(32, 14),
|
||||
ParentRoot: test_helpers.FillByteSlice(32, 12),
|
||||
StateRoot: test_helpers.FillByteSlice(32, 13),
|
||||
BodyRoot: test_helpers.FillByteSlice(32, 14),
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 15),
|
||||
Signature: test_helpers.FillByteSlice(96, 15),
|
||||
},
|
||||
Header_2: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 16,
|
||||
ProposerIndex: 17,
|
||||
ParentRoot: testhelpers.FillByteSlice(32, 18),
|
||||
StateRoot: testhelpers.FillByteSlice(32, 19),
|
||||
BodyRoot: testhelpers.FillByteSlice(32, 20),
|
||||
ParentRoot: test_helpers.FillByteSlice(32, 18),
|
||||
StateRoot: test_helpers.FillByteSlice(32, 19),
|
||||
BodyRoot: test_helpers.FillByteSlice(32, 20),
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 21),
|
||||
Signature: test_helpers.FillByteSlice(96, 21),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -141,21 +142,21 @@ func generateSignedBlindedCapellaBlock() *ethpb.GenericSignedBeaconBlock_Blinded
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 22,
|
||||
ProposerIndex: 23,
|
||||
ParentRoot: testhelpers.FillByteSlice(32, 24),
|
||||
StateRoot: testhelpers.FillByteSlice(32, 25),
|
||||
BodyRoot: testhelpers.FillByteSlice(32, 26),
|
||||
ParentRoot: test_helpers.FillByteSlice(32, 24),
|
||||
StateRoot: test_helpers.FillByteSlice(32, 25),
|
||||
BodyRoot: test_helpers.FillByteSlice(32, 26),
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 27),
|
||||
Signature: test_helpers.FillByteSlice(96, 27),
|
||||
},
|
||||
Header_2: ðpb.SignedBeaconBlockHeader{
|
||||
Header: ðpb.BeaconBlockHeader{
|
||||
Slot: 28,
|
||||
ProposerIndex: 29,
|
||||
ParentRoot: testhelpers.FillByteSlice(32, 30),
|
||||
StateRoot: testhelpers.FillByteSlice(32, 31),
|
||||
BodyRoot: testhelpers.FillByteSlice(32, 32),
|
||||
ParentRoot: test_helpers.FillByteSlice(32, 30),
|
||||
StateRoot: test_helpers.FillByteSlice(32, 31),
|
||||
BodyRoot: test_helpers.FillByteSlice(32, 32),
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 33),
|
||||
Signature: test_helpers.FillByteSlice(96, 33),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -166,34 +167,34 @@ func generateSignedBlindedCapellaBlock() *ethpb.GenericSignedBeaconBlock_Blinded
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 36,
|
||||
CommitteeIndex: 37,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 39,
|
||||
Root: testhelpers.FillByteSlice(32, 40),
|
||||
Root: test_helpers.FillByteSlice(32, 40),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 41,
|
||||
Root: testhelpers.FillByteSlice(32, 42),
|
||||
Root: test_helpers.FillByteSlice(32, 42),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 43),
|
||||
Signature: test_helpers.FillByteSlice(96, 43),
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{44, 45},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 46,
|
||||
CommitteeIndex: 47,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 49,
|
||||
Root: testhelpers.FillByteSlice(32, 50),
|
||||
Root: test_helpers.FillByteSlice(32, 50),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 51,
|
||||
Root: testhelpers.FillByteSlice(32, 52),
|
||||
Root: test_helpers.FillByteSlice(32, 52),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 53),
|
||||
Signature: test_helpers.FillByteSlice(96, 53),
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -202,90 +203,90 @@ func generateSignedBlindedCapellaBlock() *ethpb.GenericSignedBeaconBlock_Blinded
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 56,
|
||||
CommitteeIndex: 57,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 59,
|
||||
Root: testhelpers.FillByteSlice(32, 60),
|
||||
Root: test_helpers.FillByteSlice(32, 60),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 61,
|
||||
Root: testhelpers.FillByteSlice(32, 62),
|
||||
Root: test_helpers.FillByteSlice(32, 62),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 63),
|
||||
Signature: test_helpers.FillByteSlice(96, 63),
|
||||
},
|
||||
Attestation_2: ðpb.IndexedAttestation{
|
||||
AttestingIndices: []uint64{64, 65},
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 66,
|
||||
CommitteeIndex: 67,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 69,
|
||||
Root: testhelpers.FillByteSlice(32, 70),
|
||||
Root: test_helpers.FillByteSlice(32, 70),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 71,
|
||||
Root: testhelpers.FillByteSlice(32, 72),
|
||||
Root: test_helpers.FillByteSlice(32, 72),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 73),
|
||||
Signature: test_helpers.FillByteSlice(96, 73),
|
||||
},
|
||||
},
|
||||
},
|
||||
Attestations: []*ethpb.Attestation{
|
||||
{
|
||||
AggregationBits: testhelpers.FillByteSlice(4, 74),
|
||||
AggregationBits: test_helpers.FillByteSlice(4, 74),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 75,
|
||||
CommitteeIndex: 76,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 78,
|
||||
Root: testhelpers.FillByteSlice(32, 79),
|
||||
Root: test_helpers.FillByteSlice(32, 79),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 80,
|
||||
Root: testhelpers.FillByteSlice(32, 81),
|
||||
Root: test_helpers.FillByteSlice(32, 81),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 82),
|
||||
Signature: test_helpers.FillByteSlice(96, 82),
|
||||
},
|
||||
{
|
||||
AggregationBits: testhelpers.FillByteSlice(4, 83),
|
||||
AggregationBits: test_helpers.FillByteSlice(4, 83),
|
||||
Data: ðpb.AttestationData{
|
||||
Slot: 84,
|
||||
CommitteeIndex: 85,
|
||||
BeaconBlockRoot: testhelpers.FillByteSlice(32, 38),
|
||||
BeaconBlockRoot: test_helpers.FillByteSlice(32, 38),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 87,
|
||||
Root: testhelpers.FillByteSlice(32, 88),
|
||||
Root: test_helpers.FillByteSlice(32, 88),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 89,
|
||||
Root: testhelpers.FillByteSlice(32, 90),
|
||||
Root: test_helpers.FillByteSlice(32, 90),
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 91),
|
||||
Signature: test_helpers.FillByteSlice(96, 91),
|
||||
},
|
||||
},
|
||||
Deposits: []*ethpb.Deposit{
|
||||
{
|
||||
Proof: testhelpers.FillByteArraySlice(33, testhelpers.FillByteSlice(32, 92)),
|
||||
Proof: test_helpers.FillByteArraySlice(33, test_helpers.FillByteSlice(32, 92)),
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: testhelpers.FillByteSlice(48, 94),
|
||||
WithdrawalCredentials: testhelpers.FillByteSlice(32, 95),
|
||||
PublicKey: test_helpers.FillByteSlice(48, 94),
|
||||
WithdrawalCredentials: test_helpers.FillByteSlice(32, 95),
|
||||
Amount: 96,
|
||||
Signature: testhelpers.FillByteSlice(96, 97),
|
||||
Signature: test_helpers.FillByteSlice(96, 97),
|
||||
},
|
||||
},
|
||||
{
|
||||
Proof: testhelpers.FillByteArraySlice(33, testhelpers.FillByteSlice(32, 98)),
|
||||
Proof: test_helpers.FillByteArraySlice(33, test_helpers.FillByteSlice(32, 98)),
|
||||
Data: ðpb.Deposit_Data{
|
||||
PublicKey: testhelpers.FillByteSlice(48, 100),
|
||||
WithdrawalCredentials: testhelpers.FillByteSlice(32, 101),
|
||||
PublicKey: test_helpers.FillByteSlice(48, 100),
|
||||
WithdrawalCredentials: test_helpers.FillByteSlice(32, 101),
|
||||
Amount: 102,
|
||||
Signature: testhelpers.FillByteSlice(96, 103),
|
||||
Signature: test_helpers.FillByteSlice(96, 103),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -295,58 +296,58 @@ func generateSignedBlindedCapellaBlock() *ethpb.GenericSignedBeaconBlock_Blinded
|
||||
Epoch: 104,
|
||||
ValidatorIndex: 105,
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 106),
|
||||
Signature: test_helpers.FillByteSlice(96, 106),
|
||||
},
|
||||
{
|
||||
Exit: ðpb.VoluntaryExit{
|
||||
Epoch: 107,
|
||||
ValidatorIndex: 108,
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 109),
|
||||
Signature: test_helpers.FillByteSlice(96, 109),
|
||||
},
|
||||
},
|
||||
SyncAggregate: ðpb.SyncAggregate{
|
||||
SyncCommitteeBits: testhelpers.FillByteSlice(64, 110),
|
||||
SyncCommitteeSignature: testhelpers.FillByteSlice(96, 111),
|
||||
SyncCommitteeBits: test_helpers.FillByteSlice(64, 110),
|
||||
SyncCommitteeSignature: test_helpers.FillByteSlice(96, 111),
|
||||
},
|
||||
ExecutionPayloadHeader: &enginev1.ExecutionPayloadHeaderCapella{
|
||||
ParentHash: testhelpers.FillByteSlice(32, 112),
|
||||
FeeRecipient: testhelpers.FillByteSlice(20, 113),
|
||||
StateRoot: testhelpers.FillByteSlice(32, 114),
|
||||
ReceiptsRoot: testhelpers.FillByteSlice(32, 115),
|
||||
LogsBloom: testhelpers.FillByteSlice(256, 116),
|
||||
PrevRandao: testhelpers.FillByteSlice(32, 117),
|
||||
ParentHash: test_helpers.FillByteSlice(32, 112),
|
||||
FeeRecipient: test_helpers.FillByteSlice(20, 113),
|
||||
StateRoot: test_helpers.FillByteSlice(32, 114),
|
||||
ReceiptsRoot: test_helpers.FillByteSlice(32, 115),
|
||||
LogsBloom: test_helpers.FillByteSlice(256, 116),
|
||||
PrevRandao: test_helpers.FillByteSlice(32, 117),
|
||||
BlockNumber: 118,
|
||||
GasLimit: 119,
|
||||
GasUsed: 120,
|
||||
Timestamp: 121,
|
||||
ExtraData: testhelpers.FillByteSlice(32, 122),
|
||||
BaseFeePerGas: testhelpers.FillByteSlice(32, 123),
|
||||
BlockHash: testhelpers.FillByteSlice(32, 124),
|
||||
TransactionsRoot: testhelpers.FillByteSlice(32, 125),
|
||||
WithdrawalsRoot: testhelpers.FillByteSlice(32, 126),
|
||||
ExtraData: test_helpers.FillByteSlice(32, 122),
|
||||
BaseFeePerGas: test_helpers.FillByteSlice(32, 123),
|
||||
BlockHash: test_helpers.FillByteSlice(32, 124),
|
||||
TransactionsRoot: test_helpers.FillByteSlice(32, 125),
|
||||
WithdrawalsRoot: test_helpers.FillByteSlice(32, 126),
|
||||
},
|
||||
BlsToExecutionChanges: []*ethpb.SignedBLSToExecutionChange{
|
||||
{
|
||||
Message: ðpb.BLSToExecutionChange{
|
||||
ValidatorIndex: 127,
|
||||
FromBlsPubkey: testhelpers.FillByteSlice(48, 128),
|
||||
ToExecutionAddress: testhelpers.FillByteSlice(20, 129),
|
||||
FromBlsPubkey: test_helpers.FillByteSlice(48, 128),
|
||||
ToExecutionAddress: test_helpers.FillByteSlice(20, 129),
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 130),
|
||||
Signature: test_helpers.FillByteSlice(96, 130),
|
||||
},
|
||||
{
|
||||
Message: ðpb.BLSToExecutionChange{
|
||||
ValidatorIndex: 131,
|
||||
FromBlsPubkey: testhelpers.FillByteSlice(48, 132),
|
||||
ToExecutionAddress: testhelpers.FillByteSlice(20, 133),
|
||||
FromBlsPubkey: test_helpers.FillByteSlice(48, 132),
|
||||
ToExecutionAddress: test_helpers.FillByteSlice(20, 133),
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 134),
|
||||
Signature: test_helpers.FillByteSlice(96, 134),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Signature: testhelpers.FillByteSlice(96, 135),
|
||||
Signature: test_helpers.FillByteSlice(96, 135),
|
||||
},
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -6,11 +6,11 @@ import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"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"
|
||||
)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package beacon_api
|
||||
package validator_api
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
@@ -6,11 +6,11 @@ import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/api/client/beacon/mock"
|
||||
"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"
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user