Compare commits

..

8 Commits

Author SHA1 Message Date
Bastin
1f95193c25 fix gen-logs.sh bug 2026-02-04 22:33:54 +01:00
Justin Traglia
fab687d96d Improve ethspecify integration (#16304)
**What type of PR is this?**

Documentation

**What does this PR do? Why is it needed?**

* Move the ethspecify config from `/specrefs/.ethspecify` to
`/.ethspecify`.
* This allows developers to use inline specrefs (eg spec functions in
godoc comments).
* To do this, simply add a spec tag and run `ethspecify` to populate it.
* Clean up specref exceptions; organize by upgrade & put items in the
correct section.
* Update a few godoc comments to use the new inline specref feature.
* Update check-specrefs GitHub action so that it enforces up-to-date
godocs.
* Standardize specref naming; requiring a `#fork` tag for everything.
* Add new specrefs (which haven't been implemented yet) which were
missing.

**Acknowledgements**

- [x] I have read
[CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md).
- [x] I have included a uniquely named [changelog fragment
file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd).
- [x] I have added a description with sufficient context for reviewers
to understand this PR.
- [x] I have tested that my changes work as expected and I added a
testing plan to the PR description (if applicable).

---------

Co-authored-by: james-prysm <90280386+james-prysm@users.noreply.github.com>
2026-02-04 18:44:01 +00:00
james-prysm
cf94ccbf72 node fallback cleanup (#16316)
**What type of PR is this?**

 Other

**What does this PR do? Why is it needed?**

Follow up to https://github.com/OffchainLabs/prysm/pull/16215 this pr
improves logging, fixes stuttering in package naming, adds additional
unit tests, and deduplicates fallback node code.

**Which issues(s) does this PR fix?**

fixes a potential race if reconnecting to the same host very quickly
which has a stale connection still.

**Other notes for review**

**Acknowledgements**

- [x] I have read
[CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md).
- [x] I have included a uniquely named [changelog fragment
file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd).
- [x] I have added a description with sufficient context for reviewers
to understand this PR.
- [x] I have tested that my changes work as expected and I added a
testing plan to the PR description (if applicable).
2026-02-04 15:59:42 +00:00
Aarsh Shah
75895c1e0b fix: Set Beacon Node Options after reading the config file (#16320)
**What type of PR is this?**
Bug fix

**What does this PR do? Why is it needed?**
This PR ensures that we set the beacon node options AFTER reading the
config file (if one is given to override the defaults).

**Which issues(s) does this PR fix?**
It fixes the issue that Barnabas reported around the
"MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS" override not being
respected (and potentially other issues resulting from setting the
options before reading the config).

Fixes #

**Other notes for review**

**Acknowledgements**

- [x] I have read
[CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md).
- [x] I have included a uniquely named [changelog fragment
file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd).
- [x] I have added a description with sufficient context for reviewers
to understand this PR.
- [x] I have tested that my changes work as expected and I added a
testing plan to the PR description (if applicable).
2026-02-03 16:51:01 +00:00
Preston Van Loon
d1b9281677 golangci-lint: Remove test exclusion from formatting (#16318)
**What type of PR is this?**

> Other

**What does this PR do? Why is it needed?**

**Which issues(s) does this PR fix?**

Follow up to #16311

**Other notes for review**

**Acknowledgements**

- [x] I have read
[CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md).
- [x] I have included a uniquely named [changelog fragment
file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd).
- [x] I have added a description with sufficient context for reviewers
to understand this PR.
- [x] I have tested that my changes work as expected and I added a
testing plan to the PR description (if applicable).
2026-02-02 17:42:05 +00:00
james-prysm
641d90990d grpc fallback improvements (#16215)
<!-- Thanks for sending a PR! Before submitting:

1. If this is your first PR, check out our contribution guide here
https://docs.prylabs.network/docs/contribute/contribution-guidelines
You will then need to sign our Contributor License Agreement (CLA),
which will show up as a comment from a bot in this pull request after
you open it. We cannot review code without a signed CLA.
2. Please file an associated tracking issue if this pull request is
non-trivial and requires context for our team to understand. All
features and most bug fixes should have
an associated issue with a design discussed and decided upon. Small bug
   fixes and documentation improvements don't need issues.
3. New features and bug fixes must have tests. Documentation may need to
be updated. If you're unsure what to update, send the PR, and we'll
discuss
   in review.
4. Note that PRs updating dependencies and new Go versions are not
accepted.
   Please file an issue instead.
5. A changelog entry is required for user facing issues.
-->

**What type of PR is this?**

## Summary

This PR implements gRPC fallback support for the validator client,
allowing it to automatically switch between multiple beacon node
endpoints when the primary node becomes unavailable or unhealthy.

## Changes

- Added `grpcConnectionProvider` to manage multiple gRPC connections
with circular failover
- Validator automatically detects unhealthy beacon nodes and switches to
the next available endpoint
- Health checks verify both node responsiveness AND sync status before
accepting a node
- Improved logging to only show "Found fully synced beacon node" when an
actual switch occurs (reduces log noise)


I removed the old middleware that uses gRPC's built in load balancer
because:

- gRPC's pick_first load balancer doesn't provide sync-status-aware
failover
- The validator needs to ensure it connects to a fully synced node, not
just a reachable one

## Test Scenario

### Setup
Deployed a 4-node Kurtosis testnet with local validator connecting to 2
beacon nodes:

```yaml
# kurtosis-grpc-fallback-test.yaml
participants:
  - el_type: nethermind
    cl_type: prysm
    validator_count: 128  # Keeps chain advancing
  - el_type: nethermind
    cl_type: prysm
    validator_count: 64
  - el_type: nethermind
    cl_type: prysm
    validator_count: 64   # Keeps chain advancing
  - el_type: nethermind
    cl_type: prysm
    validator_count: 64   # Keeps chain advancing

network_params:
  fulu_fork_epoch: 0
  seconds_per_slot: 6
```

Local validator started with:
```bash
./validator --beacon-rpc-provider=127.0.0.1:33005,127.0.0.1:33012 ...
```

### Test 1: Primary Failover (cl-1 → cl-2)

1. Stopped cl-1 beacon node
2. Validator detected failure and switched to cl-2

**Logs:**
```
WARN  Beacon node is not responding, switching host currentHost=127.0.0.1:33005 nextHost=127.0.0.1:33012
DEBUG Trying gRPC endpoint newHost=127.0.0.1:33012 previousHost=127.0.0.1:33005
INFO  Failover succeeded: connected to healthy beacon node failedAttempts=[127.0.0.1:33005] newHost=127.0.0.1:33012 previousHost=127.0.0.1:33005
```

**Result:**  PASSED - Validator continued submitting attestations on
cl-2

### Test 2: Circular Failover (cl-2 → cl-1)

1. Restarted cl-1, stopped cl-2
2. Validator detected failure and switched back to cl-1

**Logs:**
```
WARN  Beacon node is not responding, switching host currentHost=127.0.0.1:33012 nextHost=127.0.0.1:33005
DEBUG Trying gRPC endpoint newHost=127.0.0.1:33005 previousHost=127.0.0.1:33012
INFO  Failover succeeded: connected to healthy beacon node failedAttempts=[127.0.0.1:33012] newHost=127.0.0.1:33005 previousHost=127.0.0.1:33012
```

**Result:**  PASSED - Circular fallback works correctly

## Key Log Messages

| Log Level | Message | Source |
|-----------|---------|--------|
| WARN | "Beacon node is not responding, switching host" |
`changeHost()` in validator.go |
| INFO | "Switched gRPC endpoint" | `SetHost()` in
grpc_connection_provider.go |
| INFO | "Found fully synced beacon node" | `FindHealthyHost()` in
validator.go (only on actual switch) |

## Test Plan

- [x] Verify primary failover (cl-1 → cl-2)
- [x] Verify circular failover (cl-2 → cl-1)
- [x] Verify validator continues producing attestations after switch
- [x] Verify "Found fully synced beacon node" only logs on actual switch
(not every health check)

**What does this PR do? Why is it needed?**

**Which issues(s) does this PR fix?**

Fixes # https://github.com/OffchainLabs/prysm/pull/7133


**Other notes for review**

**Acknowledgements**

- [x] I have read
[CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md).
- [x] I have included a uniquely named [changelog fragment
file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd).
- [x] I have added a description with sufficient context for reviewers
to understand this PR.
- [x] I have tested that my changes work as expected and I added a
testing plan to the PR description (if applicable).

---------

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: Manu NALEPA <enalepa@offchainlabs.com>
2026-02-02 14:51:56 +00:00
terence
d2fc250f34 Run go fmt (#16311)
Co-authored-by: Manu NALEPA <enalepa@offchainlabs.com>
2026-02-02 14:19:15 +00:00
Jun Song
571c6f39aa Add docs for SSZ Query package (#16299)
**What type of PR is this?**

Documentation

**What does this PR do? Why is it needed?**

Although godoc and comments are well-written in `encoding/ssz/query`
package, we (@rkapka, @fernantho, @syjn99)
[agreed](https://discord.com/channels/476244492043812875/1387734369527136297/1466075406523174944)
that it would be great to have human-readable documentation.

**Which issues(s) does this PR fix?**

Part of  #15587 & #15598 

**Other notes for review**

This documentation is first drafted by Claude Code, and then has a few
rounds of self-review.

**Acknowledgements**

- [x] I have read
[CONTRIBUTING.md](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md).
- [x] I have included a uniquely named [changelog fragment
file](https://github.com/prysmaticlabs/prysm/blob/develop/CONTRIBUTING.md#maintaining-changelogmd).
- [x] I have added a description with sufficient context for reviewers
to understand this PR.
- [ ] I have tested that my changes work as expected and I added a
testing plan to the PR description (if applicable).

---------

Co-authored-by: fernantho <fernantho1@gmail.com>
Co-authored-by: Radosław Kapka <radoslaw.kapka@gmail.com>
2026-02-01 03:39:53 +00:00
166 changed files with 6862 additions and 3159 deletions

View File

@@ -2,24 +2,38 @@ version: v1.7.0-alpha.1
style: full
specrefs:
search_root: ..
search_root: .
auto_standardize_names: true
auto_add_missing_entries: true
require_exceptions_have_fork: true
files:
- configs.yml
- constants.yml
- containers.yml
- dataclasses.yml
- functions.yml
- presets.yml
- specrefs/configs.yml
- specrefs/constants.yml
- specrefs/containers.yml
- specrefs/dataclasses.yml
- specrefs/functions.yml
- specrefs/presets.yml
exceptions:
presets:
# Not implemented: gloas (future fork)
# gloas
- BUILDER_PENDING_WITHDRAWALS_LIMIT#gloas
- MAX_PAYLOAD_ATTESTATIONS#gloas
- PTC_SIZE#gloas
constants:
# Constants in the KZG library
# phase0
- BASIS_POINTS#phase0
- ENDIANNESS#phase0
- MAX_CONCURRENT_REQUESTS#phase0
- UINT64_MAX#phase0
- UINT64_MAX_SQRT#phase0
# altair
- PARTICIPATION_FLAG_WEIGHTS#altair
# bellatrix
- SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY#bellatrix
# deneb
- BLS_MODULUS#deneb
- BYTES_PER_COMMITMENT#deneb
- BYTES_PER_FIELD_ELEMENT#deneb
@@ -33,18 +47,9 @@ exceptions:
- PRIMITIVE_ROOT_OF_UNITY#deneb
- RANDOM_CHALLENGE_KZG_BATCH_DOMAIN#deneb
- RANDOM_CHALLENGE_KZG_CELL_BATCH_DOMAIN#fulu
# Not implemented
- BASIS_POINTS#phase0
- ENDIANNESS#phase0
- MAX_CONCURRENT_REQUESTS#phase0
- PARTICIPATION_FLAG_WEIGHTS#altair
- SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY#bellatrix
# fulu
- UINT256_MAX#fulu
- UINT64_MAX#phase0
- UINT64_MAX_SQRT#phase0
# Not implemented: gloas (future fork)
# gloas
- BUILDER_PAYMENT_THRESHOLD_DENOMINATOR#gloas
- BUILDER_PAYMENT_THRESHOLD_NUMERATOR#gloas
- BUILDER_WITHDRAWAL_PREFIX#gloas
@@ -61,61 +66,62 @@ exceptions:
- PTC_TIMELINESS_INDEX#gloas
configs:
# Not implemented: gloas (future fork)
# gloas
- AGGREGATE_DUE_BPS_GLOAS#gloas
- ATTESTATION_DUE_BPS_GLOAS#gloas
- CONTRIBUTION_DUE_BPS_GLOAS#gloas
- GLOAS_FORK_EPOCH#gloas
- GLOAS_FORK_VERSION#gloas
- MAX_REQUEST_PAYLOADS#gloas
- MIN_BUILDER_WITHDRAWABILITY_DELAY#gloas
- PAYLOAD_ATTESTATION_DUE_BPS#gloas
- SYNC_MESSAGE_DUE_BPS_GLOAS#gloas
- MIN_BUILDER_WITHDRAWABILITY_DELAY#gloas
ssz_objects:
# Not implemented
# phase0
- Eth1Block#phase0
- MatrixEntry#fulu
# Not implemented: capella
# capella
- LightClientBootstrap#capella
- LightClientFinalityUpdate#capella
- LightClientOptimisticUpdate#capella
- LightClientUpdate#capella
# Not implemented: gloas (future fork)
# fulu
- MatrixEntry#fulu
# gloas
- BeaconBlockBody#gloas
- BeaconState#gloas
- Builder#gloas
- BuilderPendingPayment#gloas
- BuilderPendingWithdrawal#gloas
- DataColumnSidecar#gloas
- ExecutionPayloadEnvelope#gloas
- ExecutionPayloadBid#gloas
- ExecutionPayloadEnvelope#gloas
- ForkChoiceNode#gloas
- IndexedPayloadAttestation#gloas
- PayloadAttestation#gloas
- PayloadAttestationData#gloas
- PayloadAttestationMessage#gloas
- SignedExecutionPayloadEnvelope#gloas
- SignedExecutionPayloadBid#gloas
- Builder#gloas
- ProposerPreferences#gloas
- SignedExecutionPayloadBid#gloas
- SignedExecutionPayloadEnvelope#gloas
- SignedProposerPreferences#gloas
dataclasses:
# Not implemented
- BlobParameters#fulu
- ExpectedWithdrawals#capella
- ExpectedWithdrawals#electra
# phase0
- LatestMessage#phase0
- LightClientStore#altair
- OptimisticStore#bellatrix
- Store#phase0
# Not implemented: capella
# altair
- LightClientStore#altair
# bellatrix
- OptimisticStore#bellatrix
# capella
- ExpectedWithdrawals#capella
- LightClientStore#capella
# Not implemented: gloas (future fork)
# electra
- ExpectedWithdrawals#electra
# fulu
- BlobParameters#fulu
# gloas
- ExpectedWithdrawals#gloas
- LatestMessage#gloas
- Store#gloas
@@ -175,7 +181,12 @@ exceptions:
- verify_cell_kzg_proof_batch#fulu
- verify_cell_kzg_proof_batch_impl#fulu
# Not implemented: phase0
# phase0
- update_proposer_boost_root#phase0
- is_proposer_equivocation#phase0
- record_block_timeliness#phase0
- compute_proposer_score#phase0
- get_attestation_score#phase0
- calculate_committee_fraction#phase0
- compute_fork_version#phase0
- compute_pulled_up_tip#phase0
@@ -221,8 +232,7 @@ exceptions:
- validate_on_attestation#phase0
- validate_target_epoch_against_current_time#phase0
- xor#phase0
# Not implemented: altair
# altair
- compute_merkle_proof#altair
- compute_sync_committee_period_at_slot#altair
- get_contribution_and_proof#altair
@@ -244,27 +254,29 @@ exceptions:
- process_sync_committee_contributions#altair
- set_or_append_list#altair
- validate_light_client_update#altair
# Not implemented: bellatrix
# bellatrix
- get_execution_payload#bellatrix
- is_merge_transition_block#bellatrix
- is_optimistic_candidate_block#bellatrix
- latest_verified_ancestor#bellatrix
- prepare_execution_payload#bellatrix
# Not implemented: capella
# capella
- apply_withdrawals#capella
- get_balance_after_withdrawals#capella
- get_lc_execution_root#capella
- get_validators_sweep_withdrawals#capella
- is_valid_light_client_header#capella
- prepare_execution_payload#capella
- process_epoch#capella
- update_next_withdrawal_index#capella
- update_next_withdrawal_validator_index#capella
- upgrade_lc_bootstrap_to_capella#capella
- upgrade_lc_finality_update_to_capella#capella
- upgrade_lc_header_to_capella#capella
- upgrade_lc_optimistic_update_to_capella#capella
- upgrade_lc_store_to_capella#capella
- upgrade_lc_update_to_capella#capella
# Not implemented: deneb
# deneb
- get_lc_execution_root#deneb
- is_valid_light_client_header#deneb
- prepare_execution_payload#deneb
@@ -274,33 +286,34 @@ exceptions:
- upgrade_lc_optimistic_update_to_deneb#deneb
- upgrade_lc_store_to_deneb#deneb
- upgrade_lc_update_to_deneb#deneb
# Not implemented: electra
# electra
- compute_weak_subjectivity_period#electra
- current_sync_committee_gindex_at_slot#electra
- finalized_root_gindex_at_slot#electra
- get_eth1_vote#electra
- get_lc_execution_root#electra
- get_pending_partial_withdrawals#electra
- get_validators_sweep_withdrawals#electra
- is_compounding_withdrawal_credential#electra
- is_eligible_for_partial_withdrawals#electra
- is_within_weak_subjectivity_period#electra
- next_sync_committee_gindex_at_slot#electra
- normalize_merkle_branch#electra
- prepare_execution_payload#electra
- update_pending_partial_withdrawals#electra
- upgrade_lc_bootstrap_to_electra#electra
- upgrade_lc_finality_update_to_electra#electra
- upgrade_lc_header_to_electra#electra
- upgrade_lc_optimistic_update_to_electra#electra
- upgrade_lc_store_to_electra#electra
- upgrade_lc_update_to_electra#electra
# Not implemented: fulu
# fulu
- compute_matrix#fulu
- get_blob_parameters#fulu
- get_data_column_sidecars_from_block#fulu
- get_data_column_sidecars_from_column_sidecar#fulu
- recover_matrix#fulu
# Not implemented: gloas (future fork)
# gloas
- compute_balance_weighted_acceptance#gloas
- compute_balance_weighted_selection#gloas
- compute_fork_version#gloas
@@ -368,49 +381,36 @@ exceptions:
- verify_execution_payload_bid_signature#gloas
- add_builder_to_registry#gloas
- apply_deposit_for_builder#gloas
- apply_withdrawals#capella
- apply_withdrawals#gloas
- can_builder_cover_bid#gloas
- compute_proposer_score#phase0
- convert_builder_index_to_validator_index#gloas
- convert_validator_index_to_builder_index#gloas
- get_attestation_score#gloas
- get_attestation_score#phase0
- get_balance_after_withdrawals#capella
- get_builder_from_deposit#gloas
- get_builder_withdrawals#gloas
- get_builders_sweep_withdrawals#gloas
- get_index_for_new_builder#gloas
- get_pending_balance_to_withdraw_for_builder#gloas
- get_pending_partial_withdrawals#electra
- get_proposer_preferences_signature#gloas
- get_upcoming_proposal_slots#gloas
- get_validators_sweep_withdrawals#capella
- get_validators_sweep_withdrawals#electra
- initiate_builder_exit#gloas
- is_active_builder#gloas
- is_builder_index#gloas
- is_eligible_for_partial_withdrawals#electra
- is_head_late#gloas
- is_head_weak#gloas
- is_parent_strong#gloas
- is_proposer_equivocation#phase0
- is_valid_proposal_slot#gloas
- process_deposit_request#gloas
- process_voluntary_exit#gloas
- record_block_timeliness#gloas
- record_block_timeliness#phase0
- should_apply_proposer_boost#gloas
- update_builder_pending_withdrawals#gloas
- update_next_withdrawal_builder_index#gloas
- update_next_withdrawal_index#capella
- update_next_withdrawal_validator_index#capella
- update_payload_expected_withdrawals#gloas
- update_pending_partial_withdrawals#electra
- update_proposer_boost_root#gloas
- update_proposer_boost_root#phase0
presets:
# gloas
- BUILDER_PENDING_WITHDRAWALS_LIMIT#gloas
- BUILDER_REGISTRY_LIMIT#gloas
- MAX_BUILDERS_PER_WITHDRAWALS_SWEEP#gloas

View File

@@ -12,11 +12,11 @@ jobs:
- name: Check version consistency
run: |
WORKSPACE_VERSION=$(grep 'consensus_spec_version = ' WORKSPACE | sed 's/.*"\(.*\)"/\1/')
ETHSPECIFY_VERSION=$(grep '^version:' specrefs/.ethspecify.yml | sed 's/version: //')
ETHSPECIFY_VERSION=$(grep '^version:' .ethspecify.yml | sed 's/version: //')
if [ "$WORKSPACE_VERSION" != "$ETHSPECIFY_VERSION" ]; then
echo "Version mismatch between WORKSPACE and ethspecify"
echo " WORKSPACE: $WORKSPACE_VERSION"
echo " specrefs/.ethspecify.yml: $ETHSPECIFY_VERSION"
echo " .ethspecify.yml: $ETHSPECIFY_VERSION"
exit 1
else
echo "Versions match: $WORKSPACE_VERSION"
@@ -26,7 +26,7 @@ jobs:
run: python3 -mpip install ethspecify
- name: Update spec references
run: ethspecify process --path=specrefs
run: ethspecify
- name: Check for differences
run: |
@@ -40,4 +40,4 @@ jobs:
fi
- name: Check spec references
run: ethspecify check --path=specrefs
run: ethspecify check

View File

@@ -2,7 +2,7 @@ name: Go
on:
push:
branches: [ master ]
branches: [ master, develop ]
pull_request:
branches: [ '*' ]
merge_group:

View File

@@ -33,9 +33,8 @@ formatters:
generated: lax
paths:
- validator/web/site_data.go
- .*_test.go
- proto
- tools/analyzers
- third_party$
- builtin$
- examples$
- examples$

19
api/fallback/BUILD.bazel Normal file
View File

@@ -0,0 +1,19 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"fallback.go",
"log.go",
],
importpath = "github.com/OffchainLabs/prysm/v7/api/fallback",
visibility = ["//visibility:public"],
deps = ["@com_github_sirupsen_logrus//:go_default_library"],
)
go_test(
name = "go_default_test",
srcs = ["fallback_test.go"],
embed = [":go_default_library"],
deps = ["//testing/assert:go_default_library"],
)

66
api/fallback/fallback.go Normal file
View File

@@ -0,0 +1,66 @@
package fallback
import (
"context"
"github.com/sirupsen/logrus"
)
// HostProvider is the subset of connection-provider methods that EnsureReady
// needs. Both grpc.GrpcConnectionProvider and rest.RestConnectionProvider
// satisfy this interface.
type HostProvider interface {
Hosts() []string
CurrentHost() string
SwitchHost(index int) error
}
// ReadyChecker can report whether the current endpoint is ready.
// iface.NodeClient satisfies this implicitly.
type ReadyChecker interface {
IsReady(ctx context.Context) bool
}
// EnsureReady iterates through the configured hosts and returns true as soon as
// one responds as ready. It starts from the provider's current host and wraps
// around using modular arithmetic, performing failover when a host is not ready.
func EnsureReady(ctx context.Context, provider HostProvider, checker ReadyChecker) bool {
hosts := provider.Hosts()
numHosts := len(hosts)
startingHost := provider.CurrentHost()
var attemptedHosts []string
// Find current index
currentIdx := 0
for i, h := range hosts {
if h == startingHost {
currentIdx = i
break
}
}
for i := range numHosts {
if checker.IsReady(ctx) {
if len(attemptedHosts) > 0 {
log.WithFields(logrus.Fields{
"previous": startingHost,
"current": provider.CurrentHost(),
"tried": attemptedHosts,
}).Info("Switched to responsive beacon node")
}
return true
}
attemptedHosts = append(attemptedHosts, provider.CurrentHost())
// Try next host if not the last iteration
if i < numHosts-1 {
nextIdx := (currentIdx + i + 1) % numHosts
if err := provider.SwitchHost(nextIdx); err != nil {
log.WithError(err).Error("Failed to switch host")
}
}
}
log.WithField("tried", attemptedHosts).Warn("No responsive beacon node found")
return false
}

View File

@@ -0,0 +1,94 @@
package fallback
import (
"context"
"testing"
"github.com/OffchainLabs/prysm/v7/testing/assert"
)
// mockHostProvider is a minimal HostProvider for unit tests.
type mockHostProvider struct {
hosts []string
hostIndex int
}
func (m *mockHostProvider) Hosts() []string { return m.hosts }
func (m *mockHostProvider) CurrentHost() string {
return m.hosts[m.hostIndex%len(m.hosts)]
}
func (m *mockHostProvider) SwitchHost(index int) error { m.hostIndex = index; return nil }
// mockReadyChecker records per-call IsReady results in sequence.
type mockReadyChecker struct {
results []bool
idx int
}
func (m *mockReadyChecker) IsReady(_ context.Context) bool {
if m.idx >= len(m.results) {
return false
}
r := m.results[m.idx]
m.idx++
return r
}
func TestEnsureReady_SingleHostReady(t *testing.T) {
provider := &mockHostProvider{hosts: []string{"http://host1:3500"}, hostIndex: 0}
checker := &mockReadyChecker{results: []bool{true}}
assert.Equal(t, true, EnsureReady(t.Context(), provider, checker))
assert.Equal(t, 0, provider.hostIndex)
}
func TestEnsureReady_SingleHostNotReady(t *testing.T) {
provider := &mockHostProvider{hosts: []string{"http://host1:3500"}, hostIndex: 0}
checker := &mockReadyChecker{results: []bool{false}}
assert.Equal(t, false, EnsureReady(t.Context(), provider, checker))
}
func TestEnsureReady_SingleHostError(t *testing.T) {
provider := &mockHostProvider{hosts: []string{"http://host1:3500"}, hostIndex: 0}
checker := &mockReadyChecker{results: []bool{false}}
assert.Equal(t, false, EnsureReady(t.Context(), provider, checker))
}
func TestEnsureReady_MultipleHostsFirstReady(t *testing.T) {
provider := &mockHostProvider{
hosts: []string{"http://host1:3500", "http://host2:3500"},
hostIndex: 0,
}
checker := &mockReadyChecker{results: []bool{true}}
assert.Equal(t, true, EnsureReady(t.Context(), provider, checker))
assert.Equal(t, 0, provider.hostIndex)
}
func TestEnsureReady_MultipleHostsFailoverToSecond(t *testing.T) {
provider := &mockHostProvider{
hosts: []string{"http://host1:3500", "http://host2:3500"},
hostIndex: 0,
}
checker := &mockReadyChecker{results: []bool{false, true}}
assert.Equal(t, true, EnsureReady(t.Context(), provider, checker))
assert.Equal(t, 1, provider.hostIndex)
}
func TestEnsureReady_MultipleHostsNoneReady(t *testing.T) {
provider := &mockHostProvider{
hosts: []string{"http://host1:3500", "http://host2:3500", "http://host3:3500"},
hostIndex: 0,
}
checker := &mockReadyChecker{results: []bool{false, false, false}}
assert.Equal(t, false, EnsureReady(t.Context(), provider, checker))
}
func TestEnsureReady_WrapAroundFromNonZeroIndex(t *testing.T) {
provider := &mockHostProvider{
hosts: []string{"http://host0:3500", "http://host1:3500", "http://host2:3500"},
hostIndex: 1,
}
// host1 (start) fails, host2 fails, host0 succeeds
checker := &mockReadyChecker{results: []bool{false, false, true}}
assert.Equal(t, true, EnsureReady(t.Context(), provider, checker))
assert.Equal(t, 0, provider.hostIndex)
}

9
api/fallback/log.go Normal file
View File

@@ -0,0 +1,9 @@
// Code generated by hack/gen-logs.sh; DO NOT EDIT.
// This file is created and regenerated automatically. Anything added here might get removed.
package fallback
import "github.com/sirupsen/logrus"
// The prefix for logs from this package will be the text after the last slash in the package path.
// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file.
var log = logrus.WithField("package", "api/fallback")

View File

@@ -3,13 +3,16 @@ load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"grpc_connection_provider.go",
"grpcutils.go",
"log.go",
"mock_grpc_provider.go",
"parameters.go",
],
importpath = "github.com/OffchainLabs/prysm/v7/api/grpc",
visibility = ["//visibility:public"],
deps = [
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//metadata:go_default_library",
@@ -18,12 +21,17 @@ go_library(
go_test(
name = "go_default_test",
srcs = ["grpcutils_test.go"],
srcs = [
"grpc_connection_provider_test.go",
"grpcutils_test.go",
],
embed = [":go_default_library"],
deps = [
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"@com_github_sirupsen_logrus//hooks/test:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//credentials/insecure:go_default_library",
"@org_golang_google_grpc//metadata:go_default_library",
],
)

View File

@@ -0,0 +1,186 @@
package grpc
import (
"context"
"strings"
"sync"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"google.golang.org/grpc"
)
// GrpcConnectionProvider manages gRPC connections for failover support.
// It allows switching between different beacon node endpoints when the current one becomes unavailable.
// Only one connection is maintained at a time - when switching hosts, the old connection is closed.
type GrpcConnectionProvider interface {
// CurrentConn returns the currently active gRPC connection.
// The connection is created lazily on first call.
// Returns nil if the provider has been closed.
CurrentConn() *grpc.ClientConn
// CurrentHost returns the address of the currently active endpoint.
CurrentHost() string
// Hosts returns all configured endpoint addresses.
Hosts() []string
// SwitchHost switches to the endpoint at the given index.
// The new connection is created lazily on next CurrentConn() call.
SwitchHost(index int) error
// ConnectionCounter returns a monotonically increasing counter that increments
// each time SwitchHost changes the active endpoint. This allows consumers to
// detect connection changes even when the host string returns to a previous value
// (e.g., host0 → host1 → host0).
ConnectionCounter() uint64
// Close closes the current connection.
Close()
}
type grpcConnectionProvider struct {
// Immutable after construction - no lock needed for reads
endpoints []string
ctx context.Context
dialOpts []grpc.DialOption
// Current connection state (protected by mutex)
currentIndex uint64
conn *grpc.ClientConn
connCounter uint64
mu sync.Mutex
closed bool
}
// NewGrpcConnectionProvider creates a new connection provider that manages gRPC connections.
// The endpoint parameter can be a comma-separated list of addresses (e.g., "host1:4000,host2:4000").
// Only one connection is maintained at a time, created lazily on first use.
func NewGrpcConnectionProvider(
ctx context.Context,
endpoint string,
dialOpts []grpc.DialOption,
) (GrpcConnectionProvider, error) {
endpoints := parseEndpoints(endpoint)
if len(endpoints) == 0 {
return nil, errors.New("no gRPC endpoints provided")
}
log.WithFields(logrus.Fields{
"endpoints": endpoints,
"count": len(endpoints),
}).Info("Initialized gRPC connection provider")
return &grpcConnectionProvider{
endpoints: endpoints,
ctx: ctx,
dialOpts: dialOpts,
}, nil
}
// parseEndpoints splits a comma-separated endpoint string into individual endpoints.
func parseEndpoints(endpoint string) []string {
if endpoint == "" {
return nil
}
endpoints := make([]string, 0, 1)
for p := range strings.SplitSeq(endpoint, ",") {
if p = strings.TrimSpace(p); p != "" {
endpoints = append(endpoints, p)
}
}
return endpoints
}
func (p *grpcConnectionProvider) CurrentConn() *grpc.ClientConn {
p.mu.Lock()
defer p.mu.Unlock()
if p.closed {
return nil
}
// Return existing connection if available
if p.conn != nil {
return p.conn
}
// Create connection lazily
ep := p.endpoints[p.currentIndex]
conn, err := grpc.DialContext(p.ctx, ep, p.dialOpts...)
if err != nil {
log.WithError(err).WithField("endpoint", ep).Error("Failed to create gRPC connection")
return nil
}
p.conn = conn
log.WithField("endpoint", ep).Debug("Created gRPC connection")
return conn
}
func (p *grpcConnectionProvider) CurrentHost() string {
p.mu.Lock()
defer p.mu.Unlock()
return p.endpoints[p.currentIndex]
}
func (p *grpcConnectionProvider) Hosts() []string {
// Return a copy to maintain immutability
hosts := make([]string, len(p.endpoints))
copy(hosts, p.endpoints)
return hosts
}
func (p *grpcConnectionProvider) SwitchHost(index int) error {
if index < 0 || index >= len(p.endpoints) {
return errors.Errorf("invalid host index %d, must be between 0 and %d", index, len(p.endpoints)-1)
}
p.mu.Lock()
defer p.mu.Unlock()
if uint64(index) == p.currentIndex {
return nil // Already on this host
}
oldHost := p.endpoints[p.currentIndex]
oldConn := p.conn
p.conn = nil // Clear immediately - new connection created lazily
p.currentIndex = uint64(index)
p.connCounter++
// Close old connection asynchronously to avoid blocking the caller
if oldConn != nil {
go func() {
if err := oldConn.Close(); err != nil {
log.WithError(err).WithField("endpoint", oldHost).Debug("Failed to close previous connection")
}
}()
}
log.WithFields(logrus.Fields{
"previousHost": oldHost,
"newHost": p.endpoints[index],
}).Debug("Switched gRPC endpoint")
return nil
}
func (p *grpcConnectionProvider) ConnectionCounter() uint64 {
p.mu.Lock()
defer p.mu.Unlock()
return p.connCounter
}
func (p *grpcConnectionProvider) Close() {
p.mu.Lock()
defer p.mu.Unlock()
if p.closed {
return
}
p.closed = true
if p.conn != nil {
if err := p.conn.Close(); err != nil {
log.WithError(err).WithField("endpoint", p.endpoints[p.currentIndex]).Debug("Failed to close gRPC connection")
}
p.conn = nil
}
}

View File

@@ -0,0 +1,207 @@
package grpc
import (
"context"
"net"
"reflect"
"strings"
"testing"
"github.com/OffchainLabs/prysm/v7/testing/assert"
"github.com/OffchainLabs/prysm/v7/testing/require"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
)
func TestParseEndpoints(t *testing.T) {
tests := []struct {
name string
input string
expected []string
}{
{"single endpoint", "localhost:4000", []string{"localhost:4000"}},
{"multiple endpoints", "host1:4000,host2:4000,host3:4000", []string{"host1:4000", "host2:4000", "host3:4000"}},
{"endpoints with spaces", "host1:4000, host2:4000 , host3:4000", []string{"host1:4000", "host2:4000", "host3:4000"}},
{"empty string", "", nil},
{"only commas", ",,,", []string{}},
{"trailing comma", "host1:4000,host2:4000,", []string{"host1:4000", "host2:4000"}},
{"leading comma", ",host1:4000,host2:4000", []string{"host1:4000", "host2:4000"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := parseEndpoints(tt.input)
if !reflect.DeepEqual(tt.expected, got) {
t.Errorf("parseEndpoints(%q) = %v, want %v", tt.input, got, tt.expected)
}
})
}
}
func TestNewGrpcConnectionProvider_Errors(t *testing.T) {
t.Run("no endpoints", func(t *testing.T) {
dialOpts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
_, err := NewGrpcConnectionProvider(context.Background(), "", dialOpts)
require.ErrorContains(t, "no gRPC endpoints provided", err)
})
}
func TestGrpcConnectionProvider_LazyConnection(t *testing.T) {
// Start only one server but configure provider with two endpoints
lis, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
server := grpc.NewServer()
go func() { _ = server.Serve(lis) }()
defer server.Stop()
validAddr := lis.Addr().String()
invalidAddr := "127.0.0.1:1" // Port 1 is unlikely to be listening
// Provider should succeed even though second endpoint is invalid (lazy connections)
endpoint := validAddr + "," + invalidAddr
ctx := context.Background()
dialOpts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
provider, err := NewGrpcConnectionProvider(ctx, endpoint, dialOpts)
require.NoError(t, err, "Provider creation should succeed with lazy connections")
defer func() { provider.Close() }()
// First endpoint should work
conn := provider.CurrentConn()
assert.NotNil(t, conn, "First connection should be created lazily")
}
func TestGrpcConnectionProvider_SingleConnectionModel(t *testing.T) {
// Create provider with 3 endpoints
var addrs []string
var servers []*grpc.Server
for range 3 {
lis, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
server := grpc.NewServer()
go func() { _ = server.Serve(lis) }()
addrs = append(addrs, lis.Addr().String())
servers = append(servers, server)
}
defer func() {
for _, s := range servers {
s.Stop()
}
}()
endpoint := strings.Join(addrs, ",")
ctx := context.Background()
dialOpts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
provider, err := NewGrpcConnectionProvider(ctx, endpoint, dialOpts)
require.NoError(t, err)
defer func() { provider.Close() }()
// Access the internal state to verify single connection behavior
p := provider.(*grpcConnectionProvider)
// Initially no connection
p.mu.Lock()
assert.Equal(t, (*grpc.ClientConn)(nil), p.conn, "Connection should be nil before access")
p.mu.Unlock()
// Access connection - should create one
conn0 := provider.CurrentConn()
assert.NotNil(t, conn0)
p.mu.Lock()
assert.NotNil(t, p.conn, "Connection should be created after CurrentConn()")
firstConn := p.conn
p.mu.Unlock()
// Call CurrentConn again - should return same connection
conn0Again := provider.CurrentConn()
assert.Equal(t, conn0, conn0Again, "Should return same connection")
// Switch to different host - old connection should be closed, new one created lazily
require.NoError(t, provider.SwitchHost(1))
p.mu.Lock()
assert.Equal(t, (*grpc.ClientConn)(nil), p.conn, "Connection should be nil after SwitchHost (lazy)")
p.mu.Unlock()
// Get new connection
conn1 := provider.CurrentConn()
assert.NotNil(t, conn1)
assert.NotEqual(t, firstConn, conn1, "Should be a different connection after switching hosts")
}
// testProvider creates a provider with n test servers and returns cleanup function.
func testProvider(t *testing.T, n int) (GrpcConnectionProvider, []string, func()) {
var addrs []string
var cleanups []func()
for range n {
lis, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
server := grpc.NewServer()
go func() { _ = server.Serve(lis) }()
addrs = append(addrs, lis.Addr().String())
cleanups = append(cleanups, server.Stop)
}
endpoint := strings.Join(addrs, ",")
ctx := context.Background()
dialOpts := []grpc.DialOption{grpc.WithTransportCredentials(insecure.NewCredentials())}
provider, err := NewGrpcConnectionProvider(ctx, endpoint, dialOpts)
require.NoError(t, err)
cleanup := func() {
provider.Close()
for _, c := range cleanups {
c()
}
}
return provider, addrs, cleanup
}
func TestGrpcConnectionProvider(t *testing.T) {
provider, addrs, cleanup := testProvider(t, 3)
defer cleanup()
t.Run("initial state", func(t *testing.T) {
assert.Equal(t, 3, len(provider.Hosts()))
assert.Equal(t, addrs[0], provider.CurrentHost())
assert.NotNil(t, provider.CurrentConn())
})
t.Run("SwitchHost", func(t *testing.T) {
require.NoError(t, provider.SwitchHost(1))
assert.Equal(t, addrs[1], provider.CurrentHost())
assert.NotNil(t, provider.CurrentConn()) // New connection created lazily
require.NoError(t, provider.SwitchHost(0))
assert.Equal(t, addrs[0], provider.CurrentHost())
require.ErrorContains(t, "invalid host index", provider.SwitchHost(-1))
require.ErrorContains(t, "invalid host index", provider.SwitchHost(3))
})
t.Run("SwitchHost circular", func(t *testing.T) {
// Test round-robin style switching using SwitchHost with manual index
indices := []int{1, 2, 0, 1} // Simulate circular switching
for i, idx := range indices {
require.NoError(t, provider.SwitchHost(idx))
assert.Equal(t, addrs[idx], provider.CurrentHost(), "iteration %d", i)
}
})
t.Run("Hosts returns copy", func(t *testing.T) {
hosts := provider.Hosts()
original := hosts[0]
hosts[0] = "modified"
assert.Equal(t, original, provider.Hosts()[0])
})
}
func TestGrpcConnectionProvider_Close(t *testing.T) {
provider, _, cleanup := testProvider(t, 1)
defer cleanup()
assert.NotNil(t, provider.CurrentConn())
provider.Close()
assert.Equal(t, (*grpc.ClientConn)(nil), provider.CurrentConn())
provider.Close() // Double close is safe
}

View File

@@ -0,0 +1,27 @@
package grpc
import "google.golang.org/grpc"
// MockGrpcProvider implements GrpcConnectionProvider for testing.
type MockGrpcProvider struct {
MockConn *grpc.ClientConn
MockHosts []string
CurrentIndex int
ConnCounter uint64
}
func (m *MockGrpcProvider) CurrentConn() *grpc.ClientConn { return m.MockConn }
func (m *MockGrpcProvider) CurrentHost() string {
if len(m.MockHosts) > 0 {
return m.MockHosts[m.CurrentIndex]
}
return ""
}
func (m *MockGrpcProvider) Hosts() []string { return m.MockHosts }
func (m *MockGrpcProvider) SwitchHost(idx int) error {
m.CurrentIndex = idx
m.ConnCounter++
return nil
}
func (m *MockGrpcProvider) ConnectionCounter() uint64 { return m.ConnCounter }
func (m *MockGrpcProvider) Close() {}

34
api/rest/BUILD.bazel Normal file
View File

@@ -0,0 +1,34 @@
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
go_library(
name = "go_default_library",
srcs = [
"log.go",
"mock_rest_provider.go",
"rest_connection_provider.go",
"rest_handler.go",
],
importpath = "github.com/OffchainLabs/prysm/v7/api/rest",
visibility = ["//visibility:public"],
deps = [
"//api:go_default_library",
"//api/apiutil:go_default_library",
"//api/client:go_default_library",
"//config/params:go_default_library",
"//network/httputil:go_default_library",
"//runtime/version:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opentelemetry_go_contrib_instrumentation_net_http_otelhttp//:go_default_library",
],
)
go_test(
name = "go_default_test",
srcs = ["rest_connection_provider_test.go"],
embed = [":go_default_library"],
deps = [
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
],
)

9
api/rest/log.go Normal file
View File

@@ -0,0 +1,9 @@
// Code generated by hack/gen-logs.sh; DO NOT EDIT.
// This file is created and regenerated automatically. Anything added here might get removed.
package rest
import "github.com/sirupsen/logrus"
// The prefix for logs from this package will be the text after the last slash in the package path.
// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file.
var log = logrus.WithField("package", "api/rest")

View File

@@ -0,0 +1,46 @@
package rest
import (
"bytes"
"context"
"net/http"
)
// MockRestProvider implements RestConnectionProvider for testing.
type MockRestProvider struct {
MockClient *http.Client
MockHandler Handler
MockHosts []string
HostIndex int
}
func (m *MockRestProvider) HttpClient() *http.Client { return m.MockClient }
func (m *MockRestProvider) Handler() Handler { return m.MockHandler }
func (m *MockRestProvider) CurrentHost() string {
if len(m.MockHosts) > 0 {
return m.MockHosts[m.HostIndex%len(m.MockHosts)]
}
return ""
}
func (m *MockRestProvider) Hosts() []string { return m.MockHosts }
func (m *MockRestProvider) SwitchHost(index int) error { m.HostIndex = index; return nil }
// MockHandler implements Handler for testing.
type MockHandler struct {
MockHost string
}
func (m *MockHandler) Get(_ context.Context, _ string, _ any) error { return nil }
func (m *MockHandler) GetStatusCode(_ context.Context, _ string) (int, error) {
return http.StatusOK, nil
}
func (m *MockHandler) GetSSZ(_ context.Context, _ string) ([]byte, http.Header, error) {
return nil, nil, nil
}
func (m *MockHandler) Post(_ context.Context, _ string, _ map[string]string, _ *bytes.Buffer, _ any) error {
return nil
}
func (m *MockHandler) PostSSZ(_ context.Context, _ string, _ map[string]string, _ *bytes.Buffer) ([]byte, http.Header, error) {
return nil, nil, nil
}
func (m *MockHandler) Host() string { return m.MockHost }

View File

@@ -0,0 +1,158 @@
package rest
import (
"net/http"
"strings"
"sync/atomic"
"time"
"github.com/OffchainLabs/prysm/v7/api/client"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
)
// RestConnectionProvider manages HTTP client configuration for REST API with failover support.
// It allows switching between different beacon node REST endpoints when the current one becomes unavailable.
type RestConnectionProvider interface {
// HttpClient returns the configured HTTP client with headers, timeout, and optional tracing.
HttpClient() *http.Client
// Handler returns the REST handler for making API requests.
Handler() Handler
// CurrentHost returns the current REST API endpoint URL.
CurrentHost() string
// Hosts returns all configured REST API endpoint URLs.
Hosts() []string
// SwitchHost switches to the endpoint at the given index.
SwitchHost(index int) error
}
// RestConnectionProviderOption is a functional option for configuring the REST connection provider.
type RestConnectionProviderOption func(*restConnectionProvider)
// WithHttpTimeout sets the HTTP client timeout.
func WithHttpTimeout(timeout time.Duration) RestConnectionProviderOption {
return func(p *restConnectionProvider) {
p.timeout = timeout
}
}
// WithHttpHeaders sets custom HTTP headers to include in all requests.
func WithHttpHeaders(headers map[string][]string) RestConnectionProviderOption {
return func(p *restConnectionProvider) {
p.headers = headers
}
}
// WithTracing enables OpenTelemetry tracing for HTTP requests.
func WithTracing() RestConnectionProviderOption {
return func(p *restConnectionProvider) {
p.enableTracing = true
}
}
type restConnectionProvider struct {
endpoints []string
httpClient *http.Client
restHandler *handler
currentIndex atomic.Uint64
timeout time.Duration
headers map[string][]string
enableTracing bool
}
// NewRestConnectionProvider creates a new REST connection provider that manages HTTP client configuration.
// The endpoint parameter can be a comma-separated list of URLs (e.g., "http://host1:3500,http://host2:3500").
func NewRestConnectionProvider(endpoint string, opts ...RestConnectionProviderOption) (RestConnectionProvider, error) {
endpoints := parseEndpoints(endpoint)
if len(endpoints) == 0 {
return nil, errors.New("no REST API endpoints provided")
}
p := &restConnectionProvider{
endpoints: endpoints,
}
for _, opt := range opts {
opt(p)
}
// Build the HTTP transport chain
var transport http.RoundTripper = http.DefaultTransport
// Add custom headers if configured
if len(p.headers) > 0 {
transport = client.NewCustomHeadersTransport(transport, p.headers)
}
// Add tracing if enabled
if p.enableTracing {
transport = otelhttp.NewTransport(transport)
}
p.httpClient = &http.Client{
Timeout: p.timeout,
Transport: transport,
}
// Create the REST handler with the HTTP client and initial host
p.restHandler = newHandler(*p.httpClient, endpoints[0])
log.WithFields(logrus.Fields{
"endpoints": endpoints,
"count": len(endpoints),
}).Info("Initialized REST connection provider")
return p, nil
}
// parseEndpoints splits a comma-separated endpoint string into individual endpoints.
func parseEndpoints(endpoint string) []string {
if endpoint == "" {
return nil
}
endpoints := make([]string, 0, 1)
for p := range strings.SplitSeq(endpoint, ",") {
if p = strings.TrimSpace(p); p != "" {
endpoints = append(endpoints, p)
}
}
return endpoints
}
func (p *restConnectionProvider) HttpClient() *http.Client {
return p.httpClient
}
func (p *restConnectionProvider) Handler() Handler {
return p.restHandler
}
func (p *restConnectionProvider) CurrentHost() string {
return p.endpoints[p.currentIndex.Load()]
}
func (p *restConnectionProvider) Hosts() []string {
// Return a copy to maintain immutability
hosts := make([]string, len(p.endpoints))
copy(hosts, p.endpoints)
return hosts
}
func (p *restConnectionProvider) SwitchHost(index int) error {
if index < 0 || index >= len(p.endpoints) {
return errors.Errorf("invalid host index %d, must be between 0 and %d", index, len(p.endpoints)-1)
}
oldIdx := p.currentIndex.Load()
p.currentIndex.Store(uint64(index))
// Update the rest handler's host
p.restHandler.SwitchHost(p.endpoints[index])
log.WithFields(logrus.Fields{
"previousHost": p.endpoints[oldIdx],
"newHost": p.endpoints[index],
}).Debug("Switched REST endpoint")
return nil
}

View File

@@ -0,0 +1,80 @@
package rest
import (
"reflect"
"testing"
"github.com/OffchainLabs/prysm/v7/testing/assert"
"github.com/OffchainLabs/prysm/v7/testing/require"
)
func TestParseEndpoints(t *testing.T) {
tests := []struct {
name string
input string
expected []string
}{
{"single endpoint", "http://localhost:3500", []string{"http://localhost:3500"}},
{"multiple endpoints", "http://host1:3500,http://host2:3500,http://host3:3500", []string{"http://host1:3500", "http://host2:3500", "http://host3:3500"}},
{"endpoints with spaces", "http://host1:3500, http://host2:3500 , http://host3:3500", []string{"http://host1:3500", "http://host2:3500", "http://host3:3500"}},
{"empty string", "", nil},
{"only commas", ",,,", []string{}},
{"trailing comma", "http://host1:3500,http://host2:3500,", []string{"http://host1:3500", "http://host2:3500"}},
{"leading comma", ",http://host1:3500,http://host2:3500", []string{"http://host1:3500", "http://host2:3500"}},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := parseEndpoints(tt.input)
if !reflect.DeepEqual(tt.expected, got) {
t.Errorf("parseEndpoints(%q) = %v, want %v", tt.input, got, tt.expected)
}
})
}
}
func TestNewRestConnectionProvider_Errors(t *testing.T) {
t.Run("no endpoints", func(t *testing.T) {
_, err := NewRestConnectionProvider("")
require.ErrorContains(t, "no REST API endpoints provided", err)
})
}
func TestRestConnectionProvider(t *testing.T) {
provider, err := NewRestConnectionProvider("http://host1:3500,http://host2:3500,http://host3:3500")
require.NoError(t, err)
t.Run("initial state", func(t *testing.T) {
assert.Equal(t, 3, len(provider.Hosts()))
assert.Equal(t, "http://host1:3500", provider.CurrentHost())
assert.NotNil(t, provider.HttpClient())
})
t.Run("SwitchHost", func(t *testing.T) {
require.NoError(t, provider.SwitchHost(1))
assert.Equal(t, "http://host2:3500", provider.CurrentHost())
require.NoError(t, provider.SwitchHost(0))
assert.Equal(t, "http://host1:3500", provider.CurrentHost())
require.ErrorContains(t, "invalid host index", provider.SwitchHost(-1))
require.ErrorContains(t, "invalid host index", provider.SwitchHost(3))
})
t.Run("Hosts returns copy", func(t *testing.T) {
hosts := provider.Hosts()
original := hosts[0]
hosts[0] = "modified"
assert.Equal(t, original, provider.Hosts()[0])
})
}
func TestRestConnectionProvider_WithOptions(t *testing.T) {
headers := map[string][]string{"Authorization": {"Bearer token"}}
provider, err := NewRestConnectionProvider(
"http://localhost:3500",
WithHttpHeaders(headers),
WithHttpTimeout(30000000000), // 30 seconds in nanoseconds
WithTracing(),
)
require.NoError(t, err)
assert.NotNil(t, provider.HttpClient())
assert.Equal(t, "http://localhost:3500", provider.CurrentHost())
}

View File

@@ -1,4 +1,4 @@
package beacon_api
package rest
import (
"bytes"
@@ -21,37 +21,46 @@ import (
type reqOption func(*http.Request)
type RestHandler interface {
// Handler defines the interface for making REST API requests.
type Handler interface {
Get(ctx context.Context, endpoint string, resp any) error
GetStatusCode(ctx context.Context, endpoint string) (int, error)
GetSSZ(ctx context.Context, endpoint string) ([]byte, http.Header, error)
Post(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer, resp any) error
PostSSZ(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer) ([]byte, http.Header, error)
HttpClient() *http.Client
Host() string
SetHost(host string)
}
type BeaconApiRestHandler struct {
type handler struct {
client http.Client
host string
reqOverrides []reqOption
}
// NewBeaconApiRestHandler returns a RestHandler
func NewBeaconApiRestHandler(client http.Client, host string) RestHandler {
brh := &BeaconApiRestHandler{
// newHandler returns a *handler for internal use within the rest package.
func newHandler(client http.Client, host string) *handler {
rh := &handler{
client: client,
host: host,
}
brh.appendAcceptOverride()
return brh
rh.appendAcceptOverride()
return rh
}
// NewHandler returns a Handler
func NewHandler(client http.Client, host string) Handler {
rh := &handler{
client: client,
host: host,
}
rh.appendAcceptOverride()
return rh
}
// appendAcceptOverride enables the Accept header to be customized at runtime via an environment variable.
// This is specified as an env var because it is a niche option that prysm may use for performance testing or debugging
// bug which users are unlikely to need. Using an env var keeps the set of user-facing flags cleaner.
func (c *BeaconApiRestHandler) appendAcceptOverride() {
func (c *handler) appendAcceptOverride() {
if accept := os.Getenv(params.EnvNameOverrideAccept); accept != "" {
c.reqOverrides = append(c.reqOverrides, func(req *http.Request) {
req.Header.Set("Accept", accept)
@@ -60,18 +69,18 @@ func (c *BeaconApiRestHandler) appendAcceptOverride() {
}
// HttpClient returns the underlying HTTP client of the handler
func (c *BeaconApiRestHandler) HttpClient() *http.Client {
func (c *handler) HttpClient() *http.Client {
return &c.client
}
// Host returns the underlying HTTP host
func (c *BeaconApiRestHandler) Host() string {
func (c *handler) Host() string {
return c.host
}
// Get sends a GET request and decodes the response body as a JSON object into the passed in object.
// If an HTTP error is returned, the body is decoded as a DefaultJsonError JSON object and returned as the first return value.
func (c *BeaconApiRestHandler) Get(ctx context.Context, endpoint string, resp any) error {
func (c *handler) Get(ctx context.Context, endpoint string, resp any) error {
url := c.host + endpoint
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
@@ -94,7 +103,7 @@ func (c *BeaconApiRestHandler) Get(ctx context.Context, endpoint string, resp an
// GetStatusCode sends a GET request and returns only the HTTP status code.
// This is useful for endpoints like /eth/v1/node/health that communicate status via HTTP codes
// (200 = ready, 206 = syncing, 503 = unavailable) rather than response bodies.
func (c *BeaconApiRestHandler) GetStatusCode(ctx context.Context, endpoint string) (int, error) {
func (c *handler) GetStatusCode(ctx context.Context, endpoint string) (int, error) {
url := c.host + endpoint
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
@@ -113,7 +122,7 @@ func (c *BeaconApiRestHandler) GetStatusCode(ctx context.Context, endpoint strin
return httpResp.StatusCode, nil
}
func (c *BeaconApiRestHandler) GetSSZ(ctx context.Context, endpoint string) ([]byte, http.Header, error) {
func (c *handler) GetSSZ(ctx context.Context, endpoint string) ([]byte, http.Header, error) {
url := c.host + endpoint
req, err := http.NewRequestWithContext(ctx, http.MethodGet, url, nil)
if err != nil {
@@ -168,7 +177,7 @@ func (c *BeaconApiRestHandler) GetSSZ(ctx context.Context, endpoint string) ([]b
// Post sends a POST request and decodes the response body as a JSON object into the passed in object.
// If an HTTP error is returned, the body is decoded as a DefaultJsonError JSON object and returned as the first return value.
func (c *BeaconApiRestHandler) Post(
func (c *handler) Post(
ctx context.Context,
apiEndpoint string,
headers map[string]string,
@@ -204,7 +213,7 @@ func (c *BeaconApiRestHandler) Post(
}
// PostSSZ sends a POST request and prefers an SSZ (application/octet-stream) response body.
func (c *BeaconApiRestHandler) PostSSZ(
func (c *handler) PostSSZ(
ctx context.Context,
apiEndpoint string,
headers map[string]string,
@@ -305,6 +314,6 @@ func decodeResp(httpResp *http.Response, resp any) error {
return nil
}
func (c *BeaconApiRestHandler) SetHost(host string) {
func (c *handler) SwitchHost(host string) {
c.host = host
}

View File

@@ -7,7 +7,6 @@ go_library(
"payload_attestation.go",
"pending_payment.go",
"proposer_slashing.go",
"withdrawal.go",
],
importpath = "github.com/OffchainLabs/prysm/v7/beacon-chain/core/gloas",
visibility = ["//visibility:public"],

View File

@@ -17,27 +17,50 @@ import (
)
// ProcessExecutionPayloadBid processes a signed execution payload bid in the Gloas fork.
// Spec v1.7.0-alpha.0 (pseudocode):
// process_execution_payload_bid(state: BeaconState, block: BeaconBlock):
//
// signed_bid = block.body.signed_execution_payload_bid
// bid = signed_bid.message
// builder_index = bid.builder_index
// amount = bid.value
// if builder_index == BUILDER_INDEX_SELF_BUILD:
// assert amount == 0
// assert signed_bid.signature == G2_POINT_AT_INFINITY
// else:
// assert is_active_builder(state, builder_index)
// assert can_builder_cover_bid(state, builder_index, amount)
// assert verify_execution_payload_bid_signature(state, signed_bid)
// assert bid.slot == block.slot
// assert bid.parent_block_hash == state.latest_block_hash
// assert bid.parent_block_root == block.parent_root
// assert bid.prev_randao == get_randao_mix(state, get_current_epoch(state))
// if amount > 0:
// state.builder_pending_payments[...] = BuilderPendingPayment(weight=0, withdrawal=BuilderPendingWithdrawal(fee_recipient=bid.fee_recipient, amount=amount, builder_index=builder_index))
// state.latest_execution_payload_bid = bid
// <spec fn="process_execution_payload_bid" fork="gloas" hash="6dc696bb">
// def process_execution_payload_bid(state: BeaconState, block: BeaconBlock) -> None:
// signed_bid = block.body.signed_execution_payload_bid
// bid = signed_bid.message
// builder_index = bid.builder_index
// amount = bid.value
//
// # For self-builds, amount must be zero regardless of withdrawal credential prefix
// if builder_index == BUILDER_INDEX_SELF_BUILD:
// assert amount == 0
// assert signed_bid.signature == bls.G2_POINT_AT_INFINITY
// else:
// # Verify that the builder is active
// assert is_active_builder(state, builder_index)
// # Verify that the builder has funds to cover the bid
// assert can_builder_cover_bid(state, builder_index, amount)
// # Verify that the bid signature is valid
// assert verify_execution_payload_bid_signature(state, signed_bid)
//
// # Verify that the bid is for the current slot
// assert bid.slot == block.slot
// # Verify that the bid is for the right parent block
// assert bid.parent_block_hash == state.latest_block_hash
// assert bid.parent_block_root == block.parent_root
// assert bid.prev_randao == get_randao_mix(state, get_current_epoch(state))
//
// # Record the pending payment if there is some payment
// if amount > 0:
// pending_payment = BuilderPendingPayment(
// weight=0,
// withdrawal=BuilderPendingWithdrawal(
// fee_recipient=bid.fee_recipient,
// amount=amount,
// builder_index=builder_index,
// ),
// )
// state.builder_pending_payments[SLOTS_PER_EPOCH + bid.slot % SLOTS_PER_EPOCH] = (
// pending_payment
// )
//
// # Cache the signed execution payload bid
// state.latest_execution_payload_bid = bid
// </spec>
func ProcessExecutionPayloadBid(st state.BeaconState, block interfaces.ReadOnlyBeaconBlock) error {
signedBid, err := block.Body().SignedExecutionPayloadBid()
if err != nil {

View File

@@ -24,14 +24,21 @@ import (
)
// ProcessPayloadAttestations validates payload attestations in a block body.
// Spec v1.7.0-alpha.0 (pseudocode):
// process_payload_attestation(state: BeaconState, payload_attestation: PayloadAttestation):
//
// data = payload_attestation.data
// assert data.beacon_block_root == state.latest_block_header.parent_root
// assert data.slot + 1 == state.slot
// indexed = get_indexed_payload_attestation(state, data.slot, payload_attestation)
// assert is_valid_indexed_payload_attestation(state, indexed)
// <spec fn="process_payload_attestation" fork="gloas" hash="f46bf0b0">
// def process_payload_attestation(
// state: BeaconState, payload_attestation: PayloadAttestation
// ) -> None:
// data = payload_attestation.data
//
// # Check that the attestation is for the parent beacon block
// assert data.beacon_block_root == state.latest_block_header.parent_root
// # Check that the attestation is for the previous slot
// assert data.slot + 1 == state.slot
// # Verify signature
// indexed_payload_attestation = get_indexed_payload_attestation(state, payload_attestation)
// assert is_valid_indexed_payload_attestation(state, indexed_payload_attestation)
// </spec>
func ProcessPayloadAttestations(ctx context.Context, st state.BeaconState, body interfaces.ReadOnlyBeaconBlockBody) error {
atts, err := body.PayloadAttestations()
if err != nil {
@@ -90,17 +97,24 @@ func indexedPayloadAttestation(ctx context.Context, st state.ReadOnlyBeaconState
}
// payloadCommittee returns the payload timeliness committee for a given slot for the state.
// Spec v1.7.0-alpha.0 (pseudocode):
// get_ptc(state: BeaconState, slot: Slot) -> Vector[ValidatorIndex, PTC_SIZE]:
//
// epoch = compute_epoch_at_slot(slot)
// seed = hash(get_seed(state, epoch, DOMAIN_PTC_ATTESTER) + uint_to_bytes(slot))
// indices = []
// committees_per_slot = get_committee_count_per_slot(state, epoch)
// for i in range(committees_per_slot):
// committee = get_beacon_committee(state, slot, CommitteeIndex(i))
// indices.extend(committee)
// return compute_balance_weighted_selection(state, indices, seed, size=PTC_SIZE, shuffle_indices=False)
// <spec fn="get_ptc" fork="gloas" hash="ae15f761">
// def get_ptc(state: BeaconState, slot: Slot) -> Vector[ValidatorIndex, PTC_SIZE]:
// """
// Get the payload timeliness committee for the given ``slot``.
// """
// epoch = compute_epoch_at_slot(slot)
// seed = hash(get_seed(state, epoch, DOMAIN_PTC_ATTESTER) + uint_to_bytes(slot))
// indices: List[ValidatorIndex] = []
// # Concatenate all committees for this slot in order
// committees_per_slot = get_committee_count_per_slot(state, epoch)
// for i in range(committees_per_slot):
// committee = get_beacon_committee(state, slot, CommitteeIndex(i))
// indices.extend(committee)
// return compute_balance_weighted_selection(
// state, indices, seed, size=PTC_SIZE, shuffle_indices=False
// )
// </spec>
func payloadCommittee(ctx context.Context, st state.ReadOnlyBeaconState, slot primitives.Slot) ([]primitives.ValidatorIndex, error) {
epoch := slots.ToEpoch(slot)
seed, err := ptcSeed(st, epoch, slot)
@@ -152,17 +166,35 @@ func ptcSeed(st state.ReadOnlyBeaconState, epoch primitives.Epoch, slot primitiv
}
// selectByBalance selects a balance-weighted subset of input candidates.
// Spec v1.7.0-alpha.0 (pseudocode):
// compute_balance_weighted_selection(state, indices, seed, size, shuffle_indices):
// Note: shuffle_indices is false for PTC.
//
// total = len(indices); selected = []; i = 0
// while len(selected) < size:
// next = i % total
// if shuffle_indices: next = compute_shuffled_index(next, total, seed)
// if compute_balance_weighted_acceptance(state, indices[next], seed, i):
// selected.append(indices[next])
// i += 1
// <spec fn="compute_balance_weighted_selection" fork="gloas" hash="2c9f1c23">
// def compute_balance_weighted_selection(
// state: BeaconState,
// indices: Sequence[ValidatorIndex],
// seed: Bytes32,
// size: uint64,
// shuffle_indices: bool,
// ) -> Sequence[ValidatorIndex]:
// """
// Return ``size`` indices sampled by effective balance, using ``indices``
// as candidates. If ``shuffle_indices`` is ``True``, candidate indices
// are themselves sampled from ``indices`` by shuffling it, otherwise
// ``indices`` is traversed in order.
// """
// total = uint64(len(indices))
// assert total > 0
// selected: List[ValidatorIndex] = []
// i = uint64(0)
// while len(selected) < size:
// next_index = i % total
// if shuffle_indices:
// next_index = compute_shuffled_index(next_index, total, seed)
// candidate_index = indices[next_index]
// if compute_balance_weighted_acceptance(state, candidate_index, seed, i):
// selected.append(candidate_index)
// i += 1
// return selected
// </spec>
func selectByBalanceFill(
ctx context.Context,
st state.ReadOnlyBeaconState,
@@ -199,15 +231,22 @@ func selectByBalanceFill(
}
// acceptByBalance determines if a validator is accepted based on its effective balance.
// Spec v1.7.0-alpha.0 (pseudocode):
// compute_balance_weighted_acceptance(state, index, seed, i):
//
// MAX_RANDOM_VALUE = 2**16 - 1
// random_bytes = hash(seed + uint_to_bytes(i // 16))
// offset = i % 16 * 2
// random_value = bytes_to_uint64(random_bytes[offset:offset+2])
// effective_balance = state.validators[index].effective_balance
// return effective_balance * MAX_RANDOM_VALUE >= MAX_EFFECTIVE_BALANCE_ELECTRA * random_value
// <spec fn="compute_balance_weighted_acceptance" fork="gloas" hash="9954dcd0">
// def compute_balance_weighted_acceptance(
// state: BeaconState, index: ValidatorIndex, seed: Bytes32, i: uint64
// ) -> bool:
// """
// Return whether to accept the selection of the validator ``index``, with probability
// proportional to its ``effective_balance``, and randomness given by ``seed`` and ``i``.
// """
// MAX_RANDOM_VALUE = 2**16 - 1
// random_bytes = hash(seed + uint_to_bytes(i // 16))
// offset = i % 16 * 2
// random_value = bytes_to_uint64(random_bytes[offset : offset + 2])
// effective_balance = state.validators[index].effective_balance
// return effective_balance * MAX_RANDOM_VALUE >= MAX_EFFECTIVE_BALANCE_ELECTRA * random_value
// </spec>
func acceptByBalance(st state.ReadOnlyBeaconState, idx primitives.ValidatorIndex, seedBuf []byte, hashFunc func([]byte) [32]byte, maxBalance uint64, round uint64) (bool, error) {
// Reuse the seed buffer by overwriting the last 8 bytes with the round counter.
binary.LittleEndian.PutUint64(seedBuf[len(seedBuf)-8:], round/16)
@@ -224,16 +263,26 @@ func acceptByBalance(st state.ReadOnlyBeaconState, idx primitives.ValidatorIndex
}
// validIndexedPayloadAttestation verifies the signature of an indexed payload attestation.
// Spec v1.7.0-alpha.0 (pseudocode):
// is_valid_indexed_payload_attestation(state: BeaconState, indexed_payload_attestation: IndexedPayloadAttestation) -> bool:
//
// indices = indexed_payload_attestation.attesting_indices
// return len(indices) > 0 and indices == sorted(indices) and
// bls.FastAggregateVerify(
// [state.validators[i].pubkey for i in indices],
// compute_signing_root(indexed_payload_attestation.data, get_domain(state, DOMAIN_PTC_ATTESTER, compute_epoch_at_slot(attestation.data.slot)),
// indexed_payload_attestation.signature,
// )
// <spec fn="is_valid_indexed_payload_attestation" fork="gloas" hash="cf1e65b5">
// def is_valid_indexed_payload_attestation(
// state: BeaconState, indexed_payload_attestation: IndexedPayloadAttestation
// ) -> bool:
// """
// Check if ``indexed_payload_attestation`` is non-empty, has sorted indices, and has
// a valid aggregate signature.
// """
// # Verify indices are non-empty and sorted
// indices = indexed_payload_attestation.attesting_indices
// if len(indices) == 0 or not indices == sorted(indices):
// return False
//
// # Verify aggregate signature
// pubkeys = [state.validators[i].pubkey for i in indices]
// domain = get_domain(state, DOMAIN_PTC_ATTESTER, None)
// signing_root = compute_signing_root(indexed_payload_attestation.data, domain)
// return bls.FastAggregateVerify(pubkeys, signing_root, indexed_payload_attestation.signature)
// </spec>
func validIndexedPayloadAttestation(st state.ReadOnlyBeaconState, att *consensus_types.IndexedPayloadAttestation) error {
indices := att.AttestingIndices
if len(indices) == 0 || !slices.IsSorted(indices) {

View File

@@ -10,17 +10,21 @@ import (
)
// ProcessBuilderPendingPayments processes the builder pending payments from the previous epoch.
// Spec v1.7.0-alpha.0 (pseudocode):
// def process_builder_pending_payments(state: BeaconState) -> None:
//
// quorum = get_builder_payment_quorum_threshold(state)
// for payment in state.builder_pending_payments[:SLOTS_PER_EPOCH]:
// if payment.weight >= quorum:
// state.builder_pending_withdrawals.append(payment.withdrawal)
// <spec fn="process_builder_pending_payments" fork="gloas" hash="10da48dd">
// def process_builder_pending_payments(state: BeaconState) -> None:
// """
// Processes the builder pending payments from the previous epoch.
// """
// quorum = get_builder_payment_quorum_threshold(state)
// for payment in state.builder_pending_payments[:SLOTS_PER_EPOCH]:
// if payment.weight >= quorum:
// state.builder_pending_withdrawals.append(payment.withdrawal)
//
// old_payments = state.builder_pending_payments[SLOTS_PER_EPOCH:]
// new_payments = [BuilderPendingPayment() for _ in range(SLOTS_PER_EPOCH)]
// state.builder_pending_payments = old_payments + new_payments
// old_payments = state.builder_pending_payments[SLOTS_PER_EPOCH:]
// new_payments = [BuilderPendingPayment() for _ in range(SLOTS_PER_EPOCH)]
// state.builder_pending_payments = old_payments + new_payments
// </spec>
func ProcessBuilderPendingPayments(state state.BeaconState) error {
quorum, err := builderQuorumThreshold(state)
if err != nil {
@@ -53,12 +57,16 @@ func ProcessBuilderPendingPayments(state state.BeaconState) error {
}
// builderQuorumThreshold calculates the quorum threshold for builder payments.
// Spec v1.7.0-alpha.0 (pseudocode):
// def get_builder_payment_quorum_threshold(state: BeaconState) -> uint64:
//
// per_slot_balance = get_total_active_balance(state) // SLOTS_PER_EPOCH
// quorum = per_slot_balance * BUILDER_PAYMENT_THRESHOLD_NUMERATOR
// return uint64(quorum // BUILDER_PAYMENT_THRESHOLD_DENOMINATOR)
// <spec fn="get_builder_payment_quorum_threshold" fork="gloas" hash="a64b7ffb">
// def get_builder_payment_quorum_threshold(state: BeaconState) -> uint64:
// """
// Calculate the quorum threshold for builder payments.
// """
// per_slot_balance = get_total_active_balance(state) // SLOTS_PER_EPOCH
// quorum = per_slot_balance * BUILDER_PAYMENT_THRESHOLD_NUMERATOR
// return uint64(quorum // BUILDER_PAYMENT_THRESHOLD_DENOMINATOR)
// </spec>
func builderQuorumThreshold(state state.ReadOnlyBeaconState) (primitives.Gwei, error) {
activeBalance, err := helpers.TotalActiveBalance(state)
if err != nil {

View File

@@ -11,16 +11,20 @@ import (
)
// RemoveBuilderPendingPayment removes the pending builder payment for the proposal slot.
// Spec v1.7.0 (pseudocode):
//
// <spec fn="process_proposer_slashing" fork="gloas" lines="22-32" hash="4da721ef">
// # [New in Gloas:EIP7732]
// # Remove the BuilderPendingPayment corresponding to
// # this proposal if it is still in the 2-epoch window.
// slot = header_1.slot
// proposal_epoch = compute_epoch_at_slot(slot)
// if proposal_epoch == get_current_epoch(state):
// payment_index = SLOTS_PER_EPOCH + slot % SLOTS_PER_EPOCH
// state.builder_pending_payments[payment_index] = BuilderPendingPayment()
// payment_index = SLOTS_PER_EPOCH + slot % SLOTS_PER_EPOCH
// state.builder_pending_payments[payment_index] = BuilderPendingPayment()
// elif proposal_epoch == get_previous_epoch(state):
// payment_index = slot % SLOTS_PER_EPOCH
// state.builder_pending_payments[payment_index] = BuilderPendingPayment()
// payment_index = slot % SLOTS_PER_EPOCH
// state.builder_pending_payments[payment_index] = BuilderPendingPayment()
// </spec>
func RemoveBuilderPendingPayment(st state.BeaconState, header *eth.BeaconBlockHeader) error {
proposalEpoch := slots.ToEpoch(header.Slot)
currentEpoch := time.CurrentEpoch(st)

View File

@@ -1,105 +0,0 @@
package gloas
import (
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
"github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
"github.com/pkg/errors"
)
// ProcessWithdrawals applies withdrawals to the state for Gloas.
//
// Spec v1.7.0-alpha.1 (pseudocode):
//
// def process_withdrawals(
//
// state: BeaconState,
// # [Modified in Gloas:EIP7732]
// # Removed `payload`
//
// ) -> None:
//
// # [New in Gloas:EIP7732]
// # Return early if the parent block is empty
// if not is_parent_block_full(state):
// return
//
// # Get expected withdrawals
// expected = get_expected_withdrawals(state)
//
// # Apply expected withdrawals
// apply_withdrawals(state, expected.withdrawals)
//
// # Update withdrawals fields in the state
// update_next_withdrawal_index(state, expected.withdrawals)
// # [New in Gloas:EIP7732]
// update_payload_expected_withdrawals(state, expected.withdrawals)
// # [New in Gloas:EIP7732]
// update_builder_pending_withdrawals(state, expected.processed_builder_withdrawals_count)
// update_pending_partial_withdrawals(state, expected.processed_partial_withdrawals_count)
// # [New in Gloas:EIP7732]
// update_next_withdrawal_builder_index(state, expected.processed_builders_sweep_count)
// update_next_withdrawal_validator_index(state, expected.withdrawals)
func ProcessWithdrawals(st state.BeaconState) error {
full, err := st.IsParentBlockFull()
if err != nil {
return errors.Wrap(err, "could not get parent block full status")
}
if !full {
return nil
}
expected, err := st.ExpectedWithdrawalsGloas()
if err != nil {
return errors.Wrap(err, "could not get expected withdrawals")
}
if err := st.DecreaseWithdrawalBalances(expected.Withdrawals); err != nil {
return errors.Wrap(err, "could not decrease withdrawal balances")
}
if len(expected.Withdrawals) > 0 {
if err := st.SetNextWithdrawalIndex(expected.Withdrawals[len(expected.Withdrawals)-1].Index + 1); err != nil {
return errors.Wrap(err, "could not set next withdrawal index")
}
}
err = st.SetPayloadExpectedWithdrawals(expected.Withdrawals)
if err != nil {
return errors.Wrap(err, "could not set payload expected withdrawals")
}
err = st.DequeueBuilderPendingWithdrawals(expected.ProcessedBuilderWithdrawalsCount)
if err != nil {
return errors.Wrap(err, "unable to dequeue builder pending withdrawals from state")
}
if err := st.DequeuePendingPartialWithdrawals(expected.ProcessedPartialWithdrawalsCount); err != nil {
return errors.Wrap(err, "unable to dequeue partial withdrawals from state")
}
err = st.SetNextWithdrawalBuilderIndex(expected.NextWithdrawalBuilderIndex)
if err != nil {
return errors.Wrap(err, "could not set next withdrawal builder index")
}
var nextValidatorIndex primitives.ValidatorIndex
if uint64(len(expected.Withdrawals)) < params.BeaconConfig().MaxWithdrawalsPerPayload {
nextValidatorIndex, err = st.NextWithdrawalValidatorIndex()
if err != nil {
return errors.Wrap(err, "could not get next withdrawal validator index")
}
nextValidatorIndex += primitives.ValidatorIndex(params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
nextValidatorIndex = nextValidatorIndex % primitives.ValidatorIndex(st.NumValidators())
} else {
nextValidatorIndex = expected.Withdrawals[len(expected.Withdrawals)-1].ValidatorIndex + 1
if nextValidatorIndex == primitives.ValidatorIndex(st.NumValidators()) {
nextValidatorIndex = 0
}
}
if err := st.SetNextWithdrawalValidatorIndex(nextValidatorIndex); err != nil {
return errors.Wrap(err, "could not set next withdrawal validator index")
}
return nil
}

View File

@@ -143,10 +143,11 @@ func ProcessSlot(ctx context.Context, state state.BeaconState) (state.BeaconStat
return nil, err
}
// Spec v1.6.1 (pseudocode):
// <spec fn="process_slot" fork="gloas" lines="11-13" hash="62b28839">
// # [New in Gloas:EIP7732]
// # Unset the next payload availability
// state.execution_payload_availability[(state.slot + 1) % SLOTS_PER_HISTORICAL_ROOT] = 0b0
// </spec>
if state.Version() >= version.Gloas {
index := uint64((state.Slot() + 1) % params.BeaconConfig().SlotsPerHistoricalRoot)
if err := state.UpdateExecutionPayloadAvailabilityAtIndex(index, 0x0); err != nil {

View File

@@ -67,7 +67,6 @@ func getSubscriptionStatusFromDB(t *testing.T, db *Store) bool {
return subscribed
}
func TestUpdateCustodyInfo(t *testing.T) {
ctx := t.Context()

View File

@@ -134,10 +134,20 @@ type BeaconNode struct {
// New creates a new node instance, sets up configuration options, and registers
// every required service to the node.
func New(cliCtx *cli.Context, cancel context.CancelFunc, opts ...Option) (*BeaconNode, error) {
func New(cliCtx *cli.Context, cancel context.CancelFunc, optFuncs []func(*cli.Context) ([]Option, error), opts ...Option) (*BeaconNode, error) {
if err := configureBeacon(cliCtx); err != nil {
return nil, errors.Wrap(err, "could not set beacon configuration options")
}
for _, of := range optFuncs {
ofo, err := of(cliCtx)
if err != nil {
return nil, err
}
if ofo != nil {
opts = append(opts, ofo...)
}
}
ctx := cliCtx.Context
beacon := &BeaconNode{

View File

@@ -59,7 +59,7 @@ func TestNodeClose_OK(t *testing.T) {
WithDataColumnStorage(filesystem.NewEphemeralDataColumnStorage(t)),
}
node, err := New(ctx, cancel, options...)
node, err := New(ctx, cancel, nil, options...)
require.NoError(t, err)
node.Close()
@@ -87,7 +87,7 @@ func TestNodeStart_Ok(t *testing.T) {
WithDataColumnStorage(filesystem.NewEphemeralDataColumnStorage(t)),
}
node, err := New(ctx, cancel, options...)
node, err := New(ctx, cancel, nil, options...)
require.NoError(t, err)
require.NotNil(t, node.lcStore)
node.services = &runtime.ServiceRegistry{}
@@ -116,7 +116,7 @@ func TestNodeStart_SyncChecker(t *testing.T) {
WithDataColumnStorage(filesystem.NewEphemeralDataColumnStorage(t)),
}
node, err := New(ctx, cancel, options...)
node, err := New(ctx, cancel, nil, options...)
require.NoError(t, err)
go func() {
node.Start()
@@ -151,7 +151,7 @@ func TestClearDB(t *testing.T) {
WithDataColumnStorage(filesystem.NewEphemeralDataColumnStorage(t)),
}
_, err = New(context, cancel, options...)
_, err = New(context, cancel, nil, options...)
require.NoError(t, err)
require.LogsContain(t, hook, "Removing database")
}

View File

@@ -26,8 +26,8 @@ import (
"github.com/OffchainLabs/prysm/v7/beacon-chain/operations/voluntaryexits/mock"
p2pMock "github.com/OffchainLabs/prysm/v7/beacon-chain/p2p/testing"
"github.com/OffchainLabs/prysm/v7/beacon-chain/rpc/core"
mockSync "github.com/OffchainLabs/prysm/v7/beacon-chain/sync/initial-sync/testing"
state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native"
mockSync "github.com/OffchainLabs/prysm/v7/beacon-chain/sync/initial-sync/testing"
"github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v7/crypto/bls"

View File

@@ -84,7 +84,6 @@ func TestGetSpec(t *testing.T) {
config.FuluForkVersion = []byte("FuluForkVersion")
config.FuluForkEpoch = 109
config.GloasForkEpoch = 110
config.MaxBuildersPerWithdrawalsSweep = 112
config.BLSWithdrawalPrefixByte = byte('b')
config.ETH1AddressWithdrawalPrefixByte = byte('c')
config.GenesisDelay = 24
@@ -221,7 +220,7 @@ func TestGetSpec(t *testing.T) {
require.NoError(t, json.Unmarshal(writer.Body.Bytes(), &resp))
data, ok := resp.Data.(map[string]any)
require.Equal(t, true, ok)
assert.Equal(t, 194, len(data))
assert.Equal(t, 192, len(data))
for k, v := range data {
t.Run(k, func(t *testing.T) {
switch k {
@@ -303,8 +302,6 @@ func TestGetSpec(t *testing.T) {
assert.Equal(t, "109", v)
case "GLOAS_FORK_EPOCH":
assert.Equal(t, "110", v)
case "MAX_BUILDERS_PER_WITHDRAWALS_SWEEP":
assert.Equal(t, "112", v)
case "MIN_ANCHOR_POW_BLOCK_DIFFICULTY":
assert.Equal(t, "1000", v)
case "BLS_WITHDRAWAL_PREFIX":

View File

@@ -3,7 +3,6 @@ package state
import (
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
)
@@ -14,10 +13,6 @@ type writeOnlyGloasFields interface {
RotateBuilderPendingPayments() error
AppendBuilderPendingWithdrawals([]*ethpb.BuilderPendingWithdrawal) error
UpdateExecutionPayloadAvailabilityAtIndex(idx uint64, val byte) error
SetPayloadExpectedWithdrawals(withdrawals []*enginev1.Withdrawal) error
DecreaseWithdrawalBalances(withdrawals []*enginev1.Withdrawal) error
DequeueBuilderPendingWithdrawals(num uint64) error
SetNextWithdrawalBuilderIndex(idx primitives.BuilderIndex) error
}
type readOnlyGloasFields interface {
@@ -26,15 +21,4 @@ type readOnlyGloasFields interface {
CanBuilderCoverBid(primitives.BuilderIndex, primitives.Gwei) (bool, error)
LatestBlockHash() ([32]byte, error)
BuilderPendingPayments() ([]*ethpb.BuilderPendingPayment, error)
IsParentBlockFull() (bool, error)
ExpectedWithdrawalsGloas() (ExpectedWithdrawalsGloasResult, error)
}
// ExpectedWithdrawalsGloasResult bundles the expected withdrawals and related counters
// for the Gloas fork to avoid positional return mistakes.
type ExpectedWithdrawalsGloasResult struct {
Withdrawals []*enginev1.Withdrawal
ProcessedBuilderWithdrawalsCount uint64
ProcessedPartialWithdrawalsCount uint64
NextWithdrawalBuilderIndex primitives.BuilderIndex
}

View File

@@ -1,17 +1,13 @@
package state_native
import (
"bytes"
"fmt"
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
"github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/runtime/version"
"github.com/OffchainLabs/prysm/v7/time/slots"
)
// LatestBlockHash returns the hash of the latest execution block.
@@ -50,14 +46,20 @@ func (b *BeaconState) BuilderPubkey(builderIndex primitives.BuilderIndex) ([fiel
}
// IsActiveBuilder returns true if the builder placement is finalized and it has not initiated exit.
// Spec v1.7.0-alpha.0 (pseudocode):
// def is_active_builder(state: BeaconState, builder_index: BuilderIndex) -> bool:
//
// builder = state.builders[builder_index]
// return (
// builder.deposit_epoch < state.finalized_checkpoint.epoch
// and builder.withdrawable_epoch == FAR_FUTURE_EPOCH
// )
// <spec fn="is_active_builder" fork="gloas" hash="1a599fb2">
// def is_active_builder(state: BeaconState, builder_index: BuilderIndex) -> bool:
// """
// Check if the builder at ``builder_index`` is active for the given ``state``.
// """
// builder = state.builders[builder_index]
// return (
// # Placement in builder list is finalized
// builder.deposit_epoch < state.finalized_checkpoint.epoch
// # Has not initiated exit
// and builder.withdrawable_epoch == FAR_FUTURE_EPOCH
// )
// </spec>
func (b *BeaconState) IsActiveBuilder(builderIndex primitives.BuilderIndex) (bool, error) {
if b.version < version.Gloas {
return false, errNotSupported("IsActiveBuilder", b.version)
@@ -76,15 +78,18 @@ func (b *BeaconState) IsActiveBuilder(builderIndex primitives.BuilderIndex) (boo
}
// CanBuilderCoverBid returns true if the builder has enough balance to cover the given bid amount.
// Spec v1.7.0-alpha.0 (pseudocode):
// def can_builder_cover_bid(state: BeaconState, builder_index: BuilderIndex, bid_amount: Gwei) -> bool:
//
// builder_balance = state.builders[builder_index].balance
// pending_withdrawals_amount = get_pending_balance_to_withdraw_for_builder(state, builder_index)
// min_balance = MIN_DEPOSIT_AMOUNT + pending_withdrawals_amount
// if builder_balance < min_balance:
// return False
// return builder_balance - min_balance >= bid_amount
// <spec fn="can_builder_cover_bid" fork="gloas" hash="9e3f2d7c">
// def can_builder_cover_bid(
// state: BeaconState, builder_index: BuilderIndex, bid_amount: Gwei
// ) -> bool:
// builder_balance = state.builders[builder_index].balance
// pending_withdrawals_amount = get_pending_balance_to_withdraw_for_builder(state, builder_index)
// min_balance = MIN_DEPOSIT_AMOUNT + pending_withdrawals_amount
// if builder_balance < min_balance:
// return False
// return builder_balance - min_balance >= bid_amount
// </spec>
func (b *BeaconState) CanBuilderCoverBid(builderIndex primitives.BuilderIndex, bidAmount primitives.Gwei) (bool, error) {
if b.version < version.Gloas {
return false, errNotSupported("CanBuilderCoverBid", b.version)
@@ -151,223 +156,3 @@ func (b *BeaconState) BuilderPendingPayments() ([]*ethpb.BuilderPendingPayment,
return b.builderPendingPaymentsVal(), nil
}
// IsParentBlockFull returns true if the last committed payload bid was fulfilled with a payload,
// which can only happen when both beacon block and payload were present.
// This function must be called on a beacon state before processing the execution payload bid in the block.
// Spec v1.7.0-alpha.2 (pseudocode):
// def is_parent_block_full(state: BeaconState) -> bool:
//
// return state.latest_execution_payload_bid.block_hash == state.latest_block_hash
func (b *BeaconState) IsParentBlockFull() (bool, error) {
if b.version < version.Gloas {
return false, errNotSupported("IsParentBlockFull", b.version)
}
b.lock.RLock()
defer b.lock.RUnlock()
if b.latestExecutionPayloadBid == nil {
return false, nil
}
return bytes.Equal(b.latestExecutionPayloadBid.BlockHash, b.latestBlockHash), nil
}
// ExpectedWithdrawalsGloas returns the withdrawals that a proposer will need to pack in the next block
// applied to the current state. It is also used by validators to check that the execution payload carried
// the right number of withdrawals.
//
// Spec v1.7.0-alpha.1:
//
// def get_expected_withdrawals(state: BeaconState) -> ExpectedWithdrawals:
// withdrawal_index = state.next_withdrawal_index
// withdrawals: List[Withdrawal] = []
//
// # [New in Gloas:EIP7732]
// # Get builder withdrawals
// builder_withdrawals, withdrawal_index, processed_builder_withdrawals_count = (
// get_builder_withdrawals(state, withdrawal_index, withdrawals)
// )
// withdrawals.extend(builder_withdrawals)
//
// # Get partial withdrawals
// partial_withdrawals, withdrawal_index, processed_partial_withdrawals_count = (
// get_pending_partial_withdrawals(state, withdrawal_index, withdrawals)
// )
// withdrawals.extend(partial_withdrawals)
//
// # [New in Gloas:EIP7732]
// # Get builders sweep withdrawals
// builders_sweep_withdrawals, withdrawal_index, processed_builders_sweep_count = (
// get_builders_sweep_withdrawals(state, withdrawal_index, withdrawals)
// )
// withdrawals.extend(builders_sweep_withdrawals)
//
// # Get validators sweep withdrawals
// validators_sweep_withdrawals, withdrawal_index, processed_validators_sweep_count = (
// get_validators_sweep_withdrawals(state, withdrawal_index, withdrawals)
// )
// withdrawals.extend(validators_sweep_withdrawals)
//
// return ExpectedWithdrawals(
// withdrawals,
// # [New in Gloas:EIP7732]
// processed_builder_withdrawals_count,
// processed_partial_withdrawals_count,
// # [New in Gloas:EIP7732]
// processed_builders_sweep_count,
// processed_validators_sweep_count,
// )
func (b *BeaconState) ExpectedWithdrawalsGloas() (state.ExpectedWithdrawalsGloasResult, error) {
if b.version < version.Gloas {
return state.ExpectedWithdrawalsGloasResult{}, errNotSupported("ExpectedWithdrawalsGloas", b.version)
}
b.lock.RLock()
defer b.lock.RUnlock()
cfg := params.BeaconConfig()
withdrawals := make([]*enginev1.Withdrawal, 0, cfg.MaxWithdrawalsPerPayload)
withdrawalIndex := b.nextWithdrawalIndex
withdrawalIndex, processedBuilderWithdrawalsCount, err := b.appendBuilderWithdrawals(withdrawalIndex, &withdrawals)
if err != nil {
return state.ExpectedWithdrawalsGloasResult{}, err
}
withdrawalIndex, processedPartialWithdrawalsCount, err := b.appendPendingPartialWithdrawals(withdrawalIndex, &withdrawals)
if err != nil {
return state.ExpectedWithdrawalsGloasResult{}, err
}
withdrawalIndex, nextBuilderIndex, err := b.appendBuildersSweepWithdrawals(withdrawalIndex, &withdrawals)
if err != nil {
return state.ExpectedWithdrawalsGloasResult{}, err
}
err = b.appendValidatorsSweepWithdrawals(withdrawalIndex, &withdrawals)
if err != nil {
return state.ExpectedWithdrawalsGloasResult{}, err
}
return state.ExpectedWithdrawalsGloasResult{
Withdrawals: withdrawals,
ProcessedBuilderWithdrawalsCount: processedBuilderWithdrawalsCount,
ProcessedPartialWithdrawalsCount: processedPartialWithdrawalsCount,
NextWithdrawalBuilderIndex: nextBuilderIndex,
}, nil
}
// appendBuilderWithdrawals returns builder pending withdrawals, the updated withdrawal index,
// and the processed count, following spec v1.7.0-alpha.2:
//
// def get_builder_withdrawals(state, withdrawal_index, prior_withdrawals):
// withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD - 1
// assert len(prior_withdrawals) <= withdrawals_limit
// processed_count = 0
// withdrawals = []
// for withdrawal in state.builder_pending_withdrawals:
// if len(prior_withdrawals + withdrawals) >= withdrawals_limit:
// break
// withdrawals.append(Withdrawal(
// index=withdrawal_index,
// validator_index=convert_builder_index_to_validator_index(withdrawal.builder_index),
// address=withdrawal.fee_recipient,
// amount=withdrawal.amount,
// ))
// withdrawal_index += 1
// processed_count += 1
// return withdrawals, withdrawal_index, processed_count
func (b *BeaconState) appendBuilderWithdrawals(withdrawalIndex uint64, withdrawals *[]*enginev1.Withdrawal) (uint64, uint64, error) {
cfg := params.BeaconConfig()
withdrawalsLimit := int(cfg.MaxWithdrawalsPerPayload - 1)
ws := *withdrawals
if len(ws) > withdrawalsLimit {
return withdrawalIndex, 0, fmt.Errorf("prior withdrawals length %d exceeds limit %d", len(ws), withdrawalsLimit)
}
var processedCount uint64
for _, w := range b.builderPendingWithdrawals {
if len(ws) >= withdrawalsLimit {
break
}
ws = append(ws, &enginev1.Withdrawal{
Index: withdrawalIndex,
ValidatorIndex: w.BuilderIndex.ToValidatorIndex(),
Address: w.FeeRecipient,
Amount: uint64(w.Amount),
})
withdrawalIndex++
processedCount++
}
*withdrawals = ws
return withdrawalIndex, processedCount, nil
}
// appendBuildersSweepWithdrawals returns builder sweep withdrawals, the updated withdrawal index,
// and the processed count, following spec v1.7.0-alpha.2:
//
// def get_builders_sweep_withdrawals(state, withdrawal_index, prior_withdrawals):
// epoch = get_current_epoch(state)
// builders_limit = min(len(state.builders), MAX_BUILDERS_PER_WITHDRAWALS_SWEEP)
// withdrawals_limit = MAX_WITHDRAWALS_PER_PAYLOAD - 1
// assert len(prior_withdrawals) <= withdrawals_limit
// processed_count = 0
// withdrawals = []
// builder_index = state.next_withdrawal_builder_index
// for _ in range(builders_limit):
// if len(prior_withdrawals + withdrawals) >= withdrawals_limit:
// break
// builder = state.builders[builder_index]
// if builder.withdrawable_epoch <= epoch and builder.balance > 0:
// withdrawals.append(Withdrawal(
// index=withdrawal_index,
// validator_index=convert_builder_index_to_validator_index(builder_index),
// address=builder.execution_address,
// amount=builder.balance,
// ))
// withdrawal_index += 1
// builder_index = BuilderIndex((builder_index + 1) % len(state.builders))
// processed_count += 1
// return withdrawals, withdrawal_index, processed_count
func (b *BeaconState) appendBuildersSweepWithdrawals(withdrawalIndex uint64, withdrawals *[]*enginev1.Withdrawal) (uint64, primitives.BuilderIndex, error) {
cfg := params.BeaconConfig()
withdrawalsLimit := int(cfg.MaxWithdrawalsPerPayload - 1)
if len(*withdrawals) > withdrawalsLimit {
return withdrawalIndex, 0, fmt.Errorf("prior withdrawals length %d exceeds limit %d", len(*withdrawals), withdrawalsLimit)
}
ws := *withdrawals
buildersLimit := len(b.builders)
if maxBuilders := int(cfg.MaxBuildersPerWithdrawalsSweep); buildersLimit > maxBuilders {
buildersLimit = maxBuilders
}
builderIndex := b.nextWithdrawalBuilderIndex
epoch := slots.ToEpoch(b.slot)
for i := 0; i < buildersLimit; i++ {
if len(ws) >= withdrawalsLimit {
break
}
builder := b.builders[builderIndex]
if builder != nil && builder.WithdrawableEpoch <= epoch && builder.Balance > 0 {
ws = append(ws, &enginev1.Withdrawal{
Index: withdrawalIndex,
ValidatorIndex: builderIndex.ToValidatorIndex(),
Address: builder.ExecutionAddress,
Amount: uint64(builder.Balance),
})
withdrawalIndex++
}
builderIndex = primitives.BuilderIndex((uint64(builderIndex) + 1) % uint64(len(b.builders)))
}
*withdrawals = ws
return withdrawalIndex, builderIndex, nil
}

View File

@@ -1,27 +1,26 @@
package state_native
package state_native_test
import (
"bytes"
"testing"
state_native "github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native"
"github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/runtime/version"
"github.com/OffchainLabs/prysm/v7/testing/require"
"github.com/OffchainLabs/prysm/v7/time/slots"
"github.com/OffchainLabs/prysm/v7/testing/util"
)
func TestLatestBlockHash(t *testing.T) {
t.Run("returns error before gloas", func(t *testing.T) {
st := &BeaconState{version: version.Fulu}
st, _ := util.DeterministicGenesisState(t, 1)
_, err := st.LatestBlockHash()
require.ErrorContains(t, "is not supported", err)
})
t.Run("returns zero hash when unset", func(t *testing.T) {
st, err := InitializeFromProtoGloas(&ethpb.BeaconStateGloas{})
st, err := state_native.InitializeFromProtoGloas(&ethpb.BeaconStateGloas{})
require.NoError(t, err)
got, err := st.LatestBlockHash()
@@ -34,7 +33,7 @@ func TestLatestBlockHash(t *testing.T) {
var want [32]byte
copy(want[:], hashBytes)
st, err := InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
st, err := state_native.InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
LatestBlockHash: hashBytes,
})
require.NoError(t, err)
@@ -47,14 +46,17 @@ func TestLatestBlockHash(t *testing.T) {
func TestBuilderPubkey(t *testing.T) {
t.Run("returns error before gloas", func(t *testing.T) {
st := &BeaconState{version: version.Fulu}
_, err := st.BuilderPubkey(0)
stIface, _ := util.DeterministicGenesisState(t, 1)
native, ok := stIface.(*state_native.BeaconState)
require.Equal(t, true, ok)
_, err := native.BuilderPubkey(0)
require.ErrorContains(t, "is not supported", err)
})
t.Run("returns pubkey copy", func(t *testing.T) {
pubkey := bytes.Repeat([]byte{0xAA}, 48)
stIface, err := InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
stIface, err := state_native.InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
Builders: []*ethpb.Builder{
{
Pubkey: pubkey,
@@ -78,12 +80,12 @@ func TestBuilderPubkey(t *testing.T) {
})
t.Run("out of range returns error", func(t *testing.T) {
stIface, err := InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
stIface, err := state_native.InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
Builders: []*ethpb.Builder{},
})
require.NoError(t, err)
st := stIface.(*BeaconState)
st := stIface.(*state_native.BeaconState)
_, err = st.BuilderPubkey(1)
require.ErrorContains(t, "out of range", err)
})
@@ -91,7 +93,7 @@ func TestBuilderPubkey(t *testing.T) {
func TestBuilderHelpers(t *testing.T) {
t.Run("is active builder", func(t *testing.T) {
st, err := InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
st, err := state_native.InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
Builders: []*ethpb.Builder{
{
Balance: 10,
@@ -118,7 +120,7 @@ func TestBuilderHelpers(t *testing.T) {
},
FinalizedCheckpoint: &ethpb.Checkpoint{Epoch: 2},
}
stInactive, err := InitializeFromProtoGloas(stProto)
stInactive, err := state_native.InitializeFromProtoGloas(stProto)
require.NoError(t, err)
active, err = stInactive.IsActiveBuilder(0)
@@ -127,7 +129,7 @@ func TestBuilderHelpers(t *testing.T) {
})
t.Run("can builder cover bid", func(t *testing.T) {
stIface, err := InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
stIface, err := state_native.InitializeFromProtoGloas(&ethpb.BeaconStateGloas{
Builders: []*ethpb.Builder{
{
Balance: primitives.Gwei(params.BeaconConfig().MinDepositAmount + 50),
@@ -145,7 +147,7 @@ func TestBuilderHelpers(t *testing.T) {
})
require.NoError(t, err)
st := stIface.(*BeaconState)
st := stIface.(*state_native.BeaconState)
ok, err := st.CanBuilderCoverBid(0, 20)
require.NoError(t, err)
require.Equal(t, true, ok)
@@ -157,245 +159,10 @@ func TestBuilderHelpers(t *testing.T) {
}
func TestBuilderPendingPayments_UnsupportedVersion(t *testing.T) {
stIface, err := InitializeFromProtoElectra(&ethpb.BeaconStateElectra{})
stIface, err := state_native.InitializeFromProtoElectra(&ethpb.BeaconStateElectra{})
require.NoError(t, err)
st := stIface.(*BeaconState)
st := stIface.(*state_native.BeaconState)
_, err = st.BuilderPendingPayments()
require.ErrorContains(t, "BuilderPendingPayments", err)
}
func TestIsParentBlockFull(t *testing.T) {
t.Run("returns error before gloas", func(t *testing.T) {
st := &BeaconState{version: version.Fulu}
_, err := st.IsParentBlockFull()
require.ErrorContains(t, "is not supported", err)
})
t.Run("returns false when bid is nil", func(t *testing.T) {
st := &BeaconState{version: version.Gloas}
got, err := st.IsParentBlockFull()
require.NoError(t, err)
require.Equal(t, false, got)
})
t.Run("returns true when hashes match", func(t *testing.T) {
hash := bytes.Repeat([]byte{0xAB}, 32)
st := &BeaconState{
version: version.Gloas,
latestExecutionPayloadBid: &ethpb.ExecutionPayloadBid{
BlockHash: hash,
},
latestBlockHash: hash,
}
got, err := st.IsParentBlockFull()
require.NoError(t, err)
require.Equal(t, true, got)
})
t.Run("returns false when hashes differ", func(t *testing.T) {
hash := bytes.Repeat([]byte{0xAB}, 32)
other := bytes.Repeat([]byte{0xCD}, 32)
st := &BeaconState{
version: version.Gloas,
latestExecutionPayloadBid: &ethpb.ExecutionPayloadBid{
BlockHash: hash,
},
latestBlockHash: other,
}
got, err := st.IsParentBlockFull()
require.NoError(t, err)
require.Equal(t, false, got)
})
}
func TestAppendBuilderWithdrawals(t *testing.T) {
t.Run("errors when prior withdrawals exceed limit", func(t *testing.T) {
st := &BeaconState{}
limit := params.BeaconConfig().MaxWithdrawalsPerPayload - 1
withdrawals := make([]*enginev1.Withdrawal, limit+1)
nextIndex, processed, err := st.appendBuilderWithdrawals(5, &withdrawals)
require.ErrorContains(t, "exceeds limit", err)
require.Equal(t, uint64(5), nextIndex)
require.Equal(t, uint64(0), processed)
require.Equal(t, int(limit+1), len(withdrawals))
})
t.Run("appends builder withdrawals and increments index", func(t *testing.T) {
st := &BeaconState{
builderPendingWithdrawals: []*ethpb.BuilderPendingWithdrawal{
{BuilderIndex: 1, FeeRecipient: []byte{0x01}, Amount: 11},
{BuilderIndex: 2, FeeRecipient: []byte{0x02}, Amount: 22},
{BuilderIndex: 3, FeeRecipient: []byte{0x03}, Amount: 33},
},
}
withdrawals := []*enginev1.Withdrawal{
{Index: 7, ValidatorIndex: 9, Address: []byte{0xAA}, Amount: 99},
}
nextIndex, processed, err := st.appendBuilderWithdrawals(10, &withdrawals)
require.NoError(t, err)
require.Equal(t, uint64(13), nextIndex)
require.Equal(t, uint64(3), processed)
require.Equal(t, 4, len(withdrawals))
require.DeepEqual(t, &enginev1.Withdrawal{
Index: 10,
ValidatorIndex: primitives.BuilderIndex(1).ToValidatorIndex(),
Address: []byte{0x01},
Amount: 11,
}, withdrawals[1])
require.DeepEqual(t, &enginev1.Withdrawal{
Index: 11,
ValidatorIndex: primitives.BuilderIndex(2).ToValidatorIndex(),
Address: []byte{0x02},
Amount: 22,
}, withdrawals[2])
require.DeepEqual(t, &enginev1.Withdrawal{
Index: 12,
ValidatorIndex: primitives.BuilderIndex(3).ToValidatorIndex(),
Address: []byte{0x03},
Amount: 33,
}, withdrawals[3])
})
t.Run("respects per-payload limit", func(t *testing.T) {
limit := params.BeaconConfig().MaxWithdrawalsPerPayload - 1
st := &BeaconState{
builderPendingWithdrawals: []*ethpb.BuilderPendingWithdrawal{
{BuilderIndex: 4, FeeRecipient: []byte{0x04}, Amount: 44},
{BuilderIndex: 5, FeeRecipient: []byte{0x05}, Amount: 55},
},
}
withdrawals := make([]*enginev1.Withdrawal, limit-1)
nextIndex, processed, err := st.appendBuilderWithdrawals(20, &withdrawals)
require.NoError(t, err)
require.Equal(t, uint64(21), nextIndex)
require.Equal(t, uint64(1), processed)
require.Equal(t, int(limit), len(withdrawals))
require.DeepEqual(t, &enginev1.Withdrawal{
Index: 20,
ValidatorIndex: primitives.BuilderIndex(4).ToValidatorIndex(),
Address: []byte{0x04},
Amount: 44,
}, withdrawals[len(withdrawals)-1])
})
t.Run("does not append when already at limit", func(t *testing.T) {
limit := params.BeaconConfig().MaxWithdrawalsPerPayload - 1
if limit == 0 {
t.Skip("withdrawals limit too small")
}
st := &BeaconState{
builderPendingWithdrawals: []*ethpb.BuilderPendingWithdrawal{
{BuilderIndex: 6, FeeRecipient: []byte{0x06}, Amount: 66},
},
}
withdrawals := make([]*enginev1.Withdrawal, limit)
nextIndex, processed, err := st.appendBuilderWithdrawals(30, &withdrawals)
require.NoError(t, err)
require.Equal(t, uint64(30), nextIndex)
require.Equal(t, uint64(0), processed)
require.Equal(t, int(limit), len(withdrawals))
})
}
func TestAppendBuildersSweepWithdrawals(t *testing.T) {
t.Run("errors when prior withdrawals exceed limit", func(t *testing.T) {
st := &BeaconState{}
limit := params.BeaconConfig().MaxWithdrawalsPerPayload - 1
withdrawals := make([]*enginev1.Withdrawal, limit+1)
nextIndex, nextBuilderIndex, err := st.appendBuildersSweepWithdrawals(5, &withdrawals)
require.ErrorContains(t, "exceeds limit", err)
require.Equal(t, uint64(5), nextIndex)
require.Equal(t, primitives.BuilderIndex(0), nextBuilderIndex)
require.Equal(t, int(limit+1), len(withdrawals))
})
t.Run("appends eligible builders, skips ineligible", func(t *testing.T) {
epoch := primitives.Epoch(3)
st := &BeaconState{
slot: slots.UnsafeEpochStart(epoch),
nextWithdrawalBuilderIndex: 2,
builders: []*ethpb.Builder{
{ExecutionAddress: []byte{0x01}, Balance: 0, WithdrawableEpoch: epoch},
{ExecutionAddress: []byte{0x02}, Balance: 10, WithdrawableEpoch: epoch + 1},
{ExecutionAddress: []byte{0x03}, Balance: 20, WithdrawableEpoch: epoch},
},
}
withdrawals := []*enginev1.Withdrawal{}
nextIndex, nextBuilderIndex, err := st.appendBuildersSweepWithdrawals(100, &withdrawals)
require.NoError(t, err)
require.Equal(t, uint64(101), nextIndex)
require.Equal(t, primitives.BuilderIndex(2), nextBuilderIndex)
require.Equal(t, 1, len(withdrawals))
require.DeepEqual(t, &enginev1.Withdrawal{
Index: 100,
ValidatorIndex: primitives.BuilderIndex(2).ToValidatorIndex(),
Address: []byte{0x03},
Amount: 20,
}, withdrawals[0])
})
t.Run("respects max builders per sweep", func(t *testing.T) {
cfg := params.BeaconConfig()
max := int(cfg.MaxBuildersPerWithdrawalsSweep)
epoch := primitives.Epoch(1)
builders := make([]*ethpb.Builder, max+2)
for i := range builders {
builders[i] = &ethpb.Builder{
ExecutionAddress: []byte{byte(i + 1)},
Balance: 1,
WithdrawableEpoch: epoch,
}
}
start := len(builders) - 1
st := &BeaconState{
slot: slots.UnsafeEpochStart(epoch),
nextWithdrawalBuilderIndex: primitives.BuilderIndex(start),
builders: builders,
}
withdrawals := []*enginev1.Withdrawal{}
nextIndex, nextBuilderIndex, err := st.appendBuildersSweepWithdrawals(7, &withdrawals)
require.NoError(t, err)
limit := int(cfg.MaxWithdrawalsPerPayload - 1)
expectedCount := min(max, limit)
require.Equal(t, uint64(7)+uint64(expectedCount), nextIndex)
require.Equal(t, expectedCount, len(withdrawals))
expectedNext := primitives.BuilderIndex((uint64(start) + uint64(expectedCount)) % uint64(len(builders)))
require.Equal(t, expectedNext, nextBuilderIndex)
})
t.Run("stops when payload limit reached", func(t *testing.T) {
cfg := params.BeaconConfig()
limit := cfg.MaxWithdrawalsPerPayload - 1
if limit < 1 {
t.Skip("withdrawals limit too small")
}
epoch := primitives.Epoch(2)
builders := []*ethpb.Builder{
{ExecutionAddress: []byte{0x0A}, Balance: 3, WithdrawableEpoch: epoch},
{ExecutionAddress: []byte{0x0B}, Balance: 4, WithdrawableEpoch: epoch},
}
st := &BeaconState{
slot: slots.UnsafeEpochStart(epoch),
nextWithdrawalBuilderIndex: 0,
builders: builders,
}
withdrawals := make([]*enginev1.Withdrawal, limit)
nextIndex, nextBuilderIndex, err := st.appendBuildersSweepWithdrawals(20, &withdrawals)
require.NoError(t, err)
require.Equal(t, uint64(20), nextIndex)
require.Equal(t, int(limit), len(withdrawals))
require.Equal(t, primitives.BuilderIndex(0), nextBuilderIndex)
})
}

View File

@@ -133,22 +133,11 @@ func (b *BeaconState) appendPendingPartialWithdrawals(withdrawalIndex uint64, wi
return withdrawalIndex, 0, nil
}
cfg := params.BeaconConfig()
withdrawalsLimit := min(
len(*withdrawals)+int(cfg.MaxPendingPartialsPerWithdrawalsSweep),
int(cfg.MaxWithdrawalsPerPayload-1),
)
if len(*withdrawals) > withdrawalsLimit {
return withdrawalIndex, 0, fmt.Errorf("prior withdrawals length %d exceeds limit %d", len(*withdrawals), withdrawalsLimit)
}
ws := *withdrawals
epoch := slots.ToEpoch(b.slot)
var processedPartialWithdrawalsCount uint64
for _, w := range b.pendingPartialWithdrawals {
isWithdrawable := w.WithdrawableEpoch <= epoch
hasReachedLimit := len(ws) >= withdrawalsLimit
if !isWithdrawable || hasReachedLimit {
if w.WithdrawableEpoch > epoch || len(ws) >= int(params.BeaconConfig().MaxPendingPartialsPerWithdrawalsSweep) {
break
}
@@ -160,7 +149,7 @@ func (b *BeaconState) appendPendingPartialWithdrawals(withdrawalIndex uint64, wi
if err != nil {
return withdrawalIndex, 0, fmt.Errorf("could not retrieve balance at index %d: %w", w.Index, err)
}
hasSufficientEffectiveBalance := v.EffectiveBalance() >= cfg.MinActivationBalance
hasSufficientEffectiveBalance := v.EffectiveBalance() >= params.BeaconConfig().MinActivationBalance
var totalWithdrawn uint64
for _, wi := range ws {
if wi.ValidatorIndex == w.Index {
@@ -171,9 +160,9 @@ func (b *BeaconState) appendPendingPartialWithdrawals(withdrawalIndex uint64, wi
if err != nil {
return withdrawalIndex, 0, errors.Wrapf(err, "failed to subtract balance %d with total withdrawn %d", vBal, totalWithdrawn)
}
hasExcessBalance := balance > cfg.MinActivationBalance
if v.ExitEpoch() == cfg.FarFutureEpoch && hasSufficientEffectiveBalance && hasExcessBalance {
amount := min(balance-cfg.MinActivationBalance, w.Amount)
hasExcessBalance := balance > params.BeaconConfig().MinActivationBalance
if v.ExitEpoch() == params.BeaconConfig().FarFutureEpoch && hasSufficientEffectiveBalance && hasExcessBalance {
amount := min(balance-params.BeaconConfig().MinActivationBalance, w.Amount)
ws = append(ws, &enginev1.Withdrawal{
Index: withdrawalIndex,
ValidatorIndex: w.Index,
@@ -194,7 +183,7 @@ func (b *BeaconState) appendValidatorsSweepWithdrawals(withdrawalIndex uint64, w
validatorIndex := b.nextWithdrawalValidatorIndex
validatorsLen := b.validatorsLen()
epoch := slots.ToEpoch(b.slot)
bound := min(validatorsLen, int(params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep))
bound := min(uint64(validatorsLen), params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
for range bound {
val, err := b.validatorAtIndexReadOnly(validatorIndex)
if err != nil {
@@ -233,7 +222,7 @@ func (b *BeaconState) appendValidatorsSweepWithdrawals(withdrawalIndex uint64, w
})
withdrawalIndex++
}
if len(ws) == int(params.BeaconConfig().MaxWithdrawalsPerPayload) {
if uint64(len(ws)) == params.BeaconConfig().MaxWithdrawalsPerPayload {
break
}
validatorIndex += 1

View File

@@ -1,7 +1,6 @@
package state_native
import (
"errors"
"fmt"
"github.com/OffchainLabs/prysm/v7/beacon-chain/state/state-native/types"
@@ -9,10 +8,8 @@ import (
"github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/runtime/version"
pkgerrors "github.com/pkg/errors"
)
// RotateBuilderPendingPayments rotates the queue by dropping slots per epoch payments from the
@@ -164,154 +161,3 @@ func (b *BeaconState) UpdateExecutionPayloadAvailabilityAtIndex(idx uint64, val
b.markFieldAsDirty(types.ExecutionPayloadAvailability)
return nil
}
// SetPayloadExpectedWithdrawals stores the expected withdrawals for the next payload.
func (b *BeaconState) SetPayloadExpectedWithdrawals(withdrawals []*enginev1.Withdrawal) error {
if b.version < version.Gloas {
return errNotSupported("SetPayloadExpectedWithdrawals", b.version)
}
b.lock.Lock()
defer b.lock.Unlock()
b.payloadExpectedWithdrawals = withdrawals
b.markFieldAsDirty(types.PayloadExpectedWithdrawals)
return nil
}
// DequeueBuilderPendingWithdrawals removes processed builder withdrawals from the front of the queue.
func (b *BeaconState) DequeueBuilderPendingWithdrawals(n uint64) error {
if b.version < version.Gloas {
return errNotSupported("DequeueBuilderPendingWithdrawals", b.version)
}
if n > uint64(len(b.builderPendingWithdrawals)) {
return errors.New("cannot dequeue more builder withdrawals than are in the queue")
}
if n == 0 {
return nil
}
b.lock.Lock()
defer b.lock.Unlock()
if b.sharedFieldReferences[types.BuilderPendingWithdrawals].Refs() > 1 {
withdrawals := make([]*ethpb.BuilderPendingWithdrawal, len(b.builderPendingWithdrawals))
copy(withdrawals, b.builderPendingWithdrawals)
b.builderPendingWithdrawals = withdrawals
b.sharedFieldReferences[types.BuilderPendingWithdrawals].MinusRef()
b.sharedFieldReferences[types.BuilderPendingWithdrawals] = stateutil.NewRef(1)
}
b.builderPendingWithdrawals = b.builderPendingWithdrawals[n:]
b.markFieldAsDirty(types.BuilderPendingWithdrawals)
b.rebuildTrie[types.BuilderPendingWithdrawals] = true
return nil
}
// SetNextWithdrawalBuilderIndex sets the next builder index for the withdrawals sweep.
func (b *BeaconState) SetNextWithdrawalBuilderIndex(index primitives.BuilderIndex) error {
if b.version < version.Gloas {
return errNotSupported("SetNextWithdrawalBuilderIndex", b.version)
}
b.lock.Lock()
defer b.lock.Unlock()
b.nextWithdrawalBuilderIndex = index
b.markFieldAsDirty(types.NextWithdrawalBuilderIndex)
return nil
}
// DecreaseWithdrawalBalances applies withdrawal balance decreases for validators and builders.
// This method holds the state lock for the full batch to avoid lock churn.
func (b *BeaconState) DecreaseWithdrawalBalances(withdrawals []*enginev1.Withdrawal) error {
if b.version < version.Gloas {
return errNotSupported("DecreaseWithdrawalBalances", b.version)
}
if len(withdrawals) == 0 {
return nil
}
b.lock.Lock()
defer b.lock.Unlock()
var (
balanceIndices []uint64
builderIndices []uint64
)
for _, withdrawal := range withdrawals {
if withdrawal == nil {
return errors.New("withdrawal is nil")
}
if withdrawal.Amount == 0 {
continue
}
if withdrawal.ValidatorIndex.IsBuilderIndex() {
builderIndex := withdrawal.ValidatorIndex.ToBuilderIndex()
if err := b.decreaseBuilderBalanceLockFree(builderIndex, withdrawal.Amount); err != nil {
return err
}
builderIndices = append(builderIndices, uint64(builderIndex))
continue
}
balAtIdx, err := b.balanceAtIndex(withdrawal.ValidatorIndex)
if err != nil {
return err
}
newBal := decreaseBalanceWithVal(balAtIdx, withdrawal.Amount)
if err := b.balancesMultiValue.UpdateAt(b, uint64(withdrawal.ValidatorIndex), newBal); err != nil {
return pkgerrors.Wrap(err, "could not update balances")
}
balanceIndices = append(balanceIndices, uint64(withdrawal.ValidatorIndex))
}
if len(balanceIndices) > 0 {
b.markFieldAsDirty(types.Balances)
b.addDirtyIndices(types.Balances, balanceIndices)
}
if len(builderIndices) > 0 {
b.markFieldAsDirty(types.Builders)
b.addDirtyIndices(types.Builders, builderIndices)
}
return nil
}
func (b *BeaconState) decreaseBuilderBalanceLockFree(builderIndex primitives.BuilderIndex, amount uint64) error {
idx := uint64(builderIndex)
if idx >= uint64(len(b.builders)) {
return fmt.Errorf("builder index %d out of range (len=%d)", builderIndex, len(b.builders))
}
if b.sharedFieldReferences[types.Builders].Refs() > 1 {
builders := make([]*ethpb.Builder, len(b.builders))
copy(builders, b.builders)
b.builders = builders
b.sharedFieldReferences[types.Builders].MinusRef()
b.sharedFieldReferences[types.Builders] = stateutil.NewRef(1)
}
builder := b.builders[idx]
bal := uint64(builder.Balance)
if amount >= bal {
builder.Balance = 0
} else {
builder.Balance = primitives.Gwei(bal - amount)
}
return nil
}
func decreaseBalanceWithVal(currBalance, delta uint64) uint64 {
if delta > currBalance {
return 0
}
return currBalance - delta
}

View File

@@ -8,7 +8,6 @@ import (
"github.com/OffchainLabs/prysm/v7/beacon-chain/state/stateutil"
"github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
enginev1 "github.com/OffchainLabs/prysm/v7/proto/engine/v1"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/runtime/version"
"github.com/OffchainLabs/prysm/v7/testing/require"
@@ -230,235 +229,6 @@ func TestRotateBuilderPendingPayments_UnsupportedVersion(t *testing.T) {
require.ErrorContains(t, "RotateBuilderPendingPayments", err)
}
func TestSetPayloadExpectedWithdrawals(t *testing.T) {
t.Run("previous fork returns expected error", func(t *testing.T) {
st := &BeaconState{version: version.Fulu}
err := st.SetPayloadExpectedWithdrawals([]*enginev1.Withdrawal{})
require.ErrorContains(t, "SetPayloadExpectedWithdrawals", err)
})
t.Run("allows nil input and marks dirty", func(t *testing.T) {
st := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
}
require.NoError(t, st.SetPayloadExpectedWithdrawals(nil))
require.Equal(t, true, st.payloadExpectedWithdrawals == nil)
require.Equal(t, true, st.dirtyFields[types.PayloadExpectedWithdrawals])
})
t.Run("sets and marks dirty", func(t *testing.T) {
st := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
payloadExpectedWithdrawals: []*enginev1.Withdrawal{{Index: 1}, {Index: 2}},
}
withdrawals := []*enginev1.Withdrawal{{Index: 3}}
require.NoError(t, st.SetPayloadExpectedWithdrawals(withdrawals))
require.DeepEqual(t, withdrawals, st.payloadExpectedWithdrawals)
require.Equal(t, true, st.dirtyFields[types.PayloadExpectedWithdrawals])
})
}
func TestDecreaseWithdrawalBalances(t *testing.T) {
t.Run("previous fork returns expected error", func(t *testing.T) {
st := &BeaconState{version: version.Fulu}
err := st.DecreaseWithdrawalBalances([]*enginev1.Withdrawal{{}})
require.ErrorContains(t, "DecreaseWithdrawalBalances", err)
})
t.Run("rejects nil withdrawal", func(t *testing.T) {
st := &BeaconState{version: version.Gloas}
err := st.DecreaseWithdrawalBalances([]*enginev1.Withdrawal{nil})
require.ErrorContains(t, "withdrawal is nil", err)
})
t.Run("no-op on empty input", func(t *testing.T) {
st := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
dirtyIndices: make(map[types.FieldIndex][]uint64),
rebuildTrie: make(map[types.FieldIndex]bool),
}
require.NoError(t, st.DecreaseWithdrawalBalances(nil))
require.Equal(t, 0, len(st.dirtyFields))
require.Equal(t, 0, len(st.dirtyIndices))
})
t.Run("updates validator and builder balances and tracks dirty indices", func(t *testing.T) {
st := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
dirtyIndices: make(map[types.FieldIndex][]uint64),
rebuildTrie: make(map[types.FieldIndex]bool),
sharedFieldReferences: map[types.FieldIndex]*stateutil.Reference{
types.Builders: stateutil.NewRef(1),
},
balancesMultiValue: NewMultiValueBalances([]uint64{100, 200, 300}),
builders: []*ethpb.Builder{
{Balance: 1000},
{Balance: 50},
},
}
withdrawals := []*enginev1.Withdrawal{
{ValidatorIndex: primitives.ValidatorIndex(1), Amount: 20},
{ValidatorIndex: primitives.BuilderIndex(1).ToValidatorIndex(), Amount: 30},
{ValidatorIndex: primitives.ValidatorIndex(2), Amount: 400},
{ValidatorIndex: primitives.BuilderIndex(0).ToValidatorIndex(), Amount: 2000},
{ValidatorIndex: primitives.ValidatorIndex(0), Amount: 0},
}
require.NoError(t, st.DecreaseWithdrawalBalances(withdrawals))
require.DeepEqual(t, []uint64{100, 180, 0}, st.Balances())
require.Equal(t, primitives.Gwei(0), st.builders[0].Balance)
require.Equal(t, primitives.Gwei(20), st.builders[1].Balance)
require.Equal(t, true, st.dirtyFields[types.Balances])
require.Equal(t, true, st.dirtyFields[types.Builders])
require.DeepEqual(t, []uint64{1, 2}, st.dirtyIndices[types.Balances])
require.DeepEqual(t, []uint64{1, 0}, st.dirtyIndices[types.Builders])
})
t.Run("returns error on builder index out of range", func(t *testing.T) {
st := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
dirtyIndices: make(map[types.FieldIndex][]uint64),
rebuildTrie: make(map[types.FieldIndex]bool),
sharedFieldReferences: map[types.FieldIndex]*stateutil.Reference{
types.Builders: stateutil.NewRef(1),
},
builders: []*ethpb.Builder{{Balance: 5}},
}
err := st.DecreaseWithdrawalBalances([]*enginev1.Withdrawal{
{ValidatorIndex: primitives.BuilderIndex(2).ToValidatorIndex(), Amount: 1},
})
require.ErrorContains(t, "out of range", err)
require.Equal(t, false, st.dirtyFields[types.Builders])
require.Equal(t, 0, len(st.dirtyIndices[types.Builders]))
})
}
func TestDequeueBuilderPendingWithdrawals(t *testing.T) {
t.Run("previous fork returns expected error", func(t *testing.T) {
st := &BeaconState{version: version.Fulu}
err := st.DequeueBuilderPendingWithdrawals(1)
require.ErrorContains(t, "DequeueBuilderPendingWithdrawals", err)
})
t.Run("returns error when dequeueing more than length", func(t *testing.T) {
st := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
sharedFieldReferences: map[types.FieldIndex]*stateutil.Reference{
types.BuilderPendingWithdrawals: stateutil.NewRef(1),
},
builderPendingWithdrawals: []*ethpb.BuilderPendingWithdrawal{{Amount: 1}},
}
err := st.DequeueBuilderPendingWithdrawals(2)
require.ErrorContains(t, "cannot dequeue more builder withdrawals", err)
require.Equal(t, 1, len(st.builderPendingWithdrawals))
require.Equal(t, false, st.dirtyFields[types.BuilderPendingWithdrawals])
})
t.Run("no-op on zero", func(t *testing.T) {
st := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
sharedFieldReferences: map[types.FieldIndex]*stateutil.Reference{
types.BuilderPendingWithdrawals: stateutil.NewRef(1),
},
builderPendingWithdrawals: []*ethpb.BuilderPendingWithdrawal{{Amount: 1}},
}
require.NoError(t, st.DequeueBuilderPendingWithdrawals(0))
require.Equal(t, 1, len(st.builderPendingWithdrawals))
require.Equal(t, false, st.dirtyFields[types.BuilderPendingWithdrawals])
require.Equal(t, false, st.rebuildTrie[types.BuilderPendingWithdrawals])
})
t.Run("dequeues and marks dirty", func(t *testing.T) {
st := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
sharedFieldReferences: map[types.FieldIndex]*stateutil.Reference{
types.BuilderPendingWithdrawals: stateutil.NewRef(1),
},
builderPendingWithdrawals: []*ethpb.BuilderPendingWithdrawal{
{Amount: 1},
{Amount: 2},
{Amount: 3},
},
rebuildTrie: make(map[types.FieldIndex]bool),
}
require.NoError(t, st.DequeueBuilderPendingWithdrawals(2))
require.Equal(t, 1, len(st.builderPendingWithdrawals))
require.Equal(t, primitives.Gwei(3), st.builderPendingWithdrawals[0].Amount)
require.Equal(t, true, st.dirtyFields[types.BuilderPendingWithdrawals])
require.Equal(t, true, st.rebuildTrie[types.BuilderPendingWithdrawals])
})
t.Run("copy-on-write preserves shared state", func(t *testing.T) {
sharedRef := stateutil.NewRef(2)
sharedWithdrawals := []*ethpb.BuilderPendingWithdrawal{
{Amount: 1},
{Amount: 2},
{Amount: 3},
}
st1 := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
sharedFieldReferences: map[types.FieldIndex]*stateutil.Reference{
types.BuilderPendingWithdrawals: sharedRef,
},
builderPendingWithdrawals: sharedWithdrawals,
rebuildTrie: make(map[types.FieldIndex]bool),
}
st2 := &BeaconState{
sharedFieldReferences: map[types.FieldIndex]*stateutil.Reference{
types.BuilderPendingWithdrawals: sharedRef,
},
builderPendingWithdrawals: sharedWithdrawals,
}
require.NoError(t, st1.DequeueBuilderPendingWithdrawals(2))
require.Equal(t, primitives.Gwei(3), st1.builderPendingWithdrawals[0].Amount)
require.Equal(t, 3, len(st2.builderPendingWithdrawals))
require.Equal(t, primitives.Gwei(1), st2.builderPendingWithdrawals[0].Amount)
require.Equal(t, uint(1), st1.sharedFieldReferences[types.BuilderPendingWithdrawals].Refs())
require.Equal(t, uint(1), st2.sharedFieldReferences[types.BuilderPendingWithdrawals].Refs())
})
}
func TestSetNextWithdrawalBuilderIndex(t *testing.T) {
t.Run("previous fork returns expected error", func(t *testing.T) {
st := &BeaconState{version: version.Fulu}
err := st.SetNextWithdrawalBuilderIndex(1)
require.ErrorContains(t, "SetNextWithdrawalBuilderIndex", err)
})
t.Run("sets and marks dirty", func(t *testing.T) {
st := &BeaconState{
version: version.Gloas,
dirtyFields: make(map[types.FieldIndex]bool),
}
require.NoError(t, st.SetNextWithdrawalBuilderIndex(7))
require.Equal(t, primitives.BuilderIndex(7), st.nextWithdrawalBuilderIndex)
require.Equal(t, true, st.dirtyFields[types.NextWithdrawalBuilderIndex])
})
}
func TestAppendBuilderPendingWithdrawal_CopyOnWrite(t *testing.T) {
wd := &ethpb.BuilderPendingWithdrawal{
FeeRecipient: make([]byte, 20),

View File

@@ -1027,10 +1027,10 @@ func TestGetVerifyingStateEdgeCases(t *testing.T) {
sc: signatureCache,
sr: &mockStateByRooter{sbr: sbrErrorIfCalled(t)}, // Should not be called
hsp: &mockHeadStateProvider{
headRoot: parentRoot[:], // Same as parent
headSlot: 32, // Epoch 1
headState: fuluState.Copy(), // HeadState (not ReadOnly) for ProcessSlots
headStateReadOnly: nil, // Should not use ReadOnly path
headRoot: parentRoot[:], // Same as parent
headSlot: 32, // Epoch 1
headState: fuluState.Copy(), // HeadState (not ReadOnly) for ProcessSlots
headStateReadOnly: nil, // Should not use ReadOnly path
},
fc: &mockForkchoicer{
// Return same root for both to simulate same chain
@@ -1045,8 +1045,8 @@ func TestGetVerifyingStateEdgeCases(t *testing.T) {
// Wrap to detect HeadState call
originalHsp := initializer.shared.hsp.(*mockHeadStateProvider)
wrappedHsp := &mockHeadStateProvider{
headRoot: originalHsp.headRoot,
headSlot: originalHsp.headSlot,
headRoot: originalHsp.headRoot,
headSlot: originalHsp.headSlot,
headState: originalHsp.headState,
}
initializer.shared.hsp = &headStateCallTracker{

View File

@@ -0,0 +1,3 @@
### Added
- Set beacon node options after reading the config file.

View File

@@ -0,0 +1,3 @@
### Fixed
- Fixed a bug where `cmd/beacon-chain/execution` was being ignored by `hack/gen-logs.sh` due to a `.gitignore` rule.

View File

@@ -0,0 +1,7 @@
### Changed
- gRPC fallback now matches rest api implementation and will also check and connect to only synced nodes.
### Removed
- gRPC resolver for load balancing, the new implementation matches rest api's so we should remove the resolver so it's handled the same way for consistency.

View File

@@ -0,0 +1,11 @@
### Ignored
- moved finding healthy node logic to connection provider and other various cleanup on naming.
### Changed
- Improved node fallback logs.
### Fixed
- a potential race condition when switching hosts quickly and reconnecting to same host on an old connection.

View File

@@ -0,0 +1,3 @@
### Changed
- Improved integrations with ethspecify so specrefs can be used throughout the codebase.

View File

@@ -0,0 +1,3 @@
### Ignored
- Updated golangci to run lint on tests too.

View File

@@ -0,0 +1,3 @@
### Ignored
- Add handy documentation for SSZ Query package (`encoding/ssz/query`).

View File

@@ -1,2 +0,0 @@
### Added
- add modified process withdrawals for gloas

View File

@@ -0,0 +1,2 @@
### Ignored
- Run go fmt

View File

@@ -1,5 +1,9 @@
// Code generated by hack/gen-logs.sh; DO NOT EDIT.
// This file is created and regenerated automatically. Anything added here might get removed.
package execution
import "github.com/sirupsen/logrus"
var log = logrus.WithField("prefix", "execution")
// The prefix for logs from this package will be the text after the last slash in the package path.
// If you wish to change this, you should add your desired name in the runtime/logging/logrus-prefixed-formatter/prefix-replacement.go file.
var log = logrus.WithField("package", "cmd/beacon-chain/execution")

View File

@@ -367,17 +367,8 @@ func startNode(ctx *cli.Context, cancel context.CancelFunc) error {
backfill.BeaconNodeOptions,
das.BeaconNodeOptions,
}
for _, of := range optFuncs {
ofo, err := of(ctx)
if err != nil {
return err
}
if ofo != nil {
opts = append(opts, ofo...)
}
}
beacon, err := node.New(ctx, cancel, opts...)
beacon, err := node.New(ctx, cancel, optFuncs, opts...)
if err != nil {
return fmt.Errorf("unable to start beacon node: %w", err)
}

View File

@@ -130,7 +130,6 @@ type BeaconChainConfig struct {
MaxWithdrawalsPerPayload uint64 `yaml:"MAX_WITHDRAWALS_PER_PAYLOAD" spec:"true"` // MaxWithdrawalsPerPayload defines the maximum number of withdrawals in a block.
MaxBlsToExecutionChanges uint64 `yaml:"MAX_BLS_TO_EXECUTION_CHANGES" spec:"true"` // MaxBlsToExecutionChanges defines the maximum number of BLS-to-execution-change objects in a block.
MaxValidatorsPerWithdrawalsSweep uint64 `yaml:"MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP" spec:"true"` // MaxValidatorsPerWithdrawalsSweep bounds the size of the sweep searching for withdrawals per slot.
MaxBuildersPerWithdrawalsSweep uint64 `yaml:"MAX_BUILDERS_PER_WITHDRAWALS_SWEEP" spec:"true"` // MaxBuildersPerWithdrawalsSweep bounds the size of the builder withdrawals sweep per slot.
// BLS domain values.
DomainBeaconProposer [4]byte `yaml:"DOMAIN_BEACON_PROPOSER" spec:"true"` // DomainBeaconProposer defines the BLS signature domain for beacon proposal verification.

View File

@@ -194,7 +194,6 @@ func ConfigToYaml(cfg *BeaconChainConfig) []byte {
fmt.Sprintf("SHARD_COMMITTEE_PERIOD: %d", cfg.ShardCommitteePeriod),
fmt.Sprintf("MIN_VALIDATOR_WITHDRAWABILITY_DELAY: %d", cfg.MinValidatorWithdrawabilityDelay),
fmt.Sprintf("MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP: %d", cfg.MaxValidatorsPerWithdrawalsSweep),
fmt.Sprintf("MAX_BUILDERS_PER_WITHDRAWALS_SWEEP: %d", cfg.MaxBuildersPerWithdrawalsSweep),
fmt.Sprintf("MAX_SEED_LOOKAHEAD: %d", cfg.MaxSeedLookahead),
fmt.Sprintf("EJECTION_BALANCE: %d", cfg.EjectionBalance),
fmt.Sprintf("MIN_PER_EPOCH_CHURN_LIMIT: %d", cfg.MinPerEpochChurnLimit),

View File

@@ -175,7 +175,6 @@ var mainnetBeaconConfig = &BeaconChainConfig{
MaxWithdrawalsPerPayload: 16,
MaxBlsToExecutionChanges: 16,
MaxValidatorsPerWithdrawalsSweep: 16384,
MaxBuildersPerWithdrawalsSweep: 16384,
// BLS domain values.
DomainBeaconProposer: bytesutil.Uint32ToBytes4(0x00000000),

View File

@@ -94,7 +94,6 @@ func compareConfigs(t *testing.T, expected, actual *params.BeaconChainConfig) {
require.DeepEqual(t, expected.MaxDeposits, actual.MaxDeposits)
require.DeepEqual(t, expected.MaxVoluntaryExits, actual.MaxVoluntaryExits)
require.DeepEqual(t, expected.MaxWithdrawalsPerPayload, actual.MaxWithdrawalsPerPayload)
require.DeepEqual(t, expected.MaxBuildersPerWithdrawalsSweep, actual.MaxBuildersPerWithdrawalsSweep)
require.DeepEqual(t, expected.DomainBeaconProposer, actual.DomainBeaconProposer)
require.DeepEqual(t, expected.DomainRandao, actual.DomainRandao)
require.DeepEqual(t, expected.DomainBeaconAttester, actual.DomainBeaconAttester)

View File

@@ -13,16 +13,6 @@ var _ fssz.Unmarshaler = (*BuilderIndex)(nil)
// BuilderIndex is an index into the builder registry.
type BuilderIndex uint64
// ToValidatorIndex sets the builder flag on a builder index.
//
// Spec v1.6.1 (pseudocode):
// def convert_builder_index_to_validator_index(builder_index: BuilderIndex) -> ValidatorIndex:
//
// return ValidatorIndex(builder_index | BUILDER_INDEX_FLAG)
func (b BuilderIndex) ToValidatorIndex() ValidatorIndex {
return ValidatorIndex(uint64(b) | BuilderIndexFlag)
}
// HashTreeRoot returns the SSZ hash tree root of the index.
func (b BuilderIndex) HashTreeRoot() ([32]byte, error) {
return fssz.HashWithDefaultHasher(b)

View File

@@ -10,34 +10,9 @@ var _ fssz.HashRoot = (ValidatorIndex)(0)
var _ fssz.Marshaler = (*ValidatorIndex)(nil)
var _ fssz.Unmarshaler = (*ValidatorIndex)(nil)
// BuilderIndexFlag marks a ValidatorIndex as a BuilderIndex when the bit is set.
//
// Spec v1.6.1: BUILDER_INDEX_FLAG.
const BuilderIndexFlag uint64 = 1 << 40
// ValidatorIndex in eth2.
type ValidatorIndex uint64
// IsBuilderIndex returns true when the BuilderIndex flag is set on the validator index.
//
// Spec v1.6.1 (pseudocode):
// def is_builder_index(validator_index: ValidatorIndex) -> bool:
//
// return (validator_index & BUILDER_INDEX_FLAG) != 0
func (v ValidatorIndex) IsBuilderIndex() bool {
return uint64(v)&BuilderIndexFlag != 0
}
// ToBuilderIndex strips the builder flag from a validator index.
//
// Spec v1.6.1 (pseudocode):
// def convert_validator_index_to_builder_index(validator_index: ValidatorIndex) -> BuilderIndex:
//
// return BuilderIndex(validator_index & ~BUILDER_INDEX_FLAG)
func (v ValidatorIndex) ToBuilderIndex() BuilderIndex {
return BuilderIndex(uint64(v) & ^BuilderIndexFlag)
}
// Div divides validator index by x.
// This method panics if dividing by zero!
func (v ValidatorIndex) Div(x uint64) ValidatorIndex {

View File

@@ -33,32 +33,3 @@ func TestValidatorIndex_Casting(t *testing.T) {
}
})
}
func TestValidatorIndex_BuilderIndexFlagConversions(t *testing.T) {
base := uint64(42)
unflagged := ValidatorIndex(base)
if unflagged.IsBuilderIndex() {
t.Fatalf("expected unflagged validator index to not be a builder index")
}
if got, want := unflagged.ToBuilderIndex(), BuilderIndex(base); got != want {
t.Fatalf("unexpected builder index: got %d want %d", got, want)
}
flagged := ValidatorIndex(base | BuilderIndexFlag)
if !flagged.IsBuilderIndex() {
t.Fatalf("expected flagged validator index to be a builder index")
}
if got, want := flagged.ToBuilderIndex(), BuilderIndex(base); got != want {
t.Fatalf("unexpected builder index: got %d want %d", got, want)
}
builder := BuilderIndex(base)
roundTrip := builder.ToValidatorIndex()
if !roundTrip.IsBuilderIndex() {
t.Fatalf("expected round-tripped validator index to be a builder index")
}
if got, want := roundTrip.ToBuilderIndex(), builder; got != want {
t.Fatalf("unexpected round-trip builder index: got %d want %d", got, want)
}
}

190
encoding/ssz/query/doc.md Normal file
View File

@@ -0,0 +1,190 @@
# SSZ Query Package
The `encoding/ssz/query` package provides a system for analyzing and querying SSZ ([Simple Serialize](https://github.com/ethereum/consensus-specs/blob/master/ssz/simple-serialize.md)) data structures, as well as generating Merkle proofs from them. It enables runtime analysis of SSZ-serialized Go objects with reflection, path-based queries through nested structures, generalized index calculation, and Merkle proof generation.
This package is designed to be generic. It operates on arbitrary SSZ-serialized Go values at runtime, so the same query/proof machinery applies equally to any SSZ type, including the BeaconState/BeaconBlock.
## Usage Example
```go
// 1. Analyze an SSZ object
block := &ethpb.BeaconBlock{...}
info, err := query.AnalyzeObject(block)
// 2. Parse a path
path, err := query.ParsePath(".body.attestations[0].data.slot")
// 3. Get the generalized index
gindex, err := query.GetGeneralizedIndexFromPath(info, path)
// 4. Generate a Merkle proof
proof, err := info.Prove(gindex)
// 5. Get offset and length to slice the SSZ-encoded bytes
sszBytes, _ := block.MarshalSSZ()
_, offset, length, err := query.CalculateOffsetAndLength(info, path)
// slotBytes contains the SSZ-encoded value at the queried path
slotBytes := sszBytes[offset : offset+length]
```
## Exported API
The main exported API consists of:
```go
// AnalyzeObject analyzes an SSZ object and returns its structural information
func AnalyzeObject(obj SSZObject) (*SszInfo, error)
// ParsePath parses a path string like ".field1.field2[0].field3"
func ParsePath(rawPath string) (Path, error)
// CalculateOffsetAndLength computes byte offset and length for a path within an SSZ object
func CalculateOffsetAndLength(sszInfo *SszInfo, path Path) (*SszInfo, uint64, uint64, error)
// GetGeneralizedIndexFromPath calculates the generalized index for a given path
func GetGeneralizedIndexFromPath(info *SszInfo, path Path) (uint64, error)
// Prove generates a Merkle proof for a target generalized index
func (s *SszInfo) Prove(gindex uint64) (*fastssz.Proof, error)
```
## Type System
### SSZ Types
The package now supports [all standard SSZ types](https://github.com/ethereum/consensus-specs/blob/master/ssz/simple-serialize.md#typing) except `ProgressiveList`, `ProgressiveContainer`, `ProgressiveBitlist`, `Union`, and `CompatibleUnion`.
### Core Data Structures
#### `SszInfo`
The `SszInfo` structure contains complete structural metadata for an SSZ type:
```go
type SszInfo struct {
sszType SszType // SSZ Type classification
typ reflect.Type // Go reflect.Type
source SSZObject // Original SSZObject reference. Mostly used for reusing SSZ methods like `HashTreeRoot`.
isVariable bool // True if contains variable-size fields
// Composite types have corresponding metadata. Other fields would be nil except for the current type.
containerInfo *containerInfo
listInfo *listInfo
vectorInfo *vectorInfo
bitlistInfo *bitlistInfo
bitvectorInfo *bitvectorInfo
}
```
#### `Path`
The `Path` structure represents navigation paths through SSZ structures. It supports accessing a field by field name, accessing an element by index (list/vector type), and finding the length of homogenous collection types. The `ParsePath` function parses a raw string into a `Path` instance, which is commonly used in other APIs like `CalculateOffsetAndLength` and `GetGeneralizedIndexFromPath`.
```go
type Path struct {
Length bool // Flag for length queries (e.g., len(.field))
Elements []PathElement // Sequence of field accesses and indices
}
type PathElement struct {
Name string // Field name
Index *uint64 // list/vector index (nil if not an index access)
}
```
## Implementation Details
### Type Analysis (`analyzer.go`)
The `AnalyzeObject` function performs recursive type introspection using Go reflection:
1. **Type Inspection** - Examines Go `reflect.Value` to determine SSZ type
- Basic types (`uint8`, `uint16`, `uint32`, `uint64`, `bool`): `SSZType` constants
- Slices: Determined from struct tags (`ssz-size` for vectors, `ssz-max` for lists). There is a related [write-up](https://hackmd.io/@junsong/H101DKnwxl) regarding struct tags.
- Structs: Analyzed as Containers with field ordering from JSON tags
- Pointers: Dereferenced automatically
2. **Variable-Length Population** - Determines actual sizes at runtime
- For lists: Iterates elements, caches sizes for variable-element lists
- For containers: Recursively populates variable fields, adjusts offsets
- For bitlists: Decodes bit length from bitvector
3. **Offset Calculation** - Computes byte positions within serialized data
- Fixed-size fields: Offset = sum of preceding field sizes
- Variable-size fields: Offset stored as 4-byte pointer entries
### Path Parsing (`path.go`)
The `ParsePath` function parses path strings with the following rules:
- **Dot notation**: `.field1.field2` for field access
- **Array indexing**: `[0]`, `[42]` for element access
- **Length queries**: `len(.field)` for list/vector lengths
- **Character set**: Only `[A-Za-z0-9._\[\]\(\)]` allowed
Example:
```go
path, _ := ParsePath(".nested.array_field[5].inner_field")
// Returns: Path{
// Elements: [
// PathElement{Name: "nested"},
// PathElement{Name: "array_field", Index: <Pointer to uint64(5)>},
// PathElement{Name: "inner_field"}
// ]
// }
```
### Generalized Index Calculation (`generalized_index.go`)
The generalized index is a tree position identifier. This package follows the [Ethereum consensus-specs](https://github.com/ethereum/consensus-specs/blob/master/ssz/merkle-proofs.md#generalized-merkle-tree-index) to calculate the generalized index.
### Merkle Proof Generation (`merkle_proof.go`, `proof_collector.go`)
The `Prove` method generates Merkle proofs using a single-sweep merkleization algorithm:
#### Algorithm Overview
**Key Terms:**
- **Target gindex** (generalized index): The position of the SSZ element you want to prove, expressed as a generalized Merkle tree index. Stored in `Proof.Index`.
- Note: The generalized index for root is 1.
- **Registered gindices**: The set of tree positions whose node hashes must be captured during merkleization in order to later assemble the proof.
- **Sibling node**: The node that shares the same parent as another node.
- **Leaf value**: The 32-byte hash of the target node (the node being proven). Stored in `Proof.Leaf`.
**Phases:**
1. **Registration Phase** (`addTarget`)
> Goal: determine exactly which sibling hashes are needed for the proof.
- Record the target gindex as the proof target.
- Starting from the target node, walk the Merkle tree from the leaf (target gindex) to the root (gindex = 1).
- At each step:
- Compute and register the sibling gindex (`i XOR 1`) as “must collect”.
- Move to the parent (`i = i/2`).
- This produces the full set of registered gindices (the sibling nodes on the target-to-root path).
2. **Merkleization Phase** (`merkleize`)
> Goal: recursively merkleize the tree and capture the needed hashes.
- Recursively traverse the SSZ structure and compute Merkle tree node hashes from leaves to root.
- Whenever the traversal computes a node whose gindex is in registered gindices, store that nodes hash for later proof construction.
3. **Proof Assembly Phase** (`toProof`)
> Goal: create the final `fastssz.Proof` object in the correct format and order.
```go
// Proof represents a merkle proof against a general index.
type Proof struct {
Index int
Leaf []byte
Hashes [][]byte
}
```
- Set `Proof.Index` to the target gindex.
- Set `Proof.Leaf` to the 32-byte hash of the target node.
- Build `Proof.Hashes` by walking from the target node up to (but not including) the root:
- At node `i`, append the stored hash for the sibling (`i XOR 1`).
- Move to the parent (`i = i/2`).
- The resulting `Proof.Hashes` is ordered from the target level upward, containing one sibling hash per tree level on the path to the root.

View File

@@ -31,6 +31,11 @@ EXCLUDED_PATH_PREFIXES=(
".vscode"
)
# Gitignore overrides: paths that should still be scanned even if ignored by VCS.
GITIGNORE_OVERRIDES=(
"cmd/beacon-chain/execution"
)
# The logrus import path
LOGRUS_IMPORT="github.com/sirupsen/logrus"
# ----------------------------
@@ -70,6 +75,14 @@ rg_args=(
-0 # NUL-delimited output
)
if [[ ${#GITIGNORE_OVERRIDES[@]} -gt 0 ]]; then
# Disable VCS ignores so overrides are honored.
rg_args+=( --no-ignore-vcs )
for ov in "${GITIGNORE_OVERRIDES[@]}"; do
rg_args+=( --glob "$ov/**" )
done
fi
for ex in "${EXCLUDED_PATH_PREFIXES[@]}"; do
rg_args+=( --glob "!$ex/**" )
done

View File

@@ -26,21 +26,21 @@ func TestLifecycle(t *testing.T) {
port := 1000 + rand.Intn(1000)
prometheusService := NewService(t.Context(), fmt.Sprintf(":%d", port), nil)
prometheusService.Start()
// Actively wait until the service responds on /metrics (faster and less flaky than a fixed sleep)
deadline := time.Now().Add(3 * time.Second)
for {
if time.Now().After(deadline) {
t.Fatalf("metrics endpoint not ready within timeout")
}
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/metrics", port))
if err == nil {
_ = resp.Body.Close()
if resp.StatusCode == http.StatusOK {
break
}
}
time.Sleep(50 * time.Millisecond)
}
// Actively wait until the service responds on /metrics (faster and less flaky than a fixed sleep)
deadline := time.Now().Add(3 * time.Second)
for {
if time.Now().After(deadline) {
t.Fatalf("metrics endpoint not ready within timeout")
}
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/metrics", port))
if err == nil {
_ = resp.Body.Close()
if resp.StatusCode == http.StatusOK {
break
}
}
time.Sleep(50 * time.Millisecond)
}
// Query the service to ensure it really started.
resp, err := http.Get(fmt.Sprintf("http://localhost:%d/metrics", port))
@@ -49,18 +49,18 @@ func TestLifecycle(t *testing.T) {
err = prometheusService.Stop()
require.NoError(t, err)
// Actively wait until the service stops responding on /metrics
deadline = time.Now().Add(3 * time.Second)
for {
if time.Now().After(deadline) {
t.Fatalf("metrics endpoint still reachable after timeout")
}
_, err = http.Get(fmt.Sprintf("http://localhost:%d/metrics", port))
if err != nil {
break
}
time.Sleep(50 * time.Millisecond)
}
// Actively wait until the service stops responding on /metrics
deadline = time.Now().Add(3 * time.Second)
for {
if time.Now().After(deadline) {
t.Fatalf("metrics endpoint still reachable after timeout")
}
_, err = http.Get(fmt.Sprintf("http://localhost:%d/metrics", port))
if err != nil {
break
}
time.Sleep(50 * time.Millisecond)
}
// Query the service to ensure it really stopped.
_, err = http.Get(fmt.Sprintf("http://localhost:%d/metrics", port))

View File

@@ -11,17 +11,12 @@ Install `ethspecify` with the following command:
pipx install ethspecify
```
> [!NOTE]
> You can run `ethspecify <cmd>` in the `specrefs` directory or
> `ethspecify <cmd> --path=specrefs` from the project's root directory.
## Maintenance
When adding support for a new specification version, follow these steps:
0. Change directory into the `specrefs` directory.
1. Update the version in `.ethspecify.yml` configuration.
2. Run `ethspecify process` to update/populate specrefs.
2. Run `ethspecify` to update/populate specrefs.
3. Run `ethspecify check` to check specrefs.
4. If there are errors, use the error message as a guide to fix the issue. If
there are new specrefs with empty sources, implement/locate each item and

View File

@@ -1,4 +1,4 @@
- name: AGGREGATE_DUE_BPS
- name: AGGREGATE_DUE_BPS#phase0
sources:
- file: config/params/config.go
search: AggregateDueBPS\s+primitives.BP
@@ -8,7 +8,14 @@
AGGREGATE_DUE_BPS: uint64 = 6667
</spec>
- name: ALTAIR_FORK_EPOCH
- name: AGGREGATE_DUE_BPS_GLOAS#gloas
sources: []
spec: |
<spec config_var="AGGREGATE_DUE_BPS_GLOAS" fork="gloas" hash="34aa3164">
AGGREGATE_DUE_BPS_GLOAS: uint64 = 5000
</spec>
- name: ALTAIR_FORK_EPOCH#altair
sources:
- file: config/params/config.go
search: AltairForkEpoch\s+primitives.Epoch
@@ -18,7 +25,7 @@
ALTAIR_FORK_EPOCH: Epoch = 74240
</spec>
- name: ALTAIR_FORK_VERSION
- name: ALTAIR_FORK_VERSION#altair
sources:
- file: config/params/config.go
search: AltairForkVersion\s+\[]byte
@@ -28,7 +35,7 @@
ALTAIR_FORK_VERSION: Version = '0x01000000'
</spec>
- name: ATTESTATION_DUE_BPS
- name: ATTESTATION_DUE_BPS#phase0
sources:
- file: config/params/config.go
search: AttestationDueBPS\s+primitives.BP
@@ -38,7 +45,14 @@
ATTESTATION_DUE_BPS: uint64 = 3333
</spec>
- name: ATTESTATION_PROPAGATION_SLOT_RANGE
- name: ATTESTATION_DUE_BPS_GLOAS#gloas
sources: []
spec: |
<spec config_var="ATTESTATION_DUE_BPS_GLOAS" fork="gloas" hash="3863c1ef">
ATTESTATION_DUE_BPS_GLOAS: uint64 = 2500
</spec>
- name: ATTESTATION_PROPAGATION_SLOT_RANGE#phase0
sources:
- file: config/params/config.go
search: AttestationPropagationSlotRange\s+primitives.Slot
@@ -48,7 +62,7 @@
ATTESTATION_PROPAGATION_SLOT_RANGE = 32
</spec>
- name: ATTESTATION_SUBNET_COUNT
- name: ATTESTATION_SUBNET_COUNT#phase0
sources:
- file: config/params/config.go
search: AttestationSubnetCount\s+uint64
@@ -58,7 +72,7 @@
ATTESTATION_SUBNET_COUNT = 64
</spec>
- name: ATTESTATION_SUBNET_EXTRA_BITS
- name: ATTESTATION_SUBNET_EXTRA_BITS#phase0
sources:
- file: config/params/config.go
search: AttestationSubnetExtraBits\s+uint64
@@ -68,7 +82,7 @@
ATTESTATION_SUBNET_EXTRA_BITS = 0
</spec>
- name: ATTESTATION_SUBNET_PREFIX_BITS
- name: ATTESTATION_SUBNET_PREFIX_BITS#phase0
sources:
- file: config/params/config.go
search: AttestationSubnetPrefixBits\s+uint64
@@ -78,7 +92,7 @@
ATTESTATION_SUBNET_PREFIX_BITS: int = 6
</spec>
- name: BALANCE_PER_ADDITIONAL_CUSTODY_GROUP
- name: BALANCE_PER_ADDITIONAL_CUSTODY_GROUP#fulu
sources:
- file: config/params/config.go
search: BalancePerAdditionalCustodyGroup\s+uint64
@@ -88,7 +102,7 @@
BALANCE_PER_ADDITIONAL_CUSTODY_GROUP: Gwei = 32000000000
</spec>
- name: BELLATRIX_FORK_EPOCH
- name: BELLATRIX_FORK_EPOCH#bellatrix
sources:
- file: config/params/config.go
search: BellatrixForkEpoch\s+primitives.Epoch
@@ -98,7 +112,7 @@
BELLATRIX_FORK_EPOCH: Epoch = 144896
</spec>
- name: BELLATRIX_FORK_VERSION
- name: BELLATRIX_FORK_VERSION#bellatrix
sources:
- file: config/params/config.go
search: BellatrixForkVersion\s+\[]byte
@@ -108,7 +122,7 @@
BELLATRIX_FORK_VERSION: Version = '0x02000000'
</spec>
- name: BLOB_SCHEDULE
- name: BLOB_SCHEDULE#fulu
sources:
- file: config/params/config.go
search: BlobSchedule\s+\[]BlobScheduleEntry
@@ -127,7 +141,7 @@
)
</spec>
- name: BLOB_SIDECAR_SUBNET_COUNT
- name: BLOB_SIDECAR_SUBNET_COUNT#deneb
sources:
- file: config/params/config.go
search: BlobsidecarSubnetCount\s+uint64
@@ -137,7 +151,7 @@
BLOB_SIDECAR_SUBNET_COUNT = 6
</spec>
- name: BLOB_SIDECAR_SUBNET_COUNT_ELECTRA
- name: BLOB_SIDECAR_SUBNET_COUNT_ELECTRA#electra
sources:
- file: config/params/config.go
search: BlobsidecarSubnetCountElectra\s+uint64
@@ -147,7 +161,7 @@
BLOB_SIDECAR_SUBNET_COUNT_ELECTRA = 9
</spec>
- name: CAPELLA_FORK_EPOCH
- name: CAPELLA_FORK_EPOCH#capella
sources:
- file: config/params/config.go
search: CapellaForkEpoch\s+primitives.Epoch
@@ -157,7 +171,7 @@
CAPELLA_FORK_EPOCH: Epoch = 194048
</spec>
- name: CAPELLA_FORK_VERSION
- name: CAPELLA_FORK_VERSION#capella
sources:
- file: config/params/config.go
search: CapellaForkVersion\s+\[]byte
@@ -167,7 +181,7 @@
CAPELLA_FORK_VERSION: Version = '0x03000000'
</spec>
- name: CHURN_LIMIT_QUOTIENT
- name: CHURN_LIMIT_QUOTIENT#phase0
sources:
- file: config/params/config.go
search: ChurnLimitQuotient\s+uint64
@@ -177,7 +191,7 @@
CHURN_LIMIT_QUOTIENT: uint64 = 65536
</spec>
- name: CONTRIBUTION_DUE_BPS
- name: CONTRIBUTION_DUE_BPS#altair
sources:
- file: config/params/config.go
search: ContributionDueBPS\s+primitives.BP
@@ -187,7 +201,14 @@
CONTRIBUTION_DUE_BPS: uint64 = 6667
</spec>
- name: CUSTODY_REQUIREMENT
- name: CONTRIBUTION_DUE_BPS_GLOAS#gloas
sources: []
spec: |
<spec config_var="CONTRIBUTION_DUE_BPS_GLOAS" fork="gloas" hash="0ead2ac1">
CONTRIBUTION_DUE_BPS_GLOAS: uint64 = 5000
</spec>
- name: CUSTODY_REQUIREMENT#fulu
sources:
- file: config/params/config.go
search: CustodyRequirement\s+uint64.*yaml:"CUSTODY_REQUIREMENT"
@@ -197,7 +218,7 @@
CUSTODY_REQUIREMENT = 4
</spec>
- name: DATA_COLUMN_SIDECAR_SUBNET_COUNT
- name: DATA_COLUMN_SIDECAR_SUBNET_COUNT#fulu
sources:
- file: config/params/config.go
search: DataColumnSidecarSubnetCount\s+uint64
@@ -207,7 +228,7 @@
DATA_COLUMN_SIDECAR_SUBNET_COUNT = 128
</spec>
- name: DENEB_FORK_EPOCH
- name: DENEB_FORK_EPOCH#deneb
sources:
- file: config/params/config.go
search: DenebForkEpoch\s+primitives.Epoch
@@ -217,7 +238,7 @@
DENEB_FORK_EPOCH: Epoch = 269568
</spec>
- name: DENEB_FORK_VERSION
- name: DENEB_FORK_VERSION#deneb
sources:
- file: config/params/config.go
search: DenebForkVersion\s+\[]byte
@@ -227,7 +248,7 @@
DENEB_FORK_VERSION: Version = '0x04000000'
</spec>
- name: EJECTION_BALANCE
- name: EJECTION_BALANCE#phase0
sources:
- file: config/params/config.go
search: EjectionBalance\s+uint64
@@ -237,7 +258,7 @@
EJECTION_BALANCE: Gwei = 16000000000
</spec>
- name: ELECTRA_FORK_EPOCH
- name: ELECTRA_FORK_EPOCH#electra
sources:
- file: config/params/config.go
search: ElectraForkEpoch\s+primitives.Epoch
@@ -247,7 +268,7 @@
ELECTRA_FORK_EPOCH: Epoch = 364032
</spec>
- name: ELECTRA_FORK_VERSION
- name: ELECTRA_FORK_VERSION#electra
sources:
- file: config/params/config.go
search: ElectraForkVersion\s+\[]byte
@@ -257,7 +278,7 @@
ELECTRA_FORK_VERSION: Version = '0x05000000'
</spec>
- name: EPOCHS_PER_SUBNET_SUBSCRIPTION
- name: EPOCHS_PER_SUBNET_SUBSCRIPTION#phase0
sources:
- file: config/params/config.go
search: EpochsPerSubnetSubscription\s+uint64
@@ -267,7 +288,7 @@
EPOCHS_PER_SUBNET_SUBSCRIPTION = 256
</spec>
- name: ETH1_FOLLOW_DISTANCE
- name: ETH1_FOLLOW_DISTANCE#phase0
sources:
- file: config/params/config.go
search: Eth1FollowDistance\s+uint64
@@ -277,7 +298,7 @@
ETH1_FOLLOW_DISTANCE: uint64 = 2048
</spec>
- name: FULU_FORK_EPOCH
- name: FULU_FORK_EPOCH#fulu
sources:
- file: config/params/config.go
search: FuluForkEpoch\s+primitives.Epoch
@@ -287,7 +308,7 @@
FULU_FORK_EPOCH: Epoch = 411392
</spec>
- name: FULU_FORK_VERSION
- name: FULU_FORK_VERSION#fulu
sources:
- file: config/params/config.go
search: FuluForkVersion\s+\[]byte
@@ -297,7 +318,7 @@
FULU_FORK_VERSION: Version = '0x06000000'
</spec>
- name: GENESIS_DELAY
- name: GENESIS_DELAY#phase0
sources:
- file: config/params/config.go
search: GenesisDelay\s+uint64
@@ -307,7 +328,7 @@
GENESIS_DELAY: uint64 = 604800
</spec>
- name: GENESIS_FORK_VERSION
- name: GENESIS_FORK_VERSION#phase0
sources:
- file: config/params/config.go
search: GenesisForkVersion\s+\[]byte
@@ -317,7 +338,21 @@
GENESIS_FORK_VERSION: Version = '0x00000000'
</spec>
- name: INACTIVITY_SCORE_BIAS
- name: GLOAS_FORK_EPOCH#gloas
sources: []
spec: |
<spec config_var="GLOAS_FORK_EPOCH" fork="gloas" hash="c25152cf">
GLOAS_FORK_EPOCH: Epoch = 18446744073709551615
</spec>
- name: GLOAS_FORK_VERSION#gloas
sources: []
spec: |
<spec config_var="GLOAS_FORK_VERSION" fork="gloas" hash="c1c5c007">
GLOAS_FORK_VERSION: Version = '0x07000000'
</spec>
- name: INACTIVITY_SCORE_BIAS#altair
sources:
- file: config/params/config.go
search: InactivityScoreBias\s+uint64
@@ -327,7 +362,7 @@
INACTIVITY_SCORE_BIAS: uint64 = 4
</spec>
- name: INACTIVITY_SCORE_RECOVERY_RATE
- name: INACTIVITY_SCORE_RECOVERY_RATE#altair
sources:
- file: config/params/config.go
search: InactivityScoreRecoveryRate\s+uint64
@@ -337,7 +372,7 @@
INACTIVITY_SCORE_RECOVERY_RATE: uint64 = 16
</spec>
- name: MAXIMUM_GOSSIP_CLOCK_DISPARITY
- name: MAXIMUM_GOSSIP_CLOCK_DISPARITY#phase0
sources:
- file: config/params/config.go
search: MaximumGossipClockDisparity\s+uint64
@@ -347,7 +382,7 @@
MAXIMUM_GOSSIP_CLOCK_DISPARITY = 500
</spec>
- name: MAX_BLOBS_PER_BLOCK
- name: MAX_BLOBS_PER_BLOCK#deneb
sources:
- file: config/params/config.go
search: DeprecatedMaxBlobsPerBlock\s+int
@@ -357,7 +392,7 @@
MAX_BLOBS_PER_BLOCK: uint64 = 6
</spec>
- name: MAX_BLOBS_PER_BLOCK_ELECTRA
- name: MAX_BLOBS_PER_BLOCK_ELECTRA#electra
sources:
- file: config/params/config.go
search: DeprecatedMaxBlobsPerBlockElectra\s+int
@@ -367,7 +402,7 @@
MAX_BLOBS_PER_BLOCK_ELECTRA: uint64 = 9
</spec>
- name: MAX_PAYLOAD_SIZE
- name: MAX_PAYLOAD_SIZE#phase0
sources:
- file: config/params/config.go
search: MaxPayloadSize\s+uint64
@@ -377,7 +412,7 @@
MAX_PAYLOAD_SIZE = 10485760
</spec>
- name: MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT
- name: MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT#deneb
sources:
- file: config/params/config.go
search: MaxPerEpochActivationChurnLimit\s+uint64
@@ -387,7 +422,7 @@
MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT: uint64 = 8
</spec>
- name: MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT
- name: MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT#electra
sources:
- file: config/params/config.go
search: MaxPerEpochActivationExitChurnLimit\s+uint64
@@ -397,7 +432,7 @@
MAX_PER_EPOCH_ACTIVATION_EXIT_CHURN_LIMIT: Gwei = 256000000000
</spec>
- name: MAX_REQUEST_BLOB_SIDECARS
- name: MAX_REQUEST_BLOB_SIDECARS#deneb
sources:
- file: config/params/config.go
search: MaxRequestBlobSidecars\s+uint64
@@ -407,7 +442,7 @@
MAX_REQUEST_BLOB_SIDECARS = 768
</spec>
- name: MAX_REQUEST_BLOB_SIDECARS_ELECTRA
- name: MAX_REQUEST_BLOB_SIDECARS_ELECTRA#electra
sources:
- file: config/params/config.go
search: MaxRequestBlobSidecarsElectra\s+uint64
@@ -417,7 +452,7 @@
MAX_REQUEST_BLOB_SIDECARS_ELECTRA = 1152
</spec>
- name: MAX_REQUEST_BLOCKS
- name: MAX_REQUEST_BLOCKS#phase0
sources:
- file: config/params/config.go
search: MaxRequestBlocks\s+uint64
@@ -427,7 +462,7 @@
MAX_REQUEST_BLOCKS = 1024
</spec>
- name: MAX_REQUEST_BLOCKS_DENEB
- name: MAX_REQUEST_BLOCKS_DENEB#deneb
sources:
- file: config/params/config.go
search: MaxRequestBlocksDeneb\s+uint64
@@ -437,7 +472,7 @@
MAX_REQUEST_BLOCKS_DENEB = 128
</spec>
- name: MAX_REQUEST_DATA_COLUMN_SIDECARS
- name: MAX_REQUEST_DATA_COLUMN_SIDECARS#fulu
sources:
- file: config/params/config.go
search: MaxRequestDataColumnSidecars\s+uint64
@@ -447,7 +482,14 @@
MAX_REQUEST_DATA_COLUMN_SIDECARS = 16384
</spec>
- name: MESSAGE_DOMAIN_INVALID_SNAPPY
- name: MAX_REQUEST_PAYLOADS#gloas
sources: []
spec: |
<spec config_var="MAX_REQUEST_PAYLOADS" fork="gloas" hash="23399ee5">
MAX_REQUEST_PAYLOADS = 128
</spec>
- name: MESSAGE_DOMAIN_INVALID_SNAPPY#phase0
sources:
- file: config/params/config.go
search: MessageDomainInvalidSnappy\s+\[4\]byte
@@ -457,7 +499,7 @@
MESSAGE_DOMAIN_INVALID_SNAPPY: DomainType = '0x00000000'
</spec>
- name: MESSAGE_DOMAIN_VALID_SNAPPY
- name: MESSAGE_DOMAIN_VALID_SNAPPY#phase0
sources:
- file: config/params/config.go
search: MessageDomainValidSnappy\s+\[4\]byte
@@ -467,7 +509,14 @@
MESSAGE_DOMAIN_VALID_SNAPPY: DomainType = '0x01000000'
</spec>
- name: MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS
- name: MIN_BUILDER_WITHDRAWABILITY_DELAY#gloas
sources: []
spec: |
<spec config_var="MIN_BUILDER_WITHDRAWABILITY_DELAY" fork="gloas" hash="d378428f">
MIN_BUILDER_WITHDRAWABILITY_DELAY: uint64 = 4096
</spec>
- name: MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS#deneb
sources:
- file: config/params/config.go
search: MinEpochsForBlobsSidecarsRequest\s+primitives.Epoch
@@ -477,7 +526,7 @@
MIN_EPOCHS_FOR_BLOB_SIDECARS_REQUESTS = 4096
</spec>
- name: MIN_EPOCHS_FOR_BLOCK_REQUESTS
- name: MIN_EPOCHS_FOR_BLOCK_REQUESTS#phase0
sources:
- file: config/params/config.go
search: MinEpochsForBlockRequests\s+uint64
@@ -487,7 +536,7 @@
MIN_EPOCHS_FOR_BLOCK_REQUESTS = 33024
</spec>
- name: MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS
- name: MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS#fulu
sources:
- file: config/params/config.go
search: MinEpochsForDataColumnSidecarsRequest\s+primitives.Epoch
@@ -497,7 +546,7 @@
MIN_EPOCHS_FOR_DATA_COLUMN_SIDECARS_REQUESTS = 4096
</spec>
- name: MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
- name: MIN_GENESIS_ACTIVE_VALIDATOR_COUNT#phase0
sources:
- file: config/params/config.go
search: MinGenesisActiveValidatorCount\s+uint64
@@ -507,7 +556,7 @@
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: uint64 = 16384
</spec>
- name: MIN_GENESIS_TIME
- name: MIN_GENESIS_TIME#phase0
sources:
- file: config/params/config.go
search: MinGenesisTime\s+uint64
@@ -517,7 +566,7 @@
MIN_GENESIS_TIME: uint64 = 1606824000
</spec>
- name: MIN_PER_EPOCH_CHURN_LIMIT
- name: MIN_PER_EPOCH_CHURN_LIMIT#phase0
sources:
- file: config/params/config.go
search: MinPerEpochChurnLimit\s+uint64
@@ -527,7 +576,7 @@
MIN_PER_EPOCH_CHURN_LIMIT: uint64 = 4
</spec>
- name: MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA
- name: MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA#electra
sources:
- file: config/params/config.go
search: MinPerEpochChurnLimitElectra\s+uint64
@@ -537,7 +586,7 @@
MIN_PER_EPOCH_CHURN_LIMIT_ELECTRA: Gwei = 128000000000
</spec>
- name: MIN_VALIDATOR_WITHDRAWABILITY_DELAY
- name: MIN_VALIDATOR_WITHDRAWABILITY_DELAY#phase0
sources:
- file: config/params/config.go
search: MinValidatorWithdrawabilityDelay\s+primitives.Epoch
@@ -547,7 +596,7 @@
MIN_VALIDATOR_WITHDRAWABILITY_DELAY: uint64 = 256
</spec>
- name: NUMBER_OF_CUSTODY_GROUPS
- name: NUMBER_OF_CUSTODY_GROUPS#fulu
sources:
- file: config/params/config.go
search: NumberOfCustodyGroups\s+uint64
@@ -557,7 +606,14 @@
NUMBER_OF_CUSTODY_GROUPS = 128
</spec>
- name: PROPOSER_REORG_CUTOFF_BPS
- name: PAYLOAD_ATTESTATION_DUE_BPS#gloas
sources: []
spec: |
<spec config_var="PAYLOAD_ATTESTATION_DUE_BPS" fork="gloas" hash="17307d0e">
PAYLOAD_ATTESTATION_DUE_BPS: uint64 = 7500
</spec>
- name: PROPOSER_REORG_CUTOFF_BPS#phase0
sources:
- file: config/params/config.go
search: ProposerReorgCutoffBPS\s+primitives.BP
@@ -567,7 +623,7 @@
PROPOSER_REORG_CUTOFF_BPS: uint64 = 1667
</spec>
- name: PROPOSER_SCORE_BOOST
- name: PROPOSER_SCORE_BOOST#phase0
sources:
- file: config/params/config.go
search: ProposerScoreBoost\s+uint64
@@ -577,7 +633,7 @@
PROPOSER_SCORE_BOOST: uint64 = 40
</spec>
- name: REORG_HEAD_WEIGHT_THRESHOLD
- name: REORG_HEAD_WEIGHT_THRESHOLD#phase0
sources:
- file: config/params/config.go
search: ReorgHeadWeightThreshold\s+uint64
@@ -587,7 +643,7 @@
REORG_HEAD_WEIGHT_THRESHOLD: uint64 = 20
</spec>
- name: REORG_MAX_EPOCHS_SINCE_FINALIZATION
- name: REORG_MAX_EPOCHS_SINCE_FINALIZATION#phase0
sources:
- file: config/params/config.go
search: ReorgMaxEpochsSinceFinalization\s+primitives.Epoch
@@ -597,7 +653,7 @@
REORG_MAX_EPOCHS_SINCE_FINALIZATION: Epoch = 2
</spec>
- name: REORG_PARENT_WEIGHT_THRESHOLD
- name: REORG_PARENT_WEIGHT_THRESHOLD#phase0
sources:
- file: config/params/config.go
search: ReorgParentWeightThreshold\s+uint64
@@ -607,7 +663,7 @@
REORG_PARENT_WEIGHT_THRESHOLD: uint64 = 160
</spec>
- name: SAMPLES_PER_SLOT
- name: SAMPLES_PER_SLOT#fulu
sources:
- file: config/params/config.go
search: SamplesPerSlot\s+uint64
@@ -617,7 +673,7 @@
SAMPLES_PER_SLOT = 8
</spec>
- name: SECONDS_PER_ETH1_BLOCK
- name: SECONDS_PER_ETH1_BLOCK#phase0
sources:
- file: config/params/config.go
search: SecondsPerETH1Block\s+uint64
@@ -627,7 +683,7 @@
SECONDS_PER_ETH1_BLOCK: uint64 = 14
</spec>
- name: SECONDS_PER_SLOT
- name: SECONDS_PER_SLOT#phase0
sources:
- file: config/params/config.go
search: SecondsPerSlot\s+uint64
@@ -637,7 +693,7 @@
SECONDS_PER_SLOT: uint64 = 12
</spec>
- name: SHARD_COMMITTEE_PERIOD
- name: SHARD_COMMITTEE_PERIOD#phase0
sources:
- file: config/params/config.go
search: ShardCommitteePeriod\s+primitives.Epoch
@@ -647,7 +703,7 @@
SHARD_COMMITTEE_PERIOD: uint64 = 256
</spec>
- name: SLOT_DURATION_MS
- name: SLOT_DURATION_MS#phase0
sources:
- file: config/params/config.go
search: SlotDurationMilliseconds\s+uint64
@@ -657,7 +713,7 @@
SLOT_DURATION_MS: uint64 = 12000
</spec>
- name: SUBNETS_PER_NODE
- name: SUBNETS_PER_NODE#phase0
sources:
- file: config/params/config.go
search: SubnetsPerNode\s+uint64
@@ -667,7 +723,7 @@
SUBNETS_PER_NODE = 2
</spec>
- name: SYNC_MESSAGE_DUE_BPS
- name: SYNC_MESSAGE_DUE_BPS#altair
sources:
- file: config/params/config.go
search: SyncMessageDueBPS\s+primitives.BP
@@ -677,7 +733,14 @@
SYNC_MESSAGE_DUE_BPS: uint64 = 3333
</spec>
- name: TERMINAL_BLOCK_HASH
- name: SYNC_MESSAGE_DUE_BPS_GLOAS#gloas
sources: []
spec: |
<spec config_var="SYNC_MESSAGE_DUE_BPS_GLOAS" fork="gloas" hash="47f14d95">
SYNC_MESSAGE_DUE_BPS_GLOAS: uint64 = 2500
</spec>
- name: TERMINAL_BLOCK_HASH#bellatrix
sources:
- file: config/params/config.go
search: TerminalBlockHash\s+common.Hash
@@ -687,7 +750,7 @@
TERMINAL_BLOCK_HASH: Hash32 = '0x0000000000000000000000000000000000000000000000000000000000000000'
</spec>
- name: TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH
- name: TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH#bellatrix
sources:
- file: config/params/config.go
search: TerminalBlockHashActivationEpoch\s+primitives.Epoch
@@ -697,7 +760,7 @@
TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH = 18446744073709551615
</spec>
- name: TERMINAL_TOTAL_DIFFICULTY
- name: TERMINAL_TOTAL_DIFFICULTY#bellatrix
sources:
- file: config/params/config.go
search: TerminalTotalDifficulty\s+string
@@ -707,7 +770,7 @@
TERMINAL_TOTAL_DIFFICULTY = 58750000000000000000000
</spec>
- name: VALIDATOR_CUSTODY_REQUIREMENT
- name: VALIDATOR_CUSTODY_REQUIREMENT#fulu
sources:
- file: config/params/config.go
search: ValidatorCustodyRequirement\s+uint64

File diff suppressed because one or more lines are too long

View File

@@ -50,7 +50,7 @@
committee_bits: Bitvector[MAX_COMMITTEES_PER_SLOT]
</spec>
- name: AttestationData
- name: AttestationData#phase0
sources:
- file: proto/eth/v1/attestation.proto
search: message AttestationData {
@@ -88,7 +88,7 @@
attestation_2: IndexedAttestation
</spec>
- name: BLSToExecutionChange
- name: BLSToExecutionChange#capella
sources:
- file: proto/prysm/v1alpha1/withdrawals.proto
search: message BLSToExecutionChange {
@@ -100,7 +100,7 @@
to_execution_address: ExecutionAddress
</spec>
- name: BeaconBlock
- name: BeaconBlock#phase0
sources:
- file: proto/eth/v1/beacon_block.proto
search: message BeaconBlock {
@@ -239,7 +239,34 @@
execution_requests: ExecutionRequests
</spec>
- name: BeaconBlockHeader
- name: BeaconBlockBody#gloas
sources: []
spec: |
<spec ssz_object="BeaconBlockBody" fork="gloas" hash="7e472a77">
class BeaconBlockBody(Container):
randao_reveal: BLSSignature
eth1_data: Eth1Data
graffiti: Bytes32
proposer_slashings: List[ProposerSlashing, MAX_PROPOSER_SLASHINGS]
attester_slashings: List[AttesterSlashing, MAX_ATTESTER_SLASHINGS_ELECTRA]
attestations: List[Attestation, MAX_ATTESTATIONS_ELECTRA]
deposits: List[Deposit, MAX_DEPOSITS]
voluntary_exits: List[SignedVoluntaryExit, MAX_VOLUNTARY_EXITS]
sync_aggregate: SyncAggregate
# [Modified in Gloas:EIP7732]
# Removed `execution_payload`
bls_to_execution_changes: List[SignedBLSToExecutionChange, MAX_BLS_TO_EXECUTION_CHANGES]
# [Modified in Gloas:EIP7732]
# Removed `blob_kzg_commitments`
# [Modified in Gloas:EIP7732]
# Removed `execution_requests`
# [New in Gloas:EIP7732]
signed_execution_payload_bid: SignedExecutionPayloadBid
# [New in Gloas:EIP7732]
payload_attestations: List[PayloadAttestation, MAX_PAYLOAD_ATTESTATIONS]
</spec>
- name: BeaconBlockHeader#phase0
sources:
- file: proto/eth/v1/beacon_block.proto
search: message BeaconBlockHeader {
@@ -538,7 +565,69 @@
proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH]
</spec>
- name: BlobIdentifier
- name: BeaconState#gloas
sources: []
spec: |
<spec ssz_object="BeaconState" fork="gloas" hash="c33b0db2">
class BeaconState(Container):
genesis_time: uint64
genesis_validators_root: Root
slot: Slot
fork: Fork
latest_block_header: BeaconBlockHeader
block_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
historical_roots: List[Root, HISTORICAL_ROOTS_LIMIT]
eth1_data: Eth1Data
eth1_data_votes: List[Eth1Data, EPOCHS_PER_ETH1_VOTING_PERIOD * SLOTS_PER_EPOCH]
eth1_deposit_index: uint64
validators: List[Validator, VALIDATOR_REGISTRY_LIMIT]
balances: List[Gwei, VALIDATOR_REGISTRY_LIMIT]
randao_mixes: Vector[Bytes32, EPOCHS_PER_HISTORICAL_VECTOR]
slashings: Vector[Gwei, EPOCHS_PER_SLASHINGS_VECTOR]
previous_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]
current_epoch_participation: List[ParticipationFlags, VALIDATOR_REGISTRY_LIMIT]
justification_bits: Bitvector[JUSTIFICATION_BITS_LENGTH]
previous_justified_checkpoint: Checkpoint
current_justified_checkpoint: Checkpoint
finalized_checkpoint: Checkpoint
inactivity_scores: List[uint64, VALIDATOR_REGISTRY_LIMIT]
current_sync_committee: SyncCommittee
next_sync_committee: SyncCommittee
# [Modified in Gloas:EIP7732]
# Removed `latest_execution_payload_header`
# [New in Gloas:EIP7732]
latest_execution_payload_bid: ExecutionPayloadBid
next_withdrawal_index: WithdrawalIndex
next_withdrawal_validator_index: ValidatorIndex
historical_summaries: List[HistoricalSummary, HISTORICAL_ROOTS_LIMIT]
deposit_requests_start_index: uint64
deposit_balance_to_consume: Gwei
exit_balance_to_consume: Gwei
earliest_exit_epoch: Epoch
consolidation_balance_to_consume: Gwei
earliest_consolidation_epoch: Epoch
pending_deposits: List[PendingDeposit, PENDING_DEPOSITS_LIMIT]
pending_partial_withdrawals: List[PendingPartialWithdrawal, PENDING_PARTIAL_WITHDRAWALS_LIMIT]
pending_consolidations: List[PendingConsolidation, PENDING_CONSOLIDATIONS_LIMIT]
proposer_lookahead: Vector[ValidatorIndex, (MIN_SEED_LOOKAHEAD + 1) * SLOTS_PER_EPOCH]
# [New in Gloas:EIP7732]
builders: List[Builder, BUILDER_REGISTRY_LIMIT]
# [New in Gloas:EIP7732]
next_withdrawal_builder_index: BuilderIndex
# [New in Gloas:EIP7732]
execution_payload_availability: Bitvector[SLOTS_PER_HISTORICAL_ROOT]
# [New in Gloas:EIP7732]
builder_pending_payments: Vector[BuilderPendingPayment, 2 * SLOTS_PER_EPOCH]
# [New in Gloas:EIP7732]
builder_pending_withdrawals: List[BuilderPendingWithdrawal, BUILDER_PENDING_WITHDRAWALS_LIMIT]
# [New in Gloas:EIP7732]
latest_block_hash: Hash32
# [New in Gloas:EIP7732]
payload_expected_withdrawals: List[Withdrawal, MAX_WITHDRAWALS_PER_PAYLOAD]
</spec>
- name: BlobIdentifier#deneb
sources:
- file: proto/prysm/v1alpha1/blobs.proto
search: message BlobIdentifier {
@@ -549,7 +638,7 @@
index: BlobIndex
</spec>
- name: BlobSidecar
- name: BlobSidecar#deneb
sources:
- file: proto/prysm/v1alpha1/beacon_block.proto
search: message BlobSidecar {
@@ -564,7 +653,39 @@
kzg_commitment_inclusion_proof: Vector[Bytes32, KZG_COMMITMENT_INCLUSION_PROOF_DEPTH]
</spec>
- name: Checkpoint
- name: Builder#gloas
sources: []
spec: |
<spec ssz_object="Builder" fork="gloas" hash="ae177179">
class Builder(Container):
pubkey: BLSPubkey
version: uint8
execution_address: ExecutionAddress
balance: Gwei
deposit_epoch: Epoch
withdrawable_epoch: Epoch
</spec>
- name: BuilderPendingPayment#gloas
sources: []
spec: |
<spec ssz_object="BuilderPendingPayment" fork="gloas" hash="73cf1649">
class BuilderPendingPayment(Container):
weight: Gwei
withdrawal: BuilderPendingWithdrawal
</spec>
- name: BuilderPendingWithdrawal#gloas
sources: []
spec: |
<spec ssz_object="BuilderPendingWithdrawal" fork="gloas" hash="0579f0ac">
class BuilderPendingWithdrawal(Container):
fee_recipient: ExecutionAddress
amount: Gwei
builder_index: BuilderIndex
</spec>
- name: Checkpoint#phase0
sources:
- file: proto/eth/v1/attestation.proto
search: message Checkpoint {
@@ -575,7 +696,7 @@
root: Root
</spec>
- name: ConsolidationRequest
- name: ConsolidationRequest#electra
sources:
- file: proto/engine/v1/electra.proto
search: message ConsolidationRequest {
@@ -587,7 +708,7 @@
target_pubkey: BLSPubkey
</spec>
- name: ContributionAndProof
- name: ContributionAndProof#altair
sources:
- file: proto/prysm/v1alpha1/sync_committee.proto
search: message ContributionAndProof {
@@ -599,7 +720,7 @@
selection_proof: BLSSignature
</spec>
- name: DataColumnSidecar
- name: DataColumnSidecar#fulu
sources:
- file: proto/prysm/v1alpha1/data_columns.proto
search: message DataColumnSidecar {
@@ -614,7 +735,26 @@
kzg_commitments_inclusion_proof: Vector[Bytes32, KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH]
</spec>
- name: DataColumnsByRootIdentifier
- name: DataColumnSidecar#gloas
sources: []
spec: |
<spec ssz_object="DataColumnSidecar" fork="gloas" hash="8028928b">
class DataColumnSidecar(Container):
index: ColumnIndex
column: List[Cell, MAX_BLOB_COMMITMENTS_PER_BLOCK]
kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]
kzg_proofs: List[KZGProof, MAX_BLOB_COMMITMENTS_PER_BLOCK]
# [Modified in Gloas:EIP7732]
# Removed `signed_block_header`
# [Modified in Gloas:EIP7732]
# Removed `kzg_commitments_inclusion_proof`
# [New in Gloas:EIP7732]
slot: Slot
# [New in Gloas:EIP7732]
beacon_block_root: Root
</spec>
- name: DataColumnsByRootIdentifier#fulu
sources:
- file: proto/prysm/v1alpha1/data_columns.proto
search: message DataColumnsByRootIdentifier {
@@ -625,7 +765,7 @@
columns: List[ColumnIndex, NUMBER_OF_COLUMNS]
</spec>
- name: Deposit
- name: Deposit#phase0
sources:
- file: proto/eth/v1/beacon_block.proto
search: message Deposit {
@@ -636,7 +776,7 @@
data: DepositData
</spec>
- name: DepositData
- name: DepositData#phase0
sources:
- file: proto/prysm/v1alpha1/beacon_core_types.proto
search: message Data {
@@ -649,7 +789,7 @@
signature: BLSSignature
</spec>
- name: DepositMessage
- name: DepositMessage#phase0
sources:
- file: proto/prysm/v1alpha1/beacon_state.proto
search: message DepositMessage {
@@ -661,7 +801,7 @@
amount: Gwei
</spec>
- name: DepositRequest
- name: DepositRequest#electra
sources:
- file: proto/engine/v1/electra.proto
search: message DepositRequest {
@@ -675,7 +815,17 @@
index: uint64
</spec>
- name: Eth1Data
- name: Eth1Block#phase0
sources: []
spec: |
<spec ssz_object="Eth1Block" fork="phase0" hash="0a5c6b45">
class Eth1Block(Container):
timestamp: uint64
deposit_root: Root
deposit_count: uint64
</spec>
- name: Eth1Data#phase0
sources:
- file: proto/prysm/v1alpha1/beacon_core_types.proto
search: message Eth1Data {
@@ -763,6 +913,38 @@
excess_blob_gas: uint64
</spec>
- name: ExecutionPayloadBid#gloas
sources: []
spec: |
<spec ssz_object="ExecutionPayloadBid" fork="gloas" hash="aa71ba16">
class ExecutionPayloadBid(Container):
parent_block_hash: Hash32
parent_block_root: Root
block_hash: Hash32
prev_randao: Bytes32
fee_recipient: ExecutionAddress
gas_limit: uint64
builder_index: BuilderIndex
slot: Slot
value: Gwei
execution_payment: Gwei
blob_kzg_commitments_root: Root
</spec>
- name: ExecutionPayloadEnvelope#gloas
sources: []
spec: |
<spec ssz_object="ExecutionPayloadEnvelope" fork="gloas" hash="cd522f7f">
class ExecutionPayloadEnvelope(Container):
payload: ExecutionPayload
execution_requests: ExecutionRequests
builder_index: BuilderIndex
beacon_block_root: Root
slot: Slot
blob_kzg_commitments: List[KZGCommitment, MAX_BLOB_COMMITMENTS_PER_BLOCK]
state_root: Root
</spec>
- name: ExecutionPayloadHeader#bellatrix
sources:
- file: proto/engine/v1/execution_engine.proto
@@ -839,7 +1021,7 @@
excess_blob_gas: uint64
</spec>
- name: ExecutionRequests
- name: ExecutionRequests#electra
sources:
- file: proto/engine/v1/electra.proto
search: message ExecutionRequests {
@@ -854,7 +1036,7 @@
consolidations: List[ConsolidationRequest, MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD]
</spec>
- name: Fork
- name: Fork#phase0
sources:
- file: proto/prysm/v1alpha1/beacon_core_types.proto
search: message Fork {
@@ -866,7 +1048,16 @@
epoch: Epoch
</spec>
- name: ForkData
- name: ForkChoiceNode#gloas
sources: []
spec: |
<spec ssz_object="ForkChoiceNode" fork="gloas" hash="755a4b34">
class ForkChoiceNode(Container):
root: Root
payload_status: PayloadStatus # One of PAYLOAD_STATUS_* values
</spec>
- name: ForkData#phase0
sources:
- file: proto/prysm/v1alpha1/beacon_state.proto
search: message ForkData {
@@ -877,7 +1068,7 @@
genesis_validators_root: Root
</spec>
- name: HistoricalBatch
- name: HistoricalBatch#phase0
sources:
- file: proto/prysm/v1alpha1/beacon_state.proto
search: message HistoricalBatch {
@@ -888,7 +1079,7 @@
state_roots: Vector[Root, SLOTS_PER_HISTORICAL_ROOT]
</spec>
- name: HistoricalSummary
- name: HistoricalSummary#capella
sources:
- file: proto/prysm/v1alpha1/beacon_core_types.proto
search: message HistoricalSummary {
@@ -924,7 +1115,17 @@
signature: BLSSignature
</spec>
- name: LightClientBootstrap
- name: IndexedPayloadAttestation#gloas
sources: []
spec: |
<spec ssz_object="IndexedPayloadAttestation" fork="gloas" hash="fa4832c8">
class IndexedPayloadAttestation(Container):
attesting_indices: List[ValidatorIndex, PTC_SIZE]
data: PayloadAttestationData
signature: BLSSignature
</spec>
- name: LightClientBootstrap#altair
sources:
- file: proto/prysm/v1alpha1/light_client.proto
search: message LightClientBootstrapAltair {
@@ -938,7 +1139,18 @@
current_sync_committee_branch: CurrentSyncCommitteeBranch
</spec>
- name: LightClientFinalityUpdate
- name: LightClientBootstrap#capella
sources: []
spec: |
<spec ssz_object="LightClientBootstrap" fork="capella" hash="85f4f5fe">
class LightClientBootstrap(Container):
# [Modified in Capella]
header: LightClientHeader
current_sync_committee: SyncCommittee
current_sync_committee_branch: CurrentSyncCommitteeBranch
</spec>
- name: LightClientFinalityUpdate#altair
sources:
- file: proto/prysm/v1alpha1/light_client.proto
search: message LightClientFinalityUpdateAltair {
@@ -956,6 +1168,20 @@
signature_slot: Slot
</spec>
- name: LightClientFinalityUpdate#capella
sources: []
spec: |
<spec ssz_object="LightClientFinalityUpdate" fork="capella" hash="9d2b55dd">
class LightClientFinalityUpdate(Container):
# [Modified in Capella]
attested_header: LightClientHeader
# [Modified in Capella]
finalized_header: LightClientHeader
finality_branch: FinalityBranch
sync_aggregate: SyncAggregate
signature_slot: Slot
</spec>
- name: LightClientHeader#altair
sources:
- file: proto/prysm/v1alpha1/light_client.proto
@@ -980,7 +1206,7 @@
execution_branch: ExecutionBranch
</spec>
- name: LightClientOptimisticUpdate
- name: LightClientOptimisticUpdate#altair
sources:
- file: proto/prysm/v1alpha1/light_client.proto
search: message LightClientOptimisticUpdateAltair {
@@ -995,7 +1221,18 @@
signature_slot: Slot
</spec>
- name: LightClientUpdate
- name: LightClientOptimisticUpdate#capella
sources: []
spec: |
<spec ssz_object="LightClientOptimisticUpdate" fork="capella" hash="bdce7b1d">
class LightClientOptimisticUpdate(Container):
# [Modified in Capella]
attested_header: LightClientHeader
sync_aggregate: SyncAggregate
signature_slot: Slot
</spec>
- name: LightClientUpdate#altair
sources:
- file: proto/prysm/v1alpha1/light_client.proto
search: message LightClientUpdateAltair {
@@ -1016,7 +1253,65 @@
signature_slot: Slot
</spec>
- name: PendingAttestation
- name: LightClientUpdate#capella
sources: []
spec: |
<spec ssz_object="LightClientUpdate" fork="capella" hash="8d215165">
class LightClientUpdate(Container):
# [Modified in Capella]
attested_header: LightClientHeader
next_sync_committee: SyncCommittee
next_sync_committee_branch: NextSyncCommitteeBranch
# [Modified in Capella]
finalized_header: LightClientHeader
finality_branch: FinalityBranch
sync_aggregate: SyncAggregate
signature_slot: Slot
</spec>
- name: MatrixEntry#fulu
sources: []
spec: |
<spec ssz_object="MatrixEntry" fork="fulu" hash="0da9cc8e">
class MatrixEntry(Container):
cell: Cell
kzg_proof: KZGProof
column_index: ColumnIndex
row_index: RowIndex
</spec>
- name: PayloadAttestation#gloas
sources: []
spec: |
<spec ssz_object="PayloadAttestation" fork="gloas" hash="c769473d">
class PayloadAttestation(Container):
aggregation_bits: Bitvector[PTC_SIZE]
data: PayloadAttestationData
signature: BLSSignature
</spec>
- name: PayloadAttestationData#gloas
sources: []
spec: |
<spec ssz_object="PayloadAttestationData" fork="gloas" hash="9f1b7f92">
class PayloadAttestationData(Container):
beacon_block_root: Root
slot: Slot
payload_present: boolean
blob_data_available: boolean
</spec>
- name: PayloadAttestationMessage#gloas
sources: []
spec: |
<spec ssz_object="PayloadAttestationMessage" fork="gloas" hash="3707678d">
class PayloadAttestationMessage(Container):
validator_index: ValidatorIndex
data: PayloadAttestationData
signature: BLSSignature
</spec>
- name: PendingAttestation#phase0
sources:
- file: proto/prysm/v1alpha1/beacon_state.proto
search: message PendingAttestation {
@@ -1029,7 +1324,7 @@
proposer_index: ValidatorIndex
</spec>
- name: PendingConsolidation
- name: PendingConsolidation#electra
sources:
- file: proto/prysm/v1alpha1/eip_7251.proto
search: message PendingConsolidation {
@@ -1040,7 +1335,7 @@
target_index: ValidatorIndex
</spec>
- name: PendingDeposit
- name: PendingDeposit#electra
sources:
- file: proto/prysm/v1alpha1/eip_7251.proto
search: message PendingDeposit {
@@ -1054,7 +1349,7 @@
slot: Slot
</spec>
- name: PendingPartialWithdrawal
- name: PendingPartialWithdrawal#electra
sources:
- file: proto/prysm/v1alpha1/eip_7251.proto
search: message PendingPartialWithdrawal {
@@ -1066,7 +1361,7 @@
withdrawable_epoch: Epoch
</spec>
- name: PowBlock
- name: PowBlock#bellatrix
sources:
- file: proto/prysm/v1alpha1/beacon_state.proto
search: message PowBlock {
@@ -1078,7 +1373,18 @@
total_difficulty: uint256
</spec>
- name: ProposerSlashing
- name: ProposerPreferences#gloas
sources: []
spec: |
<spec ssz_object="ProposerPreferences" fork="gloas" hash="2a38b149">
class ProposerPreferences(Container):
proposal_slot: Slot
validator_index: ValidatorIndex
fee_recipient: ExecutionAddress
gas_limit: uint64
</spec>
- name: ProposerSlashing#phase0
sources:
- file: proto/eth/v1/beacon_block.proto
search: message ProposerSlashing {
@@ -1112,7 +1418,7 @@
signature: BLSSignature
</spec>
- name: SignedBLSToExecutionChange
- name: SignedBLSToExecutionChange#capella
sources:
- file: proto/prysm/v1alpha1/withdrawals.proto
search: message SignedBLSToExecutionChange {
@@ -1123,7 +1429,7 @@
signature: BLSSignature
</spec>
- name: SignedBeaconBlock
- name: SignedBeaconBlock#phase0
sources:
- file: proto/prysm/v1alpha1/beacon_block.proto
search: message SignedBeaconBlock {
@@ -1134,7 +1440,7 @@
signature: BLSSignature
</spec>
- name: SignedBeaconBlockHeader
- name: SignedBeaconBlockHeader#phase0
sources:
- file: proto/prysm/v1alpha1/beacon_core_types.proto
search: message SignedBeaconBlockHeader {
@@ -1145,7 +1451,7 @@
signature: BLSSignature
</spec>
- name: SignedContributionAndProof
- name: SignedContributionAndProof#altair
sources:
- file: proto/prysm/v1alpha1/sync_committee.proto
search: message SignedContributionAndProof {
@@ -1156,7 +1462,34 @@
signature: BLSSignature
</spec>
- name: SignedVoluntaryExit
- name: SignedExecutionPayloadBid#gloas
sources: []
spec: |
<spec ssz_object="SignedExecutionPayloadBid" fork="gloas" hash="6b344341">
class SignedExecutionPayloadBid(Container):
message: ExecutionPayloadBid
signature: BLSSignature
</spec>
- name: SignedExecutionPayloadEnvelope#gloas
sources: []
spec: |
<spec ssz_object="SignedExecutionPayloadEnvelope" fork="gloas" hash="ab8f3404">
class SignedExecutionPayloadEnvelope(Container):
message: ExecutionPayloadEnvelope
signature: BLSSignature
</spec>
- name: SignedProposerPreferences#gloas
sources: []
spec: |
<spec ssz_object="SignedProposerPreferences" fork="gloas" hash="2142774c">
class SignedProposerPreferences(Container):
message: ProposerPreferences
signature: BLSSignature
</spec>
- name: SignedVoluntaryExit#phase0
sources:
- file: proto/prysm/v1alpha1/beacon_core_types.proto
search: message SignedVoluntaryExit {
@@ -1167,7 +1500,7 @@
signature: BLSSignature
</spec>
- name: SigningData
- name: SigningData#phase0
sources:
- file: proto/prysm/v1alpha1/beacon_state.proto
search: message SigningData {
@@ -1178,7 +1511,7 @@
domain: Domain
</spec>
- name: SingleAttestation
- name: SingleAttestation#electra
sources:
- file: proto/prysm/v1alpha1/attestation.proto
search: message SingleAttestation {
@@ -1191,7 +1524,7 @@
signature: BLSSignature
</spec>
- name: SyncAggregate
- name: SyncAggregate#altair
sources:
- file: proto/prysm/v1alpha1/beacon_core_types.proto
search: message SyncAggregate {
@@ -1202,7 +1535,7 @@
sync_committee_signature: BLSSignature
</spec>
- name: SyncAggregatorSelectionData
- name: SyncAggregatorSelectionData#altair
sources:
- file: proto/prysm/v1alpha1/beacon_state.proto
search: message SyncAggregatorSelectionData {
@@ -1213,7 +1546,7 @@
subcommittee_index: uint64
</spec>
- name: SyncCommittee
- name: SyncCommittee#altair
sources:
- file: proto/prysm/v1alpha1/beacon_core_types.proto
search: message SyncCommittee {
@@ -1224,7 +1557,7 @@
aggregate_pubkey: BLSPubkey
</spec>
- name: SyncCommitteeContribution
- name: SyncCommitteeContribution#altair
sources:
- file: proto/prysm/v1alpha1/sync_committee.proto
search: message SyncCommitteeContribution {
@@ -1238,7 +1571,7 @@
signature: BLSSignature
</spec>
- name: SyncCommitteeMessage
- name: SyncCommitteeMessage#altair
sources:
- file: proto/prysm/v1alpha1/sync_committee.proto
search: message SyncCommitteeMessage {
@@ -1251,7 +1584,7 @@
signature: BLSSignature
</spec>
- name: Validator
- name: Validator#phase0
sources:
- file: proto/prysm/v1alpha1/beacon_core_types.proto
search: message Validator {
@@ -1268,7 +1601,7 @@
withdrawable_epoch: Epoch
</spec>
- name: VoluntaryExit
- name: VoluntaryExit#phase0
sources:
- file: proto/eth/v1/beacon_block.proto
search: message VoluntaryExit {
@@ -1279,7 +1612,7 @@
validator_index: ValidatorIndex
</spec>
- name: Withdrawal
- name: Withdrawal#capella
sources:
- file: proto/engine/v1/execution_engine.proto
search: message Withdrawal {
@@ -1292,7 +1625,7 @@
amount: Gwei
</spec>
- name: WithdrawalRequest
- name: WithdrawalRequest#electra
sources:
- file: proto/engine/v1/electra.proto
search: message WithdrawalRequest {

View File

@@ -1,4 +1,4 @@
- name: BlobParameters
- name: BlobParameters#fulu
sources: []
spec: |
<spec dataclass="BlobParameters" fork="fulu" hash="a4575aa8">
@@ -54,6 +54,20 @@
processed_sweep_withdrawals_count: uint64
</spec>
- name: ExpectedWithdrawals#gloas
sources: []
spec: |
<spec dataclass="ExpectedWithdrawals" fork="gloas" hash="b32cc9c9">
class ExpectedWithdrawals(object):
withdrawals: Sequence[Withdrawal]
# [New in Gloas:EIP7732]
processed_builder_withdrawals_count: uint64
processed_partial_withdrawals_count: uint64
# [New in Gloas:EIP7732]
processed_builders_sweep_count: uint64
processed_sweep_withdrawals_count: uint64
</spec>
- name: GetPayloadResponse#bellatrix
sources:
- file: consensus-types/blocks/get_payload.go
@@ -126,7 +140,7 @@
execution_requests: Sequence[bytes]
</spec>
- name: LatestMessage
- name: LatestMessage#phase0
sources: []
spec: |
<spec dataclass="LatestMessage" fork="phase0" hash="44e832d0">
@@ -136,7 +150,18 @@
root: Root
</spec>
- name: LightClientStore
- name: LatestMessage#gloas
sources: []
spec: |
<spec dataclass="LatestMessage" fork="gloas" hash="a0030894">
@dataclass(eq=True, frozen=True)
class LatestMessage(object):
slot: Slot
root: Root
payload_present: boolean
</spec>
- name: LightClientStore#altair
sources: []
spec: |
<spec dataclass="LightClientStore" fork="altair" hash="24725cec">
@@ -155,6 +180,23 @@
current_max_active_participants: uint64
</spec>
- name: LightClientStore#capella
sources: []
spec: |
<spec dataclass="LightClientStore" fork="capella" hash="04b41062">
class LightClientStore(object):
# [Modified in Capella]
finalized_header: LightClientHeader
current_sync_committee: SyncCommittee
next_sync_committee: SyncCommittee
# [Modified in Capella]
best_valid_update: Optional[LightClientUpdate]
# [Modified in Capella]
optimistic_header: LightClientHeader
previous_max_active_participants: uint64
current_max_active_participants: uint64
</spec>
- name: NewPayloadRequest#bellatrix
sources:
- file: beacon-chain/execution/engine_client.go
@@ -191,7 +233,7 @@
execution_requests: ExecutionRequests
</spec>
- name: OptimisticStore
- name: OptimisticStore#bellatrix
sources: []
spec: |
<spec dataclass="OptimisticStore" fork="bellatrix" hash="a2b2182c">
@@ -246,7 +288,7 @@
parent_beacon_block_root: Root
</spec>
- name: Store
- name: Store#phase0
sources: []
spec: |
<spec dataclass="Store" fork="phase0" hash="abe525d6">
@@ -266,3 +308,30 @@
latest_messages: Dict[ValidatorIndex, LatestMessage] = field(default_factory=dict)
unrealized_justifications: Dict[Root, Checkpoint] = field(default_factory=dict)
</spec>
- name: Store#gloas
sources: []
spec: |
<spec dataclass="Store" fork="gloas" hash="4dbfec46">
class Store(object):
time: uint64
genesis_time: uint64
justified_checkpoint: Checkpoint
finalized_checkpoint: Checkpoint
unrealized_justified_checkpoint: Checkpoint
unrealized_finalized_checkpoint: Checkpoint
proposer_boost_root: Root
equivocating_indices: Set[ValidatorIndex]
blocks: Dict[Root, BeaconBlock] = field(default_factory=dict)
block_states: Dict[Root, BeaconState] = field(default_factory=dict)
block_timeliness: Dict[Root, Vector[boolean, NUM_BLOCK_TIMELINESS_DEADLINES]] = field(
default_factory=dict
)
checkpoint_states: Dict[Checkpoint, BeaconState] = field(default_factory=dict)
latest_messages: Dict[ValidatorIndex, LatestMessage] = field(default_factory=dict)
unrealized_justifications: Dict[Root, Checkpoint] = field(default_factory=dict)
# [New in Gloas:EIP7732]
execution_payload_states: Dict[Root, BeaconState] = field(default_factory=dict)
# [New in Gloas:EIP7732]
ptc_vote: Dict[Root, Vector[boolean, PTC_SIZE]] = field(default_factory=dict)
</spec>

File diff suppressed because it is too large Load Diff

View File

@@ -1,4 +1,4 @@
- name: BASE_REWARD_FACTOR
- name: BASE_REWARD_FACTOR#phase0
sources:
- file: config/params/config.go
search: BaseRewardFactor\s+.*yaml:"BASE_REWARD_FACTOR"
@@ -8,7 +8,21 @@
BASE_REWARD_FACTOR: uint64 = 64
</spec>
- name: BYTES_PER_LOGS_BLOOM
- name: BUILDER_PENDING_WITHDRAWALS_LIMIT#gloas
sources: []
spec: |
<spec preset_var="BUILDER_PENDING_WITHDRAWALS_LIMIT" fork="gloas" hash="40b31377">
BUILDER_PENDING_WITHDRAWALS_LIMIT: uint64 = 1048576
</spec>
- name: BUILDER_REGISTRY_LIMIT#gloas
sources: []
spec: |
<spec preset_var="BUILDER_REGISTRY_LIMIT" fork="gloas" hash="e951ff73">
BUILDER_REGISTRY_LIMIT: uint64 = 1099511627776
</spec>
- name: BYTES_PER_LOGS_BLOOM#bellatrix
sources:
- file: config/params/config.go
search: BytesPerLogsBloom\s+.*yaml:"BYTES_PER_LOGS_BLOOM"
@@ -18,7 +32,7 @@
BYTES_PER_LOGS_BLOOM: uint64 = 256
</spec>
- name: CELLS_PER_EXT_BLOB
- name: CELLS_PER_EXT_BLOB#fulu
sources:
- file: beacon-chain/rpc/eth/config/handlers.go
search: data\["CELLS_PER_EXT_BLOB"\]
@@ -28,7 +42,7 @@
CELLS_PER_EXT_BLOB = 128
</spec>
- name: EFFECTIVE_BALANCE_INCREMENT
- name: EFFECTIVE_BALANCE_INCREMENT#phase0
sources:
- file: config/params/config.go
search: EffectiveBalanceIncrement\s+.*yaml:"EFFECTIVE_BALANCE_INCREMENT"
@@ -38,7 +52,7 @@
EFFECTIVE_BALANCE_INCREMENT: Gwei = 1000000000
</spec>
- name: EPOCHS_PER_ETH1_VOTING_PERIOD
- name: EPOCHS_PER_ETH1_VOTING_PERIOD#phase0
sources:
- file: config/params/config.go
search: EpochsPerEth1VotingPeriod\s+.*yaml:"EPOCHS_PER_ETH1_VOTING_PERIOD"
@@ -48,7 +62,7 @@
EPOCHS_PER_ETH1_VOTING_PERIOD: uint64 = 64
</spec>
- name: EPOCHS_PER_HISTORICAL_VECTOR
- name: EPOCHS_PER_HISTORICAL_VECTOR#phase0
sources:
- file: config/fieldparams/mainnet.go
search: RandaoMixesLength\s*=
@@ -58,7 +72,7 @@
EPOCHS_PER_HISTORICAL_VECTOR: uint64 = 65536
</spec>
- name: EPOCHS_PER_SLASHINGS_VECTOR
- name: EPOCHS_PER_SLASHINGS_VECTOR#phase0
sources:
- file: config/fieldparams/mainnet.go
search: SlashingsLength\s*=
@@ -68,7 +82,7 @@
EPOCHS_PER_SLASHINGS_VECTOR: uint64 = 8192
</spec>
- name: EPOCHS_PER_SYNC_COMMITTEE_PERIOD
- name: EPOCHS_PER_SYNC_COMMITTEE_PERIOD#altair
sources:
- file: config/params/config.go
search: EpochsPerSyncCommitteePeriod\s+.*yaml:"EPOCHS_PER_SYNC_COMMITTEE_PERIOD"
@@ -78,7 +92,7 @@
EPOCHS_PER_SYNC_COMMITTEE_PERIOD: uint64 = 256
</spec>
- name: FIELD_ELEMENTS_PER_BLOB
- name: FIELD_ELEMENTS_PER_BLOB#deneb
sources:
- file: config/params/config.go
search: FieldElementsPerBlob\s+.*yaml:"FIELD_ELEMENTS_PER_BLOB"
@@ -88,7 +102,7 @@
FIELD_ELEMENTS_PER_BLOB: uint64 = 4096
</spec>
- name: FIELD_ELEMENTS_PER_CELL
- name: FIELD_ELEMENTS_PER_CELL#fulu
sources:
- file: config/fieldparams/mainnet.go
search: CellsPerBlob\s*=
@@ -98,7 +112,7 @@
FIELD_ELEMENTS_PER_CELL: uint64 = 64
</spec>
- name: FIELD_ELEMENTS_PER_EXT_BLOB
- name: FIELD_ELEMENTS_PER_EXT_BLOB#fulu
sources:
- file: proto/ssz_proto_library.bzl
search: mainnet\s*=\s*\{[^}]*"field_elements_per_ext_blob\.size".*[^}]*\}
@@ -108,7 +122,7 @@
FIELD_ELEMENTS_PER_EXT_BLOB = 8192
</spec>
- name: HISTORICAL_ROOTS_LIMIT
- name: HISTORICAL_ROOTS_LIMIT#phase0
sources:
- file: config/fieldparams/mainnet.go
search: HistoricalRootsLength\s*=
@@ -118,7 +132,7 @@
HISTORICAL_ROOTS_LIMIT: uint64 = 16777216
</spec>
- name: HYSTERESIS_DOWNWARD_MULTIPLIER
- name: HYSTERESIS_DOWNWARD_MULTIPLIER#phase0
sources:
- file: config/params/config.go
search: HysteresisDownwardMultiplier\s+.*yaml:"HYSTERESIS_DOWNWARD_MULTIPLIER"
@@ -128,7 +142,7 @@
HYSTERESIS_DOWNWARD_MULTIPLIER: uint64 = 1
</spec>
- name: HYSTERESIS_QUOTIENT
- name: HYSTERESIS_QUOTIENT#phase0
sources:
- file: config/params/config.go
search: HysteresisQuotient\s+.*yaml:"HYSTERESIS_QUOTIENT"
@@ -138,7 +152,7 @@
HYSTERESIS_QUOTIENT: uint64 = 4
</spec>
- name: HYSTERESIS_UPWARD_MULTIPLIER
- name: HYSTERESIS_UPWARD_MULTIPLIER#phase0
sources:
- file: config/params/config.go
search: HysteresisUpwardMultiplier\s+.*yaml:"HYSTERESIS_UPWARD_MULTIPLIER"
@@ -148,7 +162,7 @@
HYSTERESIS_UPWARD_MULTIPLIER: uint64 = 5
</spec>
- name: INACTIVITY_PENALTY_QUOTIENT
- name: INACTIVITY_PENALTY_QUOTIENT#phase0
sources:
- file: config/params/config.go
search: InactivityPenaltyQuotient\s+.*yaml:"INACTIVITY_PENALTY_QUOTIENT"
@@ -158,7 +172,7 @@
INACTIVITY_PENALTY_QUOTIENT: uint64 = 67108864
</spec>
- name: INACTIVITY_PENALTY_QUOTIENT_ALTAIR
- name: INACTIVITY_PENALTY_QUOTIENT_ALTAIR#altair
sources:
- file: config/params/config.go
search: InactivityPenaltyQuotientAltair\s+.*yaml:"INACTIVITY_PENALTY_QUOTIENT_ALTAIR"
@@ -168,7 +182,7 @@
INACTIVITY_PENALTY_QUOTIENT_ALTAIR: uint64 = 50331648
</spec>
- name: INACTIVITY_PENALTY_QUOTIENT_BELLATRIX
- name: INACTIVITY_PENALTY_QUOTIENT_BELLATRIX#bellatrix
sources:
- file: config/params/config.go
search: InactivityPenaltyQuotientBellatrix\s+.*yaml:"INACTIVITY_PENALTY_QUOTIENT_BELLATRIX"
@@ -178,7 +192,7 @@
INACTIVITY_PENALTY_QUOTIENT_BELLATRIX: uint64 = 16777216
</spec>
- name: KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH
- name: KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH#fulu
sources:
- file: proto/ssz_proto_library.bzl
search: mainnet\s*=\s*\{[^}]*"kzg_commitments_inclusion_proof_depth\.size":.*[^}]*\}
@@ -188,7 +202,7 @@
KZG_COMMITMENTS_INCLUSION_PROOF_DEPTH: uint64 = 4
</spec>
- name: KZG_COMMITMENT_INCLUSION_PROOF_DEPTH
- name: KZG_COMMITMENT_INCLUSION_PROOF_DEPTH#deneb
sources:
- file: config/fieldparams/mainnet.go
search: KzgCommitmentInclusionProofDepth\s*=
@@ -198,7 +212,7 @@
KZG_COMMITMENT_INCLUSION_PROOF_DEPTH: uint64 = 17
</spec>
- name: MAX_ATTESTATIONS
- name: MAX_ATTESTATIONS#phase0
sources:
- file: config/params/config.go
search: MaxAttestations\s+.*yaml:"MAX_ATTESTATIONS"
@@ -208,7 +222,7 @@
MAX_ATTESTATIONS = 128
</spec>
- name: MAX_ATTESTATIONS_ELECTRA
- name: MAX_ATTESTATIONS_ELECTRA#electra
sources:
- file: config/params/config.go
search: MaxAttestationsElectra\s+.*yaml:"MAX_ATTESTATIONS_ELECTRA"
@@ -218,7 +232,7 @@
MAX_ATTESTATIONS_ELECTRA = 8
</spec>
- name: MAX_ATTESTER_SLASHINGS
- name: MAX_ATTESTER_SLASHINGS#phase0
sources:
- file: config/params/config.go
search: MaxAttesterSlashings\s+.*yaml:"MAX_ATTESTER_SLASHINGS"
@@ -228,7 +242,7 @@
MAX_ATTESTER_SLASHINGS = 2
</spec>
- name: MAX_ATTESTER_SLASHINGS_ELECTRA
- name: MAX_ATTESTER_SLASHINGS_ELECTRA#electra
sources:
- file: config/params/config.go
search: MaxAttesterSlashingsElectra\s+.*yaml:"MAX_ATTESTER_SLASHINGS_ELECTRA"
@@ -238,7 +252,7 @@
MAX_ATTESTER_SLASHINGS_ELECTRA = 1
</spec>
- name: MAX_BLOB_COMMITMENTS_PER_BLOCK
- name: MAX_BLOB_COMMITMENTS_PER_BLOCK#deneb
sources:
- file: config/fieldparams/mainnet.go
search: MaxBlobCommitmentsPerBlock\s*=
@@ -248,7 +262,7 @@
MAX_BLOB_COMMITMENTS_PER_BLOCK: uint64 = 4096
</spec>
- name: MAX_BLS_TO_EXECUTION_CHANGES
- name: MAX_BLS_TO_EXECUTION_CHANGES#capella
sources:
- file: config/params/config.go
search: MaxBlsToExecutionChanges\s+.*yaml:"MAX_BLS_TO_EXECUTION_CHANGES"
@@ -258,7 +272,14 @@
MAX_BLS_TO_EXECUTION_CHANGES = 16
</spec>
- name: MAX_BYTES_PER_TRANSACTION
- name: MAX_BUILDERS_PER_WITHDRAWALS_SWEEP#gloas
sources: []
spec: |
<spec preset_var="MAX_BUILDERS_PER_WITHDRAWALS_SWEEP" fork="gloas" hash="1556b314">
MAX_BUILDERS_PER_WITHDRAWALS_SWEEP = 16384
</spec>
- name: MAX_BYTES_PER_TRANSACTION#bellatrix
sources:
- file: config/params/config.go
search: MaxBytesPerTransaction\s+.*yaml:"MAX_BYTES_PER_TRANSACTION"
@@ -288,7 +309,7 @@
MAX_COMMITTEES_PER_SLOT: uint64 = 64
</spec>
- name: MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD
- name: MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD#electra
sources:
- file: config/params/config.go
search: MaxConsolidationsRequestsPerPayload\s+.*yaml:"MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD"
@@ -298,7 +319,7 @@
MAX_CONSOLIDATION_REQUESTS_PER_PAYLOAD: uint64 = 2
</spec>
- name: MAX_DEPOSITS
- name: MAX_DEPOSITS#phase0
sources:
- file: config/params/config.go
search: MaxDeposits\s+.*yaml:"MAX_DEPOSITS"
@@ -308,7 +329,7 @@
MAX_DEPOSITS = 16
</spec>
- name: MAX_DEPOSIT_REQUESTS_PER_PAYLOAD
- name: MAX_DEPOSIT_REQUESTS_PER_PAYLOAD#electra
sources:
- file: config/params/config.go
search: MaxDepositRequestsPerPayload\s+.*yaml:"MAX_DEPOSIT_REQUESTS_PER_PAYLOAD"
@@ -318,7 +339,7 @@
MAX_DEPOSIT_REQUESTS_PER_PAYLOAD: uint64 = 8192
</spec>
- name: MAX_EFFECTIVE_BALANCE
- name: MAX_EFFECTIVE_BALANCE#phase0
sources:
- file: config/params/config.go
search: MaxEffectiveBalance\s+.*yaml:"MAX_EFFECTIVE_BALANCE"
@@ -328,7 +349,7 @@
MAX_EFFECTIVE_BALANCE: Gwei = 32000000000
</spec>
- name: MAX_EFFECTIVE_BALANCE_ELECTRA
- name: MAX_EFFECTIVE_BALANCE_ELECTRA#electra
sources:
- file: config/params/config.go
search: MaxEffectiveBalanceElectra\s+.*yaml:"MAX_EFFECTIVE_BALANCE_ELECTRA"
@@ -338,7 +359,7 @@
MAX_EFFECTIVE_BALANCE_ELECTRA: Gwei = 2048000000000
</spec>
- name: MAX_EXTRA_DATA_BYTES
- name: MAX_EXTRA_DATA_BYTES#bellatrix
sources:
- file: config/params/config.go
search: MaxExtraDataBytes\s+.*yaml:"MAX_EXTRA_DATA_BYTES"
@@ -348,7 +369,14 @@
MAX_EXTRA_DATA_BYTES = 32
</spec>
- name: MAX_PENDING_DEPOSITS_PER_EPOCH
- name: MAX_PAYLOAD_ATTESTATIONS#gloas
sources: []
spec: |
<spec preset_var="MAX_PAYLOAD_ATTESTATIONS" fork="gloas" hash="fc24e7ea">
MAX_PAYLOAD_ATTESTATIONS = 4
</spec>
- name: MAX_PENDING_DEPOSITS_PER_EPOCH#electra
sources:
- file: config/params/config.go
search: MaxPendingDepositsPerEpoch\s+.*yaml:"MAX_PENDING_DEPOSITS_PER_EPOCH"
@@ -358,7 +386,7 @@
MAX_PENDING_DEPOSITS_PER_EPOCH: uint64 = 16
</spec>
- name: MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP
- name: MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP#electra
sources:
- file: config/params/config.go
search: MaxPendingPartialsPerWithdrawalsSweep\s+.*yaml:"MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP"
@@ -368,7 +396,7 @@
MAX_PENDING_PARTIALS_PER_WITHDRAWALS_SWEEP: uint64 = 8
</spec>
- name: MAX_PROPOSER_SLASHINGS
- name: MAX_PROPOSER_SLASHINGS#phase0
sources:
- file: config/params/config.go
search: MaxProposerSlashings\s+.*yaml:"MAX_PROPOSER_SLASHINGS"
@@ -378,7 +406,7 @@
MAX_PROPOSER_SLASHINGS = 16
</spec>
- name: MAX_SEED_LOOKAHEAD
- name: MAX_SEED_LOOKAHEAD#phase0
sources:
- file: config/params/config.go
search: MaxSeedLookahead\s+.*yaml:"MAX_SEED_LOOKAHEAD"
@@ -388,7 +416,7 @@
MAX_SEED_LOOKAHEAD: uint64 = 4
</spec>
- name: MAX_TRANSACTIONS_PER_PAYLOAD
- name: MAX_TRANSACTIONS_PER_PAYLOAD#bellatrix
sources:
- file: config/params/config.go
search: MaxTransactionsPerPayload\s+.*yaml:"MAX_TRANSACTIONS_PER_PAYLOAD"
@@ -418,7 +446,7 @@
MAX_VALIDATORS_PER_COMMITTEE: uint64 = 2048
</spec>
- name: MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP
- name: MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP#capella
sources:
- file: config/params/config.go
search: MaxValidatorsPerWithdrawalsSweep\s+.*yaml:"MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP"
@@ -428,7 +456,7 @@
MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP = 16384
</spec>
- name: MAX_VOLUNTARY_EXITS
- name: MAX_VOLUNTARY_EXITS#phase0
sources:
- file: config/params/config.go
search: MaxVoluntaryExits\s+.*yaml:"MAX_VOLUNTARY_EXITS"
@@ -438,7 +466,7 @@
MAX_VOLUNTARY_EXITS = 16
</spec>
- name: MAX_WITHDRAWALS_PER_PAYLOAD
- name: MAX_WITHDRAWALS_PER_PAYLOAD#capella
sources:
- file: config/fieldparams/mainnet.go
search: MaxWithdrawalsPerPayload\s*=
@@ -448,7 +476,7 @@
MAX_WITHDRAWALS_PER_PAYLOAD: uint64 = 16
</spec>
- name: MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD
- name: MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD#electra
sources:
- file: config/params/config.go
search: MaxWithdrawalRequestsPerPayload\s+.*yaml:"MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD"
@@ -458,7 +486,7 @@
MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD: uint64 = 16
</spec>
- name: MIN_ACTIVATION_BALANCE
- name: MIN_ACTIVATION_BALANCE#electra
sources:
- file: config/params/config.go
search: MinActivationBalance\s+.*yaml:"MIN_ACTIVATION_BALANCE"
@@ -468,7 +496,7 @@
MIN_ACTIVATION_BALANCE: Gwei = 32000000000
</spec>
- name: MIN_ATTESTATION_INCLUSION_DELAY
- name: MIN_ATTESTATION_INCLUSION_DELAY#phase0
sources:
- file: config/params/config.go
search: MinAttestationInclusionDelay\s+.*yaml:"MIN_ATTESTATION_INCLUSION_DELAY"
@@ -478,7 +506,7 @@
MIN_ATTESTATION_INCLUSION_DELAY: uint64 = 1
</spec>
- name: MIN_DEPOSIT_AMOUNT
- name: MIN_DEPOSIT_AMOUNT#phase0
sources:
- file: config/params/config.go
search: MinDepositAmount\s+.*yaml:"MIN_DEPOSIT_AMOUNT"
@@ -488,7 +516,7 @@
MIN_DEPOSIT_AMOUNT: Gwei = 1000000000
</spec>
- name: MIN_EPOCHS_TO_INACTIVITY_PENALTY
- name: MIN_EPOCHS_TO_INACTIVITY_PENALTY#phase0
sources:
- file: config/params/config.go
search: MinEpochsToInactivityPenalty\s+.*yaml:"MIN_EPOCHS_TO_INACTIVITY_PENALTY"
@@ -498,7 +526,7 @@
MIN_EPOCHS_TO_INACTIVITY_PENALTY: uint64 = 4
</spec>
- name: MIN_SEED_LOOKAHEAD
- name: MIN_SEED_LOOKAHEAD#phase0
sources:
- file: config/params/config.go
search: MinSeedLookahead\s+.*yaml:"MIN_SEED_LOOKAHEAD"
@@ -508,7 +536,7 @@
MIN_SEED_LOOKAHEAD: uint64 = 1
</spec>
- name: MIN_SLASHING_PENALTY_QUOTIENT
- name: MIN_SLASHING_PENALTY_QUOTIENT#phase0
sources:
- file: config/params/config.go
search: MinSlashingPenaltyQuotient\s+.*yaml:"MIN_SLASHING_PENALTY_QUOTIENT"
@@ -518,7 +546,7 @@
MIN_SLASHING_PENALTY_QUOTIENT: uint64 = 128
</spec>
- name: MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR
- name: MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR#altair
sources:
- file: config/params/config.go
search: MinSlashingPenaltyQuotientAltair\s+.*yaml:"MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR"
@@ -528,7 +556,7 @@
MIN_SLASHING_PENALTY_QUOTIENT_ALTAIR: uint64 = 64
</spec>
- name: MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX
- name: MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX#bellatrix
sources:
- file: config/params/config.go
search: MinSlashingPenaltyQuotientBellatrix\s+.*yaml:"MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX"
@@ -538,7 +566,7 @@
MIN_SLASHING_PENALTY_QUOTIENT_BELLATRIX: uint64 = 32
</spec>
- name: MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA
- name: MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA#electra
sources:
- file: config/params/config.go
search: MinSlashingPenaltyQuotientElectra\s+.*yaml:"MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA"
@@ -548,7 +576,7 @@
MIN_SLASHING_PENALTY_QUOTIENT_ELECTRA: uint64 = 4096
</spec>
- name: MIN_SYNC_COMMITTEE_PARTICIPANTS
- name: MIN_SYNC_COMMITTEE_PARTICIPANTS#altair
sources:
- file: config/params/config.go
search: MinSyncCommitteeParticipants\s+.*yaml:"MIN_SYNC_COMMITTEE_PARTICIPANTS"
@@ -558,7 +586,7 @@
MIN_SYNC_COMMITTEE_PARTICIPANTS = 1
</spec>
- name: NUMBER_OF_COLUMNS
- name: NUMBER_OF_COLUMNS#fulu
sources:
- file: config/fieldparams/mainnet.go
search: NumberOfColumns\s*=
@@ -568,7 +596,7 @@
NUMBER_OF_COLUMNS: uint64 = 128
</spec>
- name: PENDING_CONSOLIDATIONS_LIMIT
- name: PENDING_CONSOLIDATIONS_LIMIT#electra
sources:
- file: config/fieldparams/mainnet.go
search: PendingConsolidationsLimit\s*=
@@ -578,7 +606,7 @@
PENDING_CONSOLIDATIONS_LIMIT: uint64 = 262144
</spec>
- name: PENDING_DEPOSITS_LIMIT
- name: PENDING_DEPOSITS_LIMIT#electra
sources:
- file: config/fieldparams/mainnet.go
search: PendingDepositsLimit\s*=
@@ -588,7 +616,7 @@
PENDING_DEPOSITS_LIMIT: uint64 = 134217728
</spec>
- name: PENDING_PARTIAL_WITHDRAWALS_LIMIT
- name: PENDING_PARTIAL_WITHDRAWALS_LIMIT#electra
sources:
- file: config/fieldparams/mainnet.go
search: PendingPartialWithdrawalsLimit\s*=
@@ -598,7 +626,7 @@
PENDING_PARTIAL_WITHDRAWALS_LIMIT: uint64 = 134217728
</spec>
- name: PROPORTIONAL_SLASHING_MULTIPLIER
- name: PROPORTIONAL_SLASHING_MULTIPLIER#phase0
sources:
- file: config/params/config.go
search: ProportionalSlashingMultiplier\s+.*yaml:"PROPORTIONAL_SLASHING_MULTIPLIER"
@@ -608,7 +636,7 @@
PROPORTIONAL_SLASHING_MULTIPLIER: uint64 = 1
</spec>
- name: PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR
- name: PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR#altair
sources:
- file: config/params/config.go
search: ProportionalSlashingMultiplierAltair\s+.*yaml:"PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR"
@@ -618,7 +646,7 @@
PROPORTIONAL_SLASHING_MULTIPLIER_ALTAIR: uint64 = 2
</spec>
- name: PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX
- name: PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX#bellatrix
sources:
- file: config/params/config.go
search: ProportionalSlashingMultiplierBellatrix\s+.*yaml:"PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX"
@@ -628,7 +656,7 @@
PROPORTIONAL_SLASHING_MULTIPLIER_BELLATRIX: uint64 = 3
</spec>
- name: PROPOSER_REWARD_QUOTIENT
- name: PROPOSER_REWARD_QUOTIENT#phase0
sources:
- file: config/params/config.go
search: ProposerRewardQuotient\s+.*yaml:"PROPOSER_REWARD_QUOTIENT"
@@ -638,7 +666,14 @@
PROPOSER_REWARD_QUOTIENT: uint64 = 8
</spec>
- name: SHUFFLE_ROUND_COUNT
- name: PTC_SIZE#gloas
sources: []
spec: |
<spec preset_var="PTC_SIZE" fork="gloas" hash="d61c5930">
PTC_SIZE: uint64 = 512
</spec>
- name: SHUFFLE_ROUND_COUNT#phase0
sources:
- file: config/params/config.go
search: ShuffleRoundCount\s+.*yaml:"SHUFFLE_ROUND_COUNT"
@@ -648,7 +683,7 @@
SHUFFLE_ROUND_COUNT: uint64 = 90
</spec>
- name: SLOTS_PER_EPOCH
- name: SLOTS_PER_EPOCH#phase0
sources:
- file: config/fieldparams/mainnet.go
search: SlotsPerEpoch\s*=
@@ -658,7 +693,7 @@
SLOTS_PER_EPOCH: uint64 = 32
</spec>
- name: SLOTS_PER_HISTORICAL_ROOT
- name: SLOTS_PER_HISTORICAL_ROOT#phase0
sources:
- file: config/fieldparams/mainnet.go
search: BlockRootsLength\s*=
@@ -668,7 +703,7 @@
SLOTS_PER_HISTORICAL_ROOT: uint64 = 8192
</spec>
- name: SYNC_COMMITTEE_SIZE
- name: SYNC_COMMITTEE_SIZE#altair
sources:
- file: config/fieldparams/mainnet.go
search: SyncCommitteeLength\s*=
@@ -678,7 +713,7 @@
SYNC_COMMITTEE_SIZE: uint64 = 512
</spec>
- name: TARGET_COMMITTEE_SIZE
- name: TARGET_COMMITTEE_SIZE#phase0
sources:
- file: config/params/config.go
search: TargetCommitteeSize\s+.*yaml:"TARGET_COMMITTEE_SIZE"
@@ -688,7 +723,7 @@
TARGET_COMMITTEE_SIZE: uint64 = 128
</spec>
- name: UPDATE_TIMEOUT
- name: UPDATE_TIMEOUT#altair
sources:
- file: beacon-chain/rpc/eth/config/handlers.go
search: data\["UPDATE_TIMEOUT"\]
@@ -698,7 +733,7 @@
UPDATE_TIMEOUT = 8192
</spec>
- name: VALIDATOR_REGISTRY_LIMIT
- name: VALIDATOR_REGISTRY_LIMIT#phase0
sources:
- file: config/fieldparams/mainnet.go
search: ValidatorRegistryLimit\s*=
@@ -708,7 +743,7 @@
VALIDATOR_REGISTRY_LIMIT: uint64 = 1099511627776
</spec>
- name: WHISTLEBLOWER_REWARD_QUOTIENT
- name: WHISTLEBLOWER_REWARD_QUOTIENT#phase0
sources:
- file: config/params/config.go
search: WhistleBlowerRewardQuotient\s+.*yaml:"WHISTLEBLOWER_REWARD_QUOTIENT"
@@ -718,7 +753,7 @@
WHISTLEBLOWER_REWARD_QUOTIENT: uint64 = 512
</spec>
- name: WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA
- name: WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA#electra
sources:
- file: config/params/config.go
search: WhistleBlowerRewardQuotientElectra\s+.*yaml:"WHISTLEBLOWER_REWARD_QUOTIENT_ELECTRA"

View File

@@ -225,9 +225,9 @@ func (r *testRunner) testDepositsAndTx(ctx context.Context, g *errgroup.Group,
if err := helpers.ComponentsStarted(ctx, []e2etypes.ComponentRunner{r.depositor}); err != nil {
return errors.Wrap(err, "testDepositsAndTx unable to run, depositor did not Start")
}
go func() {
if r.config.TestDeposits {
log.Info("Running deposit tests")
go func() {
if r.config.TestDeposits {
log.Info("Running deposit tests")
// The validators with an index < minGenesisActiveCount all have deposits already from the chain start.
// Skip all of those chain start validators by seeking to minGenesisActiveCount in the validator list
// for further deposit testing.
@@ -238,12 +238,12 @@ func (r *testRunner) testDepositsAndTx(ctx context.Context, g *errgroup.Group,
r.t.Error(errors.Wrap(err, "depositor.SendAndMine failed"))
}
}
}
// Only generate background transactions when relevant for the test.
if r.config.TestDeposits || r.config.TestFeature || r.config.UseBuilder {
r.testTxGeneration(ctx, g, keystorePath, []e2etypes.ComponentRunner{})
}
}()
}
// Only generate background transactions when relevant for the test.
if r.config.TestDeposits || r.config.TestFeature || r.config.UseBuilder {
r.testTxGeneration(ctx, g, keystorePath, []e2etypes.ComponentRunner{})
}
}()
if r.config.TestDeposits {
return depositCheckValidator.Start(ctx)
}

View File

@@ -38,8 +38,8 @@ func TestEndToEnd_MinimalConfig(t *testing.T) {
r := e2eMinimal(t, cfg,
types.WithCheckpointSync(),
types.WithEpochs(10),
types.WithExitEpoch(4), // Minimum due to ShardCommitteePeriod=4
types.WithLargeBlobs(), // Use large blob transactions for BPO testing
types.WithExitEpoch(4), // Minimum due to ShardCommitteePeriod=4
types.WithLargeBlobs(), // Use large blob transactions for BPO testing
)
r.run()
}
}

View File

@@ -204,7 +204,6 @@ go_test(
"gloas__operations__execution_payload_header_test.go",
"gloas__operations__payload_attestation_test.go",
"gloas__operations__proposer_slashing_test.go",
"gloas__operations__withdrawals_test.go",
"gloas__sanity__slots_test.go",
"gloas__ssz_static__ssz_static_test.go",
"phase0__epoch_processing__effective_balance_updates_test.go",

View File

@@ -1,11 +0,0 @@
package mainnet
import (
"testing"
"github.com/OffchainLabs/prysm/v7/testing/spectest/shared/gloas/operations"
)
func TestMainnet_Gloas_Operations_Withdrawals(t *testing.T) {
operations.RunWithdrawalsTest(t, "mainnet")
}

View File

@@ -210,7 +210,6 @@ go_test(
"gloas__operations__execution_payload_bid_test.go",
"gloas__operations__payload_attestation_test.go",
"gloas__operations__proposer_slashing_test.go",
"gloas__operations__withdrawals_test.go",
"gloas__sanity__slots_test.go",
"gloas__ssz_static__ssz_static_test.go",
"phase0__epoch_processing__effective_balance_updates_test.go",

View File

@@ -1,11 +0,0 @@
package minimal
import (
"testing"
"github.com/OffchainLabs/prysm/v7/testing/spectest/shared/gloas/operations"
)
func TestMinimal_Gloas_Operations_Withdrawals(t *testing.T) {
operations.RunWithdrawalsTest(t, "minimal")
}

View File

@@ -8,20 +8,16 @@ go_library(
"helpers.go",
"payload_attestation.go",
"proposer_slashing.go",
"withdrawals.go",
],
importpath = "github.com/OffchainLabs/prysm/v7/testing/spectest/shared/gloas/operations",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/core/gloas:go_default_library",
"//beacon-chain/state:go_default_library",
"//beacon-chain/state/state-native:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"//testing/require:go_default_library",
"//testing/spectest/shared/common/operations:go_default_library",
"//testing/spectest/utils:go_default_library",
],
)

View File

@@ -1,48 +0,0 @@
package operations
import (
"context"
"path"
"testing"
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/gloas"
"github.com/OffchainLabs/prysm/v7/beacon-chain/state"
"github.com/OffchainLabs/prysm/v7/consensus-types/blocks"
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/runtime/version"
"github.com/OffchainLabs/prysm/v7/testing/require"
common "github.com/OffchainLabs/prysm/v7/testing/spectest/shared/common/operations"
"github.com/OffchainLabs/prysm/v7/testing/spectest/utils"
)
func emptyBlockGloas() (interfaces.SignedBeaconBlock, error) {
b := &ethpb.SignedBeaconBlockGloas{
Block: &ethpb.BeaconBlockGloas{
Body: &ethpb.BeaconBlockBodyGloas{},
},
}
return blocks.NewSignedBeaconBlock(b)
}
func RunWithdrawalsTest(t *testing.T, config string) {
require.NoError(t, utils.SetConfig(t, config))
testFolders, testsFolderPath := utils.TestFolders(t, config, version.String(version.Gloas), "operations/withdrawals/pyspec_tests")
if len(testFolders) == 0 {
t.Fatalf("No test folders found for %s/%s/%s", config, version.String(version.Gloas), "operations/withdrawals/pyspec_tests")
}
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
folderPath := path.Join(testsFolderPath, folder.Name())
blk, err := emptyBlockGloas()
require.NoError(t, err)
common.RunBlockOperationTest(t, folderPath, blk, sszToState, func(_ context.Context, s state.BeaconState, _ interfaces.ReadOnlySignedBeaconBlock) (state.BeaconState, error) {
if err := gloas.ProcessWithdrawals(s); err != nil {
return nil, err
}
return s, nil
})
})
}
}

View File

@@ -283,16 +283,18 @@ func (mr *MockValidatorClientMockRecorder) ProposeExit(ctx, in any) *gomock.Call
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ProposeExit", reflect.TypeOf((*MockValidatorClient)(nil).ProposeExit), ctx, in)
}
// SetHost mocks base method.
func (m *MockValidatorClient) SetHost(host string) {
// EnsureReady mocks base method.
func (m *MockValidatorClient) EnsureReady(ctx context.Context) bool {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetHost", host)
ret := m.ctrl.Call(m, "EnsureReady", ctx)
ret0, _ := ret[0].(bool)
return ret0
}
// SetHost indicates an expected call of SetHost.
func (mr *MockValidatorClientMockRecorder) SetHost(host any) *gomock.Call {
// EnsureReady indicates an expected call of EnsureReady.
func (mr *MockValidatorClientMockRecorder) EnsureReady(ctx any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHost", reflect.TypeOf((*MockValidatorClient)(nil).SetHost), host)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnsureReady", reflect.TypeOf((*MockValidatorClient)(nil).EnsureReady), ctx)
}
// StartEventStream mocks base method.

View File

@@ -128,18 +128,18 @@ func (mr *MockValidatorMockRecorder) EventsChan() *gomock.Call {
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EventsChan", reflect.TypeOf((*MockValidator)(nil).EventsChan))
}
// FindHealthyHost mocks base method.
func (m *MockValidator) FindHealthyHost(arg0 context.Context) bool {
// EnsureReady mocks base method.
func (m *MockValidator) EnsureReady(arg0 context.Context) bool {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "FindHealthyHost", arg0)
ret := m.ctrl.Call(m, "EnsureReady", arg0)
ret0, _ := ret[0].(bool)
return ret0
}
// FindHealthyHost indicates an expected call of FindHealthyHost.
func (mr *MockValidatorMockRecorder) FindHealthyHost(arg0 any) *gomock.Call {
// EnsureReady indicates an expected call of EnsureReady.
func (mr *MockValidatorMockRecorder) EnsureReady(arg0 any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "FindHealthyHost", reflect.TypeOf((*MockValidator)(nil).FindHealthyHost), arg0)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "EnsureReady", reflect.TypeOf((*MockValidator)(nil).EnsureReady), arg0)
}
// GenesisTime mocks base method.

View File

@@ -25,6 +25,7 @@ go_library(
],
deps = [
"//api/grpc:go_default_library",
"//api/rest:go_default_library",
"//beacon-chain/core/blocks:go_default_library",
"//cmd/validator/flags:go_default_library",
"//config/fieldparams:go_default_library",

View File

@@ -3,14 +3,13 @@ package accounts
import (
"context"
"io"
"net/http"
"os"
"time"
grpcutil "github.com/OffchainLabs/prysm/v7/api/grpc"
"github.com/OffchainLabs/prysm/v7/api/rest"
"github.com/OffchainLabs/prysm/v7/crypto/bls"
"github.com/OffchainLabs/prysm/v7/validator/accounts/wallet"
beaconApi "github.com/OffchainLabs/prysm/v7/validator/client/beacon-api"
iface "github.com/OffchainLabs/prysm/v7/validator/client/iface"
nodeClientFactory "github.com/OffchainLabs/prysm/v7/validator/client/node-client-factory"
validatorClientFactory "github.com/OffchainLabs/prysm/v7/validator/client/validator-client-factory"
@@ -77,22 +76,17 @@ func (acm *CLIManager) prepareBeaconClients(ctx context.Context) (*iface.Validat
}
ctx = grpcutil.AppendHeaders(ctx, acm.grpcHeaders)
grpcConn, err := grpc.DialContext(ctx, acm.beaconRPCProvider, acm.dialOpts...)
if err != nil {
return nil, nil, errors.Wrapf(err, "could not dial endpoint %s", acm.beaconRPCProvider)
}
conn := validatorHelpers.NewNodeConnection(
grpcConn,
acm.beaconApiEndpoint,
validatorHelpers.WithBeaconApiTimeout(acm.beaconApiTimeout),
)
restHandler := beaconApi.NewBeaconApiRestHandler(
http.Client{Timeout: acm.beaconApiTimeout},
acm.beaconApiEndpoint,
conn, err := validatorHelpers.NewNodeConnection(
validatorHelpers.WithGRPC(ctx, acm.beaconRPCProvider, acm.dialOpts),
validatorHelpers.WithREST(acm.beaconApiEndpoint, rest.WithHttpTimeout(acm.beaconApiTimeout)),
)
validatorClient := validatorClientFactory.NewValidatorClient(conn, restHandler)
nodeClient := nodeClientFactory.NewNodeClient(conn, restHandler)
if err != nil {
return nil, nil, err
}
validatorClient := validatorClientFactory.NewValidatorClient(conn)
nodeClient := nodeClientFactory.NewNodeClient(conn)
return &validatorClient, &nodeClient, nil
}

View File

@@ -10,7 +10,6 @@ go_library(
"log.go",
"log_helpers.go",
"metrics.go",
"multiple_endpoints_grpc_resolver.go",
"propose.go",
"registration.go",
"runner.go",
@@ -29,6 +28,7 @@ go_library(
"//api/client:go_default_library",
"//api/client/event:go_default_library",
"//api/grpc:go_default_library",
"//api/rest:go_default_library",
"//api/server/structs:go_default_library",
"//async:go_default_library",
"//async/event:go_default_library",
@@ -58,7 +58,6 @@ go_library(
"//time/slots:go_default_library",
"//validator/accounts/iface:go_default_library",
"//validator/accounts/wallet:go_default_library",
"//validator/client/beacon-api:go_default_library",
"//validator/client/beacon-chain-client-factory:go_default_library",
"//validator/client/iface:go_default_library",
"//validator/client/node-client-factory:go_default_library",
@@ -86,13 +85,11 @@ go_library(
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",
"@io_opentelemetry_go_contrib_instrumentation_google_golang_org_grpc_otelgrpc//:go_default_library",
"@io_opentelemetry_go_contrib_instrumentation_net_http_otelhttp//:go_default_library",
"@io_opentelemetry_go_otel_trace//:go_default_library",
"@org_golang_google_grpc//:go_default_library",
"@org_golang_google_grpc//codes:go_default_library",
"@org_golang_google_grpc//credentials:go_default_library",
"@org_golang_google_grpc//metadata:go_default_library",
"@org_golang_google_grpc//resolver:go_default_library",
"@org_golang_google_grpc//status:go_default_library",
"@org_golang_google_protobuf//proto:go_default_library",
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
@@ -124,6 +121,7 @@ go_test(
],
embed = [":go_default_library"],
deps = [
"//api/grpc:go_default_library",
"//api/server/structs:go_default_library",
"//async/event:go_default_library",
"//beacon-chain/core/signing:go_default_library",

View File

@@ -26,7 +26,6 @@ go_library(
"propose_exit.go",
"prysm_beacon_chain_client.go",
"registration.go",
"rest_handler_client.go",
"state_validators.go",
"status.go",
"stream_blocks.go",
@@ -43,6 +42,8 @@ go_library(
"//api:go_default_library",
"//api/apiutil:go_default_library",
"//api/client/event:go_default_library",
"//api/fallback:go_default_library",
"//api/rest:go_default_library",
"//api/server/structs:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/signing:go_default_library",
@@ -111,6 +112,7 @@ go_test(
deps = [
"//api:go_default_library",
"//api/apiutil:go_default_library",
"//api/rest: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",

View File

@@ -26,7 +26,7 @@ func (c *beaconApiValidatorClient) attestationData(
query := apiutil.BuildURL("/eth/v1/validator/attestation_data", params)
produceAttestationDataResponseJson := structs.GetAttestationDataResponse{}
if err := c.jsonRestHandler.Get(ctx, query, &produceAttestationDataResponseJson); err != nil {
if err := c.handler.Get(ctx, query, &produceAttestationDataResponseJson); err != nil {
return nil, err
}

View File

@@ -28,10 +28,10 @@ func TestGetAttestationData_ValidAttestation(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
produceAttestationDataResponseJson := structs.GetAttestationDataResponse{}
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
fmt.Sprintf("/eth/v1/validator/attestation_data?committee_index=%d&slot=%d", expectedCommitteeIndex, expectedSlot),
&produceAttestationDataResponseJson,
@@ -56,7 +56,7 @@ func TestGetAttestationData_ValidAttestation(t *testing.T) {
},
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
resp, err := validatorClient.attestationData(ctx, primitives.Slot(expectedSlot), primitives.CommitteeIndex(expectedCommitteeIndex))
assert.NoError(t, err)
@@ -180,8 +180,8 @@ func TestGetAttestationData_InvalidData(t *testing.T) {
defer ctrl.Finish()
produceAttestationDataResponseJson := structs.GetAttestationDataResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
"/eth/v1/validator/attestation_data?committee_index=2&slot=1",
&produceAttestationDataResponseJson,
@@ -192,7 +192,7 @@ func TestGetAttestationData_InvalidData(t *testing.T) {
testCase.generateData(),
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
_, err := validatorClient.attestationData(ctx, 1, 2)
assert.ErrorContains(t, testCase.expectedErrorMessage, err)
})
@@ -208,9 +208,9 @@ func TestGetAttestationData_JsonResponseError(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
produceAttestationDataResponseJson := structs.GetAttestationDataResponse{}
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
fmt.Sprintf("/eth/v1/validator/attestation_data?committee_index=%d&slot=%d", committeeIndex, slot),
&produceAttestationDataResponseJson,
@@ -218,7 +218,7 @@ func TestGetAttestationData_JsonResponseError(t *testing.T) {
errors.New("some specific json response error"),
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
_, err := validatorClient.attestationData(ctx, slot, committeeIndex)
assert.ErrorContains(t, "some specific json response error", err)
}

View File

@@ -5,6 +5,7 @@ import (
"reflect"
"strconv"
"github.com/OffchainLabs/prysm/v7/api/rest"
"github.com/OffchainLabs/prysm/v7/api/server/structs"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
@@ -17,13 +18,13 @@ import (
type beaconApiChainClient struct {
fallbackClient iface.ChainClient
jsonRestHandler RestHandler
handler rest.Handler
stateValidatorsProvider StateValidatorsProvider
}
func (c beaconApiChainClient) headBlockHeaders(ctx context.Context) (*structs.GetBlockHeaderResponse, error) {
blockHeader := structs.GetBlockHeaderResponse{}
err := c.jsonRestHandler.Get(ctx, "/eth/v1/beacon/headers/head", &blockHeader)
err := c.handler.Get(ctx, "/eth/v1/beacon/headers/head", &blockHeader)
if err != nil {
return nil, err
}
@@ -43,7 +44,7 @@ func (c beaconApiChainClient) ChainHead(ctx context.Context, _ *empty.Empty) (*e
const endpoint = "/eth/v1/beacon/states/head/finality_checkpoints"
finalityCheckpoints := structs.GetFinalityCheckpointsResponse{}
if err := c.jsonRestHandler.Get(ctx, endpoint, &finalityCheckpoints); err != nil {
if err := c.handler.Get(ctx, endpoint, &finalityCheckpoints); err != nil {
return nil, err
}
@@ -327,10 +328,10 @@ func (c beaconApiChainClient) ValidatorParticipation(ctx context.Context, in *et
return nil, errors.New("beaconApiChainClient.ValidatorParticipation is not implemented. To use a fallback client, pass a fallback client as the last argument of NewBeaconApiChainClientWithFallback.")
}
func NewBeaconApiChainClientWithFallback(jsonRestHandler RestHandler, fallbackClient iface.ChainClient) iface.ChainClient {
func NewBeaconApiChainClientWithFallback(handler rest.Handler, fallbackClient iface.ChainClient) iface.ChainClient {
return &beaconApiChainClient{
jsonRestHandler: jsonRestHandler,
handler: handler,
fallbackClient: fallbackClient,
stateValidatorsProvider: beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler},
stateValidatorsProvider: beaconApiStateValidatorsProvider{handler: handler},
}
}

View File

@@ -115,12 +115,12 @@ func TestListValidators(t *testing.T) {
nil,
)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(gomock.Any(), blockHeaderEndpoint, gomock.Any()).Return(errors.New("bar error"))
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(gomock.Any(), blockHeaderEndpoint, gomock.Any()).Return(errors.New("bar error"))
beaconChainClient := beaconApiChainClient{
stateValidatorsProvider: stateValidatorsProvider,
jsonRestHandler: jsonRestHandler,
handler: handler,
}
_, err := beaconChainClient.Validators(ctx, &ethpb.ListValidatorsRequest{
QueryFilter: nil,
@@ -188,8 +188,8 @@ func TestListValidators(t *testing.T) {
nil,
)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(gomock.Any(), blockHeaderEndpoint, gomock.Any()).Return(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(gomock.Any(), blockHeaderEndpoint, gomock.Any()).Return(
nil,
).SetArg(
2,
@@ -198,7 +198,7 @@ func TestListValidators(t *testing.T) {
beaconChainClient := beaconApiChainClient{
stateValidatorsProvider: stateValidatorsProvider,
jsonRestHandler: jsonRestHandler,
handler: handler,
}
_, err := beaconChainClient.Validators(ctx, &ethpb.ListValidatorsRequest{
QueryFilter: nil,
@@ -740,15 +740,15 @@ func TestGetChainHead(t *testing.T) {
ctx := t.Context()
finalityCheckpointsResponse := structs.GetFinalityCheckpointsResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(gomock.Any(), finalityCheckpointsEndpoint, &finalityCheckpointsResponse).Return(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(gomock.Any(), finalityCheckpointsEndpoint, &finalityCheckpointsResponse).Return(
testCase.finalityCheckpointsError,
).SetArg(
2,
testCase.generateFinalityCheckpointsResponse(),
)
beaconChainClient := beaconApiChainClient{jsonRestHandler: jsonRestHandler}
beaconChainClient := beaconApiChainClient{handler: handler}
_, err := beaconChainClient.ChainHead(ctx, &emptypb.Empty{})
assert.ErrorContains(t, testCase.expectedError, err)
})
@@ -837,10 +837,10 @@ func TestGetChainHead(t *testing.T) {
defer ctrl.Finish()
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
finalityCheckpointsResponse := structs.GetFinalityCheckpointsResponse{}
jsonRestHandler.EXPECT().Get(gomock.Any(), finalityCheckpointsEndpoint, &finalityCheckpointsResponse).Return(
handler.EXPECT().Get(gomock.Any(), finalityCheckpointsEndpoint, &finalityCheckpointsResponse).Return(
nil,
).SetArg(
2,
@@ -848,14 +848,14 @@ func TestGetChainHead(t *testing.T) {
)
headBlockHeadersResponse := structs.GetBlockHeaderResponse{}
jsonRestHandler.EXPECT().Get(gomock.Any(), headBlockHeadersEndpoint, &headBlockHeadersResponse).Return(
handler.EXPECT().Get(gomock.Any(), headBlockHeadersEndpoint, &headBlockHeadersResponse).Return(
testCase.headBlockHeadersError,
).SetArg(
2,
testCase.generateHeadBlockHeadersResponse(),
)
beaconChainClient := beaconApiChainClient{jsonRestHandler: jsonRestHandler}
beaconChainClient := beaconApiChainClient{handler: handler}
_, err := beaconChainClient.ChainHead(ctx, &emptypb.Empty{})
assert.ErrorContains(t, testCase.expectedError, err)
})
@@ -867,10 +867,10 @@ func TestGetChainHead(t *testing.T) {
defer ctrl.Finish()
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
finalityCheckpointsResponse := structs.GetFinalityCheckpointsResponse{}
jsonRestHandler.EXPECT().Get(gomock.Any(), finalityCheckpointsEndpoint, &finalityCheckpointsResponse).Return(
handler.EXPECT().Get(gomock.Any(), finalityCheckpointsEndpoint, &finalityCheckpointsResponse).Return(
nil,
).SetArg(
2,
@@ -878,7 +878,7 @@ func TestGetChainHead(t *testing.T) {
)
headBlockHeadersResponse := structs.GetBlockHeaderResponse{}
jsonRestHandler.EXPECT().Get(gomock.Any(), headBlockHeadersEndpoint, &headBlockHeadersResponse).Return(
handler.EXPECT().Get(gomock.Any(), headBlockHeadersEndpoint, &headBlockHeadersResponse).Return(
nil,
).SetArg(
2,
@@ -909,7 +909,7 @@ func TestGetChainHead(t *testing.T) {
HeadEpoch: slots.ToEpoch(8),
}
beaconChainClient := beaconApiChainClient{jsonRestHandler: jsonRestHandler}
beaconChainClient := beaconApiChainClient{handler: handler}
chainHead, err := beaconChainClient.ChainHead(ctx, &emptypb.Empty{})
require.NoError(t, err)
assert.DeepEqual(t, expectedChainHead, chainHead)

View File

@@ -29,7 +29,7 @@ func (c *beaconApiValidatorClient) fork(ctx context.Context) (*structs.GetStateF
stateForkResponseJson := &structs.GetStateForkResponse{}
if err := c.jsonRestHandler.Get(ctx, endpoint, stateForkResponseJson); err != nil {
if err := c.handler.Get(ctx, endpoint, stateForkResponseJson); err != nil {
return nil, err
}
@@ -41,7 +41,7 @@ func (c *beaconApiValidatorClient) headers(ctx context.Context) (*structs.GetBlo
blockHeadersResponseJson := &structs.GetBlockHeadersResponse{}
if err := c.jsonRestHandler.Get(ctx, endpoint, blockHeadersResponseJson); err != nil {
if err := c.handler.Get(ctx, endpoint, blockHeadersResponseJson); err != nil {
return nil, err
}
@@ -59,7 +59,7 @@ func (c *beaconApiValidatorClient) liveness(ctx context.Context, epoch primitive
return nil, errors.Wrapf(err, "failed to marshal validator indexes")
}
if err = c.jsonRestHandler.Post(ctx, url, nil, bytes.NewBuffer(marshalledJsonValidatorIndexes), livenessResponseJson); err != nil {
if err = c.handler.Post(ctx, url, nil, bytes.NewBuffer(marshalledJsonValidatorIndexes), livenessResponseJson); err != nil {
return nil, err
}
@@ -71,7 +71,7 @@ func (c *beaconApiValidatorClient) syncing(ctx context.Context) (*structs.SyncSt
syncingResponseJson := &structs.SyncStatusResponse{}
if err := c.jsonRestHandler.Get(ctx, endpoint, syncingResponseJson); err != nil {
if err := c.handler.Get(ctx, endpoint, syncingResponseJson); err != nil {
return nil, err
}

View File

@@ -20,7 +20,7 @@ func TestGetFork_Nominal(t *testing.T) {
defer ctrl.Finish()
stateForkResponseJson := structs.GetStateForkResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
expected := structs.GetStateForkResponse{
Data: &structs.Fork{
@@ -32,7 +32,7 @@ func TestGetFork_Nominal(t *testing.T) {
ctx := t.Context()
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
forkEndpoint,
&stateForkResponseJson,
@@ -44,7 +44,7 @@ func TestGetFork_Nominal(t *testing.T) {
).Times(1)
validatorClient := beaconApiValidatorClient{
jsonRestHandler: jsonRestHandler,
handler: handler,
}
fork, err := validatorClient.fork(ctx)
@@ -56,11 +56,11 @@ func TestGetFork_Invalid(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
ctx := t.Context()
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
forkEndpoint,
gomock.Any(),
@@ -69,7 +69,7 @@ func TestGetFork_Invalid(t *testing.T) {
).Times(1)
validatorClient := beaconApiValidatorClient{
jsonRestHandler: jsonRestHandler,
handler: handler,
}
_, err := validatorClient.fork(ctx)
@@ -83,7 +83,7 @@ func TestGetHeaders_Nominal(t *testing.T) {
defer ctrl.Finish()
blockHeadersResponseJson := structs.GetBlockHeadersResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
expected := structs.GetBlockHeadersResponse{
Data: []*structs.SignedBeaconBlockHeaderContainer{
@@ -99,7 +99,7 @@ func TestGetHeaders_Nominal(t *testing.T) {
ctx := t.Context()
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
headersEndpoint,
&blockHeadersResponseJson,
@@ -111,7 +111,7 @@ func TestGetHeaders_Nominal(t *testing.T) {
).Times(1)
validatorClient := beaconApiValidatorClient{
jsonRestHandler: jsonRestHandler,
handler: handler,
}
headers, err := validatorClient.headers(ctx)
@@ -123,11 +123,11 @@ func TestGetHeaders_Invalid(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
ctx := t.Context()
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
headersEndpoint,
gomock.Any(),
@@ -136,7 +136,7 @@ func TestGetHeaders_Invalid(t *testing.T) {
).Times(1)
validatorClient := beaconApiValidatorClient{
jsonRestHandler: jsonRestHandler,
handler: handler,
}
_, err := validatorClient.headers(ctx)
@@ -170,8 +170,8 @@ func TestGetLiveness_Nominal(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Post(
gomock.Any(),
livenessEndpoint,
nil,
@@ -184,7 +184,7 @@ func TestGetLiveness_Nominal(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
liveness, err := validatorClient.liveness(ctx, 42, indexes)
require.NoError(t, err)
@@ -197,8 +197,8 @@ func TestGetLiveness_Invalid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Post(
gomock.Any(),
livenessEndpoint,
nil,
@@ -208,7 +208,7 @@ func TestGetLiveness_Invalid(t *testing.T) {
errors.New("custom error"),
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
_, err := validatorClient.liveness(ctx, 42, nil)
require.ErrorContains(t, "custom error", err)
@@ -237,7 +237,7 @@ func TestGetIsSyncing_Nominal(t *testing.T) {
defer ctrl.Finish()
syncingResponseJson := structs.SyncStatusResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
expected := structs.SyncStatusResponse{
Data: &structs.SyncStatusResponseData{
@@ -247,7 +247,7 @@ func TestGetIsSyncing_Nominal(t *testing.T) {
ctx := t.Context()
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
syncingEndpoint,
&syncingResponseJson,
@@ -259,7 +259,7 @@ func TestGetIsSyncing_Nominal(t *testing.T) {
).Times(1)
validatorClient := beaconApiValidatorClient{
jsonRestHandler: jsonRestHandler,
handler: handler,
}
isSyncing, err := validatorClient.isSyncing(ctx)
@@ -274,11 +274,11 @@ func TestGetIsSyncing_Invalid(t *testing.T) {
defer ctrl.Finish()
syncingResponseJson := structs.SyncStatusResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
ctx := t.Context()
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
syncingEndpoint,
&syncingResponseJson,
@@ -287,7 +287,7 @@ func TestGetIsSyncing_Invalid(t *testing.T) {
).Times(1)
validatorClient := beaconApiValidatorClient{
jsonRestHandler: jsonRestHandler,
handler: handler,
}
isSyncing, err := validatorClient.isSyncing(ctx)

View File

@@ -5,6 +5,7 @@ import (
"net/http"
"strconv"
"github.com/OffchainLabs/prysm/v7/api/rest"
"github.com/OffchainLabs/prysm/v7/api/server/structs"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
"github.com/OffchainLabs/prysm/v7/validator/client/iface"
@@ -20,13 +21,13 @@ var (
type beaconApiNodeClient struct {
fallbackClient iface.NodeClient
jsonRestHandler RestHandler
handler rest.Handler
genesisProvider GenesisProvider
}
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 {
if err := c.handler.Get(ctx, "/eth/v1/node/syncing", &syncingResponse); err != nil {
return nil, err
}
@@ -56,7 +57,7 @@ func (c *beaconApiNodeClient) Genesis(ctx context.Context, _ *empty.Empty) (*eth
}
depositContractJson := structs.GetDepositContractResponse{}
if err = c.jsonRestHandler.Get(ctx, "/eth/v1/config/deposit_contract", &depositContractJson); err != nil {
if err = c.handler.Get(ctx, "/eth/v1/config/deposit_contract", &depositContractJson); err != nil {
return nil, err
}
@@ -80,7 +81,7 @@ func (c *beaconApiNodeClient) Genesis(ctx context.Context, _ *empty.Empty) (*eth
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 {
if err := c.handler.Get(ctx, "/eth/v1/node/version", &versionResponse); err != nil {
return nil, err
}
@@ -105,9 +106,9 @@ func (c *beaconApiNodeClient) Peers(ctx context.Context, in *empty.Empty) (*ethp
// IsReady returns true only if the node is fully synced (200 OK).
// A 206 Partial Content response indicates the node is syncing and not ready.
func (c *beaconApiNodeClient) IsReady(ctx context.Context) bool {
statusCode, err := c.jsonRestHandler.GetStatusCode(ctx, "/eth/v1/node/health")
statusCode, err := c.handler.GetStatusCode(ctx, "/eth/v1/node/health")
if err != nil {
log.WithError(err).Error("failed to get health of node")
log.WithError(err).WithField("url", c.handler.Host()).Error("failed to get health of node")
return false
}
// Only 200 OK means the node is fully synced and ready.
@@ -115,11 +116,11 @@ func (c *beaconApiNodeClient) IsReady(ctx context.Context) bool {
return statusCode == http.StatusOK
}
func NewNodeClientWithFallback(jsonRestHandler RestHandler, fallbackClient iface.NodeClient) iface.NodeClient {
func NewNodeClientWithFallback(handler rest.Handler, fallbackClient iface.NodeClient) iface.NodeClient {
b := &beaconApiNodeClient{
jsonRestHandler: jsonRestHandler,
handler: handler,
fallbackClient: fallbackClient,
genesisProvider: &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler},
genesisProvider: &beaconApiGenesisProvider{handler: handler},
}
return b
}

View File

@@ -120,10 +120,10 @@ func TestGetGenesis(t *testing.T) {
)
depositContractJson := structs.GetDepositContractResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
if testCase.queriesDepositContract {
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
"/eth/v1/config/deposit_contract",
&depositContractJson,
@@ -137,7 +137,7 @@ func TestGetGenesis(t *testing.T) {
nodeClient := &beaconApiNodeClient{
genesisProvider: genesisProvider,
jsonRestHandler: jsonRestHandler,
handler: handler,
}
response, err := nodeClient.Genesis(ctx, &emptypb.Empty{})
@@ -201,8 +201,8 @@ func TestGetSyncStatus(t *testing.T) {
ctx := t.Context()
syncingResponse := structs.SyncStatusResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
syncingEndpoint,
&syncingResponse,
@@ -213,7 +213,7 @@ func TestGetSyncStatus(t *testing.T) {
testCase.restEndpointResponse,
)
nodeClient := &beaconApiNodeClient{jsonRestHandler: jsonRestHandler}
nodeClient := &beaconApiNodeClient{handler: handler}
syncStatus, err := nodeClient.SyncStatus(ctx, &emptypb.Empty{})
if testCase.expectedResponse == nil {
@@ -265,8 +265,8 @@ func TestGetVersion(t *testing.T) {
ctx := t.Context()
var versionResponse structs.GetVersionResponse
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
versionEndpoint,
&versionResponse,
@@ -277,7 +277,7 @@ func TestGetVersion(t *testing.T) {
testCase.restEndpointResponse,
)
nodeClient := &beaconApiNodeClient{jsonRestHandler: jsonRestHandler}
nodeClient := &beaconApiNodeClient{handler: handler}
version, err := nodeClient.Version(ctx, &emptypb.Empty{})
if testCase.expectedResponse == nil {
@@ -331,13 +331,14 @@ func TestIsReady(t *testing.T) {
defer ctrl.Finish()
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetStatusCode(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetStatusCode(
gomock.Any(),
healthEndpoint,
).Return(tc.statusCode, tc.err)
handler.EXPECT().Host().Return("http://localhost:3500").AnyTimes()
nodeClient := &beaconApiNodeClient{jsonRestHandler: jsonRestHandler}
nodeClient := &beaconApiNodeClient{handler: handler}
result := nodeClient.IsReady(ctx)
assert.Equal(t, tc.expectedResult, result)

View File

@@ -6,6 +6,8 @@ import (
"time"
"github.com/OffchainLabs/prysm/v7/api/client/event"
"github.com/OffchainLabs/prysm/v7/api/fallback"
"github.com/OffchainLabs/prysm/v7/api/rest"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
"github.com/OffchainLabs/prysm/v7/monitoring/tracing/trace"
@@ -22,22 +24,28 @@ type beaconApiValidatorClient struct {
genesisProvider GenesisProvider
dutiesProvider dutiesProvider
stateValidatorsProvider StateValidatorsProvider
jsonRestHandler RestHandler
restProvider rest.RestConnectionProvider
handler rest.Handler
nodeClient *beaconApiNodeClient
beaconBlockConverter BeaconBlockConverter
prysmChainClient iface.PrysmChainClient
isEventStreamRunning bool
}
func NewBeaconApiValidatorClient(jsonRestHandler RestHandler, opts ...ValidatorClientOpt) iface.ValidatorClient {
func NewBeaconApiValidatorClient(provider rest.RestConnectionProvider, opts ...ValidatorClientOpt) iface.ValidatorClient {
handler := provider.Handler()
nc := &beaconApiNodeClient{handler: handler}
c := &beaconApiValidatorClient{
genesisProvider: &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler},
dutiesProvider: beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler},
stateValidatorsProvider: beaconApiStateValidatorsProvider{jsonRestHandler: jsonRestHandler},
jsonRestHandler: jsonRestHandler,
genesisProvider: &beaconApiGenesisProvider{handler: handler},
dutiesProvider: beaconApiDutiesProvider{handler: handler},
stateValidatorsProvider: beaconApiStateValidatorsProvider{handler: handler},
restProvider: provider,
handler: handler,
nodeClient: nc,
beaconBlockConverter: beaconApiBeaconBlockConverter{},
prysmChainClient: prysmChainClient{
nodeClient: &beaconApiNodeClient{jsonRestHandler: jsonRestHandler},
jsonRestHandler: jsonRestHandler,
nodeClient: nc,
handler: handler,
},
isEventStreamRunning: false,
}
@@ -279,8 +287,8 @@ func (c *beaconApiValidatorClient) WaitForChainStart(ctx context.Context, _ *emp
}
func (c *beaconApiValidatorClient) StartEventStream(ctx context.Context, topics []string, eventsChannel chan<- *event.Event) {
client := &http.Client{} // event stream should not be subject to the same settings as other api calls, so we won't use c.jsonRestHandler.HttpClient()
eventStream, err := event.NewEventStream(ctx, client, c.jsonRestHandler.Host(), topics)
client := &http.Client{} // event stream should not be subject to the same settings as other api calls
eventStream, err := event.NewEventStream(ctx, client, c.handler.Host(), topics)
if err != nil {
eventsChannel <- &event.Event{
EventType: event.EventError,
@@ -328,9 +336,9 @@ func wrapInMetrics[Resp any](action string, f func() (Resp, error)) (Resp, error
}
func (c *beaconApiValidatorClient) Host() string {
return c.jsonRestHandler.Host()
return c.handler.Host()
}
func (c *beaconApiValidatorClient) SetHost(host string) {
c.jsonRestHandler.SetHost(host)
func (c *beaconApiValidatorClient) EnsureReady(ctx context.Context) bool {
return fallback.EnsureReady(ctx, c.restProvider, c.nodeClient)
}

View File

@@ -31,9 +31,9 @@ func TestBeaconApiValidatorClient_GetAttestationDataValid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
produceAttestationDataResponseJson := structs.GetAttestationDataResponse{}
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
fmt.Sprintf("/eth/v1/validator/attestation_data?committee_index=%d&slot=%d", committeeIndex, slot),
&produceAttestationDataResponseJson,
@@ -44,7 +44,7 @@ func TestBeaconApiValidatorClient_GetAttestationDataValid(t *testing.T) {
generateValidAttestation(uint64(slot), uint64(committeeIndex)),
).Times(2)
validatorClient := beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := beaconApiValidatorClient{handler: handler}
expectedResp, expectedErr := validatorClient.attestationData(ctx, slot, committeeIndex)
resp, err := validatorClient.AttestationData(
@@ -65,9 +65,9 @@ func TestBeaconApiValidatorClient_GetAttestationDataError(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
produceAttestationDataResponseJson := structs.GetAttestationDataResponse{}
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
fmt.Sprintf("/eth/v1/validator/attestation_data?committee_index=%d&slot=%d", committeeIndex, slot),
&produceAttestationDataResponseJson,
@@ -78,7 +78,7 @@ func TestBeaconApiValidatorClient_GetAttestationDataError(t *testing.T) {
generateValidAttestation(uint64(slot), uint64(committeeIndex)),
).Times(2)
validatorClient := beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := beaconApiValidatorClient{handler: handler}
expectedResp, expectedErr := validatorClient.attestationData(ctx, slot, committeeIndex)
resp, err := validatorClient.AttestationData(
@@ -139,8 +139,8 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockValid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().PostSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().PostSSZ(
gomock.Any(),
"/eth/v2/beacon/blocks",
gomock.Any(),
@@ -149,7 +149,7 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockValid(t *testing.T) {
nil, nil, nil,
).Times(1)
validatorClient := beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := beaconApiValidatorClient{handler: handler}
expectedResp, expectedErr := validatorClient.proposeBeaconBlock(
ctx,
&ethpb.GenericSignedBeaconBlock{
@@ -166,8 +166,8 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockError_ThenPass(t *testing.T)
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().PostSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().PostSSZ(
gomock.Any(),
"/eth/v2/beacon/blocks",
gomock.Any(),
@@ -179,7 +179,7 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockError_ThenPass(t *testing.T)
},
).Times(1)
jsonRestHandler.EXPECT().Post(
handler.EXPECT().Post(
gomock.Any(),
"/eth/v2/beacon/blocks",
gomock.Any(),
@@ -189,7 +189,7 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockError_ThenPass(t *testing.T)
nil,
).Times(1)
validatorClient := beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := beaconApiValidatorClient{handler: handler}
expectedResp, expectedErr := validatorClient.proposeBeaconBlock(
ctx,
&ethpb.GenericSignedBeaconBlock{
@@ -308,10 +308,10 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockAllTypes(t *testing.T) {
defer ctrl.Finish()
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
if !tt.wantErr {
jsonRestHandler.EXPECT().PostSSZ(
handler.EXPECT().PostSSZ(
gomock.Any(),
tt.expectedPath,
gomock.Any(),
@@ -319,7 +319,7 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockAllTypes(t *testing.T) {
).Return(nil, nil, nil).Times(1)
}
validatorClient := beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := beaconApiValidatorClient{handler: handler}
resp, err := validatorClient.proposeBeaconBlock(ctx, tt.block)
if tt.wantErr {
@@ -366,9 +366,9 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockHTTPErrors(t *testing.T) {
defer ctrl.Finish()
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().PostSSZ(
handler.EXPECT().PostSSZ(
gomock.Any(),
"/eth/v2/beacon/blocks",
gomock.Any(),
@@ -377,7 +377,7 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockHTTPErrors(t *testing.T) {
if tt.expectJSON {
// When SSZ fails, it falls back to JSON
jsonRestHandler.EXPECT().Post(
handler.EXPECT().Post(
gomock.Any(),
"/eth/v2/beacon/blocks",
gomock.Any(),
@@ -386,7 +386,7 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockHTTPErrors(t *testing.T) {
).Return(tt.sszError).Times(1)
}
validatorClient := beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := beaconApiValidatorClient{handler: handler}
_, err := validatorClient.proposeBeaconBlock(
ctx,
&ethpb.GenericSignedBeaconBlock{
@@ -507,10 +507,10 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockJSONFallback(t *testing.T) {
defer ctrl.Finish()
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
// SSZ call fails with 406 to trigger JSON fallback
jsonRestHandler.EXPECT().PostSSZ(
handler.EXPECT().PostSSZ(
gomock.Any(),
tt.expectedPath,
gomock.Any(),
@@ -521,7 +521,7 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockJSONFallback(t *testing.T) {
}).Times(1)
// JSON fallback
jsonRestHandler.EXPECT().Post(
handler.EXPECT().Post(
gomock.Any(),
tt.expectedPath,
gomock.Any(),
@@ -529,7 +529,7 @@ func TestBeaconApiValidatorClient_ProposeBeaconBlockJSONFallback(t *testing.T) {
gomock.Any(),
).Return(tt.jsonError).Times(1)
validatorClient := beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := beaconApiValidatorClient{handler: handler}
resp, err := validatorClient.proposeBeaconBlock(ctx, tt.block)
if tt.wantErr {
@@ -547,29 +547,12 @@ func TestBeaconApiValidatorClient_Host(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
hosts := []string{"http://localhost:8080", "http://localhost:8081"}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().SetHost(
hosts[0],
).Times(1)
jsonRestHandler.EXPECT().Host().Return(
hosts[0],
).Times(1)
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Host().Return("http://localhost:8080").Times(1)
validatorClient := beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient.SetHost(hosts[0])
validatorClient := beaconApiValidatorClient{handler: handler}
host := validatorClient.Host()
require.Equal(t, hosts[0], host)
jsonRestHandler.EXPECT().SetHost(
hosts[1],
).Times(1)
jsonRestHandler.EXPECT().Host().Return(
hosts[1],
).Times(1)
validatorClient.SetHost(hosts[1])
host = validatorClient.Host()
require.Equal(t, hosts[1], host)
require.Equal(t, "http://localhost:8080", host)
}
// Helper functions for generating test blocks for newer consensus versions

View File

@@ -20,7 +20,7 @@ func (c *beaconApiValidatorClient) aggregatedSelection(ctx context.Context, sele
}
var resp aggregatedSelectionResponse
err = c.jsonRestHandler.Post(ctx, "/eth/v1/validator/beacon_committee_selections", nil, bytes.NewBuffer(body), &resp)
err = c.handler.Post(ctx, "/eth/v1/validator/beacon_committee_selections", nil, bytes.NewBuffer(body), &resp)
if err != nil {
return nil, errors.Wrap(err, "error calling post endpoint")
}

View File

@@ -89,13 +89,13 @@ func TestGetAggregatedSelections(t *testing.T) {
for _, test := range testcases {
t.Run(test.name, func(t *testing.T) {
ctrl := gomock.NewController(t)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
reqBody, err := json.Marshal(test.req)
require.NoError(t, err)
ctx := t.Context()
jsonRestHandler.EXPECT().Post(
handler.EXPECT().Post(
gomock.Any(),
"/eth/v1/validator/beacon_committee_selections",
nil,
@@ -108,7 +108,7 @@ func TestGetAggregatedSelections(t *testing.T) {
test.endpointError,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
res, err := validatorClient.AggregatedSelections(ctx, test.req)
if test.expectedErrorMessage != "" {
require.ErrorContains(t, test.expectedErrorMessage, err)

View File

@@ -288,12 +288,12 @@ func TestCheckDoppelGanger_Nominal(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
if testCase.getSyncingOutput != nil {
syncingResponseJson := structs.SyncStatusResponse{}
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
syncingEndpoint,
&syncingResponseJson,
@@ -308,7 +308,7 @@ func TestCheckDoppelGanger_Nominal(t *testing.T) {
if testCase.getForkOutput != nil {
stateForkResponseJson := structs.GetStateForkResponse{}
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
forkEndpoint,
&stateForkResponseJson,
@@ -323,7 +323,7 @@ func TestCheckDoppelGanger_Nominal(t *testing.T) {
if testCase.getHeadersOutput != nil {
blockHeadersResponseJson := structs.GetBlockHeadersResponse{}
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
headersEndpoint,
&blockHeadersResponseJson,
@@ -342,7 +342,7 @@ func TestCheckDoppelGanger_Nominal(t *testing.T) {
marshalledIndexes, err := json.Marshal(iface.inputStringIndexes)
require.NoError(t, err)
jsonRestHandler.EXPECT().Post(
handler.EXPECT().Post(
gomock.Any(),
iface.inputUrl,
nil,
@@ -372,7 +372,7 @@ func TestCheckDoppelGanger_Nominal(t *testing.T) {
}
validatorClient := beaconApiValidatorClient{
jsonRestHandler: jsonRestHandler,
handler: handler,
stateValidatorsProvider: stateValidatorsProvider,
}
@@ -722,12 +722,12 @@ func TestCheckDoppelGanger_Errors(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
if testCase.getSyncingOutput != nil {
syncingResponseJson := structs.SyncStatusResponse{}
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
syncingEndpoint,
&syncingResponseJson,
@@ -742,7 +742,7 @@ func TestCheckDoppelGanger_Errors(t *testing.T) {
if testCase.getForkOutput != nil {
stateForkResponseJson := structs.GetStateForkResponse{}
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
forkEndpoint,
&stateForkResponseJson,
@@ -757,7 +757,7 @@ func TestCheckDoppelGanger_Errors(t *testing.T) {
if testCase.getHeadersOutput != nil {
blockHeadersResponseJson := structs.GetBlockHeadersResponse{}
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
headersEndpoint,
&blockHeadersResponseJson,
@@ -790,7 +790,7 @@ func TestCheckDoppelGanger_Errors(t *testing.T) {
marshalledIndexes, err := json.Marshal(iface.inputStringIndexes)
require.NoError(t, err)
jsonRestHandler.EXPECT().Post(
handler.EXPECT().Post(
gomock.Any(),
iface.inputUrl,
nil,
@@ -806,7 +806,7 @@ func TestCheckDoppelGanger_Errors(t *testing.T) {
}
validatorClient := beaconApiValidatorClient{
jsonRestHandler: jsonRestHandler,
handler: handler,
stateValidatorsProvider: stateValidatorsProvider,
}

View File

@@ -9,6 +9,7 @@ import (
"strconv"
"github.com/OffchainLabs/prysm/v7/api/apiutil"
"github.com/OffchainLabs/prysm/v7/api/rest"
"github.com/OffchainLabs/prysm/v7/api/server/structs"
"github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
@@ -27,7 +28,7 @@ type dutiesProvider interface {
}
type beaconApiDutiesProvider struct {
jsonRestHandler RestHandler
handler rest.Handler
}
type attesterDuty struct {
@@ -278,7 +279,7 @@ func (c beaconApiDutiesProvider) Committees(ctx context.Context, epoch primitive
committeesRequest := apiutil.BuildURL("/eth/v1/beacon/states/head/committees", committeeParams)
var stateCommittees structs.GetCommitteesResponse
if err := c.jsonRestHandler.Get(ctx, committeesRequest, &stateCommittees); err != nil {
if err := c.handler.Get(ctx, committeesRequest, &stateCommittees); err != nil {
return nil, err
}
@@ -308,7 +309,7 @@ func (c beaconApiDutiesProvider) AttesterDuties(ctx context.Context, epoch primi
}
attesterDuties := &structs.GetAttesterDutiesResponse{}
if err = c.jsonRestHandler.Post(
if err = c.handler.Post(
ctx,
fmt.Sprintf("/eth/v1/validator/duties/attester/%d", epoch),
nil,
@@ -330,7 +331,7 @@ func (c beaconApiDutiesProvider) AttesterDuties(ctx context.Context, epoch primi
// ProposerDuties retrieves the proposer duties for the given epoch
func (c beaconApiDutiesProvider) ProposerDuties(ctx context.Context, epoch primitives.Epoch) (*structs.GetProposerDutiesResponse, error) {
proposerDuties := &structs.GetProposerDutiesResponse{}
if err := c.jsonRestHandler.Get(ctx, fmt.Sprintf("/eth/v1/validator/duties/proposer/%d", epoch), proposerDuties); err != nil {
if err := c.handler.Get(ctx, fmt.Sprintf("/eth/v1/validator/duties/proposer/%d", epoch), proposerDuties); err != nil {
return nil, err
}
@@ -360,7 +361,7 @@ func (c beaconApiDutiesProvider) SyncDuties(ctx context.Context, epoch primitive
}
syncDuties := structs.GetSyncCommitteeDutiesResponse{}
if err = c.jsonRestHandler.Post(
if err = c.handler.Post(
ctx,
fmt.Sprintf("/eth/v1/validator/duties/sync/%d", epoch),
nil,

View File

@@ -60,8 +60,8 @@ func TestGetAttesterDuties_Valid(t *testing.T) {
ctx := t.Context()
validatorIndices := []primitives.ValidatorIndex{2, 9}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Post(
gomock.Any(),
fmt.Sprintf("%s/%d", getAttesterDutiesTestEndpoint, epoch),
nil,
@@ -74,7 +74,7 @@ func TestGetAttesterDuties_Valid(t *testing.T) {
expectedAttesterDuties,
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
attesterDuties, err := dutiesProvider.AttesterDuties(ctx, epoch, validatorIndices)
require.NoError(t, err)
assert.DeepEqual(t, expectedAttesterDuties.Data, attesterDuties.Data)
@@ -88,8 +88,8 @@ func TestGetAttesterDuties_HttpError(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Post(
gomock.Any(),
fmt.Sprintf("%s/%d", getAttesterDutiesTestEndpoint, epoch),
gomock.Any(),
@@ -99,7 +99,7 @@ func TestGetAttesterDuties_HttpError(t *testing.T) {
errors.New("foo error"),
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
_, err := dutiesProvider.AttesterDuties(ctx, epoch, nil)
assert.ErrorContains(t, "foo error", err)
}
@@ -112,8 +112,8 @@ func TestGetAttesterDuties_NilAttesterDuty(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Post(
gomock.Any(),
fmt.Sprintf("%s/%d", getAttesterDutiesTestEndpoint, epoch),
gomock.Any(),
@@ -128,7 +128,7 @@ func TestGetAttesterDuties_NilAttesterDuty(t *testing.T) {
},
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
_, err := dutiesProvider.AttesterDuties(ctx, epoch, nil)
assert.ErrorContains(t, "attester duty at index `0` is nil", err)
}
@@ -156,8 +156,8 @@ func TestGetProposerDuties_Valid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
&structs.GetProposerDutiesResponse{},
@@ -168,7 +168,7 @@ func TestGetProposerDuties_Valid(t *testing.T) {
expectedProposerDuties,
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
proposerDuties, err := dutiesProvider.ProposerDuties(ctx, epoch)
require.NoError(t, err)
assert.DeepEqual(t, expectedProposerDuties.Data, proposerDuties.Data)
@@ -182,8 +182,8 @@ func TestGetProposerDuties_HttpError(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
gomock.Any(),
@@ -191,7 +191,7 @@ func TestGetProposerDuties_HttpError(t *testing.T) {
errors.New("foo error"),
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
_, err := dutiesProvider.ProposerDuties(ctx, epoch)
assert.ErrorContains(t, "foo error", err)
}
@@ -204,8 +204,8 @@ func TestGetProposerDuties_NilData(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
gomock.Any(),
@@ -218,7 +218,7 @@ func TestGetProposerDuties_NilData(t *testing.T) {
},
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
_, err := dutiesProvider.ProposerDuties(ctx, epoch)
assert.ErrorContains(t, "proposer duties data is nil", err)
}
@@ -231,8 +231,8 @@ func TestGetProposerDuties_NilProposerDuty(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
fmt.Sprintf("%s/%d", getProposerDutiesTestEndpoint, epoch),
gomock.Any(),
@@ -245,7 +245,7 @@ func TestGetProposerDuties_NilProposerDuty(t *testing.T) {
},
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
_, err := dutiesProvider.ProposerDuties(ctx, epoch)
assert.ErrorContains(t, "proposer duty at index `0` is nil", err)
}
@@ -284,8 +284,8 @@ func TestGetSyncDuties_Valid(t *testing.T) {
ctx := t.Context()
validatorIndices := []primitives.ValidatorIndex{2, 6}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Post(
gomock.Any(),
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
nil,
@@ -298,7 +298,7 @@ func TestGetSyncDuties_Valid(t *testing.T) {
expectedSyncDuties,
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
syncDuties, err := dutiesProvider.SyncDuties(ctx, epoch, validatorIndices)
require.NoError(t, err)
assert.DeepEqual(t, expectedSyncDuties.Data, syncDuties)
@@ -312,8 +312,8 @@ func TestGetSyncDuties_HttpError(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Post(
gomock.Any(),
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
gomock.Any(),
@@ -323,7 +323,7 @@ func TestGetSyncDuties_HttpError(t *testing.T) {
errors.New("foo error"),
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
_, err := dutiesProvider.SyncDuties(ctx, epoch, nil)
assert.ErrorContains(t, "foo error", err)
}
@@ -336,8 +336,8 @@ func TestGetSyncDuties_NilData(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Post(
gomock.Any(),
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
gomock.Any(),
@@ -352,7 +352,7 @@ func TestGetSyncDuties_NilData(t *testing.T) {
},
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
_, err := dutiesProvider.SyncDuties(ctx, epoch, nil)
assert.ErrorContains(t, "sync duties data is nil", err)
}
@@ -365,8 +365,8 @@ func TestGetSyncDuties_NilSyncDuty(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Post(
gomock.Any(),
fmt.Sprintf("%s/%d", getSyncDutiesTestEndpoint, epoch),
gomock.Any(),
@@ -381,7 +381,7 @@ func TestGetSyncDuties_NilSyncDuty(t *testing.T) {
},
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
_, err := dutiesProvider.SyncDuties(ctx, epoch, nil)
assert.ErrorContains(t, "sync duty at index `0` is nil", err)
}
@@ -415,8 +415,8 @@ func TestGetCommittees_Valid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
&structs.GetCommitteesResponse{},
@@ -427,7 +427,7 @@ func TestGetCommittees_Valid(t *testing.T) {
expectedCommittees,
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
committees, err := dutiesProvider.Committees(ctx, epoch)
require.NoError(t, err)
assert.DeepEqual(t, expectedCommittees.Data, committees)
@@ -441,8 +441,8 @@ func TestGetCommittees_HttpError(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
gomock.Any(),
@@ -450,7 +450,7 @@ func TestGetCommittees_HttpError(t *testing.T) {
errors.New("foo error"),
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
_, err := dutiesProvider.Committees(ctx, epoch)
assert.ErrorContains(t, "foo error", err)
}
@@ -463,8 +463,8 @@ func TestGetCommittees_NilData(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
gomock.Any(),
@@ -477,7 +477,7 @@ func TestGetCommittees_NilData(t *testing.T) {
},
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
_, err := dutiesProvider.Committees(ctx, epoch)
assert.ErrorContains(t, "state committees data is nil", err)
}
@@ -490,8 +490,8 @@ func TestGetCommittees_NilCommittee(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
fmt.Sprintf("%s?epoch=%d", getCommitteesTestEndpoint, epoch),
gomock.Any(),
@@ -504,7 +504,7 @@ func TestGetCommittees_NilCommittee(t *testing.T) {
},
).Times(1)
dutiesProvider := &beaconApiDutiesProvider{jsonRestHandler: jsonRestHandler}
dutiesProvider := &beaconApiDutiesProvider{handler: handler}
_, err := dutiesProvider.Committees(ctx, epoch)
assert.ErrorContains(t, "committee at index `0` is nil", err)
}

View File

@@ -7,6 +7,7 @@ import (
"sync"
"time"
"github.com/OffchainLabs/prysm/v7/api/rest"
"github.com/OffchainLabs/prysm/v7/api/server/structs"
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
@@ -20,9 +21,9 @@ type GenesisProvider interface {
}
type beaconApiGenesisProvider struct {
jsonRestHandler RestHandler
genesis *structs.Genesis
once sync.Once
handler rest.Handler
genesis *structs.Genesis
once sync.Once
}
func (c *beaconApiValidatorClient) waitForChainStart(ctx context.Context) (*ethpb.ChainStartResponse, error) {
@@ -68,7 +69,7 @@ func (c *beaconApiGenesisProvider) Genesis(ctx context.Context) (*structs.Genesi
genesisJson := &structs.GetGenesisResponse{}
var doErr error
c.once.Do(func() {
if err := c.jsonRestHandler.Get(ctx, "/eth/v1/beacon/genesis", genesisJson); err != nil {
if err := c.handler.Get(ctx, "/eth/v1/beacon/genesis", genesisJson); err != nil {
doErr = err
return
}

View File

@@ -18,8 +18,8 @@ func TestGetGenesis_ValidGenesis(t *testing.T) {
ctx := t.Context()
genesisResponseJson := structs.GetGenesisResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
"/eth/v1/beacon/genesis",
&genesisResponseJson,
@@ -35,7 +35,7 @@ func TestGetGenesis_ValidGenesis(t *testing.T) {
},
).Times(1)
genesisProvider := &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler}
genesisProvider := &beaconApiGenesisProvider{handler: handler}
resp, err := genesisProvider.Genesis(ctx)
assert.NoError(t, err)
require.NotNil(t, resp)
@@ -50,8 +50,8 @@ func TestGetGenesis_NilData(t *testing.T) {
ctx := t.Context()
genesisResponseJson := structs.GetGenesisResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
"/eth/v1/beacon/genesis",
&genesisResponseJson,
@@ -62,7 +62,7 @@ func TestGetGenesis_NilData(t *testing.T) {
structs.GetGenesisResponse{Data: nil},
).Times(1)
genesisProvider := &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler}
genesisProvider := &beaconApiGenesisProvider{handler: handler}
_, err := genesisProvider.Genesis(ctx)
assert.ErrorContains(t, "genesis data is nil", err)
}
@@ -74,8 +74,8 @@ func TestGetGenesis_EndpointCalledOnlyOnce(t *testing.T) {
ctx := t.Context()
genesisResponseJson := structs.GetGenesisResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
"/eth/v1/beacon/genesis",
&genesisResponseJson,
@@ -91,7 +91,7 @@ func TestGetGenesis_EndpointCalledOnlyOnce(t *testing.T) {
},
).Times(1)
genesisProvider := &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler}
genesisProvider := &beaconApiGenesisProvider{handler: handler}
_, err := genesisProvider.Genesis(ctx)
assert.NoError(t, err)
resp, err := genesisProvider.Genesis(ctx)
@@ -108,15 +108,15 @@ func TestGetGenesis_EndpointCanBeCalledAgainAfterError(t *testing.T) {
ctx := t.Context()
genesisResponseJson := structs.GetGenesisResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Get(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().Get(
gomock.Any(),
"/eth/v1/beacon/genesis",
&genesisResponseJson,
).Return(
errors.New("foo"),
).Times(1)
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
"/eth/v1/beacon/genesis",
&genesisResponseJson,
@@ -132,7 +132,7 @@ func TestGetGenesis_EndpointCanBeCalledAgainAfterError(t *testing.T) {
},
).Times(1)
genesisProvider := &beaconApiGenesisProvider{jsonRestHandler: jsonRestHandler}
genesisProvider := &beaconApiGenesisProvider{handler: handler}
_, err := genesisProvider.Genesis(ctx)
require.ErrorContains(t, "foo", err)
resp, err := genesisProvider.Genesis(ctx)

View File

@@ -26,7 +26,7 @@ func (c *beaconApiValidatorClient) beaconBlock(ctx context.Context, slot primiti
queryParams.Add("graffiti", hexutil.Encode(graffiti))
}
queryUrl := apiutil.BuildURL(fmt.Sprintf("/eth/v3/validator/blocks/%d", slot), queryParams)
data, header, err := c.jsonRestHandler.GetSSZ(ctx, queryUrl)
data, header, err := c.handler.GetSSZ(ctx, queryUrl)
if err != nil {
return nil, err
}

View File

@@ -25,8 +25,8 @@ func TestGetBeaconBlock_RequestFailed(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
gomock.Any(),
).Return(
@@ -35,7 +35,7 @@ func TestGetBeaconBlock_RequestFailed(t *testing.T) {
errors.New("foo error"),
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
_, err := validatorClient.beaconBlock(ctx, 1, []byte{1}, []byte{2})
assert.ErrorContains(t, "foo error", err)
}
@@ -149,8 +149,8 @@ func TestGetBeaconBlock_Error(t *testing.T) {
b, err := json.Marshal(resp)
require.NoError(t, err)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
gomock.Any(),
).Return(
@@ -159,7 +159,7 @@ func TestGetBeaconBlock_Error(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
_, err = validatorClient.beaconBlock(ctx, 1, []byte{1}, []byte{2})
assert.ErrorContains(t, testCase.expectedErrorMessage, err)
})
@@ -185,8 +185,8 @@ func TestGetBeaconBlock_Phase0Valid(t *testing.T) {
Data: bytes,
})
require.NoError(t, err)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -195,7 +195,7 @@ func TestGetBeaconBlock_Phase0Valid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -224,8 +224,8 @@ func TestGetBeaconBlock_SSZ_BellatrixValid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -238,7 +238,7 @@ func TestGetBeaconBlock_SSZ_BellatrixValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -266,8 +266,8 @@ func TestGetBeaconBlock_SSZ_BlindedBellatrixValid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -280,7 +280,7 @@ func TestGetBeaconBlock_SSZ_BlindedBellatrixValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -308,8 +308,8 @@ func TestGetBeaconBlock_SSZ_CapellaValid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -322,7 +322,7 @@ func TestGetBeaconBlock_SSZ_CapellaValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -350,8 +350,8 @@ func TestGetBeaconBlock_SSZ_BlindedCapellaValid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -364,7 +364,7 @@ func TestGetBeaconBlock_SSZ_BlindedCapellaValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -392,8 +392,8 @@ func TestGetBeaconBlock_SSZ_DenebValid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -406,7 +406,7 @@ func TestGetBeaconBlock_SSZ_DenebValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -434,8 +434,8 @@ func TestGetBeaconBlock_SSZ_BlindedDenebValid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -448,7 +448,7 @@ func TestGetBeaconBlock_SSZ_BlindedDenebValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -476,8 +476,8 @@ func TestGetBeaconBlock_SSZ_ElectraValid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -490,7 +490,7 @@ func TestGetBeaconBlock_SSZ_ElectraValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -518,8 +518,8 @@ func TestGetBeaconBlock_SSZ_BlindedElectraValid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -532,7 +532,7 @@ func TestGetBeaconBlock_SSZ_BlindedElectraValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -556,8 +556,8 @@ func TestGetBeaconBlock_SSZ_UnsupportedVersion(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -570,7 +570,7 @@ func TestGetBeaconBlock_SSZ_UnsupportedVersion(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
_, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
assert.ErrorContains(t, "version name doesn't map to a known value in the enum", err)
}
@@ -589,8 +589,8 @@ func TestGetBeaconBlock_SSZ_InvalidBlindedHeader(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -603,7 +603,7 @@ func TestGetBeaconBlock_SSZ_InvalidBlindedHeader(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
_, err = validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
assert.ErrorContains(t, "strconv.ParseBool: parsing \"invalid\": invalid syntax", err)
}
@@ -622,8 +622,8 @@ func TestGetBeaconBlock_SSZ_InvalidVersionHeader(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -636,7 +636,7 @@ func TestGetBeaconBlock_SSZ_InvalidVersionHeader(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
_, err = validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
assert.ErrorContains(t, "unsupported header version invalid", err)
}
@@ -651,8 +651,8 @@ func TestGetBeaconBlock_SSZ_GetSSZError(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -661,7 +661,7 @@ func TestGetBeaconBlock_SSZ_GetSSZError(t *testing.T) {
errors.New("get ssz error"),
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
_, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
assert.ErrorContains(t, "get ssz error", err)
}
@@ -680,8 +680,8 @@ func TestGetBeaconBlock_SSZ_Phase0Valid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -694,7 +694,7 @@ func TestGetBeaconBlock_SSZ_Phase0Valid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -722,8 +722,8 @@ func TestGetBeaconBlock_SSZ_AltairValid(t *testing.T) {
ctx := t.Context()
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -736,7 +736,7 @@ func TestGetBeaconBlock_SSZ_AltairValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -770,8 +770,8 @@ func TestGetBeaconBlock_AltairValid(t *testing.T) {
Data: bytes,
})
require.NoError(t, err)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -780,7 +780,7 @@ func TestGetBeaconBlock_AltairValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -814,8 +814,8 @@ func TestGetBeaconBlock_BellatrixValid(t *testing.T) {
Data: bytes,
})
require.NoError(t, err)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -824,7 +824,7 @@ func TestGetBeaconBlock_BellatrixValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -859,8 +859,8 @@ func TestGetBeaconBlock_BlindedBellatrixValid(t *testing.T) {
Data: bytes,
})
require.NoError(t, err)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -869,7 +869,7 @@ func TestGetBeaconBlock_BlindedBellatrixValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -904,8 +904,8 @@ func TestGetBeaconBlock_CapellaValid(t *testing.T) {
Data: bytes,
})
require.NoError(t, err)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -914,7 +914,7 @@ func TestGetBeaconBlock_CapellaValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -949,8 +949,8 @@ func TestGetBeaconBlock_BlindedCapellaValid(t *testing.T) {
Data: bytes,
})
require.NoError(t, err)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -959,7 +959,7 @@ func TestGetBeaconBlock_BlindedCapellaValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -994,8 +994,8 @@ func TestGetBeaconBlock_DenebValid(t *testing.T) {
Data: bytes,
})
require.NoError(t, err)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -1004,7 +1004,7 @@ func TestGetBeaconBlock_DenebValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -1039,8 +1039,8 @@ func TestGetBeaconBlock_BlindedDenebValid(t *testing.T) {
Data: bytes,
})
require.NoError(t, err)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -1049,7 +1049,7 @@ func TestGetBeaconBlock_BlindedDenebValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -1084,8 +1084,8 @@ func TestGetBeaconBlock_ElectraValid(t *testing.T) {
Data: bytes,
})
require.NoError(t, err)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -1094,7 +1094,7 @@ func TestGetBeaconBlock_ElectraValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)
@@ -1129,8 +1129,8 @@ func TestGetBeaconBlock_BlindedElectraValid(t *testing.T) {
Data: bytes,
})
require.NoError(t, err)
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().GetSSZ(
handler := mock.NewMockJsonRestHandler(ctrl)
handler.EXPECT().GetSSZ(
gomock.Any(),
fmt.Sprintf("/eth/v3/validator/blocks/%d?graffiti=%s&randao_reveal=%s", slot, hexutil.Encode(graffiti), hexutil.Encode(randaoReveal)),
).Return(
@@ -1139,7 +1139,7 @@ func TestGetBeaconBlock_BlindedElectraValid(t *testing.T) {
nil,
).Times(1)
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
validatorClient := &beaconApiValidatorClient{handler: handler}
beaconBlock, err := validatorClient.beaconBlock(ctx, slot, randaoReveal, graffiti)
require.NoError(t, err)

View File

@@ -41,9 +41,9 @@ func TestIndex_Nominal(t *testing.T) {
ctx := t.Context()
stateValidatorsResponseJson := structs.GetValidatorsResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler.EXPECT().Post(
gomock.Any(),
"/eth/v1/beacon/states/head/validators",
nil,
@@ -68,7 +68,7 @@ func TestIndex_Nominal(t *testing.T) {
validatorClient := beaconApiValidatorClient{
stateValidatorsProvider: beaconApiStateValidatorsProvider{
jsonRestHandler: jsonRestHandler,
handler: handler,
},
}
@@ -91,9 +91,9 @@ func TestIndex_UnexistingValidator(t *testing.T) {
ctx := t.Context()
stateValidatorsResponseJson := structs.GetValidatorsResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler.EXPECT().Post(
gomock.Any(),
"/eth/v1/beacon/states/head/validators",
nil,
@@ -110,7 +110,7 @@ func TestIndex_UnexistingValidator(t *testing.T) {
validatorClient := beaconApiValidatorClient{
stateValidatorsProvider: beaconApiStateValidatorsProvider{
jsonRestHandler: jsonRestHandler,
handler: handler,
},
}
@@ -133,9 +133,9 @@ func TestIndex_BadIndexError(t *testing.T) {
ctx := t.Context()
stateValidatorsResponseJson := structs.GetValidatorsResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler.EXPECT().Post(
gomock.Any(),
"/eth/v1/beacon/states/head/validators",
nil,
@@ -160,7 +160,7 @@ func TestIndex_BadIndexError(t *testing.T) {
validatorClient := beaconApiValidatorClient{
stateValidatorsProvider: beaconApiStateValidatorsProvider{
jsonRestHandler: jsonRestHandler,
handler: handler,
},
}
@@ -182,9 +182,9 @@ func TestIndex_JsonResponseError(t *testing.T) {
ctx := t.Context()
stateValidatorsResponseJson := structs.GetValidatorsResponse{}
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
handler := mock.NewMockJsonRestHandler(ctrl)
jsonRestHandler.EXPECT().Post(
handler.EXPECT().Post(
gomock.Any(),
"/eth/v1/beacon/states/head/validators",
nil,
@@ -207,7 +207,7 @@ func TestIndex_JsonResponseError(t *testing.T) {
queryParams.Add("status", st)
}
jsonRestHandler.EXPECT().Get(
handler.EXPECT().Get(
gomock.Any(),
apiutil.BuildURL("/eth/v1/beacon/states/head/validators", queryParams),
&stateValidatorsResponseJson,
@@ -217,7 +217,7 @@ func TestIndex_JsonResponseError(t *testing.T) {
validatorClient := beaconApiValidatorClient{
stateValidatorsProvider: beaconApiStateValidatorsProvider{
jsonRestHandler: jsonRestHandler,
handler: handler,
},
}

View File

@@ -1,9 +1,9 @@
// Code generated by MockGen. DO NOT EDIT.
// Source: validator/client/beacon-api/rest_handler_client.go
// Source: api/rest/rest_handler.go
//
// Generated by this command:
//
// mockgen -package=mock -source=validator/client/beacon-api/rest_handler_client.go -destination=validator/client/beacon-api/mock/json_rest_handler_mock.go RestHandler
// mockgen -package=mock -source=api/rest/rest_handler.go -destination=validator/client/beacon-api/mock/json_rest_handler_mock.go Handler
//
// Package mock is a generated GoMock package.
@@ -19,36 +19,39 @@ import (
)
// Backward compatibility aliases for the renamed mock type.
type MockJsonRestHandler = MockRestHandler
type MockJsonRestHandlerMockRecorder = MockRestHandlerMockRecorder
type MockJsonRestHandler = MockHandler
type MockJsonRestHandlerMockRecorder = MockHandlerMockRecorder
type MockRestHandler = MockHandler
type MockRestHandlerMockRecorder = MockHandlerMockRecorder
var NewMockJsonRestHandler = NewMockRestHandler
var NewMockJsonRestHandler = NewMockHandler
var NewMockRestHandler = NewMockHandler
// MockRestHandler is a mock of RestHandler interface.
type MockRestHandler struct {
// MockHandler is a mock of Handler interface.
type MockHandler struct {
ctrl *gomock.Controller
recorder *MockRestHandlerMockRecorder
recorder *MockHandlerMockRecorder
}
// MockRestHandlerMockRecorder is the mock recorder for MockRestHandler.
type MockRestHandlerMockRecorder struct {
mock *MockRestHandler
// MockHandlerMockRecorder is the mock recorder for MockHandler.
type MockHandlerMockRecorder struct {
mock *MockHandler
}
// NewMockRestHandler creates a new mock instance.
func NewMockRestHandler(ctrl *gomock.Controller) *MockRestHandler {
mock := &MockRestHandler{ctrl: ctrl}
mock.recorder = &MockRestHandlerMockRecorder{mock}
// NewMockHandler creates a new mock instance.
func NewMockHandler(ctrl *gomock.Controller) *MockHandler {
mock := &MockHandler{ctrl: ctrl}
mock.recorder = &MockHandlerMockRecorder{mock}
return mock
}
// EXPECT returns an object that allows the caller to indicate expected use.
func (m *MockRestHandler) EXPECT() *MockRestHandlerMockRecorder {
func (m *MockHandler) EXPECT() *MockHandlerMockRecorder {
return m.recorder
}
// Get mocks base method.
func (m *MockRestHandler) Get(ctx context.Context, endpoint string, resp any) error {
func (m *MockHandler) Get(ctx context.Context, endpoint string, resp any) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Get", ctx, endpoint, resp)
ret0, _ := ret[0].(error)
@@ -56,13 +59,13 @@ func (m *MockRestHandler) Get(ctx context.Context, endpoint string, resp any) er
}
// Get indicates an expected call of Get.
func (mr *MockRestHandlerMockRecorder) Get(ctx, endpoint, resp any) *gomock.Call {
func (mr *MockHandlerMockRecorder) Get(ctx, endpoint, resp any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockRestHandler)(nil).Get), ctx, endpoint, resp)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockHandler)(nil).Get), ctx, endpoint, resp)
}
// GetSSZ mocks base method.
func (m *MockRestHandler) GetSSZ(ctx context.Context, endpoint string) ([]byte, http.Header, error) {
func (m *MockHandler) GetSSZ(ctx context.Context, endpoint string) ([]byte, http.Header, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetSSZ", ctx, endpoint)
ret0, _ := ret[0].([]byte)
@@ -72,13 +75,13 @@ func (m *MockRestHandler) GetSSZ(ctx context.Context, endpoint string) ([]byte,
}
// GetSSZ indicates an expected call of GetSSZ.
func (mr *MockRestHandlerMockRecorder) GetSSZ(ctx, endpoint any) *gomock.Call {
func (mr *MockHandlerMockRecorder) GetSSZ(ctx, endpoint any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSSZ", reflect.TypeOf((*MockRestHandler)(nil).GetSSZ), ctx, endpoint)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetSSZ", reflect.TypeOf((*MockHandler)(nil).GetSSZ), ctx, endpoint)
}
// GetStatusCode mocks base method.
func (m *MockRestHandler) GetStatusCode(ctx context.Context, endpoint string) (int, error) {
func (m *MockHandler) GetStatusCode(ctx context.Context, endpoint string) (int, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "GetStatusCode", ctx, endpoint)
ret0, _ := ret[0].(int)
@@ -87,13 +90,13 @@ func (m *MockRestHandler) GetStatusCode(ctx context.Context, endpoint string) (i
}
// GetStatusCode indicates an expected call of GetStatusCode.
func (mr *MockRestHandlerMockRecorder) GetStatusCode(ctx, endpoint any) *gomock.Call {
func (mr *MockHandlerMockRecorder) GetStatusCode(ctx, endpoint any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStatusCode", reflect.TypeOf((*MockRestHandler)(nil).GetStatusCode), ctx, endpoint)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetStatusCode", reflect.TypeOf((*MockHandler)(nil).GetStatusCode), ctx, endpoint)
}
// Host mocks base method.
func (m *MockRestHandler) Host() string {
func (m *MockHandler) Host() string {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Host")
ret0, _ := ret[0].(string)
@@ -101,27 +104,13 @@ func (m *MockRestHandler) Host() string {
}
// Host indicates an expected call of Host.
func (mr *MockRestHandlerMockRecorder) Host() *gomock.Call {
func (mr *MockHandlerMockRecorder) Host() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Host", reflect.TypeOf((*MockRestHandler)(nil).Host))
}
// HttpClient mocks base method.
func (m *MockRestHandler) HttpClient() *http.Client {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "HttpClient")
ret0, _ := ret[0].(*http.Client)
return ret0
}
// HttpClient indicates an expected call of HttpClient.
func (mr *MockRestHandlerMockRecorder) HttpClient() *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "HttpClient", reflect.TypeOf((*MockRestHandler)(nil).HttpClient))
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Host", reflect.TypeOf((*MockHandler)(nil).Host))
}
// Post mocks base method.
func (m *MockRestHandler) Post(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer, resp any) error {
func (m *MockHandler) Post(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer, resp any) error {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "Post", ctx, endpoint, headers, data, resp)
ret0, _ := ret[0].(error)
@@ -129,13 +118,13 @@ func (m *MockRestHandler) Post(ctx context.Context, endpoint string, headers map
}
// Post indicates an expected call of Post.
func (mr *MockRestHandlerMockRecorder) Post(ctx, endpoint, headers, data, resp any) *gomock.Call {
func (mr *MockHandlerMockRecorder) Post(ctx, endpoint, headers, data, resp any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Post", reflect.TypeOf((*MockRestHandler)(nil).Post), ctx, endpoint, headers, data, resp)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Post", reflect.TypeOf((*MockHandler)(nil).Post), ctx, endpoint, headers, data, resp)
}
// PostSSZ mocks base method.
func (m *MockRestHandler) PostSSZ(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer) ([]byte, http.Header, error) {
func (m *MockHandler) PostSSZ(ctx context.Context, endpoint string, headers map[string]string, data *bytes.Buffer) ([]byte, http.Header, error) {
m.ctrl.T.Helper()
ret := m.ctrl.Call(m, "PostSSZ", ctx, endpoint, headers, data)
ret0, _ := ret[0].([]byte)
@@ -145,19 +134,7 @@ func (m *MockRestHandler) PostSSZ(ctx context.Context, endpoint string, headers
}
// PostSSZ indicates an expected call of PostSSZ.
func (mr *MockRestHandlerMockRecorder) PostSSZ(ctx, endpoint, headers, data any) *gomock.Call {
func (mr *MockHandlerMockRecorder) PostSSZ(ctx, endpoint, headers, data any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostSSZ", reflect.TypeOf((*MockRestHandler)(nil).PostSSZ), ctx, endpoint, headers, data)
}
// SetHost mocks base method.
func (m *MockRestHandler) SetHost(host string) {
m.ctrl.T.Helper()
m.ctrl.Call(m, "SetHost", host)
}
// SetHost indicates an expected call of SetHost.
func (mr *MockRestHandlerMockRecorder) SetHost(host any) *gomock.Call {
mr.mock.ctrl.T.Helper()
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SetHost", reflect.TypeOf((*MockRestHandler)(nil).SetHost), host)
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "PostSSZ", reflect.TypeOf((*MockHandler)(nil).PostSSZ), ctx, endpoint, headers, data)
}

Some files were not shown because too many files have changed in this diff Show More