mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-02-04 18:15:12 -05:00
Compare commits
14 Commits
debug-stat
...
fix-genlog
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ecde60c67c | ||
|
|
fab687d96d | ||
|
|
cf94ccbf72 | ||
|
|
75895c1e0b | ||
|
|
d1b9281677 | ||
|
|
641d90990d | ||
|
|
d2fc250f34 | ||
|
|
571c6f39aa | ||
|
|
55fe85c887 | ||
|
|
31f77567dd | ||
|
|
a7fdd11777 | ||
|
|
919bd5d6aa | ||
|
|
0476eeda57 | ||
|
|
1c65c8866a |
@@ -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
|
||||
8
.github/workflows/check-specrefs.yml
vendored
8
.github/workflows/check-specrefs.yml
vendored
@@ -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
|
||||
|
||||
2
.github/workflows/go.yml
vendored
2
.github/workflows/go.yml
vendored
@@ -2,7 +2,7 @@ name: Go
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
branches: [ master, develop ]
|
||||
pull_request:
|
||||
branches: [ '*' ]
|
||||
merge_group:
|
||||
|
||||
@@ -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
19
api/fallback/BUILD.bazel
Normal 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
66
api/fallback/fallback.go
Normal 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
|
||||
}
|
||||
94
api/fallback/fallback_test.go
Normal file
94
api/fallback/fallback_test.go
Normal 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
9
api/fallback/log.go
Normal 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")
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
186
api/grpc/grpc_connection_provider.go
Normal file
186
api/grpc/grpc_connection_provider.go
Normal 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
|
||||
}
|
||||
}
|
||||
207
api/grpc/grpc_connection_provider_test.go
Normal file
207
api/grpc/grpc_connection_provider_test.go
Normal 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
|
||||
}
|
||||
27
api/grpc/mock_grpc_provider.go
Normal file
27
api/grpc/mock_grpc_provider.go
Normal 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
34
api/rest/BUILD.bazel
Normal 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
9
api/rest/log.go
Normal 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")
|
||||
46
api/rest/mock_rest_provider.go
Normal file
46
api/rest/mock_rest_provider.go
Normal 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 }
|
||||
158
api/rest/rest_connection_provider.go
Normal file
158
api/rest/rest_connection_provider.go
Normal 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
|
||||
}
|
||||
80
api/rest/rest_connection_provider_test.go
Normal file
80
api/rest/rest_connection_provider_test.go
Normal 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())
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
@@ -114,17 +128,32 @@ func payloadCommittee(ctx context.Context, st state.ReadOnlyBeaconState, slot pr
|
||||
}
|
||||
|
||||
committeesPerSlot := helpers.SlotCommitteeCount(activeCount)
|
||||
out := make([]primitives.ValidatorIndex, 0, activeCount/uint64(params.BeaconConfig().SlotsPerEpoch))
|
||||
|
||||
for i := primitives.CommitteeIndex(0); i < primitives.CommitteeIndex(committeesPerSlot); i++ {
|
||||
committee, err := helpers.BeaconCommitteeFromState(ctx, st, slot, i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get beacon committee %d", i)
|
||||
selected := make([]primitives.ValidatorIndex, 0, fieldparams.PTCSize)
|
||||
var i uint64
|
||||
for uint64(len(selected)) < fieldparams.PTCSize {
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
|
||||
for committeeIndex := primitives.CommitteeIndex(0); committeeIndex < primitives.CommitteeIndex(committeesPerSlot); committeeIndex++ {
|
||||
if uint64(len(selected)) >= fieldparams.PTCSize {
|
||||
break
|
||||
}
|
||||
|
||||
committee, err := helpers.BeaconCommitteeFromState(ctx, st, slot, committeeIndex)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to get beacon committee %d", committeeIndex)
|
||||
}
|
||||
|
||||
selected, i, err = selectByBalanceFill(ctx, st, committee, seed, selected, i)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to sample beacon committee %d", committeeIndex)
|
||||
}
|
||||
}
|
||||
out = append(out, committee...)
|
||||
}
|
||||
|
||||
return selectByBalance(ctx, st, out, seed, fieldparams.PTCSize)
|
||||
return selected, nil
|
||||
}
|
||||
|
||||
// ptcSeed computes the seed for the payload timeliness committee.
|
||||
@@ -137,56 +166,87 @@ 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
|
||||
func selectByBalance(ctx context.Context, st state.ReadOnlyBeaconState, candidates []primitives.ValidatorIndex, seed [32]byte, count uint64) ([]primitives.ValidatorIndex, error) {
|
||||
if len(candidates) == 0 {
|
||||
return nil, errors.New("no candidates for balance weighted selection")
|
||||
}
|
||||
|
||||
// <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,
|
||||
candidates []primitives.ValidatorIndex,
|
||||
seed [32]byte,
|
||||
selected []primitives.ValidatorIndex,
|
||||
i uint64,
|
||||
) ([]primitives.ValidatorIndex, uint64, error) {
|
||||
hashFunc := hash.CustomSHA256Hasher()
|
||||
// Pre-allocate buffer for hash input: seed (32 bytes) + round counter (8 bytes).
|
||||
var buf [40]byte
|
||||
copy(buf[:], seed[:])
|
||||
maxBalance := params.BeaconConfig().MaxEffectiveBalanceElectra
|
||||
|
||||
selected := make([]primitives.ValidatorIndex, 0, count)
|
||||
total := uint64(len(candidates))
|
||||
for i := uint64(0); uint64(len(selected)) < count; i++ {
|
||||
for _, idx := range candidates {
|
||||
if ctx.Err() != nil {
|
||||
return nil, ctx.Err()
|
||||
return nil, i, ctx.Err()
|
||||
}
|
||||
idx := candidates[i%total]
|
||||
|
||||
ok, err := acceptByBalance(st, idx, buf[:], hashFunc, maxBalance, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, i, err
|
||||
}
|
||||
if ok {
|
||||
selected = append(selected, idx)
|
||||
}
|
||||
if uint64(len(selected)) == fieldparams.PTCSize {
|
||||
break
|
||||
}
|
||||
i++
|
||||
}
|
||||
return selected, nil
|
||||
|
||||
return selected, i, nil
|
||||
}
|
||||
|
||||
// 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)
|
||||
@@ -203,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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -67,7 +67,6 @@ func getSubscriptionStatusFromDB(t *testing.T, db *Store) bool {
|
||||
return subscribed
|
||||
}
|
||||
|
||||
|
||||
func TestUpdateCustodyInfo(t *testing.T) {
|
||||
ctx := t.Context()
|
||||
|
||||
|
||||
@@ -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{
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -48,6 +48,7 @@ go_test(
|
||||
"@com_github_ethereum_go_ethereum//crypto:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//p2p/enode:go_default_library",
|
||||
"@org_golang_google_grpc//:go_default_library",
|
||||
"@org_golang_google_grpc//metadata:go_default_library",
|
||||
"@org_golang_google_grpc//reflection:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/emptypb:go_default_library",
|
||||
"@org_golang_google_protobuf//types/known/timestamppb:go_default_library",
|
||||
|
||||
@@ -35,18 +35,19 @@ import (
|
||||
// providing RPC endpoints for verifying a beacon node's sync status, genesis and
|
||||
// version information, and services the node implements and runs.
|
||||
type Server struct {
|
||||
LogsStreamer logs.Streamer
|
||||
StreamLogsBufferSize int
|
||||
SyncChecker sync.Checker
|
||||
Server *grpc.Server
|
||||
BeaconDB db.ReadOnlyDatabase
|
||||
PeersFetcher p2p.PeersProvider
|
||||
PeerManager p2p.PeerManager
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
GenesisFetcher blockchain.GenesisFetcher
|
||||
POWChainInfoFetcher execution.ChainInfoFetcher
|
||||
BeaconMonitoringHost string
|
||||
BeaconMonitoringPort int
|
||||
LogsStreamer logs.Streamer
|
||||
StreamLogsBufferSize int
|
||||
SyncChecker sync.Checker
|
||||
Server *grpc.Server
|
||||
BeaconDB db.ReadOnlyDatabase
|
||||
PeersFetcher p2p.PeersProvider
|
||||
PeerManager p2p.PeerManager
|
||||
GenesisTimeFetcher blockchain.TimeFetcher
|
||||
GenesisFetcher blockchain.GenesisFetcher
|
||||
POWChainInfoFetcher execution.ChainInfoFetcher
|
||||
BeaconMonitoringHost string
|
||||
BeaconMonitoringPort int
|
||||
OptimisticModeFetcher blockchain.OptimisticModeFetcher
|
||||
}
|
||||
|
||||
// Deprecated: The gRPC API will remain the default and fully supported through v8 (expected in 2026) but will be eventually removed in favor of REST API.
|
||||
@@ -61,21 +62,28 @@ func (ns *Server) GetHealth(ctx context.Context, request *ethpb.HealthRequest) (
|
||||
ctx, cancel := context.WithTimeout(ctx, timeoutDuration)
|
||||
defer cancel() // Important to avoid a context leak
|
||||
|
||||
if ns.SyncChecker.Synced() {
|
||||
// Check optimistic status - validators should not participate when optimistic
|
||||
isOptimistic, err := ns.OptimisticModeFetcher.IsOptimistic(ctx)
|
||||
if err != nil {
|
||||
return &empty.Empty{}, status.Errorf(codes.Internal, "Could not check optimistic status: %v", err)
|
||||
}
|
||||
|
||||
if ns.SyncChecker.Synced() && !isOptimistic {
|
||||
return &empty.Empty{}, nil
|
||||
}
|
||||
if ns.SyncChecker.Syncing() || ns.SyncChecker.Initialized() {
|
||||
if request.SyncingStatus != 0 {
|
||||
// override the 200 success with the provided request status
|
||||
if err := grpc.SetHeader(ctx, metadata.Pairs("x-http-code", strconv.FormatUint(request.SyncingStatus, 10))); err != nil {
|
||||
return &empty.Empty{}, status.Errorf(codes.Internal, "Could not set custom success code header: %v", err)
|
||||
}
|
||||
return &empty.Empty{}, nil
|
||||
}
|
||||
// Set header for REST API clients (via gRPC-gateway)
|
||||
if err := grpc.SetHeader(ctx, metadata.Pairs("x-http-code", strconv.FormatUint(http.StatusPartialContent, 10))); err != nil {
|
||||
return &empty.Empty{}, status.Errorf(codes.Internal, "Could not set custom success code header: %v", err)
|
||||
return &empty.Empty{}, status.Errorf(codes.Internal, "Could not set status code header: %v", err)
|
||||
}
|
||||
return &empty.Empty{}, nil
|
||||
return &empty.Empty{}, status.Error(codes.Unavailable, "node is syncing")
|
||||
}
|
||||
if isOptimistic {
|
||||
// Set header for REST API clients (via gRPC-gateway)
|
||||
if err := grpc.SetHeader(ctx, metadata.Pairs("x-http-code", strconv.FormatUint(http.StatusPartialContent, 10))); err != nil {
|
||||
return &empty.Empty{}, status.Errorf(codes.Internal, "Could not set status code header: %v", err)
|
||||
}
|
||||
return &empty.Empty{}, status.Error(codes.Unavailable, "node is optimistic")
|
||||
}
|
||||
return &empty.Empty{}, status.Errorf(codes.Unavailable, "service unavailable")
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package node
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"maps"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -21,6 +22,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/p2p/enode"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/metadata"
|
||||
"google.golang.org/grpc/reflection"
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
"google.golang.org/protobuf/types/known/timestamppb"
|
||||
@@ -187,32 +189,71 @@ func TestNodeServer_GetETH1ConnectionStatus(t *testing.T) {
|
||||
assert.Equal(t, errStr, res.CurrentConnectionError)
|
||||
}
|
||||
|
||||
// mockServerTransportStream implements grpc.ServerTransportStream for testing
|
||||
type mockServerTransportStream struct {
|
||||
headers map[string][]string
|
||||
}
|
||||
|
||||
func (m *mockServerTransportStream) Method() string { return "" }
|
||||
func (m *mockServerTransportStream) SetHeader(md metadata.MD) error {
|
||||
maps.Copy(m.headers, md)
|
||||
return nil
|
||||
}
|
||||
func (m *mockServerTransportStream) SendHeader(metadata.MD) error { return nil }
|
||||
func (m *mockServerTransportStream) SetTrailer(metadata.MD) error { return nil }
|
||||
|
||||
func TestNodeServer_GetHealth(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input *mockSync.Sync
|
||||
customStatus uint64
|
||||
isOptimistic bool
|
||||
wantedErr string
|
||||
}{
|
||||
{
|
||||
name: "happy path",
|
||||
input: &mockSync.Sync{IsSyncing: false, IsSynced: true},
|
||||
name: "happy path - synced and not optimistic",
|
||||
input: &mockSync.Sync{IsSyncing: false, IsSynced: true},
|
||||
isOptimistic: false,
|
||||
},
|
||||
{
|
||||
name: "syncing",
|
||||
input: &mockSync.Sync{IsSyncing: false},
|
||||
wantedErr: "service unavailable",
|
||||
name: "returns error when not synced and not syncing",
|
||||
input: &mockSync.Sync{IsSyncing: false, IsSynced: false},
|
||||
isOptimistic: false,
|
||||
wantedErr: "service unavailable",
|
||||
},
|
||||
{
|
||||
name: "returns error when syncing",
|
||||
input: &mockSync.Sync{IsSyncing: true, IsSynced: false},
|
||||
isOptimistic: false,
|
||||
wantedErr: "node is syncing",
|
||||
},
|
||||
{
|
||||
name: "returns error when synced but optimistic",
|
||||
input: &mockSync.Sync{IsSyncing: false, IsSynced: true},
|
||||
isOptimistic: true,
|
||||
wantedErr: "node is optimistic",
|
||||
},
|
||||
{
|
||||
name: "returns error when syncing and optimistic",
|
||||
input: &mockSync.Sync{IsSyncing: true, IsSynced: false},
|
||||
isOptimistic: true,
|
||||
wantedErr: "node is syncing",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
server := grpc.NewServer()
|
||||
ns := &Server{
|
||||
SyncChecker: tt.input,
|
||||
SyncChecker: tt.input,
|
||||
OptimisticModeFetcher: &mock.ChainService{Optimistic: tt.isOptimistic},
|
||||
}
|
||||
ethpb.RegisterNodeServer(server, ns)
|
||||
reflection.Register(server)
|
||||
_, err := ns.GetHealth(t.Context(), ðpb.HealthRequest{SyncingStatus: tt.customStatus})
|
||||
|
||||
// Create context with mock transport stream so grpc.SetHeader works
|
||||
stream := &mockServerTransportStream{headers: make(map[string][]string)}
|
||||
ctx := grpc.NewContextWithServerTransportStream(t.Context(), stream)
|
||||
|
||||
_, err := ns.GetHealth(ctx, ðpb.HealthRequest{})
|
||||
if tt.wantedErr == "" {
|
||||
require.NoError(t, err)
|
||||
return
|
||||
|
||||
@@ -259,18 +259,19 @@ func NewService(ctx context.Context, cfg *Config) *Service {
|
||||
}
|
||||
s.validatorServer = validatorServer
|
||||
nodeServer := &nodev1alpha1.Server{
|
||||
LogsStreamer: logs.NewStreamServer(),
|
||||
StreamLogsBufferSize: 1000, // Enough to handle bursts of beacon node logs for gRPC streaming.
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
Server: s.grpcServer,
|
||||
SyncChecker: s.cfg.SyncService,
|
||||
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
PeersFetcher: s.cfg.PeersFetcher,
|
||||
PeerManager: s.cfg.PeerManager,
|
||||
GenesisFetcher: s.cfg.GenesisFetcher,
|
||||
POWChainInfoFetcher: s.cfg.ExecutionChainInfoFetcher,
|
||||
BeaconMonitoringHost: s.cfg.BeaconMonitoringHost,
|
||||
BeaconMonitoringPort: s.cfg.BeaconMonitoringPort,
|
||||
LogsStreamer: logs.NewStreamServer(),
|
||||
StreamLogsBufferSize: 1000, // Enough to handle bursts of beacon node logs for gRPC streaming.
|
||||
BeaconDB: s.cfg.BeaconDB,
|
||||
Server: s.grpcServer,
|
||||
SyncChecker: s.cfg.SyncService,
|
||||
GenesisTimeFetcher: s.cfg.GenesisTimeFetcher,
|
||||
PeersFetcher: s.cfg.PeersFetcher,
|
||||
PeerManager: s.cfg.PeerManager,
|
||||
GenesisFetcher: s.cfg.GenesisFetcher,
|
||||
POWChainInfoFetcher: s.cfg.ExecutionChainInfoFetcher,
|
||||
BeaconMonitoringHost: s.cfg.BeaconMonitoringHost,
|
||||
BeaconMonitoringPort: s.cfg.BeaconMonitoringPort,
|
||||
OptimisticModeFetcher: s.cfg.OptimisticModeFetcher,
|
||||
}
|
||||
beaconChainServer := &beaconv1alpha1.Server{
|
||||
Ctx: s.ctx,
|
||||
|
||||
@@ -46,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)
|
||||
@@ -72,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)
|
||||
|
||||
@@ -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{
|
||||
|
||||
3
changelog/aarshkshah1992_set-beacon-node-options.md
Normal file
3
changelog/aarshkshah1992_set-beacon-node-options.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Added
|
||||
|
||||
- Set beacon node options after reading the config file.
|
||||
3
changelog/bastin_fix-genlogs-gitignore-bug.md
Normal file
3
changelog/bastin_fix-genlogs-gitignore-bug.md
Normal 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.
|
||||
3
changelog/farazdagi_fix-hashtree-darwin-amd64.md
Normal file
3
changelog/farazdagi_fix-hashtree-darwin-amd64.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Fixed
|
||||
|
||||
- Fix Bazel build failure on macOS x86_64 (darwin_amd64) (adds missing assembly stub to hashtree patch).
|
||||
@@ -0,0 +1,6 @@
|
||||
### Added
|
||||
|
||||
- Added new proofCollector type to ssz-query
|
||||
|
||||
### Ignored
|
||||
- Added testing covering the production of Merkle proof from Phase0 beacon state and benchmarked against real Hoodi beacon state (Fulu version)
|
||||
7
changelog/james-prysm_grpc-fallback.md
Normal file
7
changelog/james-prysm_grpc-fallback.md
Normal 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.
|
||||
11
changelog/james-prysm_host-fallback-cleanup.md
Normal file
11
changelog/james-prysm_host-fallback-cleanup.md
Normal 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.
|
||||
3
changelog/james-prysm_update-health-endpoint.md
Normal file
3
changelog/james-prysm_update-health-endpoint.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- gRPC health endpoint will now return an error on syncing or optimistic status showing that it's unavailable.
|
||||
3
changelog/jtraglia-add-specrefs-readme.md
Normal file
3
changelog/jtraglia-add-specrefs-readme.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Added
|
||||
|
||||
- Added README for maintaining specrefs.
|
||||
3
changelog/jtraglia-improve-ethspecify-integration.md
Normal file
3
changelog/jtraglia-improve-ethspecify-integration.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Changed
|
||||
|
||||
- Improved integrations with ethspecify so specrefs can be used throughout the codebase.
|
||||
3
changelog/jtraglia-nightly-reftests-with-run-id.md
Normal file
3
changelog/jtraglia-nightly-reftests-with-run-id.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Added
|
||||
|
||||
- The ability to download the nightly reference tests from a specific day.
|
||||
3
changelog/pvl-golangci-tests.md
Normal file
3
changelog/pvl-golangci-tests.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Ignored
|
||||
|
||||
- Updated golangci to run lint on tests too.
|
||||
3
changelog/syjn99_docs-ssz-ql.md
Normal file
3
changelog/syjn99_docs-ssz-ql.md
Normal file
@@ -0,0 +1,3 @@
|
||||
### Ignored
|
||||
|
||||
- Add handy documentation for SSZ Query package (`encoding/ssz/query`).
|
||||
2
changelog/terencechain_gloas-ptc-sampling.md
Normal file
2
changelog/terencechain_gloas-ptc-sampling.md
Normal file
@@ -0,0 +1,2 @@
|
||||
### Changed
|
||||
- Sample PTC per committee to reduce allocations.
|
||||
2
changelog/tt_run-gofmt.md
Normal file
2
changelog/tt_run-gofmt.md
Normal file
@@ -0,0 +1,2 @@
|
||||
### Ignored
|
||||
- Run go fmt
|
||||
@@ -1,5 +0,0 @@
|
||||
package execution
|
||||
|
||||
import "github.com/sirupsen/logrus"
|
||||
|
||||
var log = logrus.WithField("prefix", "execution")
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -163,3 +163,18 @@ func Uint256ToSSZBytes(num string) ([]byte, error) {
|
||||
}
|
||||
return PadTo(ReverseByteOrder(uint256.Bytes()), 32), nil
|
||||
}
|
||||
|
||||
// PutLittleEndian writes an unsigned integer value in little-endian format.
|
||||
// Supports sizes 1, 2, 4, or 8 bytes for uint8/16/32/64 respectively.
|
||||
func PutLittleEndian(dst []byte, val uint64, size int) {
|
||||
switch size {
|
||||
case 1:
|
||||
dst[0] = byte(val)
|
||||
case 2:
|
||||
binary.LittleEndian.PutUint16(dst, uint16(val))
|
||||
case 4:
|
||||
binary.LittleEndian.PutUint32(dst, uint32(val))
|
||||
case 8:
|
||||
binary.LittleEndian.PutUint64(dst, val)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,9 @@ go_library(
|
||||
"container.go",
|
||||
"generalized_index.go",
|
||||
"list.go",
|
||||
"merkle_proof.go",
|
||||
"path.go",
|
||||
"proof_collector.go",
|
||||
"query.go",
|
||||
"ssz_info.go",
|
||||
"ssz_object.go",
|
||||
@@ -20,7 +22,12 @@ go_library(
|
||||
importpath = "github.com/OffchainLabs/prysm/v7/encoding/ssz/query",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//container/trie:go_default_library",
|
||||
"//crypto/hash/htr:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//encoding/ssz:go_default_library",
|
||||
"//math:go_default_library",
|
||||
"@com_github_prysmaticlabs_fastssz//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -29,15 +36,24 @@ go_test(
|
||||
name = "go_default_test",
|
||||
srcs = [
|
||||
"generalized_index_test.go",
|
||||
"merkle_proof_test.go",
|
||||
"path_test.go",
|
||||
"proof_collector_test.go",
|
||||
"query_test.go",
|
||||
"tag_parser_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
":go_default_library",
|
||||
"//beacon-chain/state/stateutil:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//encoding/ssz:go_default_library",
|
||||
"//encoding/ssz/query/testutil:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//proto/ssz_query/testing:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"@com_github_prysmaticlabs_fastssz//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
190
encoding/ssz/query/doc.md
Normal file
190
encoding/ssz/query/doc.md
Normal 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 := ðpb.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 node’s 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.
|
||||
34
encoding/ssz/query/merkle_proof.go
Normal file
34
encoding/ssz/query/merkle_proof.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"reflect"
|
||||
|
||||
fastssz "github.com/prysmaticlabs/fastssz"
|
||||
)
|
||||
|
||||
// Prove is the entrypoint to generate an SSZ Merkle proof for the given generalized index.
|
||||
// Parameters:
|
||||
// - gindex: the generalized index of the node to prove inclusion for.
|
||||
// Returns:
|
||||
// - fastssz.Proof: the Merkle proof containing the leaf, index, and sibling hashes.
|
||||
// - error: any error encountered during proof generation.
|
||||
func (info *SszInfo) Prove(gindex uint64) (*fastssz.Proof, error) {
|
||||
if info == nil {
|
||||
return nil, fmt.Errorf("nil SszInfo")
|
||||
}
|
||||
|
||||
collector := newProofCollector()
|
||||
collector.addTarget(gindex)
|
||||
|
||||
// info.source is guaranteed to be valid and dereferenced by AnalyzeObject
|
||||
v := reflect.ValueOf(info.source).Elem()
|
||||
|
||||
// Start the merkleization and proof collection process.
|
||||
// In SSZ generalized indices, the root is always at index 1.
|
||||
if _, err := collector.merkleize(info, v, 1); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return collector.toProof()
|
||||
}
|
||||
163
encoding/ssz/query/merkle_proof_test.go
Normal file
163
encoding/ssz/query/merkle_proof_test.go
Normal file
@@ -0,0 +1,163 @@
|
||||
package query_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/OffchainLabs/go-bitfield"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/blocks"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
"github.com/OffchainLabs/prysm/v7/encoding/ssz/query"
|
||||
eth "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
||||
"github.com/OffchainLabs/prysm/v7/testing/require"
|
||||
"github.com/OffchainLabs/prysm/v7/testing/util"
|
||||
ssz "github.com/prysmaticlabs/fastssz"
|
||||
)
|
||||
|
||||
func TestProve_FixedTestContainer(t *testing.T) {
|
||||
obj := createFixedTestContainer()
|
||||
|
||||
tests := []string{
|
||||
".field_uint32",
|
||||
".nested.value2",
|
||||
".vector_field[3]",
|
||||
".bitvector64_field",
|
||||
".trailing_field",
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc, func(t *testing.T) {
|
||||
proveAndVerify(t, obj, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProve_VariableTestContainer(t *testing.T) {
|
||||
obj := createVariableTestContainer()
|
||||
|
||||
tests := []string{
|
||||
".leading_field",
|
||||
".field_list_uint64[2]",
|
||||
"len(field_list_uint64)",
|
||||
".nested.nested_list_field[1]",
|
||||
".variable_container_list[0].inner_1.field_list_uint64[1]",
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc, func(t *testing.T) {
|
||||
proveAndVerify(t, obj, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProve_BeaconBlock(t *testing.T) {
|
||||
randaoReveal := make([]byte, 96)
|
||||
for i := range randaoReveal {
|
||||
randaoReveal[i] = 0x42
|
||||
}
|
||||
root32 := make([]byte, 32)
|
||||
for i := range root32 {
|
||||
root32[i] = 0x24
|
||||
}
|
||||
sig := make([]byte, 96)
|
||||
for i := range sig {
|
||||
sig[i] = 0x99
|
||||
}
|
||||
|
||||
att := ð.Attestation{
|
||||
AggregationBits: bitfield.Bitlist{0x01},
|
||||
Data: ð.AttestationData{
|
||||
Slot: 1,
|
||||
CommitteeIndex: 1,
|
||||
BeaconBlockRoot: root32,
|
||||
Source: ð.Checkpoint{
|
||||
Epoch: 1,
|
||||
Root: root32,
|
||||
},
|
||||
Target: ð.Checkpoint{
|
||||
Epoch: 1,
|
||||
Root: root32,
|
||||
},
|
||||
},
|
||||
Signature: sig,
|
||||
}
|
||||
|
||||
b := util.NewBeaconBlock()
|
||||
b.Block.Slot = 123
|
||||
b.Block.Body.RandaoReveal = randaoReveal
|
||||
b.Block.Body.Attestations = []*eth.Attestation{att}
|
||||
|
||||
sb, err := blocks.NewSignedBeaconBlock(b)
|
||||
require.NoError(t, err)
|
||||
|
||||
protoBlock, err := sb.Block().Proto()
|
||||
require.NoError(t, err)
|
||||
|
||||
obj, ok := protoBlock.(query.SSZObject)
|
||||
require.Equal(t, true, ok, "block proto does not implement query.SSZObject")
|
||||
|
||||
tests := []string{
|
||||
".slot",
|
||||
".body.randao_reveal",
|
||||
".body.attestations[0].data.slot",
|
||||
"len(body.attestations)",
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc, func(t *testing.T) {
|
||||
proveAndVerify(t, obj, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProve_BeaconState(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisState(t, 16)
|
||||
require.NoError(t, st.SetSlot(primitives.Slot(42)))
|
||||
|
||||
sszObj, ok := st.ToProtoUnsafe().(query.SSZObject)
|
||||
require.Equal(t, true, ok, "state proto does not implement query.SSZObject")
|
||||
|
||||
tests := []string{
|
||||
".slot",
|
||||
".latest_block_header",
|
||||
".validators[0].effective_balance",
|
||||
"len(validators)",
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
t.Run(tc, func(t *testing.T) {
|
||||
proveAndVerify(t, sszObj, tc)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// proveAndVerify helper to analyze an object, generate a merkle proof for the given path,
|
||||
// and verify the proof against the object's root.
|
||||
func proveAndVerify(t *testing.T, obj query.SSZObject, pathStr string) {
|
||||
t.Helper()
|
||||
|
||||
info, err := query.AnalyzeObject(obj)
|
||||
require.NoError(t, err)
|
||||
|
||||
path, err := query.ParsePath(pathStr)
|
||||
require.NoError(t, err)
|
||||
|
||||
gi, err := query.GetGeneralizedIndexFromPath(info, path)
|
||||
require.NoError(t, err)
|
||||
|
||||
proof, err := info.Prove(gi)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int(gi), proof.Index)
|
||||
|
||||
root, err := obj.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
|
||||
ok, err := ssz.VerifyProof(root[:], proof)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, ok, "merkle proof verification failed")
|
||||
|
||||
require.Equal(t, 32, len(proof.Leaf))
|
||||
for i, h := range proof.Hashes {
|
||||
require.Equal(t, 32, len(h), "proof hash %d is not 32 bytes", i)
|
||||
}
|
||||
|
||||
}
|
||||
672
encoding/ssz/query/proof_collector.go
Normal file
672
encoding/ssz/query/proof_collector.go
Normal file
@@ -0,0 +1,672 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/bits"
|
||||
"reflect"
|
||||
"runtime"
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
"github.com/OffchainLabs/go-bitfield"
|
||||
"github.com/OffchainLabs/prysm/v7/container/trie"
|
||||
"github.com/OffchainLabs/prysm/v7/crypto/hash/htr"
|
||||
"github.com/OffchainLabs/prysm/v7/encoding/bytesutil"
|
||||
ssz "github.com/OffchainLabs/prysm/v7/encoding/ssz"
|
||||
"github.com/OffchainLabs/prysm/v7/math"
|
||||
fastssz "github.com/prysmaticlabs/fastssz"
|
||||
)
|
||||
|
||||
// proofCollector collects sibling hashes and leaves needed for Merkle proofs.
|
||||
//
|
||||
// Multiproof-ready design:
|
||||
// - requiredSiblings/requiredLeaves store which gindices we want to collect (registered before merkleization).
|
||||
// - siblings/leaves store the actual collected hashes.
|
||||
//
|
||||
// Concurrency:
|
||||
// - required* maps are read-only during merkleization.
|
||||
// - siblings/leaves writes are protected by mutex.
|
||||
type proofCollector struct {
|
||||
sync.Mutex
|
||||
|
||||
// Required gindices (registered before merkleization)
|
||||
requiredSiblings map[uint64]struct{}
|
||||
requiredLeaves map[uint64]struct{}
|
||||
|
||||
// Collected hashes
|
||||
siblings map[uint64][32]byte
|
||||
leaves map[uint64][32]byte
|
||||
}
|
||||
|
||||
func newProofCollector() *proofCollector {
|
||||
return &proofCollector{
|
||||
requiredSiblings: make(map[uint64]struct{}),
|
||||
requiredLeaves: make(map[uint64]struct{}),
|
||||
siblings: make(map[uint64][32]byte),
|
||||
leaves: make(map[uint64][32]byte),
|
||||
}
|
||||
}
|
||||
|
||||
func (pc *proofCollector) reset() {
|
||||
pc.Lock()
|
||||
defer pc.Unlock()
|
||||
|
||||
pc.requiredSiblings = make(map[uint64]struct{})
|
||||
pc.requiredLeaves = make(map[uint64]struct{})
|
||||
pc.siblings = make(map[uint64][32]byte)
|
||||
pc.leaves = make(map[uint64][32]byte)
|
||||
}
|
||||
|
||||
// addTarget register the target leaf and its required sibling nodes for proof construction.
|
||||
// Registration should happen before merkleization begins.
|
||||
func (pc *proofCollector) addTarget(gindex uint64) {
|
||||
pc.Lock()
|
||||
defer pc.Unlock()
|
||||
|
||||
pc.requiredLeaves[gindex] = struct{}{}
|
||||
|
||||
// Walk from the target leaf up to (but not including) the root (gindex=1).
|
||||
// At each step, register the sibling node required to prove inclusion.
|
||||
nodeGindex := gindex
|
||||
for nodeGindex > 1 {
|
||||
siblingGindex := nodeGindex ^ 1 // flip the last bit: left<->right sibling
|
||||
pc.requiredSiblings[siblingGindex] = struct{}{}
|
||||
|
||||
// Move to parent
|
||||
nodeGindex /= 2
|
||||
}
|
||||
}
|
||||
|
||||
// toProof converts the collected siblings and leaves into a fastssz.Proof structure.
|
||||
// Current behavior expects a single target leaf (single proof).
|
||||
func (pc *proofCollector) toProof() (*fastssz.Proof, error) {
|
||||
pc.Lock()
|
||||
defer pc.Unlock()
|
||||
|
||||
proof := &fastssz.Proof{}
|
||||
if len(pc.leaves) == 0 {
|
||||
return nil, errors.New("no leaves collected: add target leaves before merkleization")
|
||||
}
|
||||
|
||||
leafGindices := make([]uint64, 0, len(pc.leaves))
|
||||
for g := range pc.leaves {
|
||||
leafGindices = append(leafGindices, g)
|
||||
}
|
||||
slices.Sort(leafGindices)
|
||||
|
||||
// single proof resides in leafGindices[0]
|
||||
targetGindex := leafGindices[0]
|
||||
proofIndex, err := math.Int(targetGindex)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("gindex %d overflows int: %w", targetGindex, err)
|
||||
}
|
||||
proof.Index = proofIndex
|
||||
|
||||
// store the leaf
|
||||
leaf := pc.leaves[targetGindex]
|
||||
leafBuf := make([]byte, 32)
|
||||
copy(leafBuf, leaf[:])
|
||||
proof.Leaf = leafBuf
|
||||
|
||||
// Walk from target up to root, collecting siblings.
|
||||
steps := bits.Len64(targetGindex) - 1
|
||||
proof.Hashes = make([][]byte, 0, steps)
|
||||
|
||||
for targetGindex > 1 {
|
||||
sib := targetGindex ^ 1
|
||||
h, ok := pc.siblings[sib]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("missing sibling hash for gindex %d", sib)
|
||||
}
|
||||
proof.Hashes = append(proof.Hashes, h[:])
|
||||
targetGindex /= 2
|
||||
}
|
||||
|
||||
return proof, nil
|
||||
}
|
||||
|
||||
// collectLeaf checks if the given gindex is a required leaf for the proof,
|
||||
// and if so, stores the provided leaf hash in the collector.
|
||||
func (pc *proofCollector) collectLeaf(gindex uint64, leaf [32]byte) {
|
||||
if _, ok := pc.requiredLeaves[gindex]; !ok {
|
||||
return
|
||||
}
|
||||
pc.Lock()
|
||||
pc.leaves[gindex] = leaf
|
||||
pc.Unlock()
|
||||
}
|
||||
|
||||
// collectSibling stores the hash for a sibling node identified by gindex.
|
||||
// It only stores the hash if gindex was pre-registered via addTarget (present in requiredSiblings).
|
||||
// Writes to the collected siblings map are protected by the collector mutex.
|
||||
func (pc *proofCollector) collectSibling(gindex uint64, hash [32]byte) {
|
||||
if _, ok := pc.requiredSiblings[gindex]; !ok {
|
||||
return
|
||||
}
|
||||
pc.Lock()
|
||||
pc.siblings[gindex] = hash
|
||||
pc.Unlock()
|
||||
}
|
||||
|
||||
// Merkleizers and proof collection methods
|
||||
|
||||
// merkleize recursively traverses an SSZ info and computes the Merkle root of the subtree.
|
||||
//
|
||||
// Proof collection:
|
||||
// - During traversal it calls collectLeaf/collectSibling with the SSZ generalized indices (gindices)
|
||||
// of visited nodes.
|
||||
// - The collector only stores hashes for gindices that were pre-registered via addTarget
|
||||
// (requiredLeaves/requiredSiblings). This makes the traversal multiproof-ready: you can register
|
||||
// multiple targets before calling merkleize.
|
||||
//
|
||||
// SSZ types handled: basic types, containers, lists, vectors, bitlists, and bitvectors.
|
||||
//
|
||||
// Parameters:
|
||||
// - info: SSZ type metadata for the current value.
|
||||
// - v: reflect.Value of the current value.
|
||||
// - currentGindex: generalized index of the current subtree root.
|
||||
//
|
||||
// Returns:
|
||||
// - [32]byte: Merkle root of the current subtree.
|
||||
// - error: any error encountered during traversal/merkleization.
|
||||
func (pc *proofCollector) merkleize(info *SszInfo, v reflect.Value, currentGindex uint64) ([32]byte, error) {
|
||||
if info.sszType.isBasic() {
|
||||
return pc.merkleizeBasicType(info.sszType, v, currentGindex)
|
||||
}
|
||||
switch info.sszType {
|
||||
case Container:
|
||||
return pc.merkleizeContainer(info, v, currentGindex)
|
||||
case List:
|
||||
return pc.merkleizeList(info, v, currentGindex)
|
||||
case Vector:
|
||||
return pc.merkleizeVector(info, v, currentGindex)
|
||||
case Bitlist:
|
||||
return pc.merkleizeBitlist(info, v, currentGindex)
|
||||
case Bitvector:
|
||||
return pc.merkleizeBitvector(info, v, currentGindex)
|
||||
default:
|
||||
return [32]byte{}, fmt.Errorf("unsupported SSZ type: %v", info.sszType)
|
||||
}
|
||||
}
|
||||
|
||||
// merkleizeBasicType serializes a basic SSZ value into a 32-byte leaf chunk (little-endian, zero-padded).
|
||||
//
|
||||
// Proof collection:
|
||||
// - It calls collectLeaf(currentGindex, leaf) and stores the leaf if currentGindex was pre-registered via addTarget.
|
||||
//
|
||||
// Parameters:
|
||||
// - t: the SSZType (basic).
|
||||
// - v: the reflect.Value of the basic value.
|
||||
// - currentGindex: the generalized index (gindex) of this leaf.
|
||||
//
|
||||
// Returns:
|
||||
// - [32]byte: the 32-byte SSZ leaf chunk.
|
||||
// - error: if the SSZType is not a supported basic type.
|
||||
func (pc *proofCollector) merkleizeBasicType(t SSZType, v reflect.Value, currentGindex uint64) ([32]byte, error) {
|
||||
var leaf [32]byte
|
||||
|
||||
// Serialize the value into a 32-byte chunk (little-endian, zero-padded)
|
||||
switch t {
|
||||
case Uint8:
|
||||
leaf[0] = uint8(v.Uint())
|
||||
case Uint16:
|
||||
binary.LittleEndian.PutUint16(leaf[:2], uint16(v.Uint()))
|
||||
case Uint32:
|
||||
binary.LittleEndian.PutUint32(leaf[:4], uint32(v.Uint()))
|
||||
case Uint64:
|
||||
binary.LittleEndian.PutUint64(leaf[:8], v.Uint())
|
||||
case Boolean:
|
||||
if v.Bool() {
|
||||
leaf[0] = 1
|
||||
}
|
||||
default:
|
||||
return [32]byte{}, fmt.Errorf("unexpected basic type: %v", t)
|
||||
}
|
||||
|
||||
pc.collectLeaf(currentGindex, leaf)
|
||||
|
||||
return leaf, nil
|
||||
}
|
||||
|
||||
// merkleizeContainer computes the Merkle root of an SSZ container by:
|
||||
// 1. Merkleizing each field into a 32-byte subtree root
|
||||
// 2. Merkleizing the field roots into the container root (padding to the next power-of-2)
|
||||
//
|
||||
// Generalized indices (gindices): depth = ssz.Depth(uint64(N)) and field i has gindex = (currentGindex << depth) + uint64(i).
|
||||
// Proof collection: merkleize() computes each field root, merkleizeVectorAndCollect collects required siblings, and collectLeaf stores the container root if registered.
|
||||
//
|
||||
// Parameters:
|
||||
// - info: SSZ type metadata for the container.
|
||||
// - v: reflect.Value of the container value.
|
||||
// - currentGindex: generalized index (gindex) of the container root.
|
||||
//
|
||||
// Returns:
|
||||
// - [32]byte: Merkle root of the container.
|
||||
// - error: any error encountered while merkleizing fields.
|
||||
func (pc *proofCollector) merkleizeContainer(info *SszInfo, v reflect.Value, currentGindex uint64) ([32]byte, error) {
|
||||
// If the container root itself is the target, compute directly and return early.
|
||||
// This avoids full subtree merkleization when we only need the root.
|
||||
if _, ok := pc.requiredLeaves[currentGindex]; ok {
|
||||
root, err := info.HashTreeRoot()
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
pc.collectLeaf(currentGindex, root)
|
||||
return root, nil
|
||||
}
|
||||
|
||||
ci, err := info.ContainerInfo()
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
v = dereferencePointer(v)
|
||||
|
||||
// Calculate depth: how many levels from container root to field leaves
|
||||
numFields := len(ci.order)
|
||||
depth := ssz.Depth(uint64(numFields))
|
||||
|
||||
// Step 1: Compute HTR for each subtree (field)
|
||||
fieldRoots := make([][32]byte, numFields)
|
||||
|
||||
for i, name := range ci.order {
|
||||
fieldInfo := ci.fields[name]
|
||||
fieldVal := v.FieldByName(fieldInfo.goFieldName)
|
||||
|
||||
// Field i's gindex: shift currentGindex left by depth, then OR with field index
|
||||
fieldGindex := currentGindex<<depth + uint64(i)
|
||||
|
||||
htr, err := pc.merkleize(fieldInfo.sszInfo, fieldVal, fieldGindex)
|
||||
if err != nil {
|
||||
return [32]byte{}, fmt.Errorf("field %s: %w", name, err)
|
||||
}
|
||||
fieldRoots[i] = htr
|
||||
}
|
||||
|
||||
// Step 2: Merkleize the field hashes into the container root,
|
||||
// collecting sibling hashes if target is within this subtree
|
||||
root := pc.merkleizeVectorAndCollect(fieldRoots, currentGindex, uint64(depth))
|
||||
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// merkleizeVectorBody computes the Merkle root of the "data" subtree for vector-like SSZ types
|
||||
// (vectors and the data-part of lists/bitlists).
|
||||
//
|
||||
// Generalized indices (gindices): depth = ssz.Depth(limit); leafBase = subtreeRootGindex << depth; element/chunk i gindex = leafBase + uint64(i).
|
||||
// Proof collection: merkleize() is called for composite elements; merkleizeVectorAndCollect collects required siblings at this layer.
|
||||
// Padding: merkleizeVectorAndCollect uses trie.ZeroHashes as needed.
|
||||
//
|
||||
// Parameters:
|
||||
// - elemInfo: SSZ type metadata for the element.
|
||||
// - v: reflect.Value of the vector/list data.
|
||||
// - length: number of actual elements present.
|
||||
// - limit: virtual leaf capacity used for padding/Depth (fixed length for vectors, limit for lists).
|
||||
// - subtreeRootGindex: gindex of the data subtree root.
|
||||
//
|
||||
// Returns:
|
||||
// - [32]byte: Merkle root of the data subtree.
|
||||
// - error: any error encountered while merkleizing composite elements.
|
||||
func (pc *proofCollector) merkleizeVectorBody(elemInfo *SszInfo, v reflect.Value, length int, limit uint64, subtreeRootGindex uint64) ([32]byte, error) {
|
||||
depth := uint64(ssz.Depth(limit))
|
||||
|
||||
var chunks [][32]byte
|
||||
if elemInfo.sszType.isBasic() {
|
||||
// Serialize basic elements and pack into 32-byte chunks using ssz.PackByChunk.
|
||||
elemSize, err := math.Int(itemLength(elemInfo))
|
||||
if err != nil {
|
||||
return [32]byte{}, fmt.Errorf("element size %d overflows int: %w", itemLength(elemInfo), err)
|
||||
}
|
||||
serialized := make([][]byte, length)
|
||||
// Single contiguous allocation for all element data
|
||||
allData := make([]byte, length*elemSize)
|
||||
for i := range length {
|
||||
buf := allData[i*elemSize : (i+1)*elemSize]
|
||||
elem := v.Index(i)
|
||||
if elemInfo.sszType == Boolean && elem.Bool() {
|
||||
buf[0] = 1
|
||||
} else {
|
||||
bytesutil.PutLittleEndian(buf, elem.Uint(), elemSize)
|
||||
}
|
||||
serialized[i] = buf
|
||||
}
|
||||
chunks, err = ssz.PackByChunk(serialized)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
} else {
|
||||
// Composite elements: compute each element root (no padding here; merkleizeVectorAndCollect pads).
|
||||
chunks = make([][32]byte, length)
|
||||
|
||||
// Fall back to per-element merkleization with proper gindices for proof collection.
|
||||
// Parallel execution
|
||||
workerCount := min(runtime.GOMAXPROCS(0), length)
|
||||
|
||||
jobs := make(chan int, workerCount*16)
|
||||
errCh := make(chan error, 1) // only need the first error
|
||||
stopCh := make(chan struct{})
|
||||
var stopOnce sync.Once
|
||||
var wg sync.WaitGroup
|
||||
|
||||
worker := func() {
|
||||
defer wg.Done()
|
||||
for idx := range jobs {
|
||||
select {
|
||||
case <-stopCh:
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
elemGindex := subtreeRootGindex<<depth + uint64(idx)
|
||||
htr, err := pc.merkleize(elemInfo, v.Index(idx), elemGindex)
|
||||
if err != nil {
|
||||
stopOnce.Do(func() { close(stopCh) })
|
||||
select {
|
||||
case errCh <- fmt.Errorf("index %d: %w", idx, err):
|
||||
default:
|
||||
}
|
||||
return
|
||||
}
|
||||
chunks[idx] = htr
|
||||
}
|
||||
}
|
||||
|
||||
wg.Add(workerCount)
|
||||
for range workerCount {
|
||||
go worker()
|
||||
}
|
||||
|
||||
// Enqueue jobs; stop early if any worker reports an error.
|
||||
enqueue:
|
||||
for i := range length {
|
||||
select {
|
||||
case <-stopCh:
|
||||
break enqueue
|
||||
case jobs <- i:
|
||||
}
|
||||
}
|
||||
close(jobs)
|
||||
|
||||
wg.Wait()
|
||||
|
||||
select {
|
||||
case err := <-errCh:
|
||||
return [32]byte{}, err
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
root := pc.merkleizeVectorAndCollect(chunks, subtreeRootGindex, depth)
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// merkleizeVector computes the Merkle root of an SSZ vector (fixed-length).
|
||||
//
|
||||
// Generalized indices (gindices): currentGindex is the gindex of the vector root; element/chunk gindices are derived
|
||||
// inside merkleizeVectorBody using leafBase = currentGindex << ssz.Depth(leaves).
|
||||
//
|
||||
// Proof collection: merkleizeVectorBody performs element/chunk merkleization and collects required siblings at the
|
||||
// vector layer; collectLeaf stores the vector root if currentGindex was registered via addTarget.
|
||||
//
|
||||
// Parameters:
|
||||
// - info: SSZ type metadata for the vector.
|
||||
// - v: reflect.Value of the vector value.
|
||||
// - currentGindex: generalized index (gindex) of the vector root.
|
||||
//
|
||||
// Returns:
|
||||
// - [32]byte: Merkle root of the vector.
|
||||
// - error: any error encountered while merkleizing composite elements.
|
||||
func (pc *proofCollector) merkleizeVector(info *SszInfo, v reflect.Value, currentGindex uint64) ([32]byte, error) {
|
||||
vi, err := info.VectorInfo()
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
length, err := math.Int(vi.Length())
|
||||
if err != nil {
|
||||
return [32]byte{}, fmt.Errorf("vector length %d overflows int: %w", vi.Length(), err)
|
||||
}
|
||||
elemInfo := vi.element
|
||||
|
||||
// Determine the virtual leaf capacity for the vector.
|
||||
leaves, err := getChunkCount(info)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
root, err := pc.merkleizeVectorBody(elemInfo, v, length, leaves, currentGindex)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
// If the vector root itself is the target
|
||||
pc.collectLeaf(currentGindex, root)
|
||||
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// merkleizeList computes the Merkle root of an SSZ list by merkleizing its data subtree and mixing in the length.
|
||||
//
|
||||
// Generalized indices (gindices): dataRoot is the left child of the list root (dataRootGindex = currentGindex*2); the length mixin is the right child (currentGindex*2+1).
|
||||
// Proof collection: merkleizeVectorBody computes the data root (collecting required siblings in the data subtree), and mixinLengthAndCollect collects required siblings at the length-mixin level; collectLeaf stores the list root if registered.
|
||||
//
|
||||
// Parameters:
|
||||
// - info: SSZ type metadata for the list.
|
||||
// - v: reflect.Value of the list value.
|
||||
// - currentGindex: generalized index (gindex) of the list root.
|
||||
//
|
||||
// Returns:
|
||||
// - [32]byte: Merkle root of the list.
|
||||
// - error: any error encountered while merkleizing the data subtree.
|
||||
func (pc *proofCollector) merkleizeList(info *SszInfo, v reflect.Value, currentGindex uint64) ([32]byte, error) {
|
||||
li, err := info.ListInfo()
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
length := v.Len()
|
||||
elemInfo := li.element
|
||||
|
||||
chunks := make([][32]byte, 2)
|
||||
// Compute the length hash (little-endian uint256)
|
||||
binary.LittleEndian.PutUint64(chunks[1][:8], uint64(length))
|
||||
|
||||
// Data subtree root is the left child of the list root.
|
||||
dataRootGindex := currentGindex * 2
|
||||
|
||||
// Compute virtual leaf capacity for the data subtree.
|
||||
leaves, err := getChunkCount(info)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
chunks[0], err = pc.merkleizeVectorBody(elemInfo, v, length, leaves, dataRootGindex)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
// Handle the length mixin level (and proof bookkeeping at this level).
|
||||
// Compute the final list root: hash(dataRoot || lengthHash)
|
||||
root := pc.mixinLengthAndCollect(currentGindex, chunks)
|
||||
|
||||
// If the list root itself is the target
|
||||
pc.collectLeaf(currentGindex, root)
|
||||
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// merkleizeBitvectorBody computes the Merkle root of a bitvector-like byte sequence by packing it into 32-byte chunks
|
||||
// and merkleizing those chunks as a fixed-capacity vector (padding with trie.ZeroHashes as needed).
|
||||
//
|
||||
// Generalized indices (gindices): depth = ssz.Depth(chunkLimit); leafBase = subtreeRootGindex << depth; chunk i uses gindex = leafBase + uint64(i).
|
||||
// Proof collection: merkleizeVectorAndCollect collects required sibling hashes at the chunk-merkleization layer.
|
||||
//
|
||||
// Parameters:
|
||||
// - data: raw byte sequence representing the bitvector payload.
|
||||
// - chunkLimit: fixed/limit number of 32-byte chunks (used for padding/Depth).
|
||||
// - subtreeRootGindex: gindex of the bitvector data subtree root.
|
||||
//
|
||||
// Returns:
|
||||
// - [32]byte: Merkle root of the bitvector data subtree.
|
||||
// - error: any error encountered while packing data into chunks.
|
||||
func (pc *proofCollector) merkleizeBitvectorBody(data []byte, chunkLimit uint64, subtreeRootGindex uint64) ([32]byte, error) {
|
||||
depth := ssz.Depth(chunkLimit)
|
||||
chunks, err := ssz.PackByChunk([][]byte{data})
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
root := pc.merkleizeVectorAndCollect(chunks, subtreeRootGindex, uint64(depth))
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// merkleizeBitvector computes the Merkle root of a fixed-length SSZ bitvector and collects proof nodes for targets.
|
||||
//
|
||||
// Parameters:
|
||||
// - info: SSZ type metadata for the bitvector.
|
||||
// - v: reflect.Value of the bitvector value.
|
||||
// - currentGindex: generalized index (gindex) of the bitvector root.
|
||||
//
|
||||
// Returns:
|
||||
// - [32]byte: Merkle root of the bitvector.
|
||||
// - error: any error encountered during packing or merkleization.
|
||||
func (pc *proofCollector) merkleizeBitvector(info *SszInfo, v reflect.Value, currentGindex uint64) ([32]byte, error) {
|
||||
bitvectorBytes := v.Bytes()
|
||||
if len(bitvectorBytes) == 0 {
|
||||
return [32]byte{}, fmt.Errorf("bitvector field is uninitialized (nil or empty slice)")
|
||||
}
|
||||
|
||||
// Compute virtual leaf capacity for the bitvector.
|
||||
numChunks, err := getChunkCount(info)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
root, err := pc.merkleizeBitvectorBody(bitvectorBytes, numChunks, currentGindex)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
pc.collectLeaf(currentGindex, root)
|
||||
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// merkleizeBitlist computes the Merkle root of an SSZ bitlist by merkleizing its data chunks and mixing in the bit length.
|
||||
//
|
||||
// Generalized indices (gindices): dataRoot is the left child (dataRootGindex = currentGindex*2) and the length mixin is the right child (currentGindex*2+1).
|
||||
// Proof collection: merkleizeBitvectorBody computes the data root (collecting required siblings under dataRootGindex), and mixinLengthAndCollect collects required siblings at the length-mixin level; collectLeaf stores the bitlist root if registered.
|
||||
//
|
||||
// Parameters:
|
||||
// - info: SSZ type metadata for the bitlist.
|
||||
// - v: reflect.Value of the bitlist value.
|
||||
// - currentGindex: generalized index (gindex) of the bitlist root.
|
||||
//
|
||||
// Returns:
|
||||
// - [32]byte: Merkle root of the bitlist.
|
||||
// - error: any error encountered while merkleizing the data subtree.
|
||||
func (pc *proofCollector) merkleizeBitlist(info *SszInfo, v reflect.Value, currentGindex uint64) ([32]byte, error) {
|
||||
bi, err := info.BitlistInfo()
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
bitlistBytes := v.Bytes()
|
||||
|
||||
// Use go-bitfield to get bytes with termination bit cleared
|
||||
bl := bitfield.Bitlist(bitlistBytes)
|
||||
data := bl.BytesNoTrim()
|
||||
|
||||
// Get the bit length from bitlistInfo
|
||||
bitLength := bi.Length()
|
||||
|
||||
// Get the chunk limit from getChunkCount
|
||||
limitChunks, err := getChunkCount(info)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
chunks := make([][32]byte, 2)
|
||||
// Compute the length hash (little-endian uint256)
|
||||
binary.LittleEndian.PutUint64(chunks[1][:8], uint64(bitLength))
|
||||
|
||||
dataRootGindex := currentGindex * 2
|
||||
chunks[0], err = pc.merkleizeBitvectorBody(data, limitChunks, dataRootGindex)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
}
|
||||
|
||||
// Handle the length mixin level (and proof bookkeeping at this level).
|
||||
root := pc.mixinLengthAndCollect(currentGindex, chunks)
|
||||
|
||||
pc.collectLeaf(currentGindex, root)
|
||||
|
||||
return root, nil
|
||||
}
|
||||
|
||||
// merkleizeVectorAndCollect merkleizes a slice of 32-byte leaf nodes into a subtree root, padding to a virtual size of 2^depth.
|
||||
//
|
||||
// Generalized indices (gindices): at layer i (0-based), nodes have gindices levelBase = subtreeGeneralizedIndex << (depth-i) and node gindex = levelBase + idx.
|
||||
// Proof collection: for each layer it calls collectSibling(nodeGindex, nodeHash) and stores only those gindices registered via addTarget.
|
||||
//
|
||||
// Parameters:
|
||||
// - elements: leaf-level hashes (may be shorter than 2^depth; padding is applied with trie.ZeroHashes).
|
||||
// - subtreeGeneralizedIndex: gindex of the subtree root.
|
||||
// - depth: number of merkleization layers from subtree root to leaves.
|
||||
//
|
||||
// Returns:
|
||||
// - [32]byte: Merkle root of the subtree.
|
||||
func (pc *proofCollector) merkleizeVectorAndCollect(elements [][32]byte, subtreeGeneralizedIndex uint64, depth uint64) [32]byte {
|
||||
// Return zerohash at depth
|
||||
if len(elements) == 0 {
|
||||
return trie.ZeroHashes[depth]
|
||||
}
|
||||
for i := range depth {
|
||||
layerLen := len(elements)
|
||||
oddNodeLength := layerLen%2 == 1
|
||||
if oddNodeLength {
|
||||
zerohash := trie.ZeroHashes[i]
|
||||
elements = append(elements, zerohash)
|
||||
}
|
||||
|
||||
levelBaseGindex := subtreeGeneralizedIndex << (depth - i)
|
||||
for idx := range elements {
|
||||
gindex := levelBaseGindex + uint64(idx)
|
||||
pc.collectSibling(gindex, elements[idx])
|
||||
pc.collectLeaf(gindex, elements[idx])
|
||||
}
|
||||
|
||||
elements = htr.VectorizedSha256(elements)
|
||||
}
|
||||
return elements[0]
|
||||
}
|
||||
|
||||
// mixinLengthAndCollect computes the final mix-in root for list/bitlist values:
|
||||
//
|
||||
// root = hash(dataRoot, lengthHash)
|
||||
//
|
||||
// where chunks[0] is dataRoot and chunks[1] is the 32-byte length hash.
|
||||
//
|
||||
// Generalized indices (gindices): dataRoot is the left child (dataRootGindex = currentGindex*2) and lengthHash is the right child (lengthHashGindex = currentGindex*2+1).
|
||||
// Proof collection: it calls collectSibling/collectLeaf for both child gindices; the collector stores them only if they were registered via addTarget.
|
||||
//
|
||||
// Parameters:
|
||||
// - currentGindex: gindex of the parent node (list/bitlist root).
|
||||
// - chunks: two 32-byte nodes: [dataRoot, lengthHash].
|
||||
//
|
||||
// Returns:
|
||||
// - [32]byte: mixed-in Merkle root (or zero value on hashing error).
|
||||
// - error: any error encountered during hashing.
|
||||
func (pc *proofCollector) mixinLengthAndCollect(currentGindex uint64, chunks [][32]byte) [32]byte {
|
||||
dataRoot, lengthHash := chunks[0], chunks[1]
|
||||
dataRootGindex, lengthHashGindex := currentGindex*2, currentGindex*2+1
|
||||
|
||||
pc.collectSibling(dataRootGindex, dataRoot)
|
||||
pc.collectSibling(lengthHashGindex, lengthHash)
|
||||
|
||||
pc.collectLeaf(dataRootGindex, dataRoot)
|
||||
pc.collectLeaf(lengthHashGindex, lengthHash)
|
||||
|
||||
return ssz.MixInLength(dataRoot, lengthHash[:])
|
||||
}
|
||||
531
encoding/ssz/query/proof_collector_test.go
Normal file
531
encoding/ssz/query/proof_collector_test.go
Normal file
@@ -0,0 +1,531 @@
|
||||
package query
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"encoding/binary"
|
||||
"reflect"
|
||||
"slices"
|
||||
"testing"
|
||||
|
||||
"github.com/OffchainLabs/go-bitfield"
|
||||
"github.com/OffchainLabs/prysm/v7/beacon-chain/state/stateutil"
|
||||
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
|
||||
ssz "github.com/OffchainLabs/prysm/v7/encoding/ssz"
|
||||
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
|
||||
sszquerypb "github.com/OffchainLabs/prysm/v7/proto/ssz_query/testing"
|
||||
"github.com/OffchainLabs/prysm/v7/testing/require"
|
||||
)
|
||||
|
||||
func TestProofCollector_New(t *testing.T) {
|
||||
pc := newProofCollector()
|
||||
|
||||
require.NotNil(t, pc)
|
||||
require.Equal(t, 0, len(pc.requiredSiblings))
|
||||
require.Equal(t, 0, len(pc.requiredLeaves))
|
||||
require.Equal(t, 0, len(pc.siblings))
|
||||
require.Equal(t, 0, len(pc.leaves))
|
||||
}
|
||||
|
||||
func TestProofCollector_Reset(t *testing.T) {
|
||||
pc := newProofCollector()
|
||||
pc.requiredSiblings[3] = struct{}{}
|
||||
pc.requiredLeaves[5] = struct{}{}
|
||||
pc.siblings[3] = [32]byte{1}
|
||||
pc.leaves[5] = [32]byte{2}
|
||||
|
||||
pc.reset()
|
||||
|
||||
require.Equal(t, 0, len(pc.requiredSiblings))
|
||||
require.Equal(t, 0, len(pc.requiredLeaves))
|
||||
require.Equal(t, 0, len(pc.siblings))
|
||||
require.Equal(t, 0, len(pc.leaves))
|
||||
}
|
||||
|
||||
func TestProofCollector_AddTarget(t *testing.T) {
|
||||
pc := newProofCollector()
|
||||
pc.addTarget(5)
|
||||
|
||||
_, hasLeaf := pc.requiredLeaves[5]
|
||||
_, hasSibling4 := pc.requiredSiblings[4]
|
||||
_, hasSibling3 := pc.requiredSiblings[3]
|
||||
_, hasSibling1 := pc.requiredSiblings[1] // GI 1 is the root
|
||||
|
||||
require.Equal(t, true, hasLeaf)
|
||||
require.Equal(t, true, hasSibling4)
|
||||
require.Equal(t, true, hasSibling3)
|
||||
require.Equal(t, false, hasSibling1)
|
||||
}
|
||||
|
||||
func TestProofCollector_ToProof(t *testing.T) {
|
||||
pc := newProofCollector()
|
||||
pc.addTarget(5)
|
||||
|
||||
leaf := [32]byte{9}
|
||||
sibling4 := [32]byte{4}
|
||||
sibling3 := [32]byte{3}
|
||||
|
||||
pc.collectLeaf(5, leaf)
|
||||
pc.collectSibling(4, sibling4)
|
||||
pc.collectSibling(3, sibling3)
|
||||
|
||||
proof, err := pc.toProof()
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, 5, proof.Index)
|
||||
require.DeepEqual(t, leaf[:], proof.Leaf)
|
||||
require.Equal(t, 2, len(proof.Hashes))
|
||||
require.DeepEqual(t, sibling4[:], proof.Hashes[0])
|
||||
require.DeepEqual(t, sibling3[:], proof.Hashes[1])
|
||||
}
|
||||
|
||||
func TestProofCollector_ToProof_NoLeaves(t *testing.T) {
|
||||
pc := newProofCollector()
|
||||
_, err := pc.toProof()
|
||||
require.NotNil(t, err)
|
||||
}
|
||||
|
||||
func TestProofCollector_CollectLeaf(t *testing.T) {
|
||||
pc := newProofCollector()
|
||||
leaf := [32]byte{7}
|
||||
|
||||
pc.collectLeaf(10, leaf)
|
||||
require.Equal(t, 0, len(pc.leaves))
|
||||
|
||||
pc.addTarget(10)
|
||||
pc.collectLeaf(10, leaf)
|
||||
stored, ok := pc.leaves[10]
|
||||
require.Equal(t, true, ok)
|
||||
require.Equal(t, leaf, stored)
|
||||
}
|
||||
|
||||
func TestProofCollector_CollectSibling(t *testing.T) {
|
||||
pc := newProofCollector()
|
||||
hash := [32]byte{5}
|
||||
|
||||
pc.collectSibling(4, hash)
|
||||
require.Equal(t, 0, len(pc.siblings))
|
||||
|
||||
pc.addTarget(5)
|
||||
pc.collectSibling(4, hash)
|
||||
stored, ok := pc.siblings[4]
|
||||
require.Equal(t, true, ok)
|
||||
require.Equal(t, hash, stored)
|
||||
}
|
||||
|
||||
func TestProofCollector_Merkleize_BasicTypes(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
sszType SSZType
|
||||
value any
|
||||
expected [32]byte
|
||||
}{
|
||||
{
|
||||
name: "uint8",
|
||||
sszType: Uint8,
|
||||
value: uint8(0x11),
|
||||
expected: func() [32]byte {
|
||||
var leaf [32]byte
|
||||
leaf[0] = 0x11
|
||||
return leaf
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "uint16",
|
||||
sszType: Uint16,
|
||||
value: uint16(0x2211),
|
||||
expected: func() [32]byte {
|
||||
var leaf [32]byte
|
||||
binary.LittleEndian.PutUint16(leaf[:2], 0x2211)
|
||||
return leaf
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "uint32",
|
||||
sszType: Uint32,
|
||||
value: uint32(0x44332211),
|
||||
expected: func() [32]byte {
|
||||
var leaf [32]byte
|
||||
binary.LittleEndian.PutUint32(leaf[:4], 0x44332211)
|
||||
return leaf
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "uint64",
|
||||
sszType: Uint64,
|
||||
value: uint64(0x8877665544332211),
|
||||
expected: func() [32]byte {
|
||||
var leaf [32]byte
|
||||
binary.LittleEndian.PutUint64(leaf[:8], 0x8877665544332211)
|
||||
return leaf
|
||||
}(),
|
||||
},
|
||||
{
|
||||
name: "bool",
|
||||
sszType: Boolean,
|
||||
value: true,
|
||||
expected: func() [32]byte {
|
||||
var leaf [32]byte
|
||||
leaf[0] = 1
|
||||
return leaf
|
||||
}(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
pc := newProofCollector()
|
||||
gindex := uint64(3)
|
||||
pc.addTarget(gindex)
|
||||
|
||||
leaf, err := pc.merkleizeBasicType(tc.sszType, reflect.ValueOf(tc.value), gindex)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, tc.expected, leaf)
|
||||
|
||||
stored, ok := pc.leaves[gindex]
|
||||
require.Equal(t, true, ok)
|
||||
require.Equal(t, tc.expected, stored)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestProofCollector_Merkleize_Container(t *testing.T) {
|
||||
container := makeFixedTestContainer()
|
||||
|
||||
info, err := AnalyzeObject(container)
|
||||
require.NoError(t, err)
|
||||
|
||||
pc := newProofCollector()
|
||||
pc.addTarget(1)
|
||||
|
||||
root, err := pc.merkleize(info, reflect.ValueOf(container), 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
expected, err := container.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, root)
|
||||
|
||||
stored, ok := pc.leaves[1]
|
||||
require.Equal(t, true, ok)
|
||||
require.Equal(t, expected, stored)
|
||||
}
|
||||
|
||||
func TestProofCollector_Merkleize_Vector(t *testing.T) {
|
||||
container := makeFixedTestContainer()
|
||||
info, err := AnalyzeObject(container)
|
||||
require.NoError(t, err)
|
||||
|
||||
ci, err := info.ContainerInfo()
|
||||
require.NoError(t, err)
|
||||
field := ci.fields["vector_field"]
|
||||
|
||||
pc := newProofCollector()
|
||||
root, err := pc.merkleizeVector(field.sszInfo, reflect.ValueOf(container.VectorField), 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
serialized := make([][]byte, len(container.VectorField))
|
||||
for i, v := range container.VectorField {
|
||||
buf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(buf, v)
|
||||
serialized[i] = buf
|
||||
}
|
||||
chunks, err := ssz.PackByChunk(serialized)
|
||||
require.NoError(t, err)
|
||||
limit, err := getChunkCount(field.sszInfo)
|
||||
require.NoError(t, err)
|
||||
expected := ssz.MerkleizeVector(chunks, limit)
|
||||
|
||||
require.Equal(t, expected, root)
|
||||
}
|
||||
|
||||
func TestProofCollector_Merkleize_List(t *testing.T) {
|
||||
list := []*sszquerypb.FixedNestedContainer{
|
||||
makeFixedNestedContainer(1),
|
||||
makeFixedNestedContainer(2),
|
||||
}
|
||||
container := makeVariableTestContainer(list, bitfield.NewBitlist(1))
|
||||
info, err := AnalyzeObject(container)
|
||||
require.NoError(t, err)
|
||||
|
||||
ci, err := info.ContainerInfo()
|
||||
require.NoError(t, err)
|
||||
field := ci.fields["field_list_container"]
|
||||
|
||||
pc := newProofCollector()
|
||||
root, err := pc.merkleizeList(field.sszInfo, reflect.ValueOf(list), 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
listInfo, err := field.sszInfo.ListInfo()
|
||||
require.NoError(t, err)
|
||||
expected, err := ssz.MerkleizeListSSZ(list, listInfo.Limit())
|
||||
require.NoError(t, err)
|
||||
|
||||
require.Equal(t, expected, root)
|
||||
}
|
||||
|
||||
func TestProofCollector_Merkleize_Bitvector(t *testing.T) {
|
||||
container := makeFixedTestContainer()
|
||||
info, err := AnalyzeObject(container)
|
||||
require.NoError(t, err)
|
||||
|
||||
ci, err := info.ContainerInfo()
|
||||
require.NoError(t, err)
|
||||
field := ci.fields["bitvector64_field"]
|
||||
|
||||
pc := newProofCollector()
|
||||
root, err := pc.merkleizeBitvector(field.sszInfo, reflect.ValueOf(container.Bitvector64Field), 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
expected, err := ssz.MerkleizeByteSliceSSZ([]byte(container.Bitvector64Field))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, root)
|
||||
}
|
||||
|
||||
func TestProofCollector_Merkleize_Bitlist(t *testing.T) {
|
||||
bitlist := bitfield.NewBitlist(16)
|
||||
bitlist.SetBitAt(3, true)
|
||||
bitlist.SetBitAt(8, true)
|
||||
|
||||
container := makeVariableTestContainer(nil, bitlist)
|
||||
info, err := AnalyzeObject(container)
|
||||
require.NoError(t, err)
|
||||
|
||||
ci, err := info.ContainerInfo()
|
||||
require.NoError(t, err)
|
||||
field := ci.fields["bitlist_field"]
|
||||
|
||||
pc := newProofCollector()
|
||||
root, err := pc.merkleizeBitlist(field.sszInfo, reflect.ValueOf(container.BitlistField), 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
bitlistInfo, err := field.sszInfo.BitlistInfo()
|
||||
require.NoError(t, err)
|
||||
expected, err := ssz.BitlistRoot(bitfield.Bitlist(bitlist), bitlistInfo.Limit())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, root)
|
||||
}
|
||||
|
||||
func TestProofCollector_MerkleizeVectorBody_Basic(t *testing.T) {
|
||||
container := makeFixedTestContainer()
|
||||
info, err := AnalyzeObject(container)
|
||||
require.NoError(t, err)
|
||||
|
||||
ci, err := info.ContainerInfo()
|
||||
require.NoError(t, err)
|
||||
field := ci.fields["vector_field"]
|
||||
vectorInfo, err := field.sszInfo.VectorInfo()
|
||||
require.NoError(t, err)
|
||||
length := len(container.VectorField)
|
||||
limit, err := getChunkCount(field.sszInfo)
|
||||
require.NoError(t, err)
|
||||
|
||||
pc := newProofCollector()
|
||||
root, err := pc.merkleizeVectorBody(vectorInfo.element, reflect.ValueOf(container.VectorField), length, limit, 2)
|
||||
require.NoError(t, err)
|
||||
|
||||
serialized := make([][]byte, len(container.VectorField))
|
||||
for i, v := range container.VectorField {
|
||||
buf := make([]byte, 8)
|
||||
binary.LittleEndian.PutUint64(buf, v)
|
||||
serialized[i] = buf
|
||||
}
|
||||
chunks, err := ssz.PackByChunk(serialized)
|
||||
require.NoError(t, err)
|
||||
expected := ssz.MerkleizeVector(chunks, limit)
|
||||
|
||||
require.Equal(t, expected, root)
|
||||
}
|
||||
|
||||
func TestProofCollector_MerkleizeVectorAndCollect(t *testing.T) {
|
||||
pc := newProofCollector()
|
||||
pc.addTarget(6)
|
||||
|
||||
elements := [][32]byte{{1}, {2}}
|
||||
expected := ssz.MerkleizeVector(slices.Clone(elements), 2)
|
||||
root := pc.merkleizeVectorAndCollect(elements, 3, 1)
|
||||
|
||||
storedLeaf, hasLeaf := pc.leaves[6]
|
||||
storedSibling, hasSibling := pc.siblings[7]
|
||||
|
||||
require.Equal(t, true, hasLeaf)
|
||||
require.Equal(t, true, hasSibling)
|
||||
require.Equal(t, elements[0], storedLeaf)
|
||||
require.Equal(t, elements[1], storedSibling)
|
||||
|
||||
require.Equal(t, expected, root)
|
||||
}
|
||||
|
||||
func TestProofCollector_MixinLengthAndCollect(t *testing.T) {
|
||||
list := []*sszquerypb.FixedNestedContainer{
|
||||
makeFixedNestedContainer(1),
|
||||
makeFixedNestedContainer(2),
|
||||
}
|
||||
container := makeVariableTestContainer(list, bitfield.NewBitlist(1))
|
||||
info, err := AnalyzeObject(container)
|
||||
require.NoError(t, err)
|
||||
|
||||
ci, err := info.ContainerInfo()
|
||||
require.NoError(t, err)
|
||||
field := ci.fields["field_list_container"]
|
||||
|
||||
// Target gindex 2 (data root) - sibling at gindex 3 (length hash) should be collected
|
||||
pc := newProofCollector()
|
||||
pc.addTarget(2)
|
||||
root, err := pc.merkleizeList(field.sszInfo, reflect.ValueOf(list), 1)
|
||||
require.NoError(t, err)
|
||||
|
||||
listInfo, err := field.sszInfo.ListInfo()
|
||||
require.NoError(t, err)
|
||||
expected, err := ssz.MerkleizeListSSZ(list, listInfo.Limit())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, root)
|
||||
|
||||
// Verify data root is collected as leaf at gindex 2
|
||||
storedLeaf, hasLeaf := pc.leaves[2]
|
||||
require.Equal(t, true, hasLeaf)
|
||||
|
||||
// Verify length hash is collected as sibling at gindex 3
|
||||
storedSibling, hasSibling := pc.siblings[3]
|
||||
require.Equal(t, true, hasSibling)
|
||||
|
||||
// Verify the root is hash(dataRoot || lengthHash)
|
||||
expectedBuf := append(storedLeaf[:], storedSibling[:]...)
|
||||
expectedRoot := sha256.Sum256(expectedBuf)
|
||||
require.Equal(t, expectedRoot, root)
|
||||
}
|
||||
|
||||
func BenchmarkOptimizedValidatorRoots(b *testing.B) {
|
||||
validators := make([]*ethpb.Validator, 1000)
|
||||
for i := range validators {
|
||||
validators[i] = makeTestValidator(i)
|
||||
}
|
||||
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
_, err := stateutil.OptimizedValidatorRoots(validators)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkProofCollectorMerkleize(b *testing.B) {
|
||||
validators := make([]*ethpb.Validator, 1000)
|
||||
for i := range validators {
|
||||
validators[i] = makeTestValidator(i)
|
||||
}
|
||||
|
||||
info, err := AnalyzeObject(validators[0])
|
||||
require.NoError(b, err)
|
||||
|
||||
b.ResetTimer()
|
||||
for b.Loop() {
|
||||
for _, val := range validators {
|
||||
pc := newProofCollector()
|
||||
v := reflect.ValueOf(val)
|
||||
_, err := pc.merkleize(info, v, 1)
|
||||
if err != nil {
|
||||
b.Fatal(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func makeTestValidator(i int) *ethpb.Validator {
|
||||
pubkey := make([]byte, 48)
|
||||
for j := range pubkey {
|
||||
pubkey[j] = byte(i + j)
|
||||
}
|
||||
|
||||
withdrawalCredentials := make([]byte, 32)
|
||||
for j := range withdrawalCredentials {
|
||||
withdrawalCredentials[j] = byte(255 - ((i + j) % 256))
|
||||
}
|
||||
|
||||
return ðpb.Validator{
|
||||
PublicKey: pubkey,
|
||||
WithdrawalCredentials: withdrawalCredentials,
|
||||
EffectiveBalance: uint64(32000000000 + i),
|
||||
Slashed: i%2 == 0,
|
||||
ActivationEligibilityEpoch: primitives.Epoch(i),
|
||||
ActivationEpoch: primitives.Epoch(i + 1),
|
||||
ExitEpoch: primitives.Epoch(i + 2),
|
||||
WithdrawableEpoch: primitives.Epoch(i + 3),
|
||||
}
|
||||
}
|
||||
|
||||
func makeFixedNestedContainer(value uint64) *sszquerypb.FixedNestedContainer {
|
||||
value2 := make([]byte, 32)
|
||||
for i := range value2 {
|
||||
value2[i] = byte(i)
|
||||
}
|
||||
return &sszquerypb.FixedNestedContainer{
|
||||
Value1: value,
|
||||
Value2: value2,
|
||||
}
|
||||
}
|
||||
|
||||
func makeFixedTestContainer() *sszquerypb.FixedTestContainer {
|
||||
fieldBytes32 := make([]byte, 32)
|
||||
for i := range fieldBytes32 {
|
||||
fieldBytes32[i] = byte(i)
|
||||
}
|
||||
|
||||
vectorField := make([]uint64, 24)
|
||||
for i := range vectorField {
|
||||
vectorField[i] = uint64(i)
|
||||
}
|
||||
|
||||
rows := make([][]byte, 5)
|
||||
for i := range rows {
|
||||
row := make([]byte, 32)
|
||||
for j := range row {
|
||||
row[j] = byte(i) + byte(j)
|
||||
}
|
||||
rows[i] = row
|
||||
}
|
||||
|
||||
bitvector64 := bitfield.NewBitvector64()
|
||||
bitvector64.SetBitAt(1, true)
|
||||
bitvector512 := bitfield.NewBitvector512()
|
||||
bitvector512.SetBitAt(10, true)
|
||||
|
||||
trailing := make([]byte, 56)
|
||||
for i := range trailing {
|
||||
trailing[i] = byte(i)
|
||||
}
|
||||
|
||||
return &sszquerypb.FixedTestContainer{
|
||||
FieldUint32: 1,
|
||||
FieldUint64: 2,
|
||||
FieldBool: true,
|
||||
FieldBytes32: fieldBytes32,
|
||||
Nested: makeFixedNestedContainer(3),
|
||||
VectorField: vectorField,
|
||||
TwoDimensionBytesField: rows,
|
||||
Bitvector64Field: bitvector64,
|
||||
Bitvector512Field: bitvector512,
|
||||
TrailingField: trailing,
|
||||
}
|
||||
}
|
||||
|
||||
func makeVariableTestContainer(list []*sszquerypb.FixedNestedContainer, bitlist bitfield.Bitlist) *sszquerypb.VariableTestContainer {
|
||||
leading := make([]byte, 32)
|
||||
for i := range leading {
|
||||
leading[i] = byte(i)
|
||||
}
|
||||
trailing := make([]byte, 56)
|
||||
for i := range trailing {
|
||||
trailing[i] = byte(255 - i)
|
||||
}
|
||||
|
||||
if bitlist == nil {
|
||||
bitlist = bitfield.NewBitlist(0)
|
||||
}
|
||||
|
||||
return &sszquerypb.VariableTestContainer{
|
||||
LeadingField: leading,
|
||||
FieldListContainer: list,
|
||||
BitlistField: bitlist,
|
||||
TrailingField: trailing,
|
||||
}
|
||||
}
|
||||
@@ -389,6 +389,7 @@ func TestHashTreeRoot(t *testing.T) {
|
||||
require.NoError(t, err, "HashTreeRoot should not return an error")
|
||||
expectedHashTreeRoot, err := tt.obj.HashTreeRoot()
|
||||
require.NoError(t, err, "HashTreeRoot on original object should not return an error")
|
||||
// Verify the Merkle tree root matches with the SSZ generated HashTreeRoot
|
||||
require.Equal(t, expectedHashTreeRoot, hashTreeRoot, "HashTreeRoot from sszInfo should match original object's HashTreeRoot")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
30
specrefs/README.md
Normal file
30
specrefs/README.md
Normal file
@@ -0,0 +1,30 @@
|
||||
# Specification References
|
||||
|
||||
This directory contains specification reference tracking files managed by
|
||||
[ethspecify](https://github.com/jtraglia/ethspecify).
|
||||
|
||||
## Installation
|
||||
|
||||
Install `ethspecify` with the following command:
|
||||
|
||||
```bash
|
||||
pipx install ethspecify
|
||||
```
|
||||
|
||||
## Maintenance
|
||||
|
||||
When adding support for a new specification version, follow these steps:
|
||||
|
||||
1. Update the version in `.ethspecify.yml` configuration.
|
||||
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
|
||||
update each specref source list. If you choose not to implement an item,
|
||||
add an exception to the appropriate section the the `.ethspecify.yml`
|
||||
configuration.
|
||||
5. Repeat steps 3 and 4 until `ethspecify check` passes.
|
||||
6. Run `git diff` to view updated specrefs. If an object/function/etc has
|
||||
changed, make the necessary updates to the implementation.
|
||||
7. Lastly, in the project's root directory, run `act -j check-specrefs` to
|
||||
ensure everything is correct.
|
||||
@@ -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
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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"
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,14 @@ There are tests for mainnet and minimal config, so for each config we will add a
|
||||
|
||||
## Running nightly spectests
|
||||
|
||||
Since [PR 15312](https://github.com/OffchainLabs/prysm/pull/15312), Prysm has support to download "nightly" spectests from github via a starlark rule configuration by environment variable.
|
||||
Set `--repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly` when running spectest to download the "nightly" spectests.
|
||||
Note: A GITHUB_TOKEN environment variable is required to be set. The github token must be a [fine grained token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens#creating-a-fine-grained-personal-access-token).
|
||||
Since [PR 15312](https://github.com/OffchainLabs/prysm/pull/15312), Prysm has support to download "nightly" spectests from github via a starlark rule configuration by environment variable.
|
||||
Set `--repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly` or `--repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly-<run_id>` when running spectest to download the "nightly" spectests.
|
||||
Note: A GITHUB_TOKEN environment variable is required to be set. The github token does not need to be associated with your main account; it can be from a "burner account". And the token does not need to be a fine-grained token; it can be a classic token.
|
||||
|
||||
```
|
||||
bazel test //... --test_tag_filters=spectest --repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly
|
||||
```
|
||||
|
||||
```
|
||||
bazel test //... --test_tag_filters=spectest --repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly-21422848633
|
||||
```
|
||||
|
||||
14
testing/validator-mock/validator_client_mock.go
generated
14
testing/validator-mock/validator_client_mock.go
generated
@@ -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.
|
||||
|
||||
12
testing/validator-mock/validator_mock.go
generated
12
testing/validator-mock/validator_mock.go
generated
@@ -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.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
diff -urN a/BUILD.bazel b/BUILD.bazel
|
||||
--- a/BUILD.bazel 1969-12-31 18:00:00.000000000 -0600
|
||||
+++ b/BUILD.bazel 2025-01-05 12:00:00.000000000 -0600
|
||||
@@ -0,0 +1,89 @@
|
||||
@@ -0,0 +1,90 @@
|
||||
+load("@io_bazel_rules_go//go:def.bzl", "go_library")
|
||||
+
|
||||
+go_library(
|
||||
@@ -32,6 +32,7 @@ diff -urN a/BUILD.bazel b/BUILD.bazel
|
||||
+ ],
|
||||
+ "@io_bazel_rules_go//go/platform:darwin_amd64": [
|
||||
+ "bindings_darwin_amd64.go",
|
||||
+ "wrapper_darwin_amd64.s",
|
||||
+ ],
|
||||
+ "//conditions:default": [],
|
||||
+ }),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
# bazel build @consensus_spec_tests//:test_data
|
||||
# bazel build @consensus_spec_tests//:test_data --repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly
|
||||
# bazel build @consensus_spec_tests//:test_data --repo_env=CONSENSUS_SPEC_TESTS_VERSION=nightly-<run_id>
|
||||
|
||||
def _get_redirected_url(repository_ctx, url, headers):
|
||||
if not repository_ctx.which("curl"):
|
||||
@@ -24,7 +25,7 @@ def _impl(repository_ctx):
|
||||
version = repository_ctx.getenv("CONSENSUS_SPEC_TESTS_VERSION") or repository_ctx.attr.version
|
||||
token = repository_ctx.getenv("GITHUB_TOKEN") or ""
|
||||
|
||||
if version == "nightly":
|
||||
if version == "nightly" or version.startswith("nightly-"):
|
||||
print("Downloading nightly tests")
|
||||
if not token:
|
||||
fail("Error GITHUB_TOKEN is not set")
|
||||
@@ -34,16 +35,22 @@ def _impl(repository_ctx):
|
||||
"Accept": "application/vnd.github+json",
|
||||
}
|
||||
|
||||
repository_ctx.download(
|
||||
"https://api.github.com/repos/%s/actions/workflows/%s/runs?branch=%s&status=success&per_page=1"
|
||||
% (repository_ctx.attr.repo, repository_ctx.attr.workflow, repository_ctx.attr.branch),
|
||||
headers = headers,
|
||||
output = "runs.json"
|
||||
)
|
||||
if version.startswith("nightly-"):
|
||||
run_id = version.split("nightly-", 1)[1]
|
||||
if not run_id:
|
||||
fail("Error invalid run id")
|
||||
else:
|
||||
repository_ctx.download(
|
||||
"https://api.github.com/repos/%s/actions/workflows/%s/runs?branch=%s&status=success&per_page=1"
|
||||
% (repository_ctx.attr.repo, repository_ctx.attr.workflow, repository_ctx.attr.branch),
|
||||
headers = headers,
|
||||
output = "runs.json"
|
||||
)
|
||||
|
||||
run_id = json.decode(repository_ctx.read("runs.json"))["workflow_runs"][0]["id"]
|
||||
repository_ctx.delete("runs.json")
|
||||
run_id = json.decode(repository_ctx.read("runs.json"))["workflow_runs"][0]["id"]
|
||||
repository_ctx.delete("runs.json")
|
||||
|
||||
print("Run id:", run_id)
|
||||
repository_ctx.download(
|
||||
"https://api.github.com/repos/%s/actions/runs/%s/artifacts"
|
||||
% (repository_ctx.attr.repo, run_id),
|
||||
@@ -108,8 +115,8 @@ consensus_spec_tests = repository_rule(
|
||||
"version": attr.string(mandatory = True),
|
||||
"flavors": attr.string_dict(mandatory = True),
|
||||
"repo": attr.string(default = "ethereum/consensus-specs"),
|
||||
"workflow": attr.string(default = "generate_vectors.yml"),
|
||||
"branch": attr.string(default = "dev"),
|
||||
"workflow": attr.string(default = "nightly-reftests.yml"),
|
||||
"branch": attr.string(default = "master"),
|
||||
"release_url_template": attr.string(default = "https://github.com/ethereum/consensus-specs/releases/download/%s"),
|
||||
},
|
||||
)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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, ðpb.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, ðpb.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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
ðpb.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,
|
||||
ðpb.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,
|
||||
ðpb.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
|
||||
|
||||
@@ -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")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -26,5 +26,5 @@ func (c *beaconApiValidatorClient) prepareBeaconProposer(ctx context.Context, re
|
||||
return errors.Wrap(err, "failed to marshal recipients")
|
||||
}
|
||||
|
||||
return c.jsonRestHandler.Post(ctx, "/eth/v1/validator/prepare_beacon_proposer", nil, bytes.NewBuffer(marshalledJsonRecipients), nil)
|
||||
return c.handler.Post(ctx, "/eth/v1/validator/prepare_beacon_proposer", nil, bytes.NewBuffer(marshalledJsonRecipients), nil)
|
||||
}
|
||||
|
||||
@@ -45,8 +45,8 @@ func TestPrepareBeaconProposer_Valid(t *testing.T) {
|
||||
marshalledJsonRecipients, err := json.Marshal(jsonRecipients)
|
||||
require.NoError(t, err)
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
handler := mock.NewMockJsonRestHandler(ctrl)
|
||||
handler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
prepareBeaconProposerTestEndpoint,
|
||||
nil,
|
||||
@@ -78,7 +78,7 @@ func TestPrepareBeaconProposer_Valid(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
validatorClient := &beaconApiValidatorClient{handler: handler}
|
||||
err = validatorClient.prepareBeaconProposer(ctx, protoRecipients)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -89,8 +89,8 @@ func TestPrepareBeaconProposer_BadRequest(t *testing.T) {
|
||||
|
||||
ctx := t.Context()
|
||||
|
||||
jsonRestHandler := mock.NewMockJsonRestHandler(ctrl)
|
||||
jsonRestHandler.EXPECT().Post(
|
||||
handler := mock.NewMockJsonRestHandler(ctrl)
|
||||
handler.EXPECT().Post(
|
||||
gomock.Any(),
|
||||
prepareBeaconProposerTestEndpoint,
|
||||
nil,
|
||||
@@ -100,7 +100,7 @@ func TestPrepareBeaconProposer_BadRequest(t *testing.T) {
|
||||
errors.New("foo error"),
|
||||
).Times(1)
|
||||
|
||||
validatorClient := &beaconApiValidatorClient{jsonRestHandler: jsonRestHandler}
|
||||
validatorClient := &beaconApiValidatorClient{handler: handler}
|
||||
err := validatorClient.prepareBeaconProposer(ctx, nil)
|
||||
assert.ErrorContains(t, "foo error", err)
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user