mirror of
https://github.com/wealdtech/ethdo.git
synced 2026-01-08 21:48:05 -05:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b450e96dde | ||
|
|
30d7f6989a | ||
|
|
00ea75e5c8 | ||
|
|
34647927ab | ||
|
|
44cfb68e2c | ||
|
|
70df67e6ab | ||
|
|
08fb16ff9e | ||
|
|
903ecc8581 | ||
|
|
93f4f6d68c | ||
|
|
1eee5a1349 | ||
|
|
9c4e9bcb2f | ||
|
|
83a950e5d1 | ||
|
|
b2c0ae3fa2 | ||
|
|
3059aa270f | ||
|
|
8b7aab7180 | ||
|
|
c46483586d | ||
|
|
e4f0b934d7 | ||
|
|
25a5bd917f | ||
|
|
889a884f6e | ||
|
|
1c23926295 | ||
|
|
992a969eaf | ||
|
|
58d8587471 |
55
.github/workflows/docker.yml
vendored
55
.github/workflows/docker.yml
vendored
@@ -1,58 +1,45 @@
|
||||
name: Docker
|
||||
|
||||
# This workflow is triggered on a push to a tag that follows semantic versioning
|
||||
# e.g., v1.2.3, v2.0.0-rc1
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- 'v[0-9]+.[0-9]+.[0-9]+**'
|
||||
|
||||
jobs:
|
||||
# Set variables that will be available to all builds.
|
||||
env_vars:
|
||||
# Build and push the Docker image
|
||||
build-and-push:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
release_version: ${{ steps.release_version.outputs.release_version }}
|
||||
binary: ${{ steps.binary.outputs.binary }}
|
||||
steps:
|
||||
- id: release_version
|
||||
run: |
|
||||
RELEASE_VERSION=$(echo ${{ github.ref_name }} | sed -e 's/^[vt]//')
|
||||
echo "release_version=${RELEASE_VERSION}" >> $GITHUB_OUTPUT
|
||||
- id: binary
|
||||
run: |
|
||||
BINARY=$(basename ${{ github.repository }})
|
||||
echo "binary=${BINARY}" >> $GITHUB_OUTPUT
|
||||
- name: Check out repository
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Build.
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [env_vars]
|
||||
steps:
|
||||
- name: Check out repository into the Go module directory
|
||||
uses: actions/checkout@v3
|
||||
# This step extracts the version number from the tag
|
||||
# e.g., if the tag is 'v1.2.3', this will output '1.2.3'
|
||||
- name: Extract release version
|
||||
id: release_version
|
||||
run: |
|
||||
echo "version=$(echo ${{ github.ref_name }} | sed -e 's/^v//')" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Login to Docker Hub
|
||||
uses: docker/login-action@v2
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64/v8
|
||||
push: true
|
||||
tags: wealdtech/ethdo:latest
|
||||
|
||||
- name: build and push on release
|
||||
uses: docker/build-push-action@v4
|
||||
if: ${{ github.event.release.tag_name != '' }}
|
||||
with:
|
||||
context: .
|
||||
platforms: linux/amd64,linux/arm64/v8
|
||||
push: true
|
||||
tags: wealdtech/ethdo:${{ github.event.release.tag_name }}
|
||||
tags: |
|
||||
wealdtech/ethdo:${{ steps.release_version.outputs.version }}
|
||||
wealdtech/ethdo:latest
|
||||
|
||||
16
CHANGELOG.md
16
CHANGELOG.md
@@ -1,3 +1,19 @@
|
||||
dev:
|
||||
|
||||
1.39.0:
|
||||
- support Fulu
|
||||
|
||||
1.38.0:
|
||||
- update latest version of go-eth2-client to support complex Spec types
|
||||
- adapt event handling to use new event handler structures in go-eth2-client
|
||||
|
||||
1.37.4:
|
||||
- add support for eip-7044 in exit verify command
|
||||
- provide ETH values as well as validator numbers in "epoch summary"
|
||||
|
||||
1.37.3:
|
||||
- add "hoodi" to the list of supported networks
|
||||
|
||||
1.37.2:
|
||||
- add "block trail"
|
||||
|
||||
|
||||
@@ -528,6 +528,13 @@ func (c *command) analyzeSyncCommittees(_ context.Context, block *spec.Versioned
|
||||
c.analysis.SyncCommitee.Value = c.analysis.SyncCommitee.Score * float64(c.analysis.SyncCommitee.Contributions)
|
||||
c.analysis.Value += c.analysis.SyncCommitee.Value
|
||||
return nil
|
||||
case spec.DataVersionFulu:
|
||||
c.analysis.SyncCommitee.Contributions = int(block.Fulu.Message.Body.SyncAggregate.SyncCommitteeBits.Count())
|
||||
c.analysis.SyncCommitee.PossibleContributions = int(block.Fulu.Message.Body.SyncAggregate.SyncCommitteeBits.Len())
|
||||
c.analysis.SyncCommitee.Score = float64(c.syncRewardWeight) / float64(c.weightDenominator)
|
||||
c.analysis.SyncCommitee.Value = c.analysis.SyncCommitee.Score * float64(c.analysis.SyncCommitee.Contributions)
|
||||
c.analysis.Value += c.analysis.SyncCommitee.Value
|
||||
return nil
|
||||
default:
|
||||
return fmt.Errorf("unsupported block version %d", block.Version)
|
||||
}
|
||||
|
||||
@@ -90,6 +90,8 @@ func process(ctx context.Context, data *dataIn) (*dataOut, error) {
|
||||
err = processDenebBlock(ctx, data, block)
|
||||
case spec.DataVersionElectra:
|
||||
err = processElectraBlock(ctx, data, block)
|
||||
case spec.DataVersionFulu:
|
||||
err = processFuluBlock(ctx, data, block)
|
||||
default:
|
||||
return nil, errors.New("unknown block version")
|
||||
}
|
||||
@@ -103,7 +105,10 @@ func process(ctx context.Context, data *dataIn) (*dataOut, error) {
|
||||
if !jsonOutput && !sszOutput {
|
||||
fmt.Println("")
|
||||
}
|
||||
err := data.eth2Client.(eth2client.EventsProvider).Events(ctx, []string{"head"}, headEventHandler)
|
||||
err := data.eth2Client.(eth2client.EventsProvider).Events(ctx, &api.EventsOpts{
|
||||
Topics: []string{"head"},
|
||||
HeadHandler: headEventHandler,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to start block stream")
|
||||
}
|
||||
@@ -212,15 +217,37 @@ func processElectraBlock(ctx context.Context,
|
||||
return nil
|
||||
}
|
||||
|
||||
func headEventHandler(event *apiv1.Event) {
|
||||
ctx := context.Background()
|
||||
|
||||
// Only interested in head events.
|
||||
if event.Topic != "head" {
|
||||
return
|
||||
func processFuluBlock(ctx context.Context,
|
||||
data *dataIn,
|
||||
block *spec.VersionedSignedBeaconBlock,
|
||||
) error {
|
||||
var blobSidecars []*deneb.BlobSidecar
|
||||
kzgCommitments, err := block.BlobKZGCommitments()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(kzgCommitments) > 0 {
|
||||
blobSidecarsResponse, err := results.eth2Client.(eth2client.BlobSidecarsProvider).BlobSidecars(ctx, &api.BlobSidecarsOpts{
|
||||
Block: data.blockID,
|
||||
})
|
||||
if err != nil {
|
||||
var apiErr *api.Error
|
||||
if errors.As(err, &apiErr) && apiErr.StatusCode != http.StatusNotFound {
|
||||
return errors.Wrap(err, "failed to obtain blob sidecars")
|
||||
}
|
||||
} else {
|
||||
blobSidecars = blobSidecarsResponse.Data
|
||||
}
|
||||
}
|
||||
if err := outputFuluBlock(ctx, data.jsonOutput, data.sszOutput, block.Fulu, blobSidecars); err != nil {
|
||||
return errors.Wrap(err, "failed to output block")
|
||||
}
|
||||
|
||||
blockID := fmt.Sprintf("%#x", event.Data.(*apiv1.HeadEvent).Block[:])
|
||||
return nil
|
||||
}
|
||||
|
||||
func headEventHandler(ctx context.Context, headEvent *apiv1.HeadEvent) {
|
||||
blockID := fmt.Sprintf("%#x", headEvent.Block[:])
|
||||
blockResponse, err := results.eth2Client.(eth2client.SignedBeaconBlockProvider).SignedBeaconBlock(ctx, &api.SignedBeaconBlockOpts{
|
||||
Block: blockID,
|
||||
})
|
||||
@@ -267,6 +294,46 @@ func headEventHandler(event *apiv1.Event) {
|
||||
blobSidecars = blobSidecarsResponse.Data
|
||||
}
|
||||
err = outputDenebBlock(context.Background(), jsonOutput, sszOutput, block.Deneb, blobSidecars)
|
||||
case spec.DataVersionElectra:
|
||||
var blobSidecars []*deneb.BlobSidecar
|
||||
var kzgCommitments []deneb.KZGCommitment
|
||||
kzgCommitments, err = block.BlobKZGCommitments()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to obtain KZG commitments: %v\n", err)
|
||||
return
|
||||
}
|
||||
if len(kzgCommitments) > 0 {
|
||||
var blobSidecarsResponse *api.Response[[]*deneb.BlobSidecar]
|
||||
blobSidecarsResponse, err = results.eth2Client.(eth2client.BlobSidecarsProvider).BlobSidecars(ctx, &api.BlobSidecarsOpts{
|
||||
Block: blockID,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to obtain blob sidecars: %v\n", err)
|
||||
return
|
||||
}
|
||||
blobSidecars = blobSidecarsResponse.Data
|
||||
}
|
||||
err = outputElectraBlock(context.Background(), jsonOutput, sszOutput, block.Electra, blobSidecars)
|
||||
case spec.DataVersionFulu:
|
||||
var blobSidecars []*deneb.BlobSidecar
|
||||
var kzgCommitments []deneb.KZGCommitment
|
||||
kzgCommitments, err = block.BlobKZGCommitments()
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to obtain KZG commitments: %v\n", err)
|
||||
return
|
||||
}
|
||||
if len(kzgCommitments) > 0 {
|
||||
var blobSidecarsResponse *api.Response[[]*deneb.BlobSidecar]
|
||||
blobSidecarsResponse, err = results.eth2Client.(eth2client.BlobSidecarsProvider).BlobSidecars(ctx, &api.BlobSidecarsOpts{
|
||||
Block: blockID,
|
||||
})
|
||||
if err != nil {
|
||||
fmt.Fprintf(os.Stderr, "Failed to obtain blob sidecars: %v\n", err)
|
||||
return
|
||||
}
|
||||
blobSidecars = blobSidecarsResponse.Data
|
||||
}
|
||||
err = outputFuluBlock(context.Background(), jsonOutput, sszOutput, block.Fulu, blobSidecars)
|
||||
default:
|
||||
err = errors.New("unknown block version")
|
||||
}
|
||||
@@ -428,6 +495,35 @@ func outputElectraBlock(ctx context.Context,
|
||||
return nil
|
||||
}
|
||||
|
||||
func outputFuluBlock(ctx context.Context,
|
||||
jsonOutput bool,
|
||||
sszOutput bool,
|
||||
signedBlock *electra.SignedBeaconBlock,
|
||||
blobs []*deneb.BlobSidecar,
|
||||
) error {
|
||||
switch {
|
||||
case jsonOutput:
|
||||
data, err := json.Marshal(signedBlock)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to generate JSON")
|
||||
}
|
||||
fmt.Printf("%s\n", string(data))
|
||||
case sszOutput:
|
||||
data, err := signedBlock.MarshalSSZ()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to generate SSZ")
|
||||
}
|
||||
fmt.Printf("%x\n", data)
|
||||
default:
|
||||
data, err := outputElectraBlockText(ctx, results, signedBlock, blobs)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to generate text")
|
||||
}
|
||||
fmt.Print(data)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func timeToBlockID(ctx context.Context, eth2Client eth2client.Service, input string) (string, error) {
|
||||
var timestamp time.Time
|
||||
|
||||
|
||||
@@ -100,6 +100,9 @@ func (c *command) process(ctx context.Context) error {
|
||||
case spec.DataVersionElectra:
|
||||
c.incumbent = state.Electra.ETH1Data
|
||||
c.eth1DataVotes = state.Electra.ETH1DataVotes
|
||||
case spec.DataVersionFulu:
|
||||
c.incumbent = state.Fulu.ETH1Data
|
||||
c.eth1DataVotes = state.Fulu.ETH1DataVotes
|
||||
default:
|
||||
return fmt.Errorf("unhandled beacon state version %v", state.Version)
|
||||
}
|
||||
|
||||
@@ -97,7 +97,7 @@ In quiet mode this will return 0 if the chain status can be obtained, otherwise
|
||||
res.WriteString(fmt.Sprintf("%d", headSlot))
|
||||
if headSlot != slot {
|
||||
if slot-headSlot == 1 {
|
||||
res.WriteString("(1 slot behind)")
|
||||
res.WriteString(" (1 slot behind)")
|
||||
} else {
|
||||
res.WriteString(" (")
|
||||
res.WriteString(fmt.Sprintf("%d", slot-headSlot))
|
||||
|
||||
@@ -15,9 +15,11 @@ package epochsummary
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
eth2client "github.com/attestantio/go-eth2-client"
|
||||
apiv1 "github.com/attestantio/go-eth2-client/api/v1"
|
||||
"github.com/attestantio/go-eth2-client/spec"
|
||||
"github.com/attestantio/go-eth2-client/spec/phase0"
|
||||
"github.com/pkg/errors"
|
||||
@@ -52,6 +54,16 @@ type command struct {
|
||||
beaconCommitteesProvider eth2client.BeaconCommitteesProvider
|
||||
beaconBlockHeadersProvider eth2client.BeaconBlockHeadersProvider
|
||||
|
||||
// Intermediate data.
|
||||
validatorInfo map[phase0.ValidatorIndex]*apiv1.Validator
|
||||
participatingValidators map[phase0.ValidatorIndex]struct{}
|
||||
headCorrectValidators map[phase0.ValidatorIndex]struct{}
|
||||
headTimelyValidators map[phase0.ValidatorIndex]struct{}
|
||||
sourceTimelyValidators map[phase0.ValidatorIndex]struct{}
|
||||
targetCorrectValidators map[phase0.ValidatorIndex]struct{}
|
||||
targetTimelyValidators map[phase0.ValidatorIndex]struct{}
|
||||
participations map[phase0.ValidatorIndex]*attestingValidator
|
||||
|
||||
// Caches.
|
||||
blocksCache map[string]*spec.VersionedSignedBeaconBlock
|
||||
|
||||
@@ -68,12 +80,19 @@ type epochSummary struct {
|
||||
SyncCommitteeValidators int `json:"sync_committee_validators"`
|
||||
SyncCommittee []*epochSyncCommittee `json:"sync_committees"`
|
||||
ActiveValidators int `json:"active_validators"`
|
||||
ActiveBalance *big.Int `json:"active_balance"`
|
||||
ParticipatingValidators int `json:"participating_validators"`
|
||||
ParticipatingBalance *big.Int `json:"participating_balance"`
|
||||
HeadCorrectValidators int `json:"head_correct_validators"`
|
||||
HeadCorrectBalance *big.Int `json:"head_correct_balance"`
|
||||
HeadTimelyValidators int `json:"head_timely_validators"`
|
||||
HeadTimelyBalance *big.Int `json:"head_timely_balance"`
|
||||
SourceTimelyValidators int `json:"source_timely_validators"`
|
||||
SourceTimelyBalance *big.Int `json:"source_timely_balance"`
|
||||
TargetCorrectValidators int `json:"target_correct_validators"`
|
||||
TargetCorrectBalance *big.Int `json:"target_correct_balance"`
|
||||
TargetTimelyValidators int `json:"target_timely_validators"`
|
||||
TargetTimelyBalance *big.Int `json:"target_timely_balance"`
|
||||
NonParticipatingValidators []*attestingValidator `json:"nonparticipating_validators"`
|
||||
NonHeadCorrectValidators []*attestingValidator `json:"nonheadcorrect_validators"`
|
||||
NonHeadTimelyValidators []*attestingValidator `json:"nonheadtimely_validators"`
|
||||
@@ -95,14 +114,15 @@ type epochSyncCommittee struct {
|
||||
}
|
||||
|
||||
type attestingValidator struct {
|
||||
Validator phase0.ValidatorIndex `json:"validator_index"`
|
||||
Slot phase0.Slot `json:"slot"`
|
||||
Committee phase0.CommitteeIndex `json:"committee_index"`
|
||||
HeadVote *phase0.Root `json:"head_vote,omitempty"`
|
||||
Head *phase0.Root `json:"head,omitempty"`
|
||||
TargetVote *phase0.Root `json:"target_vote,omitempty"`
|
||||
Target *phase0.Root `json:"target,omitempty"`
|
||||
InclusionSlot phase0.Slot `json:"inclusion_slot,omitempty"`
|
||||
Validator phase0.ValidatorIndex `json:"validator_index"`
|
||||
EffectiveBalance phase0.Gwei `json:"effective_balance"`
|
||||
Slot phase0.Slot `json:"slot"`
|
||||
Committee phase0.CommitteeIndex `json:"committee_index"`
|
||||
HeadVote *phase0.Root `json:"head_vote,omitempty"`
|
||||
Head *phase0.Root `json:"head,omitempty"`
|
||||
TargetVote *phase0.Root `json:"target_vote,omitempty"`
|
||||
Target *phase0.Root `json:"target,omitempty"`
|
||||
InclusionSlot phase0.Slot `json:"inclusion_slot,omitempty"`
|
||||
}
|
||||
|
||||
func newCommand(_ context.Context) (*command, error) {
|
||||
@@ -112,10 +132,24 @@ func newCommand(_ context.Context) (*command, error) {
|
||||
debug: viper.GetBool("debug"),
|
||||
validatorsStr: viper.GetStringSlice("validators"),
|
||||
summary: &epochSummary{
|
||||
Proposals: make([]*epochProposal, 0),
|
||||
Proposals: make([]*epochProposal, 0),
|
||||
ActiveBalance: big.NewInt(0),
|
||||
ParticipatingBalance: big.NewInt(0),
|
||||
HeadCorrectBalance: big.NewInt(0),
|
||||
HeadTimelyBalance: big.NewInt(0),
|
||||
SourceTimelyBalance: big.NewInt(0),
|
||||
TargetCorrectBalance: big.NewInt(0),
|
||||
TargetTimelyBalance: big.NewInt(0),
|
||||
},
|
||||
validators: make(map[phase0.ValidatorIndex]struct{}),
|
||||
blocksCache: make(map[string]*spec.VersionedSignedBeaconBlock),
|
||||
validators: make(map[phase0.ValidatorIndex]struct{}),
|
||||
participatingValidators: make(map[phase0.ValidatorIndex]struct{}),
|
||||
headCorrectValidators: make(map[phase0.ValidatorIndex]struct{}),
|
||||
headTimelyValidators: make(map[phase0.ValidatorIndex]struct{}),
|
||||
sourceTimelyValidators: make(map[phase0.ValidatorIndex]struct{}),
|
||||
targetCorrectValidators: make(map[phase0.ValidatorIndex]struct{}),
|
||||
targetTimelyValidators: make(map[phase0.ValidatorIndex]struct{}),
|
||||
participations: make(map[phase0.ValidatorIndex]*attestingValidator),
|
||||
blocksCache: make(map[string]*spec.VersionedSignedBeaconBlock),
|
||||
}
|
||||
|
||||
// Timeout.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright © 2022 Weald Technology Trading.
|
||||
// Copyright © 2022, 2025 Weald Technology Trading.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@@ -69,12 +70,80 @@ func (c *command) outputTxt(_ context.Context) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
builder.WriteString(fmt.Sprintf("\n Attestations: %d/%d (%0.2f%%)", c.summary.ParticipatingValidators, c.summary.ActiveValidators, 100.0*float64(c.summary.ParticipatingValidators)/float64(c.summary.ActiveValidators)))
|
||||
builder.WriteString(fmt.Sprintf("\n Source timely: %d/%d (%0.2f%%)", c.summary.SourceTimelyValidators, c.summary.ActiveValidators, 100.0*float64(c.summary.SourceTimelyValidators)/float64(c.summary.ActiveValidators)))
|
||||
builder.WriteString(fmt.Sprintf("\n Target correct: %d/%d (%0.2f%%)", c.summary.TargetCorrectValidators, c.summary.ActiveValidators, 100.0*float64(c.summary.TargetCorrectValidators)/float64(c.summary.ActiveValidators)))
|
||||
builder.WriteString(fmt.Sprintf("\n Target timely: %d/%d (%0.2f%%)", c.summary.TargetTimelyValidators, c.summary.ActiveValidators, 100.0*float64(c.summary.TargetTimelyValidators)/float64(c.summary.ActiveValidators)))
|
||||
builder.WriteString(fmt.Sprintf("\n Head correct: %d/%d (%0.2f%%)", c.summary.HeadCorrectValidators, c.summary.ActiveValidators, 100.0*float64(c.summary.HeadCorrectValidators)/float64(c.summary.ActiveValidators)))
|
||||
builder.WriteString(fmt.Sprintf("\n Head timely: %d/%d (%0.2f%%)", c.summary.HeadTimelyValidators, c.summary.ActiveValidators, 100.0*float64(c.summary.HeadTimelyValidators)/float64(c.summary.ActiveValidators)))
|
||||
gweiToEth := big.NewInt(1e9)
|
||||
mul := big.NewInt(10000)
|
||||
participatingBalancePct := new(big.Int).Div(new(big.Int).Mul(c.summary.ParticipatingBalance, mul), c.summary.ActiveBalance)
|
||||
builder.WriteString(fmt.Sprintf("\n Attesting balance: %s/%s (%0.2f%%)",
|
||||
new(big.Int).Div(c.summary.ParticipatingBalance, gweiToEth).String(),
|
||||
new(big.Int).Div(c.summary.ActiveBalance, gweiToEth).String(),
|
||||
float64(participatingBalancePct.Uint64())/100.0,
|
||||
))
|
||||
|
||||
sourceTimelyBalancePct := new(big.Int).Div(new(big.Int).Mul(c.summary.SourceTimelyBalance, mul), c.summary.ActiveBalance)
|
||||
builder.WriteString(fmt.Sprintf("\n Source timely: %s/%s (%0.2f%%)",
|
||||
new(big.Int).Div(c.summary.SourceTimelyBalance, gweiToEth).String(),
|
||||
new(big.Int).Div(c.summary.ActiveBalance, gweiToEth).String(),
|
||||
float64(sourceTimelyBalancePct.Uint64())/100.0,
|
||||
))
|
||||
|
||||
targetCorrectBalancePct := new(big.Int).Div(new(big.Int).Mul(c.summary.TargetCorrectBalance, mul), c.summary.ActiveBalance)
|
||||
builder.WriteString(fmt.Sprintf("\n Target correct: %s/%s (%0.2f%%)",
|
||||
new(big.Int).Div(c.summary.TargetCorrectBalance, gweiToEth).String(),
|
||||
new(big.Int).Div(c.summary.ActiveBalance, gweiToEth).String(),
|
||||
float64(targetCorrectBalancePct.Uint64())/100.0,
|
||||
))
|
||||
|
||||
targetTimelyBalancePct := new(big.Int).Div(new(big.Int).Mul(c.summary.TargetTimelyBalance, mul), c.summary.ActiveBalance)
|
||||
builder.WriteString(fmt.Sprintf("\n Target timely: %s/%s (%0.2f%%)",
|
||||
new(big.Int).Div(c.summary.TargetTimelyBalance, gweiToEth).String(),
|
||||
new(big.Int).Div(c.summary.ActiveBalance, gweiToEth).String(),
|
||||
float64(targetTimelyBalancePct.Uint64())/100.0,
|
||||
))
|
||||
|
||||
headCorrectBalancePct := new(big.Int).Div(new(big.Int).Mul(c.summary.HeadCorrectBalance, mul), c.summary.ActiveBalance)
|
||||
builder.WriteString(fmt.Sprintf("\n Head correct: %s/%s (%0.2f%%)",
|
||||
new(big.Int).Div(c.summary.HeadCorrectBalance, gweiToEth).String(),
|
||||
new(big.Int).Div(c.summary.ActiveBalance, gweiToEth).String(),
|
||||
float64(headCorrectBalancePct.Uint64())/100.0,
|
||||
))
|
||||
|
||||
headTimelyBalancePct := new(big.Int).Div(new(big.Int).Mul(c.summary.HeadTimelyBalance, mul), c.summary.ActiveBalance)
|
||||
builder.WriteString(fmt.Sprintf("\n Head timely: %s/%s (%0.2f%%)",
|
||||
new(big.Int).Div(c.summary.HeadTimelyBalance, gweiToEth).String(),
|
||||
new(big.Int).Div(c.summary.ActiveBalance, gweiToEth).String(),
|
||||
float64(headTimelyBalancePct.Uint64())/100.0,
|
||||
))
|
||||
|
||||
builder.WriteString(fmt.Sprintf("\n Attesting validators: %d/%d (%0.2f%%)",
|
||||
c.summary.ParticipatingValidators,
|
||||
c.summary.ActiveValidators,
|
||||
100.0*float64(c.summary.ParticipatingValidators)/float64(c.summary.ActiveValidators),
|
||||
))
|
||||
builder.WriteString(fmt.Sprintf("\n Source timely: %d/%d (%0.2f%%)",
|
||||
c.summary.SourceTimelyValidators,
|
||||
c.summary.ActiveValidators,
|
||||
100.0*float64(c.summary.SourceTimelyValidators)/float64(c.summary.ActiveValidators),
|
||||
))
|
||||
builder.WriteString(fmt.Sprintf("\n Target correct: %d/%d (%0.2f%%)",
|
||||
c.summary.TargetCorrectValidators,
|
||||
c.summary.ActiveValidators,
|
||||
100.0*float64(c.summary.TargetCorrectValidators)/float64(c.summary.ActiveValidators),
|
||||
))
|
||||
builder.WriteString(fmt.Sprintf("\n Target timely: %d/%d (%0.2f%%)",
|
||||
c.summary.TargetTimelyValidators,
|
||||
c.summary.ActiveValidators,
|
||||
100.0*float64(c.summary.TargetTimelyValidators)/float64(c.summary.ActiveValidators),
|
||||
))
|
||||
builder.WriteString(fmt.Sprintf("\n Head correct: %d/%d (%0.2f%%)",
|
||||
c.summary.HeadCorrectValidators,
|
||||
c.summary.ActiveValidators,
|
||||
100.0*float64(c.summary.HeadCorrectValidators)/float64(c.summary.ActiveValidators),
|
||||
))
|
||||
builder.WriteString(fmt.Sprintf("\n Head timely: %d/%d (%0.2f%%)",
|
||||
c.summary.HeadTimelyValidators,
|
||||
c.summary.ActiveValidators,
|
||||
100.0*float64(c.summary.HeadTimelyValidators)/float64(c.summary.ActiveValidators),
|
||||
))
|
||||
if c.verbose {
|
||||
// Sort list by validator index.
|
||||
for _, validator := range c.summary.NonParticipatingValidators {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright © 2022, 2023 Weald Technology Trading.
|
||||
// Copyright © 2022 - 2025 Weald Technology Trading.
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
@@ -16,6 +16,7 @@ package epochsummary
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"net/http"
|
||||
"sort"
|
||||
|
||||
@@ -105,12 +106,14 @@ func (c *command) activeValidators(ctx context.Context) (map[phase0.ValidatorInd
|
||||
}
|
||||
|
||||
response, err := c.validatorsProvider.Validators(ctx, &api.ValidatorsOpts{
|
||||
State: "head",
|
||||
State: fmt.Sprintf("%d", c.chainTime.FirstSlotOfEpoch(c.summary.Epoch)),
|
||||
Indices: validatorIndices,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to obtain validators for epoch")
|
||||
}
|
||||
c.validatorInfo = response.Data
|
||||
|
||||
activeValidators := make(map[phase0.ValidatorIndex]*apiv1.Validator)
|
||||
for _, validator := range response.Data {
|
||||
_, exists := c.validators[validator.Index]
|
||||
@@ -133,6 +136,10 @@ func (c *command) processAttesterDuties(ctx context.Context) error {
|
||||
}
|
||||
c.summary.ActiveValidators = len(activeValidators)
|
||||
|
||||
for _, validator := range activeValidators {
|
||||
c.summary.ActiveBalance = c.summary.ActiveBalance.Add(c.summary.ActiveBalance, big.NewInt(int64(validator.Validator.EffectiveBalance)))
|
||||
}
|
||||
|
||||
// Obtain number of validators that voted for blocks in the epoch.
|
||||
// These votes can be included anywhere from the second slot of
|
||||
// the epoch to the first slot of the next-but-one epoch.
|
||||
@@ -142,43 +149,42 @@ func (c *command) processAttesterDuties(ctx context.Context) error {
|
||||
lastSlot = c.chainTime.CurrentSlot()
|
||||
}
|
||||
|
||||
participatingValidators, headCorrectValidators, headTimelyValidators, sourceTimelyValidators, targetCorrectValidators, targetTimelyValidators, participations, err := c.processSlots(ctx, firstSlot, lastSlot)
|
||||
if err != nil {
|
||||
if err := c.processSlots(ctx, firstSlot, lastSlot); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
c.summary.ParticipatingValidators = len(participatingValidators)
|
||||
c.summary.HeadCorrectValidators = len(headCorrectValidators)
|
||||
c.summary.HeadTimelyValidators = len(headTimelyValidators)
|
||||
c.summary.SourceTimelyValidators = len(sourceTimelyValidators)
|
||||
c.summary.TargetCorrectValidators = len(targetCorrectValidators)
|
||||
c.summary.TargetTimelyValidators = len(targetTimelyValidators)
|
||||
c.summary.ParticipatingValidators = len(c.participatingValidators)
|
||||
c.summary.HeadCorrectValidators = len(c.headCorrectValidators)
|
||||
c.summary.HeadTimelyValidators = len(c.headTimelyValidators)
|
||||
c.summary.SourceTimelyValidators = len(c.sourceTimelyValidators)
|
||||
c.summary.TargetCorrectValidators = len(c.targetCorrectValidators)
|
||||
c.summary.TargetTimelyValidators = len(c.targetTimelyValidators)
|
||||
|
||||
c.summary.NonParticipatingValidators = make([]*attestingValidator, 0, len(activeValidators)-len(participatingValidators))
|
||||
c.summary.NonParticipatingValidators = make([]*attestingValidator, 0, len(activeValidators)-len(c.participatingValidators))
|
||||
for activeValidatorIndex := range activeValidators {
|
||||
if _, exists := participatingValidators[activeValidatorIndex]; !exists {
|
||||
if _, exists := participations[activeValidatorIndex]; exists {
|
||||
c.summary.NonParticipatingValidators = append(c.summary.NonParticipatingValidators, participations[activeValidatorIndex])
|
||||
if _, exists := c.participatingValidators[activeValidatorIndex]; !exists {
|
||||
if _, exists := c.participations[activeValidatorIndex]; exists {
|
||||
c.summary.NonParticipatingValidators = append(c.summary.NonParticipatingValidators, c.participations[activeValidatorIndex])
|
||||
}
|
||||
}
|
||||
if _, exists := headCorrectValidators[activeValidatorIndex]; !exists {
|
||||
if _, exists := participations[activeValidatorIndex]; exists {
|
||||
c.summary.NonHeadCorrectValidators = append(c.summary.NonHeadCorrectValidators, participations[activeValidatorIndex])
|
||||
if _, exists := c.headCorrectValidators[activeValidatorIndex]; !exists {
|
||||
if _, exists := c.participations[activeValidatorIndex]; exists {
|
||||
c.summary.NonHeadCorrectValidators = append(c.summary.NonHeadCorrectValidators, c.participations[activeValidatorIndex])
|
||||
}
|
||||
}
|
||||
if _, exists := headTimelyValidators[activeValidatorIndex]; !exists {
|
||||
if _, exists := participations[activeValidatorIndex]; exists {
|
||||
c.summary.NonHeadTimelyValidators = append(c.summary.NonHeadTimelyValidators, participations[activeValidatorIndex])
|
||||
if _, exists := c.headTimelyValidators[activeValidatorIndex]; !exists {
|
||||
if _, exists := c.participations[activeValidatorIndex]; exists {
|
||||
c.summary.NonHeadTimelyValidators = append(c.summary.NonHeadTimelyValidators, c.participations[activeValidatorIndex])
|
||||
}
|
||||
}
|
||||
if _, exists := targetCorrectValidators[activeValidatorIndex]; !exists {
|
||||
if _, exists := participations[activeValidatorIndex]; exists {
|
||||
c.summary.NonTargetCorrectValidators = append(c.summary.NonTargetCorrectValidators, participations[activeValidatorIndex])
|
||||
if _, exists := c.targetCorrectValidators[activeValidatorIndex]; !exists {
|
||||
if _, exists := c.participations[activeValidatorIndex]; exists {
|
||||
c.summary.NonTargetCorrectValidators = append(c.summary.NonTargetCorrectValidators, c.participations[activeValidatorIndex])
|
||||
}
|
||||
}
|
||||
if _, exists := sourceTimelyValidators[activeValidatorIndex]; !exists {
|
||||
if _, exists := participations[activeValidatorIndex]; exists {
|
||||
c.summary.NonSourceTimelyValidators = append(c.summary.NonSourceTimelyValidators, participations[activeValidatorIndex])
|
||||
if _, exists := c.sourceTimelyValidators[activeValidatorIndex]; !exists {
|
||||
if _, exists := c.participations[activeValidatorIndex]; exists {
|
||||
c.summary.NonSourceTimelyValidators = append(c.summary.NonSourceTimelyValidators, c.participations[activeValidatorIndex])
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -199,24 +205,8 @@ func (c *command) processAttesterDuties(ctx context.Context) error {
|
||||
func (c *command) processSlots(ctx context.Context,
|
||||
firstSlot phase0.Slot,
|
||||
lastSlot phase0.Slot,
|
||||
) (
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]*attestingValidator,
|
||||
error,
|
||||
) {
|
||||
votes := make(map[phase0.ValidatorIndex]struct{})
|
||||
headCorrects := make(map[phase0.ValidatorIndex]struct{})
|
||||
headTimelys := make(map[phase0.ValidatorIndex]struct{})
|
||||
sourceTimelys := make(map[phase0.ValidatorIndex]struct{})
|
||||
targetCorrects := make(map[phase0.ValidatorIndex]struct{})
|
||||
targetTimelys := make(map[phase0.ValidatorIndex]struct{})
|
||||
) error {
|
||||
allCommittees := make(map[phase0.Slot]map[phase0.CommitteeIndex][]phase0.ValidatorIndex)
|
||||
participations := make(map[phase0.ValidatorIndex]*attestingValidator)
|
||||
|
||||
// Need a cache of beacon block headers to reduce lookup times.
|
||||
headersCache := util.NewBeaconBlockHeaderCache(c.beaconBlockHeadersProvider)
|
||||
@@ -224,7 +214,7 @@ func (c *command) processSlots(ctx context.Context,
|
||||
for slot := firstSlot; slot <= lastSlot; slot++ {
|
||||
block, err := c.fetchBlock(ctx, fmt.Sprintf("%d", slot))
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, errors.Wrap(err, fmt.Sprintf("failed to obtain block for slot %d", slot))
|
||||
return errors.Wrap(err, fmt.Sprintf("failed to obtain block for slot %d", slot))
|
||||
}
|
||||
if block == nil {
|
||||
// No block at this slot; that's fine.
|
||||
@@ -232,16 +222,16 @@ func (c *command) processSlots(ctx context.Context,
|
||||
}
|
||||
slot, err := block.Slot()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, err
|
||||
return err
|
||||
}
|
||||
attestations, err := block.Attestations()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, err
|
||||
return err
|
||||
}
|
||||
for _, attestation := range attestations {
|
||||
attestationData, err := attestation.Data()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, errors.Wrap(err, "failed to obtain attestation data")
|
||||
return errors.Wrap(err, "failed to obtain attestation data")
|
||||
}
|
||||
if attestationData.Slot < c.chainTime.FirstSlotOfEpoch(c.summary.Epoch) || attestationData.Slot >= c.chainTime.FirstSlotOfEpoch(c.summary.Epoch+1) {
|
||||
// Outside of this epoch's range.
|
||||
@@ -253,7 +243,7 @@ func (c *command) processSlots(ctx context.Context,
|
||||
State: fmt.Sprintf("%d", attestationData.Slot),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, errors.Wrap(err, fmt.Sprintf("failed to obtain committees for slot %d", attestationData.Slot))
|
||||
return errors.Wrap(err, fmt.Sprintf("failed to obtain committees for slot %d", attestationData.Slot))
|
||||
}
|
||||
for _, beaconCommittee := range response.Data {
|
||||
if _, exists := allCommittees[beaconCommittee.Slot]; !exists {
|
||||
@@ -270,94 +260,71 @@ func (c *command) processSlots(ctx context.Context,
|
||||
}
|
||||
}
|
||||
|
||||
if _, exists := participations[index]; !exists {
|
||||
participations[index] = &attestingValidator{
|
||||
Validator: index,
|
||||
Slot: beaconCommittee.Slot,
|
||||
Committee: beaconCommittee.Index,
|
||||
if _, exists := c.participations[index]; !exists {
|
||||
c.participations[index] = &attestingValidator{
|
||||
Validator: index,
|
||||
EffectiveBalance: c.validatorInfo[index].Validator.EffectiveBalance,
|
||||
Slot: beaconCommittee.Slot,
|
||||
Committee: beaconCommittee.Index,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
slotCommittees = allCommittees[attestationData.Slot]
|
||||
}
|
||||
if attestation.Version >= spec.DataVersionElectra {
|
||||
participations, votes, headCorrects, headTimelys, sourceTimelys, targetCorrects, targetTimelys, err = c.extractElectraAttestationData(
|
||||
ctx, attestation, attestationData, slotCommittees, slot, headersCache, participations, votes, headCorrects, headTimelys, sourceTimelys, targetCorrects, targetTimelys)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, err
|
||||
}
|
||||
} else {
|
||||
participations, votes, headCorrects, headTimelys, sourceTimelys, targetCorrects, targetTimelys, err = c.extractPhase0AttestationData(
|
||||
ctx, attestation, attestationData, slotCommittees, slot, headersCache, participations, votes, headCorrects, headTimelys, sourceTimelys, targetCorrects, targetTimelys)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, err
|
||||
}
|
||||
if err := c.extractAttestationData(ctx, attestation, attestationData, slotCommittees, slot, headersCache); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return votes,
|
||||
headCorrects,
|
||||
headTimelys,
|
||||
sourceTimelys,
|
||||
targetCorrects,
|
||||
targetTimelys,
|
||||
participations,
|
||||
nil
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *command) extractPhase0AttestationData(ctx context.Context,
|
||||
func (c *command) extractAttestationData(ctx context.Context,
|
||||
attestation *spec.VersionedAttestation,
|
||||
attestationData *phase0.AttestationData,
|
||||
slotCommittees map[phase0.CommitteeIndex][]phase0.ValidatorIndex,
|
||||
slot phase0.Slot,
|
||||
headersCache *util.BeaconBlockHeaderCache,
|
||||
participations map[phase0.ValidatorIndex]*attestingValidator,
|
||||
votes map[phase0.ValidatorIndex]struct{},
|
||||
headCorrects map[phase0.ValidatorIndex]struct{},
|
||||
headTimelys map[phase0.ValidatorIndex]struct{},
|
||||
sourceTimelys map[phase0.ValidatorIndex]struct{},
|
||||
targetCorrects map[phase0.ValidatorIndex]struct{},
|
||||
targetTimelys map[phase0.ValidatorIndex]struct{},
|
||||
) (
|
||||
map[phase0.ValidatorIndex]*attestingValidator,
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
error,
|
||||
) {
|
||||
committee := slotCommittees[attestationData.Index]
|
||||
|
||||
) error {
|
||||
inclusionDistance := slot - attestationData.Slot
|
||||
|
||||
head, err := util.AttestationHead(ctx, headersCache, attestation)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, err
|
||||
return err
|
||||
}
|
||||
headCorrect, err := util.AttestationHeadCorrect(ctx, headersCache, attestation)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, err
|
||||
return err
|
||||
}
|
||||
target, err := util.AttestationTarget(ctx, headersCache, c.chainTime, attestation)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, err
|
||||
return err
|
||||
}
|
||||
targetCorrect, err := util.AttestationTargetCorrect(ctx, headersCache, c.chainTime, attestation)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
committee := slotCommittees[attestationData.Index]
|
||||
// Update with all of the committees if we have committee bits (from Electra onwards).
|
||||
committeeBits, err := attestation.CommitteeBits()
|
||||
if err == nil {
|
||||
committee = make([]phase0.ValidatorIndex, 0)
|
||||
for _, index := range committeeBits.BitIndices() {
|
||||
committee = append(committee, slotCommittees[phase0.CommitteeIndex(index)]...)
|
||||
}
|
||||
}
|
||||
|
||||
aggregationBits, err := attestation.AggregationBits()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, errors.Wrap(err, "failed to obtain aggregation bits")
|
||||
return errors.Wrap(err, "failed to obtain aggregation bits")
|
||||
}
|
||||
|
||||
for i := range aggregationBits.Len() {
|
||||
if aggregationBits.BitAt(i) {
|
||||
validatorIndex := committee[int(i)]
|
||||
validatorIndex := committee[i]
|
||||
if len(c.validators) > 0 {
|
||||
if _, exists := c.validators[validatorIndex]; !exists {
|
||||
// Not one of our validators.
|
||||
@@ -366,140 +333,43 @@ func (c *command) extractPhase0AttestationData(ctx context.Context,
|
||||
}
|
||||
|
||||
// Only set the information from the first attestation we find for this validator.
|
||||
if participations[validatorIndex].InclusionSlot == 0 {
|
||||
participations[validatorIndex].HeadVote = &attestationData.BeaconBlockRoot
|
||||
participations[validatorIndex].Head = &head
|
||||
participations[validatorIndex].TargetVote = &attestationData.Target.Root
|
||||
participations[validatorIndex].Target = &target
|
||||
participations[validatorIndex].InclusionSlot = slot
|
||||
if c.participations[validatorIndex].InclusionSlot == 0 {
|
||||
c.participations[validatorIndex].HeadVote = &attestationData.BeaconBlockRoot
|
||||
c.participations[validatorIndex].Head = &head
|
||||
c.participations[validatorIndex].TargetVote = &attestationData.Target.Root
|
||||
c.participations[validatorIndex].Target = &target
|
||||
c.participations[validatorIndex].InclusionSlot = slot
|
||||
}
|
||||
|
||||
votes[validatorIndex] = struct{}{}
|
||||
if _, exists := headCorrects[validatorIndex]; !exists && headCorrect {
|
||||
headCorrects[validatorIndex] = struct{}{}
|
||||
validatorBalance := big.NewInt(int64(c.validatorInfo[validatorIndex].Validator.EffectiveBalance))
|
||||
if _, exists := c.participatingValidators[validatorIndex]; !exists {
|
||||
c.summary.ParticipatingBalance = c.summary.ParticipatingBalance.Add(c.summary.ParticipatingBalance, validatorBalance)
|
||||
c.participatingValidators[validatorIndex] = struct{}{}
|
||||
}
|
||||
if _, exists := headTimelys[validatorIndex]; !exists && headCorrect && inclusionDistance == 1 {
|
||||
headTimelys[validatorIndex] = struct{}{}
|
||||
if _, exists := c.headCorrectValidators[validatorIndex]; !exists && headCorrect {
|
||||
c.headCorrectValidators[validatorIndex] = struct{}{}
|
||||
c.summary.HeadCorrectBalance = c.summary.HeadCorrectBalance.Add(c.summary.HeadCorrectBalance, validatorBalance)
|
||||
}
|
||||
if _, exists := sourceTimelys[validatorIndex]; !exists && inclusionDistance <= 5 {
|
||||
sourceTimelys[validatorIndex] = struct{}{}
|
||||
if _, exists := c.headTimelyValidators[validatorIndex]; !exists && headCorrect && inclusionDistance == 1 {
|
||||
c.headTimelyValidators[validatorIndex] = struct{}{}
|
||||
c.summary.HeadTimelyBalance = c.summary.HeadTimelyBalance.Add(c.summary.HeadTimelyBalance, validatorBalance)
|
||||
}
|
||||
if _, exists := targetCorrects[validatorIndex]; !exists && targetCorrect {
|
||||
targetCorrects[validatorIndex] = struct{}{}
|
||||
if _, exists := c.sourceTimelyValidators[validatorIndex]; !exists && inclusionDistance <= 5 {
|
||||
c.sourceTimelyValidators[validatorIndex] = struct{}{}
|
||||
c.summary.SourceTimelyBalance = c.summary.SourceTimelyBalance.Add(c.summary.SourceTimelyBalance, validatorBalance)
|
||||
}
|
||||
if _, exists := targetTimelys[validatorIndex]; !exists && targetCorrect && inclusionDistance <= 32 {
|
||||
targetTimelys[validatorIndex] = struct{}{}
|
||||
if _, exists := c.targetCorrectValidators[validatorIndex]; !exists && targetCorrect {
|
||||
c.targetCorrectValidators[validatorIndex] = struct{}{}
|
||||
c.summary.TargetCorrectBalance = c.summary.TargetCorrectBalance.Add(c.summary.TargetCorrectBalance, validatorBalance)
|
||||
}
|
||||
if _, exists := c.targetTimelyValidators[validatorIndex]; !exists && targetCorrect && inclusionDistance <= 32 {
|
||||
c.targetTimelyValidators[validatorIndex] = struct{}{}
|
||||
c.summary.TargetTimelyBalance = c.summary.TargetTimelyBalance.Add(c.summary.TargetTimelyBalance, validatorBalance)
|
||||
}
|
||||
}
|
||||
}
|
||||
return participations, votes, headCorrects, headTimelys, sourceTimelys, targetCorrects, targetTimelys, err
|
||||
}
|
||||
|
||||
func (c *command) extractElectraAttestationData(ctx context.Context,
|
||||
attestation *spec.VersionedAttestation,
|
||||
attestationData *phase0.AttestationData,
|
||||
slotCommittees map[phase0.CommitteeIndex][]phase0.ValidatorIndex,
|
||||
slot phase0.Slot,
|
||||
headersCache *util.BeaconBlockHeaderCache,
|
||||
participations map[phase0.ValidatorIndex]*attestingValidator,
|
||||
votes map[phase0.ValidatorIndex]struct{},
|
||||
headCorrects map[phase0.ValidatorIndex]struct{},
|
||||
headTimelys map[phase0.ValidatorIndex]struct{},
|
||||
sourceTimelys map[phase0.ValidatorIndex]struct{},
|
||||
targetCorrects map[phase0.ValidatorIndex]struct{},
|
||||
targetTimelys map[phase0.ValidatorIndex]struct{},
|
||||
) (
|
||||
map[phase0.ValidatorIndex]*attestingValidator,
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
map[phase0.ValidatorIndex]struct{},
|
||||
error,
|
||||
) {
|
||||
committeeBits, err := attestation.CommitteeBits()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, errors.Wrap(err, "failed to obtain committee bits")
|
||||
}
|
||||
for _, committeeIndex := range committeeBits.BitIndices() {
|
||||
committee := slotCommittees[phase0.CommitteeIndex(committeeIndex)]
|
||||
|
||||
inclusionDistance := slot - attestationData.Slot
|
||||
|
||||
head, err := util.AttestationHead(ctx, headersCache, attestation)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, err
|
||||
}
|
||||
headCorrect, err := util.AttestationHeadCorrect(ctx, headersCache, attestation)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, err
|
||||
}
|
||||
target, err := util.AttestationTarget(ctx, headersCache, c.chainTime, attestation)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, err
|
||||
}
|
||||
targetCorrect, err := util.AttestationTargetCorrect(ctx, headersCache, c.chainTime, attestation)
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, err
|
||||
}
|
||||
|
||||
aggregationBits, err := attestation.AggregationBits()
|
||||
if err != nil {
|
||||
return nil, nil, nil, nil, nil, nil, nil, errors.Wrap(err, "failed to obtain aggregation bits")
|
||||
}
|
||||
// Calculate the offset for the committee so we can extract the validator from the aggregate_bits.
|
||||
committeeOffset := calcCommitteeOffset(phase0.CommitteeIndex(committeeIndex), slotCommittees)
|
||||
|
||||
// Range over the committee rather than the aggregate_bits as it's the smaller set.
|
||||
for i := range committee {
|
||||
aggregateIndex := committeeOffset + uint64(i)
|
||||
if aggregationBits.BitAt(aggregateIndex) {
|
||||
validatorIndex := committee[i]
|
||||
if len(c.validators) > 0 {
|
||||
if _, exists := c.validators[validatorIndex]; !exists {
|
||||
// Not one of our validators.
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Only set the information from the first attestation we find for this validator.
|
||||
if participations[validatorIndex].InclusionSlot == 0 {
|
||||
participations[validatorIndex].HeadVote = &attestationData.BeaconBlockRoot
|
||||
participations[validatorIndex].Head = &head
|
||||
participations[validatorIndex].TargetVote = &attestationData.Target.Root
|
||||
participations[validatorIndex].Target = &target
|
||||
participations[validatorIndex].InclusionSlot = slot
|
||||
}
|
||||
|
||||
votes[validatorIndex] = struct{}{}
|
||||
if _, exists := headCorrects[validatorIndex]; !exists && headCorrect {
|
||||
headCorrects[validatorIndex] = struct{}{}
|
||||
}
|
||||
if _, exists := headTimelys[validatorIndex]; !exists && headCorrect && inclusionDistance == 1 {
|
||||
headTimelys[validatorIndex] = struct{}{}
|
||||
}
|
||||
if _, exists := sourceTimelys[validatorIndex]; !exists && inclusionDistance <= 5 {
|
||||
sourceTimelys[validatorIndex] = struct{}{}
|
||||
}
|
||||
if _, exists := targetCorrects[validatorIndex]; !exists && targetCorrect {
|
||||
targetCorrects[validatorIndex] = struct{}{}
|
||||
}
|
||||
if _, exists := targetTimelys[validatorIndex]; !exists && targetCorrect && inclusionDistance <= 32 {
|
||||
targetTimelys[validatorIndex] = struct{}{}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return participations, votes, headCorrects, headTimelys, sourceTimelys, targetCorrects, targetTimelys, err
|
||||
}
|
||||
|
||||
func calcCommitteeOffset(committeeIndex phase0.CommitteeIndex, slotCommittees map[phase0.CommitteeIndex][]phase0.ValidatorIndex) uint64 {
|
||||
var total uint64
|
||||
for i := range committeeIndex {
|
||||
total += uint64(len(slotCommittees[i]))
|
||||
}
|
||||
return total
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *command) processSyncCommitteeDuties(ctx context.Context) error {
|
||||
@@ -556,8 +426,10 @@ func (c *command) processSyncCommitteeDuties(ctx context.Context) error {
|
||||
for i := range aggregate.SyncCommitteeBits.Len() {
|
||||
validatorIndex := committee.Validators[int(i)]
|
||||
if _, exists := c.validators[validatorIndex]; !exists {
|
||||
// Not one of ours.
|
||||
continue
|
||||
if len(c.validators) > 0 {
|
||||
// Not one of ours.
|
||||
continue
|
||||
}
|
||||
}
|
||||
if !aggregate.SyncCommitteeBits.BitAt(i) {
|
||||
missed[validatorIndex]++
|
||||
@@ -657,6 +529,8 @@ func (c *command) processBlobs(ctx context.Context) error {
|
||||
c.summary.Blobs += len(block.Deneb.Message.Body.BlobKZGCommitments)
|
||||
case spec.DataVersionElectra:
|
||||
c.summary.Blobs += len(block.Electra.Message.Body.BlobKZGCommitments)
|
||||
case spec.DataVersionFulu:
|
||||
c.summary.Blobs += len(block.Fulu.Message.Body.BlobKZGCommitments)
|
||||
default:
|
||||
return fmt.Errorf("unhandled block version %v", block.Version)
|
||||
}
|
||||
|
||||
@@ -72,32 +72,35 @@ In quiet mode this will return 0 if the exit is verified correctly, otherwise 1.
|
||||
errCheck(err, "Failed to obtain beacon chain genesis")
|
||||
genesis := genesisResponse.Data
|
||||
|
||||
response, err := eth2Client.(consensusclient.ForkProvider).Fork(ctx, &api.ForkOpts{State: "head"})
|
||||
errCheck(err, "Failed to obtain fork information")
|
||||
response, err := eth2Client.(consensusclient.SpecProvider).Spec(ctx, &api.SpecOpts{})
|
||||
errCheck(err, "Failed to obtain spec information")
|
||||
|
||||
// Check against current and prior fork versions.
|
||||
// Check against Capella fork version (EIP-7044)
|
||||
signatureBytes := make([]byte, 96)
|
||||
copy(signatureBytes, signedOp.Signature[:])
|
||||
sig, err := e2types.BLSSignatureFromBytes(signatureBytes)
|
||||
errCheck(err, "Invalid signature")
|
||||
|
||||
verified := false
|
||||
|
||||
// Try with the current fork.
|
||||
domain := phase0.Domain{}
|
||||
currentExitDomain, err := e2types.ComputeDomain(e2types.DomainVoluntaryExit, response.Data.CurrentVersion[:], genesis.GenesisValidatorsRoot[:])
|
||||
errCheck(err, "Failed to compute domain")
|
||||
copy(domain[:], currentExitDomain)
|
||||
verified, err = util.VerifyRoot(account, opRoot, domain, sig)
|
||||
errCheck(err, "Failed to verify voluntary exit")
|
||||
if !verified {
|
||||
// Try again with the previous fork.
|
||||
previousExitDomain, err := e2types.ComputeDomain(e2types.DomainVoluntaryExit, response.Data.PreviousVersion[:], genesis.GenesisValidatorsRoot[:])
|
||||
copy(domain[:], previousExitDomain)
|
||||
errCheck(err, "Failed to compute domain")
|
||||
verified, err = util.VerifyRoot(account, opRoot, domain, sig)
|
||||
errCheck(err, "Failed to verify voluntary exit")
|
||||
forkRaw, ok := response.Data["CAPELLA_FORK_VERSION"]
|
||||
if !ok {
|
||||
err = errors.New("failed to obtain Capella fork version")
|
||||
}
|
||||
errCheck(err, "Failed to obtain fork version")
|
||||
|
||||
fork, ok := forkRaw.(phase0.Version)
|
||||
if !ok {
|
||||
err = errors.New("fork version is not of a valid type")
|
||||
}
|
||||
errCheck(err, "Failed to obtain fork version")
|
||||
|
||||
exitDomain, err := e2types.ComputeDomain(e2types.DomainVoluntaryExit, fork[:], genesis.GenesisValidatorsRoot[:])
|
||||
errCheck(err, "Failed to compute domain")
|
||||
|
||||
copy(domain[:], exitDomain)
|
||||
verified, err := util.VerifyRoot(account, opRoot, domain, sig)
|
||||
errCheck(err, "Failed to verify voluntary exit")
|
||||
|
||||
assert(verified, "Voluntary exit failed to verify against current and previous fork versions")
|
||||
|
||||
outputIf(viper.GetBool("verbose"), "Verified")
|
||||
|
||||
@@ -19,7 +19,8 @@ import (
|
||||
"fmt"
|
||||
|
||||
eth2client "github.com/attestantio/go-eth2-client"
|
||||
api "github.com/attestantio/go-eth2-client/api/v1"
|
||||
"github.com/attestantio/go-eth2-client/api"
|
||||
apiv1 "github.com/attestantio/go-eth2-client/api/v1"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -28,7 +29,10 @@ func process(ctx context.Context, data *dataIn) error {
|
||||
return errors.New("no data")
|
||||
}
|
||||
|
||||
err := data.eth2Client.(eth2client.EventsProvider).Events(ctx, data.topics, eventHandler)
|
||||
err := data.eth2Client.(eth2client.EventsProvider).Events(ctx, &api.EventsOpts{
|
||||
Topics: data.topics,
|
||||
Handler: eventHandler,
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to connect for events")
|
||||
}
|
||||
@@ -38,7 +42,7 @@ func process(ctx context.Context, data *dataIn) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func eventHandler(event *api.Event) {
|
||||
func eventHandler(event *apiv1.Event) {
|
||||
if event.Data == nil {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -127,6 +127,13 @@ func (c *command) process(ctx context.Context) error {
|
||||
} else {
|
||||
c.inclusions = append(c.inclusions, 2)
|
||||
}
|
||||
case spec.DataVersionFulu:
|
||||
aggregate = block.Fulu.Message.Body.SyncAggregate
|
||||
if aggregate.SyncCommitteeBits.BitAt(c.committeeIndex) {
|
||||
c.inclusions = append(c.inclusions, 1)
|
||||
} else {
|
||||
c.inclusions = append(c.inclusions, 2)
|
||||
}
|
||||
default:
|
||||
return fmt.Errorf("unhandled block version %v", block.Version)
|
||||
}
|
||||
|
||||
@@ -114,6 +114,7 @@ func validatorDepositDataOutputLaunchpad(datum *dataOut) (string, error) {
|
||||
[4]byte{0x80, 0x00, 0x00, 0x69}: "ropsten",
|
||||
[4]byte{0x90, 0x00, 0x00, 0x69}: "sepolia",
|
||||
[4]byte{0x01, 0x01, 0x70, 0x00}: "holesky",
|
||||
[4]byte{0x10, 0x00, 0x09, 0x10}: "hoodi",
|
||||
}
|
||||
|
||||
if datum.validatorPubKey == nil {
|
||||
|
||||
@@ -28,14 +28,16 @@ var validatorCredentialsSetCmd = &cobra.Command{
|
||||
|
||||
ethdo validator credentials set --validator=primary/validator --withdrawal-address=0x00...13 --private-key=0x00...1f
|
||||
|
||||
Note that to change credentials the private key to the existing BLS withdrawal credentials must be available, either directly as an account or private key, or via the mnemonic that was used when generating the initial deposits.
|
||||
|
||||
The validator account can be specified in one of a number of ways:
|
||||
|
||||
- mnemonic using --mnemonic; this will scan the mnemonic and generate all applicable operations
|
||||
- mnemonic and path to the validator key using --mnemonic and --path; this will generate a single operation
|
||||
- mnemonic and validator index or public key --mnemonic and --validator; this will generate a single operation
|
||||
- mnemonic and withdrawal private key using --mnemonic and --private-key; this will generate all applicable operations
|
||||
- validator and withdrawal private key using --validator and --private-key; this will generate a single operation
|
||||
- account and withdrawal account using --account and --withdrawal-account; this will generate a single operation
|
||||
- mnemonic and existing BLS withdrawal private key using --mnemonic and --private-key; this will generate all applicable operations
|
||||
- validator and existing BLS withdrawal private key using --validator and --private-key; this will generate a single operation
|
||||
- account and existing BLS withdrawal account using --account and --withdrawal-account; this will generate a single operation
|
||||
|
||||
In quiet mode this will return 0 if the credentials operation has been generated (and successfully broadcast if online), otherwise 1.`,
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
|
||||
@@ -24,7 +24,7 @@ import (
|
||||
|
||||
// ReleaseVersion is the release version of the codebase.
|
||||
// Usually overridden by tag names when building binaries.
|
||||
var ReleaseVersion = "local build (latest release 1.37.2)"
|
||||
var ReleaseVersion = "local build (latest release 1.39.0)"
|
||||
|
||||
// versionCmd represents the version command.
|
||||
var versionCmd = &cobra.Command{
|
||||
|
||||
70
go.mod
70
go.mod
@@ -1,11 +1,11 @@
|
||||
module github.com/wealdtech/ethdo
|
||||
|
||||
go 1.22.7
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.2
|
||||
|
||||
require (
|
||||
github.com/attestantio/go-eth2-client v0.24.0
|
||||
github.com/attestantio/go-eth2-client v0.27.1
|
||||
github.com/ferranbt/fastssz v0.1.4
|
||||
github.com/gofrs/uuid v4.4.0+incompatible
|
||||
github.com/google/uuid v1.6.0
|
||||
@@ -18,50 +18,49 @@ require (
|
||||
github.com/prysmaticlabs/go-ssz v0.0.0-20210121151755-f6208871c388
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/shopspring/decimal v1.4.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/spf13/viper v1.19.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/spf13/pflag v1.0.6
|
||||
github.com/spf13/viper v1.20.0
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/tyler-smith/go-bip39 v1.1.0
|
||||
github.com/wealdtech/go-bytesutil v1.2.1
|
||||
github.com/wealdtech/go-ecodec v1.1.4
|
||||
github.com/wealdtech/go-eth2-types/v2 v2.8.2
|
||||
github.com/wealdtech/go-eth2-util v1.8.2
|
||||
github.com/wealdtech/go-eth2-wallet v1.17.0
|
||||
github.com/wealdtech/go-eth2-wallet v1.17.2
|
||||
github.com/wealdtech/go-eth2-wallet-dirk v1.5.1
|
||||
github.com/wealdtech/go-eth2-wallet-distributed v1.2.1
|
||||
github.com/wealdtech/go-eth2-wallet-distributed v1.2.2
|
||||
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.4.1
|
||||
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.7.1
|
||||
github.com/wealdtech/go-eth2-wallet-keystore v1.0.0
|
||||
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.5.0
|
||||
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.7.2
|
||||
github.com/wealdtech/go-eth2-wallet-keystore v1.0.2
|
||||
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.5.1
|
||||
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.18.1
|
||||
github.com/wealdtech/go-eth2-wallet-store-s3 v1.12.0
|
||||
github.com/wealdtech/go-eth2-wallet-store-scratch v1.7.2
|
||||
github.com/wealdtech/go-eth2-wallet-types/v2 v2.12.0
|
||||
github.com/wealdtech/go-string2eth v1.2.1
|
||||
golang.org/x/text v0.21.0
|
||||
golang.org/x/text v0.23.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/aws/aws-sdk-go v1.55.5 // indirect
|
||||
github.com/aws/aws-sdk-go v1.55.6 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/dgraph-io/ristretto v0.2.0 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/emicklei/dot v1.6.4 // indirect
|
||||
github.com/emicklei/dot v1.8.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/goccy/go-yaml v1.15.12 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/goccy/go-yaml v1.16.0 // indirect
|
||||
github.com/holiman/uint256 v1.3.2 // indirect
|
||||
github.com/huandu/go-clone v1.7.2 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 // indirect
|
||||
github.com/magiconair/properties v1.8.9 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/minio/highwayhash v1.0.3 // indirect
|
||||
@@ -69,41 +68,38 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/pk910/dynamic-ssz v0.0.5 // indirect
|
||||
github.com/pk910/dynamic-ssz v0.0.6 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/prometheus/client_golang v1.20.5 // indirect
|
||||
github.com/prometheus/client_golang v1.21.1 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.61.0 // indirect
|
||||
github.com/prometheus/common v0.63.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/protolambda/zssz v0.1.5 // indirect
|
||||
github.com/r3labs/sse/v2 v2.10.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.8.0 // indirect
|
||||
github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/afero v1.14.0 // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/wealdtech/eth2-signer-api v1.7.2 // indirect
|
||||
github.com/wealdtech/go-indexer v1.1.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect
|
||||
go.opentelemetry.io/otel v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.33.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
|
||||
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/crypto v0.32.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 // indirect
|
||||
golang.org/x/net v0.33.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/sys v0.29.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241219192143-6b3ec007d9bb // indirect
|
||||
google.golang.org/grpc v1.69.2 // indirect
|
||||
google.golang.org/protobuf v1.36.0 // indirect
|
||||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/net v0.37.0 // indirect
|
||||
golang.org/x/sync v0.12.0 // indirect
|
||||
golang.org/x/sys v0.31.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 // indirect
|
||||
google.golang.org/grpc v1.71.0 // indirect
|
||||
google.golang.org/protobuf v1.36.5 // indirect
|
||||
gopkg.in/Knetic/govaluate.v3 v3.0.0 // indirect
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
154
go.sum
154
go.sum
@@ -1,13 +1,13 @@
|
||||
github.com/attestantio/go-eth2-client v0.24.0 h1:lGVbcnhlBwRglt1Zs56JOCgXVyLWKFZOmZN8jKhE7Ws=
|
||||
github.com/attestantio/go-eth2-client v0.24.0/go.mod h1:/KTLN3WuH1xrJL7ZZrpBoWM1xCCihnFbzequD5L+83o=
|
||||
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
|
||||
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
||||
github.com/attestantio/go-eth2-client v0.27.1 h1:g7bm+gG/p+gfzYdEuxuAepVWYb8EO+2KojV5/Lo2BxM=
|
||||
github.com/attestantio/go-eth2-client v0.27.1/go.mod h1:fvULSL9WtNskkOB4i+Yyr6BKpNHXvmpGZj9969fCrfY=
|
||||
github.com/aws/aws-sdk-go v1.55.6 h1:cSg4pvZ3m8dgYcgqB97MrcdjUmZ1BeMYKUxMMB89IPk=
|
||||
github.com/aws/aws-sdk-go v1.55.6/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
@@ -18,8 +18,8 @@ github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 h1:fAjc9m62+UWV/WA
|
||||
github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/emicklei/dot v1.6.4 h1:cG9ycT67d9Yw22G+mAb4XiuUz6E6H1S0zePp/5Cwe/c=
|
||||
github.com/emicklei/dot v1.6.4/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
|
||||
github.com/emicklei/dot v1.8.0 h1:HnD60yAKFAevNeT+TPYr9pb8VB9bqdeSo0nzwIW6IOI=
|
||||
github.com/emicklei/dot v1.8.0/go.mod h1:DeV7GvQtIw4h2u73RKBkkFdvVAz0D9fzeJrgPW6gy/s=
|
||||
github.com/ferranbt/fastssz v0.1.4 h1:OCDB+dYDEQDvAgtAGnTSidK1Pe2tW3nFV40XyMkTeDY=
|
||||
github.com/ferranbt/fastssz v0.1.4/go.mod h1:Ea3+oeoRGGLGm5shYAeDgu6PGUlcvQhE2fILyD9+tGg=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
@@ -31,8 +31,10 @@ github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
|
||||
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/goccy/go-yaml v1.15.12 h1:KLUSwfrUcTU6F8sAkf23OIPYC6aFVMNFSu4btROEm6w=
|
||||
github.com/goccy/go-yaml v1.15.12/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/goccy/go-yaml v1.16.0 h1:d7m1G7A0t+logajVtklHfDYJs2Et9g3gHwdBNNFou0w=
|
||||
github.com/goccy/go-yaml v1.16.0/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||
@@ -40,14 +42,12 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek
|
||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b h1:wDUNC2eKiL35DbLvsDhiblTUXHxcOPwQSCzi7xpQUN4=
|
||||
github.com/hako/durafmt v0.0.0-20210608085754-5c1018a4e16b/go.mod h1:VzxiSdG6j1pi7rwGm/xYI5RbtpBgM8sARDXlvEvxlu0=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/herumi/bls-eth-go-binary v1.36.4 h1:yff41RSbfyZwfE1NF/qddP5nXhgdU0c3RGOpYOoM7YM=
|
||||
github.com/herumi/bls-eth-go-binary v1.36.4/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
|
||||
github.com/holiman/uint256 v1.3.2 h1:a9EgMPSC1AAaj1SZL5zIQD3WbwTuHrMGOerLjGmM/TA=
|
||||
@@ -66,16 +66,14 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9 h1:66ze0taIn2H33fBvCkXuv9BmCwDfafmiIVpKV9kKGuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.9/go.mod h1:rqkxqrZ1EhYM9G+hXH7YdowN5R5RGN6NK4QwQ3WMXF8=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10 h1:tBs3QSyvjDyFTq3uoc/9xFpCuOsJQFNPiAhYdw2skhE=
|
||||
github.com/klauspost/cpuid/v2 v2.2.10/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
|
||||
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
@@ -97,19 +95,19 @@ github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354 h1:4kuARK6Y6Fx
|
||||
github.com/nbutton23/zxcvbn-go v0.0.0-20210217022336-fa2cb2858354/go.mod h1:KSVJerMDfblTH7p5MZaTt+8zaT2iEk3AkVb9PQdZuE8=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pk910/dynamic-ssz v0.0.5 h1:VP9heGYUwzlpyhk28P2nCAzhvGsePJOOOO5vQMDh2qQ=
|
||||
github.com/pk910/dynamic-ssz v0.0.5/go.mod h1:b6CrLaB2X7pYA+OSEEbkgXDEcRnjLOZIxZTsMuO/Y9c=
|
||||
github.com/pk910/dynamic-ssz v0.0.6 h1:Tu97LSc2TtCyqRfoSbhG9XuR/FbA7CkKeAnlkgUydFY=
|
||||
github.com/pk910/dynamic-ssz v0.0.6/go.mod h1:b6CrLaB2X7pYA+OSEEbkgXDEcRnjLOZIxZTsMuO/Y9c=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_golang v1.21.1 h1:DOvXXTqVzvkIewV/CDPFdejpMCGeMcbGCQ8YOmu+Ibk=
|
||||
github.com/prometheus/client_golang v1.21.1/go.mod h1:U9NM32ykUErtVBxdvD3zfi+EuFkkaBvMb09mIfe0Zgg=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
|
||||
github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
|
||||
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
||||
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/protolambda/zssz v0.1.5 h1:7fjJjissZIIaa2QcvmhS/pZISMX21zVITt49sW1ouek=
|
||||
@@ -128,26 +126,24 @@ github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
|
||||
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sagikazarmark/locafero v0.8.0 h1:mXaMVw7IqxNBxfv3LdWt9MDmcWDQ1fagDH918lOdVaQ=
|
||||
github.com/sagikazarmark/locafero v0.8.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk=
|
||||
github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0 h1:Xuk8ma/ibJ1fOy4Ee11vHhUFHQNpHhrBneOCNHVXS5w=
|
||||
github.com/shibukawa/configdir v0.0.0-20170330084843-e180dbdc8da0/go.mod h1:7AwjWCpdPhkSmNAgUv5C7EJ4AbmjEB3r047r3DXWu3Y=
|
||||
github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k=
|
||||
github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
|
||||
github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.20.0 h1:zrxIyR3RQIOsarIrgL8+sAvALXul9jeEPa06Y0Ph6vY=
|
||||
github.com/spf13/viper v1.20.0/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.1.4/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
@@ -168,22 +164,22 @@ github.com/wealdtech/go-eth2-types/v2 v2.8.2 h1:b5aXlNBLKgjAg/Fft9VvGlqAUCQMP5Lz
|
||||
github.com/wealdtech/go-eth2-types/v2 v2.8.2/go.mod h1:IAz9Lz1NVTaHabQa+4zjk2QDKMv8LVYo0n46M9o/TXw=
|
||||
github.com/wealdtech/go-eth2-util v1.8.2 h1:gq+JMrnadifyKadUr75wmfP7+usiqMu9t3VVoob5Dvo=
|
||||
github.com/wealdtech/go-eth2-util v1.8.2/go.mod h1:/80GAK0K/3+PqUBZHvaOPd3b1sjHeimxQh1nrJzgaPk=
|
||||
github.com/wealdtech/go-eth2-wallet v1.17.0 h1:hMjGRjvpk95gguW6UXFDkRHWjYqE0cdrO7cOClF9Ubo=
|
||||
github.com/wealdtech/go-eth2-wallet v1.17.0/go.mod h1:qMmDrx//GrdZ3q+0Jf9SNwCaLsFOxOmXgr1yptpSMIE=
|
||||
github.com/wealdtech/go-eth2-wallet v1.17.2 h1:tFkWddJwH8Iq3H9K1Fnp4avxNn+4qbE3Go7k81a/c1U=
|
||||
github.com/wealdtech/go-eth2-wallet v1.17.2/go.mod h1:CMtJ9IpvrkW2lD3B6ZAn3q/uALcxCBPBliFpIovV8+4=
|
||||
github.com/wealdtech/go-eth2-wallet-dirk v1.5.1 h1:h1wZK31yonLkwddajg+Prhhd2rrvIIxQ3HxwZ3udnaY=
|
||||
github.com/wealdtech/go-eth2-wallet-dirk v1.5.1/go.mod h1:Yz1Mc+HfbG1CODeBpAQ++/Us76OdXzI5kVs1qGvUiBM=
|
||||
github.com/wealdtech/go-eth2-wallet-distributed v1.2.1 h1:+pbG9i9b5TrWd7GDRX8yq4FKA+D7k7aI6uySEvAZ+Kk=
|
||||
github.com/wealdtech/go-eth2-wallet-distributed v1.2.1/go.mod h1:jYkDax2VhUNKIct6TVlgxAagvR56/eg7y7J+JFq+gDo=
|
||||
github.com/wealdtech/go-eth2-wallet-distributed v1.2.2 h1:O6nfhMRTUpblOzj8KiCLFgQAyAqrv2dweorzss/V6PU=
|
||||
github.com/wealdtech/go-eth2-wallet-distributed v1.2.2/go.mod h1:jYkDax2VhUNKIct6TVlgxAagvR56/eg7y7J+JFq+gDo=
|
||||
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.4.1 h1:9j7bpwjT9wmwBb54ZkBhTm1uNIlFFcCJXefd/YskZPw=
|
||||
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.4.1/go.mod h1:+tI1VD76E1WINI+Nstg7RVGpUolL5ql10nu2YztMO/4=
|
||||
github.com/wealdtech/go-eth2-wallet-encryptor-unencrypted v1.0.2 h1:IMIyl70hbJlxOkgTcCK//3vKe5ylhGIk6oUlIlK9xp0=
|
||||
github.com/wealdtech/go-eth2-wallet-encryptor-unencrypted v1.0.2/go.mod h1:T8nyAscWIWNcNa6EG/19PwH/OCt2Ly7Orn5okmiuSP4=
|
||||
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.7.1 h1:CrcPeJhMcNxSW+GAJwtpXz3mtGJjx4p9ykLlKvwZZZ4=
|
||||
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.7.1/go.mod h1:aWgnEi07w1L9wMBRB69sYvoEONppAUly6FDQRWQGqH8=
|
||||
github.com/wealdtech/go-eth2-wallet-keystore v1.0.0 h1:DYR6TAyi7RxXoAanLSPdiufGxCX617BQwWOdCxHqHX4=
|
||||
github.com/wealdtech/go-eth2-wallet-keystore v1.0.0/go.mod h1:6DGINunnasS9y9F7KH3ya2h74fHWgSCfP3dAJWe4A6U=
|
||||
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.5.0 h1:vphAFklkYMRJVo9f5rVWly7PECHrLS4yarjemBa7fRM=
|
||||
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.5.0/go.mod h1:kBZUZogqwvvxulEvXi5l6OjZyd7EBmCKxce5Q+lW7fs=
|
||||
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.7.2 h1:7wB8j12LVdUR/IFLmwTxdXfuTvpXSn4yj+ZD1OhDSJY=
|
||||
github.com/wealdtech/go-eth2-wallet-hd/v2 v2.7.2/go.mod h1:aWgnEi07w1L9wMBRB69sYvoEONppAUly6FDQRWQGqH8=
|
||||
github.com/wealdtech/go-eth2-wallet-keystore v1.0.2 h1:OseWEBvr13voALVCdg7ojsU3Kly/FPR9sCadnsx3/tM=
|
||||
github.com/wealdtech/go-eth2-wallet-keystore v1.0.2/go.mod h1:SjHHqYS0IragcGcOkbFqjX0lIxRe4d0mE7tPiR+R7HI=
|
||||
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.5.1 h1:bSdDCn+o4wq5MHogGkUtqbPp6Z7Tndt2qBb1zjof96Y=
|
||||
github.com/wealdtech/go-eth2-wallet-nd/v2 v2.5.1/go.mod h1:kBZUZogqwvvxulEvXi5l6OjZyd7EBmCKxce5Q+lW7fs=
|
||||
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.18.1 h1:Ceq74WL57jdBQnrZJFJyGRBKOOFI5wwq9VoxeAbjoEk=
|
||||
github.com/wealdtech/go-eth2-wallet-store-filesystem v1.18.1/go.mod h1:woTpldN8qThnmya/0yeD+a3u/3Zj42u6/ijgF9CGaz8=
|
||||
github.com/wealdtech/go-eth2-wallet-store-s3 v1.12.0 h1:noknYCbHw2soPhwke1LvC99Kk/2CLN787KcgxdZ7OGo=
|
||||
@@ -198,51 +194,49 @@ github.com/wealdtech/go-string2eth v1.2.1 h1:u9sofvGFkp+uvTg4Nvsvy5xBaiw8AibGLLn
|
||||
github.com/wealdtech/go-string2eth v1.2.1/go.mod h1:9uwxm18zKZfrReXrGIbdiRYJtbE91iGcj6TezKKEx80=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0=
|
||||
go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
|
||||
go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
|
||||
go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=
|
||||
go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=
|
||||
go.opentelemetry.io/otel/sdk v1.31.0 h1:xLY3abVHYZ5HSfOg3l2E5LUj2Cwva5Y7yGxnSW9H5Gk=
|
||||
go.opentelemetry.io/otel/sdk v1.31.0/go.mod h1:TfRbMdhvxIIr/B2N2LQW2S5v9m3gOQ/08KsbbO5BPT0=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.31.0 h1:i9hxxLJF/9kkvfHppyLL55aW7iIJz4JjxTeYusH7zMc=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.31.0/go.mod h1:CRInTMVvNhUKgSAMbKyTMxqOBC0zgyxzW55lZzX43Y8=
|
||||
go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
|
||||
go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
|
||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
|
||||
go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
|
||||
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
|
||||
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67 h1:1UoZQm6f0P/ZO0w1Ri+f+ifG/gXhegadRdwBIXEFWDo=
|
||||
golang.org/x/exp v0.0.0-20241217172543-b2144cdd0a67/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||
golang.org/x/net v0.37.0/go.mod h1:ivrbrMbzFq5J41QOQh0siUuly180yBYtLp+CKbEaFx8=
|
||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb h1:B7GIB7sr443wZ/EAEl7VZjmh1V6qzkt5V+RYcUYtS1U=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20241219192143-6b3ec007d9bb/go.mod h1:E5//3O5ZIG2l71Xnt+P/CYUY8Bxs8E7WMoZ9tlcMbAY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241219192143-6b3ec007d9bb h1:3oy2tynMOP1QbTC0MsNNAV+Se8M2Bd0A5+x1QHyw+pI=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20241219192143-6b3ec007d9bb/go.mod h1:lcTa1sDdWEIHMWlITnIczmw5w60CF9ffkb8Z+DVmmjA=
|
||||
google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
|
||||
google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
|
||||
google.golang.org/protobuf v1.36.0 h1:mjIs9gYtt56AzC4ZaffQuh88TZurBGhIJMBZGSxNerQ=
|
||||
google.golang.org/protobuf v1.36.0/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4 h1:IFnXJq3UPB3oBREOodn1v1aGQeZYQclEmvWRMN0PSsY=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:c8q6Z6OCqnfVIqUFJkCzKcrj8eCvUrz+K4KRzSTuANg=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4 h1:iK2jbkWL86DXjEx0qiHcRE9dE4/Ahua5k6V8OWFb//c=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250313205543-e70fdf4c4cb4/go.mod h1:LuRYeWDFV6WOn90g357N17oMCaxpgCnbi/44qJvDn2I=
|
||||
google.golang.org/grpc v1.71.0 h1:kF77BGdPTQ4/JZWMlb9VpJ5pa25aqvVqogsxNHHdeBg=
|
||||
google.golang.org/grpc v1.71.0/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
|
||||
google.golang.org/protobuf v1.36.5 h1:tPhr+woSbjfYvY6/GPufUoYizxw1cF/yFoxJ2fmpwlM=
|
||||
google.golang.org/protobuf v1.36.5/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
gopkg.in/Knetic/govaluate.v3 v3.0.0 h1:18mUyIt4ZlRlFZAAfVetz4/rzlJs9yhN+U02F4u1AOc=
|
||||
gopkg.in/Knetic/govaluate.v3 v3.0.0/go.mod h1:csKLBORsPbafmSCGTEh3U7Ozmsuq8ZSIlKk1bcqph0E=
|
||||
gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y=
|
||||
@@ -250,8 +244,6 @@ gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UD
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||
|
||||
@@ -57,6 +57,11 @@ func ParseValidators(ctx context.Context, validatorsProvider eth2client.Validato
|
||||
}
|
||||
}
|
||||
|
||||
if len(validators) == 0 && len(indices) == 0 {
|
||||
// Nothing to obtain.
|
||||
return validators, nil
|
||||
}
|
||||
|
||||
response, err := validatorsProvider.Validators(ctx, &api.ValidatorsOpts{State: stateID, Indices: indices})
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, fmt.Sprintf("failed to obtain validators %v", indices))
|
||||
|
||||
Reference in New Issue
Block a user