Skip to content

Commit

Permalink
Update to use electra version of go-eth2-client
Browse files Browse the repository at this point in the history
  • Loading branch information
Bez625 committed Jan 27, 2025
1 parent fcafa03 commit 7d0e607
Show file tree
Hide file tree
Showing 11 changed files with 161 additions and 73 deletions.
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@ coverage.html
# Project-local glide cache, RE: https://github.com/Masterminds/glide/issues/736
.glide/

# Intellij
.idea/

# Makefile
Makefile

# Vim
*.sw?

Expand Down
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
electra:
- update to handle versioned attestations from go-eth2-client electra branch

1.36.2:
- avoid crash when signing and verifing signatures using keys rather than accounts

Expand Down
3 changes: 2 additions & 1 deletion cmd/attester/inclusion/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"strconv"
"strings"

"github.com/attestantio/go-eth2-client/spec"
"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/pkg/errors"
)
Expand All @@ -27,7 +28,7 @@ type dataOut struct {
debug bool
quiet bool
verbose bool
attestation *phase0.Attestation
attestation *spec.VersionedAttestation
slot phase0.Slot
attestationIndex uint64
inclusionDelay phase0.Slot
Expand Down
35 changes: 26 additions & 9 deletions cmd/attester/inclusion/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
eth2client "github.com/attestantio/go-eth2-client"
"github.com/attestantio/go-eth2-client/api"
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"
standardchaintime "github.com/wealdtech/ethdo/services/chaintime/standard"
Expand Down Expand Up @@ -93,9 +94,17 @@ func process(ctx context.Context, data *dataIn) (*dataOut, error) {
return nil, errors.Wrap(err, "failed to obtain block attestations")
}
for i, attestation := range attestations {
if attestation.Data.Slot == duty.Slot &&
attestation.Data.Index == duty.CommitteeIndex &&
attestation.AggregationBits.BitAt(duty.ValidatorCommitteeIndex) {
attestationData, err := attestation.Data()
if err != nil {
return nil, errors.Wrap(err, "failed to obtain attestation data")
}
aggregationBits, err := attestation.AggregationBits()
if err != nil {
return nil, errors.Wrap(err, "failed to obtain aggregation bits")
}
if attestationData.Slot == duty.Slot &&
attestationData.Index == duty.CommitteeIndex &&
aggregationBits.BitAt(duty.ValidatorCommitteeIndex) {
headCorrect := false
targetCorrect := false
if data.verbose {
Expand Down Expand Up @@ -128,8 +137,12 @@ func process(ctx context.Context, data *dataIn) (*dataOut, error) {
return results, nil
}

func calcHeadCorrect(ctx context.Context, data *dataIn, attestation *phase0.Attestation) (bool, error) {
slot := attestation.Data.Slot
func calcHeadCorrect(ctx context.Context, data *dataIn, attestation *spec.VersionedAttestation) (bool, error) {
attestationData, err := attestation.Data()
if err != nil {
return false, errors.Wrap(err, "failed to obtain attestation data")
}
slot := attestationData.Slot
for {
response, err := data.eth2Client.(eth2client.BeaconBlockHeadersProvider).BeaconBlockHeader(ctx, &api.BeaconBlockHeaderOpts{
Block: fmt.Sprintf("%d", slot),
Expand All @@ -149,13 +162,17 @@ func calcHeadCorrect(ctx context.Context, data *dataIn, attestation *phase0.Atte
slot--
continue
}
return bytes.Equal(response.Data.Root[:], attestation.Data.BeaconBlockRoot[:]), nil
return bytes.Equal(response.Data.Root[:], attestationData.BeaconBlockRoot[:]), nil
}
}

func calcTargetCorrect(ctx context.Context, data *dataIn, attestation *phase0.Attestation) (bool, error) {
func calcTargetCorrect(ctx context.Context, data *dataIn, attestation *spec.VersionedAttestation) (bool, error) {
attestationData, err := attestation.Data()
if err != nil {
return false, errors.Wrap(err, "failed to obtain attestation data")
}
// Start with first slot of the target epoch.
slot := data.chainTime.FirstSlotOfEpoch(attestation.Data.Target.Epoch)
slot := data.chainTime.FirstSlotOfEpoch(attestationData.Target.Epoch)
for {
response, err := data.eth2Client.(eth2client.BeaconBlockHeadersProvider).BeaconBlockHeader(ctx, &api.BeaconBlockHeaderOpts{
Block: fmt.Sprintf("%d", slot),
Expand All @@ -175,7 +192,7 @@ func calcTargetCorrect(ctx context.Context, data *dataIn, attestation *phase0.At
slot--
continue
}
return bytes.Equal(response.Data.Root[:], attestation.Data.Target.Root[:]), nil
return bytes.Equal(response.Data.Root[:], attestationData.Target.Root[:]), nil
}
}

Expand Down
91 changes: 58 additions & 33 deletions cmd/block/analyze/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,12 @@ func (c *command) process(ctx context.Context) error {
// Calculate how many parents we need to fetch.
minSlot := slot
for _, attestation := range attestations {
if attestation.Data.Slot < minSlot {
minSlot = attestation.Data.Slot
attestData, err := attestation.Data()
if err != nil {
return errors.Wrap(err, "failed to obtain attestation data")
}
if attestData.Slot < minSlot {
minSlot = attestData.Slot
}
}
if c.debug {
Expand Down Expand Up @@ -103,10 +107,14 @@ func (c *command) analyzeAttestations(ctx context.Context, block *spec.Versioned
if c.debug {
fmt.Printf("Processing attestation %d\n", i)
}
attestData, err := attestation.Data()
if err != nil {
return errors.Wrap(err, "failed to obtain attestation data")
}
analysis := &attestationAnalysis{
Head: attestation.Data.BeaconBlockRoot,
Target: attestation.Data.Target.Root,
Distance: int(slot - attestation.Data.Slot),
Head: attestData.BeaconBlockRoot,
Target: attestData.Target.Root,
Distance: int(slot - attestData.Slot),
}

root, err := attestation.HashTreeRoot()
Expand All @@ -116,45 +124,47 @@ func (c *command) analyzeAttestations(ctx context.Context, block *spec.Versioned
if info, exists := c.priorAttestations[fmt.Sprintf("%#x", root)]; exists {
analysis.Duplicate = info
} else {
data := attestation.Data
_, exists := blockVotes[data.Slot]
aggregationBits, err := attestation.AggregationBits()
if err != nil {
return err
}
_, exists := blockVotes[attestData.Slot]
if !exists {
blockVotes[data.Slot] = make(map[phase0.CommitteeIndex]bitfield.Bitlist)
blockVotes[attestData.Slot] = make(map[phase0.CommitteeIndex]bitfield.Bitlist)
}
_, exists = blockVotes[data.Slot][data.Index]
_, exists = blockVotes[attestData.Slot][attestData.Index]
if !exists {
blockVotes[data.Slot][data.Index] = bitfield.NewBitlist(attestation.AggregationBits.Len())
blockVotes[attestData.Slot][attestData.Index] = bitfield.NewBitlist(aggregationBits.Len())
}

// Count new votes.
analysis.PossibleVotes = int(attestation.AggregationBits.Len())
for j := range attestation.AggregationBits.Len() {
if attestation.AggregationBits.BitAt(j) {
analysis.PossibleVotes = int(aggregationBits.Len())
for j := range aggregationBits.Len() {
if aggregationBits.BitAt(j) {
analysis.Votes++
if blockVotes[data.Slot][data.Index].BitAt(j) {
if blockVotes[attestData.Slot][attestData.Index].BitAt(j) {
// Already attested to in this block; skip.
continue
}
if c.votes[data.Slot][data.Index].BitAt(j) {
if c.votes[attestData.Slot][attestData.Index].BitAt(j) {
// Already attested to in a previous block; skip.
continue
}
analysis.NewVotes++
blockVotes[data.Slot][data.Index].SetBitAt(j, true)
blockVotes[attestData.Slot][attestData.Index].SetBitAt(j, true)
}
}
// Calculate head correct.
var err error
analysis.HeadCorrect, err = c.calcHeadCorrect(ctx, attestation)
if err != nil {
return err
}

// Calculate head timely.
analysis.HeadTimely = analysis.HeadCorrect && attestation.Data.Slot == slot-1
analysis.HeadTimely = analysis.HeadCorrect && attestData.Slot == slot-1

// Calculate source timely.
analysis.SourceTimely = attestation.Data.Slot >= slot-5
analysis.SourceTimely = attestData.Slot >= slot-5

// Calculate target correct.
analysis.TargetCorrect, err = c.calcTargetCorrect(ctx, attestation)
Expand All @@ -164,7 +174,7 @@ func (c *command) analyzeAttestations(ctx context.Context, block *spec.Versioned

// Calculate target timely.
if block.Version < spec.DataVersionDeneb {
analysis.TargetTimely = attestation.Data.Slot >= slot-32
analysis.TargetTimely = attestData.Slot >= slot-32
} else {
analysis.TargetTimely = true
}
Expand Down Expand Up @@ -260,17 +270,24 @@ func (c *command) processParentBlock(_ context.Context, block *spec.VersionedSig
Index: i,
}

data := attestation.Data
data, err := attestation.Data()
if err != nil {
return err
}
_, exists := c.votes[data.Slot]
if !exists {
c.votes[data.Slot] = make(map[phase0.CommitteeIndex]bitfield.Bitlist)
}
_, exists = c.votes[data.Slot][data.Index]
aggregationBits, err := attestation.AggregationBits()
if err != nil {
return err
}
if !exists {
c.votes[data.Slot][data.Index] = bitfield.NewBitlist(attestation.AggregationBits.Len())
c.votes[data.Slot][data.Index] = bitfield.NewBitlist(aggregationBits.Len())
}
for j := range attestation.AggregationBits.Len() {
if attestation.AggregationBits.BitAt(j) {
for j := range aggregationBits.Len() {
if aggregationBits.BitAt(j) {
c.votes[data.Slot][data.Index].SetBitAt(j, true)
}
}
Expand Down Expand Up @@ -385,8 +402,12 @@ func (c *command) setup(ctx context.Context) error {
return nil
}

func (c *command) calcHeadCorrect(ctx context.Context, attestation *phase0.Attestation) (bool, error) {
slot := attestation.Data.Slot
func (c *command) calcHeadCorrect(ctx context.Context, attestation *spec.VersionedAttestation) (bool, error) {
attestData, err := attestation.Data()
if err != nil {
return false, errors.Wrap(err, "failed to obtain attestation data")
}
slot := attestData.Slot
root, exists := c.headRoots[slot]
if !exists {
for {
Expand All @@ -413,20 +434,24 @@ func (c *command) calcHeadCorrect(ctx context.Context, attestation *phase0.Attes
slot--
continue
}
c.headRoots[attestation.Data.Slot] = response.Data.Root
c.headRoots[attestData.Slot] = response.Data.Root
root = response.Data.Root
break
}
}

return bytes.Equal(root[:], attestation.Data.BeaconBlockRoot[:]), nil
return bytes.Equal(root[:], attestData.BeaconBlockRoot[:]), nil
}

func (c *command) calcTargetCorrect(ctx context.Context, attestation *phase0.Attestation) (bool, error) {
root, exists := c.targetRoots[attestation.Data.Slot]
func (c *command) calcTargetCorrect(ctx context.Context, attestation *spec.VersionedAttestation) (bool, error) {
attestData, err := attestation.Data()
if err != nil {
return false, errors.Wrap(err, "failed to obtain attestation data")
}
root, exists := c.targetRoots[attestData.Slot]
if !exists {
// Start with first slot of the target epoch.
slot := c.chainTime.FirstSlotOfEpoch(attestation.Data.Target.Epoch)
slot := c.chainTime.FirstSlotOfEpoch(attestData.Target.Epoch)
for {
response, err := c.blockHeadersProvider.BeaconBlockHeader(ctx, &api.BeaconBlockHeaderOpts{
Block: fmt.Sprintf("%d", slot),
Expand All @@ -450,12 +475,12 @@ func (c *command) calcTargetCorrect(ctx context.Context, attestation *phase0.Att
slot--
continue
}
c.targetRoots[attestation.Data.Slot] = response.Data.Root
c.targetRoots[attestData.Slot] = response.Data.Root
root = response.Data.Root
break
}
}
return bytes.Equal(root[:], attestation.Data.Target.Root[:]), nil
return bytes.Equal(root[:], attestData.Target.Root[:]), nil
}

func (c *command) analyzeSyncCommittees(_ context.Context, block *spec.VersionedSignedBeaconBlock) error {
Expand Down
30 changes: 19 additions & 11 deletions cmd/epoch/summary/process.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,17 +239,21 @@ func (c *command) processSlots(ctx context.Context,
return nil, nil, nil, nil, nil, nil, nil, err
}
for _, attestation := range attestations {
if attestation.Data.Slot < c.chainTime.FirstSlotOfEpoch(c.summary.Epoch) || attestation.Data.Slot >= c.chainTime.FirstSlotOfEpoch(c.summary.Epoch+1) {
attestationData, err := attestation.Data()
if err != nil {
return nil, nil, nil, nil, nil, nil, nil, 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.
continue
}
slotCommittees, exists := allCommittees[attestation.Data.Slot]
slotCommittees, exists := allCommittees[attestationData.Slot]
if !exists {
response, err := c.beaconCommitteesProvider.BeaconCommittees(ctx, &api.BeaconCommitteesOpts{
State: fmt.Sprintf("%d", attestation.Data.Slot),
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", attestation.Data.Slot))
return nil, nil, nil, nil, nil, nil, nil, 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 {
Expand All @@ -275,11 +279,11 @@ func (c *command) processSlots(ctx context.Context,
}
}
}
slotCommittees = allCommittees[attestation.Data.Slot]
slotCommittees = allCommittees[attestationData.Slot]
}
committee := slotCommittees[attestation.Data.Index]
committee := slotCommittees[attestationData.Index]

inclusionDistance := slot - attestation.Data.Slot
inclusionDistance := slot - attestationData.Slot

head, err := util.AttestationHead(ctx, headersCache, attestation)
if err != nil {
Expand All @@ -298,8 +302,12 @@ func (c *command) processSlots(ctx context.Context,
return nil, nil, nil, nil, nil, nil, nil, err
}

for i := range attestation.AggregationBits.Len() {
if attestation.AggregationBits.BitAt(i) {
aggregationBits, err := attestation.AggregationBits()
if err != nil {
return nil, nil, nil, nil, nil, nil, nil, errors.Wrap(err, "failed to obtain aggregation bits")
}
for i := range aggregationBits.Len() {
if aggregationBits.BitAt(i) {
validatorIndex := committee[int(i)]
if len(c.validators) > 0 {
if _, exists := c.validators[validatorIndex]; !exists {
Expand All @@ -310,9 +318,9 @@ func (c *command) processSlots(ctx context.Context,

// Only set the information from the first attestation we find for this validator.
if participations[validatorIndex].InclusionSlot == 0 {
participations[validatorIndex].HeadVote = &attestation.Data.BeaconBlockRoot
participations[validatorIndex].HeadVote = &attestationData.BeaconBlockRoot
participations[validatorIndex].Head = &head
participations[validatorIndex].TargetVote = &attestation.Data.Target.Root
participations[validatorIndex].TargetVote = &attestationData.Target.Root
participations[validatorIndex].Target = &target
participations[validatorIndex].InclusionSlot = slot
}
Expand Down
Loading

0 comments on commit 7d0e607

Please sign in to comment.