Skip to content

Commit

Permalink
Merge pull request #205 from attestantio/update-events
Browse files Browse the repository at this point in the history
Update event to emit spec.VersionedAttestation
  • Loading branch information
mcdee authored Feb 17, 2025
2 parents c92fd5e + 9ba0fb5 commit da982dd
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
dev:
- support single_attestation event
- support change to attestation event; this event now emits a spec.VersionedAttestation

0.24.0:
- support electra
- the most notable change is that a number of functions now use spec.VersionedAttestation in place of phase0.Attestation
Expand Down
9 changes: 7 additions & 2 deletions api/v1/event.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2020, 2021 Attestant Limited.
// Copyright © 2020 - 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
Expand All @@ -17,8 +17,10 @@ import (
"encoding/json"
"fmt"

"github.com/attestantio/go-eth2-client/spec"
"github.com/attestantio/go-eth2-client/spec/altair"
"github.com/attestantio/go-eth2-client/spec/capella"
"github.com/attestantio/go-eth2-client/spec/electra"
"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/pkg/errors"
)
Expand All @@ -45,6 +47,7 @@ var SupportedEventTopics = map[string]bool{
"head": true,
"payload_attributes": true,
"proposer_slashing": true,
"single_attestation": true,
"voluntary_exit": true,
}

Expand Down Expand Up @@ -90,7 +93,7 @@ func (e *Event) UnmarshalJSON(input []byte) error {
}
switch eventJSON.Topic {
case "attestation":
e.Data = &phase0.Attestation{}
e.Data = &spec.VersionedAttestation{}
case "attester_slashing":
e.Data = &phase0.AttesterSlashing{}
case "blob_sidecar":
Expand All @@ -113,6 +116,8 @@ func (e *Event) UnmarshalJSON(input []byte) error {
e.Data = &PayloadAttributesEvent{}
case "proposer_slashing":
e.Data = &phase0.ProposerSlashing{}
case "single_attestation":
e.Data = &electra.SingleAttestation{}
case "voluntary_exit":
e.Data = &phase0.SignedVoluntaryExit{}
default:
Expand Down
18 changes: 13 additions & 5 deletions api/v1/event_test.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright © 2020 Attestant Limited.
// Copyright © 2020, 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
Expand All @@ -18,8 +18,8 @@ import (
"testing"

api "github.com/attestantio/go-eth2-client/api/v1"
require "github.com/stretchr/testify/require"
"github.com/stretchr/testify/assert"
require "github.com/stretchr/testify/require"
)

func TestEvent(t *testing.T) {
Expand Down Expand Up @@ -58,9 +58,17 @@ func TestEvent(t *testing.T) {
err: "data missing",
},
{
name: "GoodAttestation",
name: "GoodPhase0Attestation",
input: []byte(`{"topic":"attestation","data":{"aggregation_bits":"0x010203","data":{"beacon_block_root":"0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f","index":"1","slot":"100","source":{"epoch":"1","root":"0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f"},"target":{"epoch":"2","root":"0x404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f"}},"signature":"0x606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaabacadaeafb0b1b2b3b4b5b6b7b8b9babbbcbdbebf"}}`),
},
{
name: "GoodElectraAttestation",
input: []byte(`{"topic":"attestation","data":{"aggregation_bits":"0xf77ffffffdfbfffffffdbfffffe5fff71f","data":{"slot":"98106","index":"0","beacon_block_root":"0xf8df02ed08b9adcb88a22cb22cd2a6074b184128ae6a240e3172109fdfacaa7b","source":{"epoch":"3064","root":"0x19ffd95e92753046cf63b4298f859e1fb1271a160ef0139ea1eb9f06d45d3b93"},"target":{"epoch":"3065","root":"0xffac9506e2262991ed19b1804bec9f7a1c4c4e61eb37444e6c8826bb362716d6"}},"signature":"0xb4f12c02e0f1a5db07999ceb8c1a4ccd41a3cb46ca15abe1c145337f1287360c49d5780fb7b44dfebeb96f3898824605008c9d458bdd2413358da3edf1b181d4e98edfe90d5fd016ac8f6aebc6646b2da83ab98722a7b4ee5264506bf6ae08e9","committee_bits":"0x0040000000000000"}}`),
},
{
name: "GoodSingleAttestation",
input: []byte(`{"topic":"single_attestation","data":{"committee_index":"11","attester_index":"23784","data":{"slot":"98122","index":"0","beacon_block_root":"0x497033a5af8e64b748c554524e1e269da3c3af71515cf31f2d7bf9bab256a03c","source":{"epoch":"3065","root":"0xffac9506e2262991ed19b1804bec9f7a1c4c4e61eb37444e6c8826bb362716d6"},"target":{"epoch":"3066","root":"0x5982836668f92d786ef82f8841011a0888be5583bd09ab73760563855789d49b"}},"signature":"0xa448d3dc9520d4cb8e70094108169893a94ef7d074151ba333169ea92e2586da6f6efa622722743725c8012707f78efa02d99dd8ee094fa5bf5ca2b24066096ab0bc7671d4037521cbe69411871dd614e60d2c0eed8d2a0b2e4b77602b39d50e"}}`),
},
{
name: "GoodBlock",
input: []byte(`{"topic":"block","data":{"block":"0xbe36e714a6114cf718e35dafc4ac530ce8f01e4a9a360e78098eb129772dcc39","slot":"1"}}`),
Expand Down Expand Up @@ -97,8 +105,8 @@ func TestEvent(t *testing.T) {
require.NoError(t, err)
rt, err := json.Marshal(&res)
require.NoError(t, err)
assert.Equal(t, string(test.input), string(rt))
assert.Equal(t, string(rt), res.String())
assert.JSONEq(t, string(test.input), string(rt))
assert.JSONEq(t, string(rt), res.String())
}
})
}
Expand Down
13 changes: 12 additions & 1 deletion http/events.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ import (

consensusclient "github.com/attestantio/go-eth2-client"
api "github.com/attestantio/go-eth2-client/api/v1"
"github.com/attestantio/go-eth2-client/spec"
"github.com/attestantio/go-eth2-client/spec/altair"
"github.com/attestantio/go-eth2-client/spec/capella"
"github.com/attestantio/go-eth2-client/spec/electra"
"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/r3labs/sse/v2"
"github.com/rs/zerolog"
Expand Down Expand Up @@ -115,7 +117,7 @@ func (*Service) handleEvent(ctx context.Context, msg *sse.Event, handler consens
}
switch string(msg.Event) {
case "attestation":
data := &phase0.Attestation{}
data := &spec.VersionedAttestation{}
err := json.Unmarshal(msg.Data, data)
if err != nil {
log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse attestation")
Expand Down Expand Up @@ -222,6 +224,15 @@ func (*Service) handleEvent(ctx context.Context, msg *sse.Event, handler consens
return
}
event.Data = data
case "single_attestation":
data := &electra.SingleAttestation{}
err := json.Unmarshal(msg.Data, data)
if err != nil {
log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse single attestation event")

return
}
event.Data = data
case "voluntary_exit":
data := &phase0.SignedVoluntaryExit{}
err := json.Unmarshal(msg.Data, data)
Expand Down
48 changes: 48 additions & 0 deletions spec/versionedattestation_json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// 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 spec

import (
"encoding/json"

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

// attestationIdentificationJSON contains fields that allow us to identify the attestation variant.
type attestationIdentificationJSON struct {
CommitteeBits *string `json:"committee_bits"`
}

// UnmarshalJSON implements json.Unmarshaler.
func (v *VersionedAttestation) UnmarshalJSON(input []byte) error {
var id attestationIdentificationJSON
if err := json.Unmarshal(input, &id); err != nil {
return errors.Wrap(err, "invalid JSON")
}

switch {
case id.CommitteeBits != nil:
v.Version = DataVersionElectra
v.Electra = &electra.Attestation{}

return v.Electra.UnmarshalJSON(input)
default:
v.Version = DataVersionPhase0
v.Phase0 = &phase0.Attestation{}

return v.Phase0.UnmarshalJSON(input)
}
}

0 comments on commit da982dd

Please sign in to comment.