Skip to content

Commit

Permalink
Merge pull request #181 from attestantio/electra_merge_master
Browse files Browse the repository at this point in the history
Electra merge master
  • Loading branch information
mcdee authored Jan 14, 2025
2 parents 07b6ce3 + 553a219 commit 1691823
Show file tree
Hide file tree
Showing 51 changed files with 1,656 additions and 36 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
dev:
0.23.0:
- add attester_slashing, block_gossip, bls_to_execution_change and proposer_slashing events
- add AttestationRewards, BlockRewards, and SyncCommitteeRewards functions

0.21.10:
- better validator state when balance not supplied
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

Go library providing an abstraction to multiple Ethereum 2 beacon nodes. Its external API follows the official [Ethereum beacon APIs](https://github.com/ethereum/beacon-APIs) specification.

This library is under development; expect APIs and data structures to change until it reaches version 1.0. In addition, clients' implementations of both their own and the standard API are themselves under development so implementation of the the full API can be incomplete.
This library is under development; expect APIs and data structures to change until it reaches version 1.0. In addition, clients' implementations of both their own and the standard API are themselves under development so implementation of the full API can be incomplete.

> Between versions 0.18.0 and 0.19.0 the API has undergone a number of changes. Please see [the detailed documentation](docs/0.19.0-changes.md) regarding these changes.
Expand Down
2 changes: 1 addition & 1 deletion api/attestationpoolopts.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type AttestationPoolOpts struct {
// data for all slots will be obtained.
Slot *phase0.Slot

// CommmitteeIndex is the committee index for which the data is obtained.
// CommitteeIndex is the committee index for which the data is obtained.
// If not present then data for all committee indices will be obtained.
CommitteeIndex *phase0.CommitteeIndex
}
30 changes: 30 additions & 0 deletions api/attestationrewardsopts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright © 2025 Attestant Limited.
// 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import "github.com/attestantio/go-eth2-client/spec/phase0"

// AttestationRewardsOpts are the options for obtaining attestation rewards.
type AttestationRewardsOpts struct {
Common CommonOpts

// Epoch is the epoch for which the data is obtained.
Epoch phase0.Epoch
// Indices is a list of validator indices to restrict the returned values.
// If no indices are supplied then no filter will be applied.
Indices []phase0.ValidatorIndex
// PubKeys is a list of validator public keys to restrict the returned values.
// If no public keys are supplied then no filter will be applied.
PubKeys []phase0.BLSPubKey
}
2 changes: 1 addition & 1 deletion api/blindedproposalopts.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ type BlindedProposalOpts struct {
Slot phase0.Slot
// RandaoReveal is the RANDAO reveal for the proposal.
RandaoReveal phase0.BLSSignature
// Graffit is the graffiti to be included in the beacon block body.
// Graffiti is the graffiti to be included in the beacon block body.
Graffiti [32]byte
// SkipRandaoVerification is true if we do not want the server to verify our RANDAO reveal.
// If this is set then the RANDAO reveal should be passed as the point at infinity (0xc0…00)
Expand Down
22 changes: 22 additions & 0 deletions api/blockrewardsopts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright © 2025 Attestant Limited.
// 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

// BlockRewardsOpts are the options for proposing a block.
type BlockRewardsOpts struct {
Common CommonOpts

// Block is the ID of the block which the data is obtained.
Block string
}
30 changes: 30 additions & 0 deletions api/synccommitteerewardsopts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright © 2025 Attestant Limited.
// 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package api

import "github.com/attestantio/go-eth2-client/spec/phase0"

// SyncCommitteeRewardsOpts are the options for obtaining sync committee rewards.
type SyncCommitteeRewardsOpts struct {
Common CommonOpts

// Block is the ID of the block which the data is obtained.
Block string
// Indices is a list of validator indices to restrict the returned values.
// If no indices are supplied then no filter will be applied.
Indices []phase0.ValidatorIndex
// PubKeys is a list of validator public keys to restrict the returned values.
// If no public keys are supplied then no filter will be applied.
PubKeys []phase0.BLSPubKey
}
255 changes: 255 additions & 0 deletions api/v1/attestationrewards.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,255 @@
// Copyright © 2025 Attestant Limited.
// 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
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v1

import (
"encoding/json"
"fmt"
"strconv"

"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/pkg/errors"
)

// AttestationRewards are the rewards for a number of attesting validators.
type AttestationRewards struct {
IdealRewards []IdealAttestationRewards `json:"ideal_rewards"`
TotalRewards []ValidatorAttestationRewards `json:"total_rewards"`
}

// IdealAttestationRewards are the ideal attestation rewards for an attestation.
type IdealAttestationRewards struct {
EffectiveBalance phase0.Gwei
Head phase0.Gwei
Target phase0.Gwei
Source phase0.Gwei
InclusionDelay *phase0.Gwei
Inactivity phase0.Gwei
}

// idealAttestationRewardsJSON is the spec representation of the struct.
type idealAttestationRewardsJSON struct {
EffectiveBalance string `json:"effective_balance"`
Head string `json:"head"`
Target string `json:"target"`
Source string `json:"source"`
InclusionDelay string `json:"inclusion_delay,omitempty"`
Inactivity string `json:"inactivity"`
}

// MarshalJSON implements json.Marshaler.
func (i *IdealAttestationRewards) MarshalJSON() ([]byte, error) {
inclusionDelay := ""
if i.InclusionDelay != nil {
inclusionDelay = fmt.Sprintf("%d", *i.InclusionDelay)
}

return json.Marshal(&idealAttestationRewardsJSON{
EffectiveBalance: fmt.Sprintf("%d", i.EffectiveBalance),
Head: fmt.Sprintf("%d", i.Head),
Target: fmt.Sprintf("%d", i.Target),
Source: fmt.Sprintf("%d", i.Source),
InclusionDelay: inclusionDelay,
Inactivity: fmt.Sprintf("%d", i.Inactivity),
})
}

// UnmarshalJSON implements json.Unmarshaler.
func (i *IdealAttestationRewards) UnmarshalJSON(input []byte) error {
var err error

var data idealAttestationRewardsJSON
if err = json.Unmarshal(input, &data); err != nil {
return errors.Wrap(err, "invalid JSON")
}

if data.EffectiveBalance == "" {
return errors.New("effective balance missing")
}
effectiveBalance, err := strconv.ParseUint(data.EffectiveBalance, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for effective balance")
}
i.EffectiveBalance = phase0.Gwei(effectiveBalance)

if data.Head == "" {
return errors.New("head missing")
}
head, err := strconv.ParseUint(data.Head, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for head")
}
i.Head = phase0.Gwei(head)

if data.Target == "" {
return errors.New("target missing")
}
target, err := strconv.ParseUint(data.Target, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for target")
}
i.Target = phase0.Gwei(target)

if data.Source == "" {
return errors.New("source missing")
}
source, err := strconv.ParseInt(data.Source, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for source")
}
i.Source = phase0.Gwei(source)

if data.InclusionDelay != "" {
inclusionDelay, err := strconv.ParseUint(data.InclusionDelay, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for inclusion delay")
}
tmp := phase0.Gwei(inclusionDelay)
i.InclusionDelay = &tmp
}

if data.Inactivity == "" {
return errors.New("inactivity missing")
}
inactivity, err := strconv.ParseUint(data.Inactivity, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for inactivity")
}
i.Inactivity = phase0.Gwei(inactivity)

return nil
}

// String returns a string version of the structure.
func (i *IdealAttestationRewards) String() string {
data, err := json.Marshal(i)
if err != nil {
return fmt.Sprintf("ERR: %v", err)
}

return string(data)
}

// ValidatorAttestationRewards are the ideal attestation rewards for a validator.
type ValidatorAttestationRewards struct {
ValidatorIndex phase0.ValidatorIndex
Head phase0.Gwei
// Target can be negative, so it is an int64 (but still a Gwei value).
Target int64
// Source can be negative, so it is an int64 (but still a Gwei value).
Source int64
InclusionDelay *phase0.Gwei
Inactivity phase0.Gwei
}

// validatorAttestationRewardsJSON is the spec representation of the struct.
type validatorAttestationRewardsJSON struct {
ValidatorIndex string `json:"validator_index"`
Head string `json:"head"`
Target string `json:"target"`
Source string `json:"source"`
InclusionDelay string `json:"inclusion_delay,omitempty"`
Inactivity string `json:"inactivity"`
}

// MarshalJSON implements json.Marshaler.
func (v *ValidatorAttestationRewards) MarshalJSON() ([]byte, error) {
inclusionDelay := ""
if v.InclusionDelay != nil {
inclusionDelay = fmt.Sprintf("%d", *v.InclusionDelay)
}

return json.Marshal(&validatorAttestationRewardsJSON{
ValidatorIndex: fmt.Sprintf("%d", v.ValidatorIndex),
Head: fmt.Sprintf("%d", v.Head),
Target: fmt.Sprintf("%d", v.Target),
Source: fmt.Sprintf("%d", v.Source),
InclusionDelay: inclusionDelay,
Inactivity: fmt.Sprintf("%d", v.Inactivity),
})
}

// UnmarshalJSON implements json.Unmarshaler.
func (v *ValidatorAttestationRewards) UnmarshalJSON(input []byte) error {
var err error

var data validatorAttestationRewardsJSON
if err = json.Unmarshal(input, &data); err != nil {
return errors.Wrap(err, "invalid JSON")
}

if data.ValidatorIndex == "" {
return errors.New("validator index missing")
}
validatorIndex, err := strconv.ParseUint(data.ValidatorIndex, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for validator index")
}
v.ValidatorIndex = phase0.ValidatorIndex(validatorIndex)

if data.Head == "" {
return errors.New("head missing")
}
head, err := strconv.ParseUint(data.Head, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for head")
}
v.Head = phase0.Gwei(head)

if data.Target == "" {
return errors.New("target missing")
}
v.Target, err = strconv.ParseInt(data.Target, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for target")
}

if data.Source == "" {
return errors.New("source missing")
}
v.Source, err = strconv.ParseInt(data.Source, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for source")
}

if data.InclusionDelay != "" {
inclusionDelay, err := strconv.ParseUint(data.InclusionDelay, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for inclusion delay")
}
tmp := phase0.Gwei(inclusionDelay)
v.InclusionDelay = &tmp
}

if data.Inactivity == "" {
return errors.New("inactivity missing")
}
inactivity, err := strconv.ParseUint(data.Inactivity, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for inactivity")
}
v.Inactivity = phase0.Gwei(inactivity)

return nil
}

// String returns a string version of the structure.
func (v *ValidatorAttestationRewards) String() string {
data, err := json.Marshal(v)
if err != nil {
return fmt.Sprintf("ERR: %v", err)
}

return string(data)
}
2 changes: 1 addition & 1 deletion api/v1/beaconcommitteesubscription.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (

// BeaconCommitteeSubscription is the data required for a beacon committee subscription.
type BeaconCommitteeSubscription struct {
// ValidatorIdex is the index of the validator making the subscription request.
// ValidatorIndex is the index of the validator making the subscription request.
ValidatorIndex phase0.ValidatorIndex
// Slot is the slot for which the validator is attesting.
Slot phase0.Slot
Expand Down
Loading

0 comments on commit 1691823

Please sign in to comment.