From 490d07a8e0c258f4528d3039109696679d79787d Mon Sep 17 00:00:00 2001 From: Jim McDonald Date: Mon, 12 Aug 2024 17:45:11 +0100 Subject: [PATCH 01/11] Add events. --- CHANGELOG.md | 3 + api/v1/blockgossipevent.go | 86 +++++++++++++++++++++++ api/v1/blockgossipevent_test.go | 101 ++++++++++++++++++++++++++ api/v1/event.go | 43 ++++++++---- http/events.go | 121 +++++++++++++++++--------------- 5 files changed, 283 insertions(+), 71 deletions(-) create mode 100644 api/v1/blockgossipevent.go create mode 100644 api/v1/blockgossipevent_test.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 51bb6fde..d4117082 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +dev: + - add attester_slashing, block_gossip, bls_to_execution_change and proposer_slashing events + 0.21.10: - better validator state when balance not supplied diff --git a/api/v1/blockgossipevent.go b/api/v1/blockgossipevent.go new file mode 100644 index 00000000..1b38ae7a --- /dev/null +++ b/api/v1/blockgossipevent.go @@ -0,0 +1,86 @@ +// Copyright © 2024 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/hex" + "encoding/json" + "fmt" + "strconv" + "strings" + + "github.com/attestantio/go-eth2-client/spec/phase0" + "github.com/pkg/errors" +) + +// BlockGossipEvent is the data for the block gossip event. +type BlockGossipEvent struct { + Slot phase0.Slot + Block phase0.Root +} + +// blockGossipEventJSON is the spec representation of the struct. +type blockGossipEventJSON struct { + Slot string `json:"slot"` + Block string `json:"block"` +} + +// MarshalJSON implements json.Marshaler. +func (e *BlockGossipEvent) MarshalJSON() ([]byte, error) { + return json.Marshal(&blockGossipEventJSON{ + Slot: fmt.Sprintf("%d", e.Slot), + Block: fmt.Sprintf("%#x", e.Block), + }) +} + +// UnmarshalJSON implements json.Unmarshaler. +func (e *BlockGossipEvent) UnmarshalJSON(input []byte) error { + var err error + + var data blockGossipEventJSON + if err = json.Unmarshal(input, &data); err != nil { + return errors.Wrap(err, "invalid JSON") + } + if data.Slot == "" { + return errors.New("slot missing") + } + slot, err := strconv.ParseUint(data.Slot, 10, 64) + if err != nil { + return errors.Wrap(err, "invalid value for slot") + } + e.Slot = phase0.Slot(slot) + if data.Block == "" { + return errors.New("block missing") + } + block, err := hex.DecodeString(strings.TrimPrefix(data.Block, "0x")) + if err != nil { + return errors.Wrap(err, "invalid value for block") + } + if len(block) != rootLength { + return fmt.Errorf("incorrect length %d for block", len(block)) + } + copy(e.Block[:], block) + + return nil +} + +// String returns a string version of the structure. +func (e *BlockGossipEvent) String() string { + data, err := json.Marshal(e) + if err != nil { + return fmt.Sprintf("ERR: %v", err) + } + + return string(data) +} diff --git a/api/v1/blockgossipevent_test.go b/api/v1/blockgossipevent_test.go new file mode 100644 index 00000000..b73fae73 --- /dev/null +++ b/api/v1/blockgossipevent_test.go @@ -0,0 +1,101 @@ +// Copyright © 2024 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_test + +import ( + "encoding/json" + "testing" + + api "github.com/attestantio/go-eth2-client/api/v1" + "github.com/stretchr/testify/assert" + require "github.com/stretchr/testify/require" +) + +func TestBlockGossipEventJSON(t *testing.T) { + tests := []struct { + name string + input []byte + err string + }{ + { + name: "Empty", + err: "unexpected end of JSON input", + }, + { + name: "JSONBad", + input: []byte("[]"), + err: "invalid JSON: json: cannot unmarshal array into Go value of type v1.blockGossipEventJSON", + }, + { + name: "SlotMissing", + input: []byte(`{"block":"0x99e3f24aab3dd084045a0c927a33b8463eb5c7b17eeadfecdcf4e4badf7b6028"}`), + err: "slot missing", + }, + { + name: "SlotWrongType", + input: []byte(`{"slot":true,"block":"0x99e3f24aab3dd084045a0c927a33b8463eb5c7b17eeadfecdcf4e4badf7b6028"}`), + err: "invalid JSON: json: cannot unmarshal bool into Go struct field blockGossipEventJSON.slot of type string", + }, + { + name: "SlotInvalid", + input: []byte(`{"slot":"-1","block":"0x99e3f24aab3dd084045a0c927a33b8463eb5c7b17eeadfecdcf4e4badf7b6028"}`), + err: "invalid value for slot: strconv.ParseUint: parsing \"-1\": invalid syntax", + }, + { + name: "BlockMissing", + input: []byte(`{"slot":"525277"}`), + err: "block missing", + }, + { + name: "BlockWrongType", + input: []byte(`{"slot":"525277","block":true}`), + err: "invalid JSON: json: cannot unmarshal bool into Go struct field blockGossipEventJSON.block of type string", + }, + { + name: "BlockInvalid", + input: []byte(`{"slot":"525277","block":"invalid"}`), + err: "invalid value for block: encoding/hex: invalid byte: U+0069 'i'", + }, + { + name: "BlockShort", + input: []byte(`{"slot":"525277","block":"0xe3f24aab3dd084045a0c927a33b8463eb5c7b17eeadfecdcf4e4badf7b6028"}`), + err: "incorrect length 31 for block", + }, + { + name: "BlockLong", + input: []byte(`{"slot":"525277","block":"0x9999e3f24aab3dd084045a0c927a33b8463eb5c7b17eeadfecdcf4e4badf7b6028"}`), + err: "incorrect length 33 for block", + }, + { + name: "Good", + input: []byte(`{"slot":"525277","block":"0x99e3f24aab3dd084045a0c927a33b8463eb5c7b17eeadfecdcf4e4badf7b6028"}`), + }, + } + + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + var res api.BlockGossipEvent + err := json.Unmarshal(test.input, &res) + if test.err != "" { + require.EqualError(t, err, test.err) + } else { + 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()) + } + }) + } +} diff --git a/api/v1/event.go b/api/v1/event.go index 8a991d39..977cdb49 100644 --- a/api/v1/event.go +++ b/api/v1/event.go @@ -18,6 +18,7 @@ import ( "fmt" "github.com/attestantio/go-eth2-client/spec/altair" + "github.com/attestantio/go-eth2-client/spec/capella" "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/pkg/errors" ) @@ -32,15 +33,19 @@ type Event struct { // SupportedEventTopics is a map of supported event topics. var SupportedEventTopics = map[string]bool{ - "attestation": true, - "block": true, - "chain_reorg": true, - "finalized_checkpoint": true, - "head": true, - "voluntary_exit": true, - "contribution_and_proof": true, - "payload_attributes": true, - "blob_sidecar": true, + "attestation": true, + "attester_slashing": true, + "blob_sidecar": true, + "block": true, + "block_gossip": true, + "bls_to_execution_change": true, + "chain_reorg": true, + "contribution_and_proof": true, + "finalized_checkpoint": true, + "head": true, + "payload_attributes": true, + "proposer_slashing": true, + "voluntary_exit": true, } // eventJSON is the spec representation of the struct. @@ -86,22 +91,30 @@ func (e *Event) UnmarshalJSON(input []byte) error { switch eventJSON.Topic { case "attestation": e.Data = &phase0.Attestation{} + case "attester_slashing": + e.Data = &phase0.AttesterSlashing{} + case "blob_sidecar": + e.Data = &BlobSidecarEvent{} case "block": e.Data = &BlockEvent{} + case "block_gossip": + e.Data = &BlockGossipEvent{} + case "bls_to_execution_change": + e.Data = &capella.SignedBLSToExecutionChange{} case "chain_reorg": e.Data = &ChainReorgEvent{} + case "contribution_and_proof": + e.Data = &altair.SignedContributionAndProof{} case "finalized_checkpoint": e.Data = &FinalizedCheckpointEvent{} case "head": e.Data = &HeadEvent{} - case "voluntary_exit": - e.Data = &phase0.SignedVoluntaryExit{} - case "contribution_and_proof": - e.Data = &altair.SignedContributionAndProof{} case "payload_attributes": e.Data = &PayloadAttributesEvent{} - case "blob_sidecar": - e.Data = &BlobSidecarEvent{} + case "proposer_slashing": + e.Data = &phase0.ProposerSlashing{} + case "voluntary_exit": + e.Data = &phase0.SignedVoluntaryExit{} default: return fmt.Errorf("unsupported event topic %s", eventJSON.Topic) } diff --git a/http/events.go b/http/events.go index 589859f5..cb3f189d 100644 --- a/http/events.go +++ b/http/events.go @@ -117,114 +117,123 @@ func (*Service) handleEvent(ctx context.Context, msg *sse.Event, handler consens Topic: string(msg.Event), } switch string(msg.Event) { - case "head": - headEvent := &api.HeadEvent{} - err := json.Unmarshal(msg.Data, headEvent) + case "attestation": + data := &phase0.Attestation{} + err := json.Unmarshal(msg.Data, data) if err != nil { - log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse head event") + log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse attestation") return } - event.Data = headEvent - case "block": - blockEvent := &api.BlockEvent{} - err := json.Unmarshal(msg.Data, blockEvent) + event.Data = data + case "attester_slashing": + data := &phase0.AttesterSlashing{} + err := json.Unmarshal(msg.Data, data) if err != nil { - log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse block event") + log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse attester slashing event") return } - event.Data = blockEvent - case "attestation": - attestation := &phase0.Attestation{} - err := json.Unmarshal(msg.Data, attestation) + event.Data = data + case "blob_sidecar": + data := &api.BlobSidecarEvent{} + err := json.Unmarshal(msg.Data, data) if err != nil { - log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse attestation") + log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse blob sidecar event") return } - event.Data = attestation - case "voluntary_exit": - voluntaryExit := &phase0.SignedVoluntaryExit{} - err := json.Unmarshal(msg.Data, voluntaryExit) + event.Data = data + case "block": + data := &api.BlockEvent{} + err := json.Unmarshal(msg.Data, data) if err != nil { - log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse voluntary exit") + log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse block event") return } - event.Data = voluntaryExit - case "finalized_checkpoint": - finalizedCheckpointEvent := &api.FinalizedCheckpointEvent{} - err := json.Unmarshal(msg.Data, finalizedCheckpointEvent) + event.Data = data + case "block_gossip": + data := &api.BlockGossipEvent{} + err := json.Unmarshal(msg.Data, data) if err != nil { - log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse finalized checkpoint event") + log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse block gossip event") + + return + } + event.Data = data + case "bls_to_execution_change": + data := &capella.SignedBLSToExecutionChange{} + err := json.Unmarshal(msg.Data, data) + if err != nil { + log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse bls to execution change event") return } - event.Data = finalizedCheckpointEvent + event.Data = data case "chain_reorg": - chainReorgEvent := &api.ChainReorgEvent{} - err := json.Unmarshal(msg.Data, chainReorgEvent) + data := &api.ChainReorgEvent{} + err := json.Unmarshal(msg.Data, data) if err != nil { log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse chain reorg event") return } - event.Data = chainReorgEvent + event.Data = data case "contribution_and_proof": - contributionAndProofEvent := &altair.SignedContributionAndProof{} - err := json.Unmarshal(msg.Data, contributionAndProofEvent) + data := &altair.SignedContributionAndProof{} + err := json.Unmarshal(msg.Data, data) if err != nil { log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse contribution and proof event") return } - event.Data = contributionAndProofEvent - case "payload_attributes": - payloadAttributesEvent := &api.PayloadAttributesEvent{} - err := json.Unmarshal(msg.Data, payloadAttributesEvent) + event.Data = data + case "finalized_checkpoint": + data := &api.FinalizedCheckpointEvent{} + err := json.Unmarshal(msg.Data, data) if err != nil { - log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse payload attributes event") + log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse finalized checkpoint event") return } - event.Data = payloadAttributesEvent - case "proposer_slashing": - proposerSlashingEvent := &phase0.ProposerSlashing{} - err := json.Unmarshal(msg.Data, proposerSlashingEvent) + event.Data = data + case "head": + data := &api.HeadEvent{} + err := json.Unmarshal(msg.Data, data) if err != nil { - log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse proposer slashing event") + log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse head event") return } - event.Data = proposerSlashingEvent - case "attester_slashing": - attesterSlashingEvent := &phase0.AttesterSlashing{} - err := json.Unmarshal(msg.Data, attesterSlashingEvent) + event.Data = data + case "payload_attributes": + data := &api.PayloadAttributesEvent{} + err := json.Unmarshal(msg.Data, data) if err != nil { - log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse attester slashing event") + log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse payload attributes event") return } - event.Data = attesterSlashingEvent - case "bls_to_execution_change": - blsToExecutionChangeEvent := &capella.BLSToExecutionChange{} - err := json.Unmarshal(msg.Data, blsToExecutionChangeEvent) + event.Data = data + case "proposer_slashing": + data := &phase0.ProposerSlashing{} + err := json.Unmarshal(msg.Data, data) if err != nil { - log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse bls to execution change event") + log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse proposer slashing event") return } - event.Data = blsToExecutionChangeEvent - case "blob_sidecar": - blobSidecar := &api.BlobSidecarEvent{} - err := json.Unmarshal(msg.Data, blobSidecar) + event.Data = data + case "voluntary_exit": + data := &phase0.SignedVoluntaryExit{} + err := json.Unmarshal(msg.Data, data) if err != nil { - log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse blob sidecar event") + log.Error().Err(err).RawJSON("data", msg.Data).Msg("Failed to parse voluntary exit") return } - event.Data = blobSidecar + event.Data = data case "": // Used as keepalive. Ignore. return From 5608aaa67b9ff2e5ee41280c6bd447fe4531139b Mon Sep 17 00:00:00 2001 From: Jim McDonald Date: Sat, 24 Aug 2024 17:41:36 +0100 Subject: [PATCH 02/11] Allow filtering of attestationpool by committee index. --- api/attestationpoolopts.go | 11 ++++++++--- http/attestationpool.go | 16 +++++++++++++--- http/http.go | 2 +- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/api/attestationpoolopts.go b/api/attestationpoolopts.go index 57349fd0..9994e109 100644 --- a/api/attestationpoolopts.go +++ b/api/attestationpoolopts.go @@ -1,4 +1,4 @@ -// Copyright © 2023 Attestant Limited. +// Copyright © 2023, 2024 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 @@ -19,6 +19,11 @@ import "github.com/attestantio/go-eth2-client/spec/phase0" type AttestationPoolOpts struct { Common CommonOpts - // Slot is the slot for which the data is obtained. - Slot phase0.Slot + // Slot is the slot for which the data is obtained. If not present then + // data for all slots will be obtained. + Slot *phase0.Slot + + // CommmitteeIndex 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 } diff --git a/http/attestationpool.go b/http/attestationpool.go index 8ec46e90..d9d968ef 100644 --- a/http/attestationpool.go +++ b/http/attestationpool.go @@ -18,6 +18,7 @@ import ( "context" "errors" "fmt" + "strings" client "github.com/attestantio/go-eth2-client" "github.com/attestantio/go-eth2-client/api" @@ -39,8 +40,14 @@ func (s *Service) AttestationPool(ctx context.Context, } endpoint := "/eth/v1/beacon/pool/attestations" - query := fmt.Sprintf("slot=%d", opts.Slot) - httpResponse, err := s.get(ctx, endpoint, query, &opts.Common, false) + queryItems := make([]string, 0) + if opts.Slot != nil { + queryItems = append(queryItems, fmt.Sprintf("slot=%d", *opts.Slot)) + } + if opts.CommitteeIndex != nil { + queryItems = append(queryItems, fmt.Sprintf("committee_index=%d", *opts.CommitteeIndex)) + } + httpResponse, err := s.get(ctx, endpoint, strings.Join(queryItems, "&"), &opts.Common, false) if err != nil { return nil, err } @@ -77,9 +84,12 @@ func (*Service) attestationPoolFromJSON(_ context.Context, func verifyAttestationPool(opts *api.AttestationPoolOpts, data []*phase0.Attestation) error { for _, datum := range data { - if datum.Data.Slot != opts.Slot { + if opts.Slot != nil && datum.Data.Slot != *opts.Slot { return errors.New("attestation data not for requested slot") } + if opts.CommitteeIndex != nil && datum.Data.Index != *opts.CommitteeIndex { + return errors.New("attestation data not for requested committee index") + } } return nil diff --git a/http/http.go b/http/http.go index 109fb801..9a899e2a 100644 --- a/http/http.go +++ b/http/http.go @@ -34,7 +34,7 @@ import ( ) // defaultUserAgent is sent with requests if no other user agent has been supplied. -const defaultUserAgent = "go-eth2-client/0.21.10" +const defaultUserAgent = "go-eth2-client/0.21.11" // post sends an HTTP post request and returns the body. func (s *Service) post(ctx context.Context, endpoint string, body io.Reader) (io.Reader, error) { From d9f769146b6da451d781cd696df56fe0214af68f Mon Sep 17 00:00:00 2001 From: Jim McDonald Date: Sat, 24 Aug 2024 17:43:41 +0100 Subject: [PATCH 03/11] Update test. --- http/attestationpool_test.go | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/http/attestationpool_test.go b/http/attestationpool_test.go index 57d439dd..46eeb138 100644 --- a/http/attestationpool_test.go +++ b/http/attestationpool_test.go @@ -27,6 +27,11 @@ import ( "github.com/stretchr/testify/require" ) +func slotptr(slot uint64) *phase0.Slot { + res := phase0.Slot(slot) + return &res +} + func TestAttestationPool(t *testing.T) { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -57,14 +62,14 @@ func TestAttestationPool(t *testing.T) { { name: "Empty", opts: &api.AttestationPoolOpts{ - Slot: 1, + Slot: slotptr(1), }, expected: make([]*phase0.Attestation, 0), }, { name: "Current", opts: &api.AttestationPoolOpts{ - Slot: phase0.Slot(uint64(time.Since(genesisResponse.Data.GenesisTime).Seconds()) / uint64(slotDuration.Seconds())), + Slot: slotptr(uint64(time.Since(genesisResponse.Data.GenesisTime).Seconds()) / uint64(slotDuration.Seconds())), }, }, } From 50179b8bd4d75c956248c8af698373fac1ddb6c9 Mon Sep 17 00:00:00 2001 From: Jim McDonald Date: Sat, 24 Aug 2024 18:25:11 +0100 Subject: [PATCH 04/11] Tidy-ups. --- .golangci.yml | 5 +++++ api/v1/forkchoice.go | 2 +- http/events_internal_test.go | 2 +- http/spec.go | 4 ++-- spec/builderversion.go | 2 +- spec/dataversion.go | 2 +- 6 files changed, 11 insertions(+), 6 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 9356cb7d..b94397e5 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -106,6 +106,10 @@ output: # All available settings of specific linters. linters-settings: + gosec: + excludes: + - G115 # This generates a lot of false positives. + lll: line-length: 132 @@ -162,6 +166,7 @@ linters: - execinquery - exhaustive - exhaustruct + - exportloopref - forcetypeassert - funlen - gci diff --git a/api/v1/forkchoice.go b/api/v1/forkchoice.go index d890b4a9..0de7e006 100644 --- a/api/v1/forkchoice.go +++ b/api/v1/forkchoice.go @@ -147,7 +147,7 @@ func (d *ForkChoiceNodeValidity) UnmarshalJSON(input []byte) error { // String returns a string representation of the ForkChoiceNodeValidity. func (d ForkChoiceNodeValidity) String() string { - if int(d) >= len(ForkChoiceNodeValidityStrings) { + if uint64(d) >= uint64(len(ForkChoiceNodeValidityStrings)) { return "unknown" } diff --git a/http/events_internal_test.go b/http/events_internal_test.go index 683460ba..f00e7c95 100644 --- a/http/events_internal_test.go +++ b/http/events_internal_test.go @@ -147,7 +147,7 @@ func TestEventHandler(t *testing.T) { name: "BLSToExecutionChangeGood", message: &sse.Event{ Event: []byte("bls_to_execution_change"), - Data: []byte(`{"validator_index":"63401","from_bls_pubkey":"0xa46ed2574770ec1942d577ef89e0bf7b0d601349dab791740dead3fb5a6e2624cf62b9e58de1074c49f44b986eb39002","to_execution_address":"0xd641D2Cc74C7b6A641861260d07D67eB67bc7403"}`), + Data: []byte(`{"message":{"validator_index":"63401","from_bls_pubkey":"0xa46ed2574770ec1942d577ef89e0bf7b0d601349dab791740dead3fb5a6e2624cf62b9e58de1074c49f44b986eb39002","to_execution_address":"0xd641D2Cc74C7b6A641861260d07D67eB67bc7403"},"signature":"0xb9ce6f10137a8bc73cd5545e5d6c7c61bc1294b853e71e5eb090a7a773d7773c4d7732f4244e9891cd5c1f7a5fbc951c0b368a8bd7dc44b1598a6d1bdb4476f9f364ef521c366e55565792810f0cb8bf8cc20134f32ed8dde54507f622402d6e"}`), }, handler: handler, handled: true, diff --git a/http/spec.go b/http/spec.go index e3162068..a2a2f5cd 100644 --- a/http/spec.go +++ b/http/spec.go @@ -121,8 +121,8 @@ func (s *Service) Spec(ctx context.Context, // Handle durations. if strings.HasPrefix(k, "SECONDS_PER_") || k == "GENESIS_DELAY" { - intVal, err := strconv.ParseUint(v, 10, 64) - if err == nil && intVal != 0 { + intVal, err := strconv.ParseInt(v, 10, 64) + if err == nil && intVal >= 0 { config[k] = time.Duration(intVal) * time.Second continue diff --git a/spec/builderversion.go b/spec/builderversion.go index c6871432..17a6cc41 100644 --- a/spec/builderversion.go +++ b/spec/builderversion.go @@ -50,7 +50,7 @@ func (d *BuilderVersion) UnmarshalJSON(input []byte) error { // String returns a string representation of the struct. func (d BuilderVersion) String() string { - if int(d) >= len(responseBuilderVersionStrings) { + if uint64(d) >= uint64(len(responseBuilderVersionStrings)) { return "unknown" } diff --git a/spec/dataversion.go b/spec/dataversion.go index ef09d06e..45dbcb82 100644 --- a/spec/dataversion.go +++ b/spec/dataversion.go @@ -73,7 +73,7 @@ func (d *DataVersion) UnmarshalJSON(input []byte) error { // String returns a string representation of the struct. func (d DataVersion) String() string { - if int(d) >= len(dataVersionStrings) { + if uint64(d) >= uint64(len(dataVersionStrings)) { return "unknown" } From ae1d6ab0a4f23353927ba79d4e9a50c3124cb423 Mon Sep 17 00:00:00 2001 From: pk910 Date: Sat, 21 Sep 2024 17:47:43 +0200 Subject: [PATCH 05/11] update electra specs to `v1.5.0-alpha.6` --- spec/electra/beaconblockbody.go | 6 +- spec/electra/beaconblockbody_json.go | 9 +- spec/electra/beaconblockbody_ssz.go | 45 +- spec/electra/beaconblockbody_yaml.go | 5 +- spec/electra/beaconstate.go | 3 +- spec/electra/beaconstate_json.go | 59 ++- spec/electra/beaconstate_ssz.go | 7 +- spec/electra/beaconstate_yaml.go | 75 +-- spec/electra/consensusspec_test.go | 8 +- spec/electra/consolidationrequest_ssz.go | 40 +- spec/electra/depositrequest_ssz.go | 2 +- spec/electra/executionpayload.go | 58 -- spec/electra/executionpayload_json.go | 281 ---------- spec/electra/executionpayload_ssz.go | 560 -------------------- spec/electra/executionpayload_yaml.go | 105 ---- spec/electra/executionpayloadheader.go | 57 -- spec/electra/executionpayloadheader_json.go | 238 --------- spec/electra/executionpayloadheader_ssz.go | 291 ---------- spec/electra/executionpayloadheader_yaml.go | 101 ---- spec/electra/executionrequests.go | 37 ++ spec/electra/executionrequests_json.go | 77 +++ spec/electra/executionrequests_ssz.go | 234 ++++++++ spec/electra/executionrequests_yaml.go | 59 +++ spec/electra/generate.go | 6 +- spec/electra/withdrawalrequest_ssz.go | 40 +- 25 files changed, 578 insertions(+), 1825 deletions(-) delete mode 100644 spec/electra/executionpayload.go delete mode 100644 spec/electra/executionpayload_json.go delete mode 100644 spec/electra/executionpayload_ssz.go delete mode 100644 spec/electra/executionpayload_yaml.go delete mode 100644 spec/electra/executionpayloadheader.go delete mode 100644 spec/electra/executionpayloadheader_json.go delete mode 100644 spec/electra/executionpayloadheader_ssz.go delete mode 100644 spec/electra/executionpayloadheader_yaml.go create mode 100644 spec/electra/executionrequests.go create mode 100644 spec/electra/executionrequests_json.go create mode 100644 spec/electra/executionrequests_ssz.go create mode 100644 spec/electra/executionrequests_yaml.go diff --git a/spec/electra/beaconblockbody.go b/spec/electra/beaconblockbody.go index 5edba161..f722d2d5 100644 --- a/spec/electra/beaconblockbody.go +++ b/spec/electra/beaconblockbody.go @@ -16,10 +16,9 @@ package electra import ( "fmt" - "github.com/attestantio/go-eth2-client/spec/deneb" - "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/capella" + "github.com/attestantio/go-eth2-client/spec/deneb" "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/goccy/go-yaml" ) @@ -35,9 +34,10 @@ type BeaconBlockBody struct { Deposits []*phase0.Deposit `ssz-max:"16"` VoluntaryExits []*phase0.SignedVoluntaryExit `ssz-max:"16"` SyncAggregate *altair.SyncAggregate - ExecutionPayload *ExecutionPayload + ExecutionPayload *deneb.ExecutionPayload BLSToExecutionChanges []*capella.SignedBLSToExecutionChange `ssz-max:"16"` BlobKZGCommitments []deneb.KZGCommitment `ssz-max:"4096" ssz-size:"?,48"` + ExecutionRequests *ExecutionRequests } // String returns a string version of the structure. diff --git a/spec/electra/beaconblockbody_json.go b/spec/electra/beaconblockbody_json.go index 41afd46d..874859e8 100644 --- a/spec/electra/beaconblockbody_json.go +++ b/spec/electra/beaconblockbody_json.go @@ -22,6 +22,7 @@ import ( "github.com/attestantio/go-eth2-client/codecs" "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/capella" + "github.com/attestantio/go-eth2-client/spec/deneb" "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/pkg/errors" ) @@ -37,9 +38,10 @@ type beaconBlockBodyJSON struct { Deposits []*phase0.Deposit `json:"deposits"` VoluntaryExits []*phase0.SignedVoluntaryExit `json:"voluntary_exits"` SyncAggregate *altair.SyncAggregate `json:"sync_aggregate"` - ExecutionPayload *ExecutionPayload `json:"execution_payload"` + ExecutionPayload *deneb.ExecutionPayload `json:"execution_payload"` BLSToExecutionChanges []*capella.SignedBLSToExecutionChange `json:"bls_to_execution_changes"` BlobKZGCommitments []string `json:"blob_kzg_commitments"` + ExecutionRequests *ExecutionRequests `json:"execution_requests"` } // MarshalJSON implements json.Marshaler. @@ -62,6 +64,7 @@ func (b *BeaconBlockBody) MarshalJSON() ([]byte, error) { ExecutionPayload: b.ExecutionPayload, BLSToExecutionChanges: b.BLSToExecutionChanges, BlobKZGCommitments: blobKZGCommitments, + ExecutionRequests: b.ExecutionRequests, }) } @@ -164,5 +167,9 @@ func (b *BeaconBlockBody) UnmarshalJSON(input []byte) error { return errors.Wrap(err, "blob_kzg_commitments") } + if err := json.Unmarshal(raw["execution_requests"], &b.ExecutionRequests); err != nil { + return errors.Wrap(err, "execution_requests") + } + return nil } diff --git a/spec/electra/beaconblockbody_ssz.go b/spec/electra/beaconblockbody_ssz.go index 2045a353..19a2a06a 100644 --- a/spec/electra/beaconblockbody_ssz.go +++ b/spec/electra/beaconblockbody_ssz.go @@ -19,7 +19,7 @@ func (b *BeaconBlockBody) MarshalSSZ() ([]byte, error) { // MarshalSSZTo ssz marshals the BeaconBlockBody object to a target array func (b *BeaconBlockBody) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(392) + offset := int(396) // Field (0) 'RANDAOReveal' dst = append(dst, b.RANDAOReveal[:]...) @@ -72,7 +72,7 @@ func (b *BeaconBlockBody) MarshalSSZTo(buf []byte) (dst []byte, err error) { // Offset (9) 'ExecutionPayload' dst = ssz.WriteOffset(dst, offset) if b.ExecutionPayload == nil { - b.ExecutionPayload = new(ExecutionPayload) + b.ExecutionPayload = new(deneb.ExecutionPayload) } offset += b.ExecutionPayload.SizeSSZ() @@ -185,12 +185,12 @@ func (b *BeaconBlockBody) MarshalSSZTo(buf []byte) (dst []byte, err error) { func (b *BeaconBlockBody) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 392 { + if size < 396 { return ssz.ErrSize } tail := buf - var o3, o4, o5, o6, o7, o9, o10, o11 uint64 + var o3, o4, o5, o6, o7, o9, o10, o11, o12 uint64 // Field (0) 'RANDAOReveal' copy(b.RANDAOReveal[:], buf[0:96]) @@ -211,7 +211,7 @@ func (b *BeaconBlockBody) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } - if o3 < 392 { + if o3 < 396 { return ssz.ErrInvalidVariableOffset } @@ -258,6 +258,11 @@ func (b *BeaconBlockBody) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } + // Offset (12) 'ExecutionRequests' + if o12 = ssz.ReadOffset(buf[392:396]); o12 > size || o11 > o12 { + return ssz.ErrOffset + } + // Field (3) 'ProposerSlashings' { buf = tail[o3:o4] @@ -360,7 +365,7 @@ func (b *BeaconBlockBody) UnmarshalSSZ(buf []byte) error { { buf = tail[o9:o10] if b.ExecutionPayload == nil { - b.ExecutionPayload = new(ExecutionPayload) + b.ExecutionPayload = new(deneb.ExecutionPayload) } if err = b.ExecutionPayload.UnmarshalSSZ(buf); err != nil { return err @@ -387,7 +392,7 @@ func (b *BeaconBlockBody) UnmarshalSSZ(buf []byte) error { // Field (11) 'BlobKZGCommitments' { - buf = tail[o11:] + buf = tail[o11:o12] num, err := ssz.DivideInt2(len(buf), 48, 4096) if err != nil { return err @@ -397,13 +402,24 @@ func (b *BeaconBlockBody) UnmarshalSSZ(buf []byte) error { copy(b.BlobKZGCommitments[ii][:], buf[ii*48:(ii+1)*48]) } } + + // Field (12) 'ExecutionRequests' + { + buf = tail[o12:] + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(ExecutionRequests) + } + if err = b.ExecutionRequests.UnmarshalSSZ(buf); err != nil { + return err + } + } return err } // SizeSSZ returns the ssz encoded size in bytes for the BeaconBlockBody object func (b *BeaconBlockBody) SizeSSZ() (size int) { - size = 392 + size = 396 // Field (3) 'ProposerSlashings' size += len(b.ProposerSlashings) * 416 @@ -428,7 +444,7 @@ func (b *BeaconBlockBody) SizeSSZ() (size int) { // Field (9) 'ExecutionPayload' if b.ExecutionPayload == nil { - b.ExecutionPayload = new(ExecutionPayload) + b.ExecutionPayload = new(deneb.ExecutionPayload) } size += b.ExecutionPayload.SizeSSZ() @@ -438,6 +454,12 @@ func (b *BeaconBlockBody) SizeSSZ() (size int) { // Field (11) 'BlobKZGCommitments' size += len(b.BlobKZGCommitments) * 48 + // Field (12) 'ExecutionRequests' + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(ExecutionRequests) + } + size += b.ExecutionRequests.SizeSSZ() + return } @@ -587,6 +609,11 @@ func (b *BeaconBlockBody) HashTreeRootWith(hh ssz.HashWalker) (err error) { hh.MerkleizeWithMixin(subIndx, numItems, 4096) } + // Field (12) 'ExecutionRequests' + if err = b.ExecutionRequests.HashTreeRootWith(hh); err != nil { + return + } + hh.Merkleize(indx) return } diff --git a/spec/electra/beaconblockbody_yaml.go b/spec/electra/beaconblockbody_yaml.go index b934835f..77ab850c 100644 --- a/spec/electra/beaconblockbody_yaml.go +++ b/spec/electra/beaconblockbody_yaml.go @@ -20,6 +20,7 @@ import ( "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/capella" + "github.com/attestantio/go-eth2-client/spec/deneb" "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/goccy/go-yaml" "github.com/pkg/errors" @@ -36,9 +37,10 @@ type beaconBlockBodyYAML struct { Deposits []*phase0.Deposit `yaml:"deposits"` VoluntaryExits []*phase0.SignedVoluntaryExit `yaml:"voluntary_exits"` SyncAggregate *altair.SyncAggregate `yaml:"sync_aggregate"` - ExecutionPayload *ExecutionPayload `yaml:"execution_payload"` + ExecutionPayload *deneb.ExecutionPayload `yaml:"execution_payload"` BLSToExecutionChanges []*capella.SignedBLSToExecutionChange `yaml:"bls_to_execution_changes"` BlobKZGCommitments []string `yaml:"blob_kzg_commitments"` + ExecutionRequests *ExecutionRequests `yaml:"execution_requests"` } // MarshalYAML implements yaml.Marshaler. @@ -61,6 +63,7 @@ func (b *BeaconBlockBody) MarshalYAML() ([]byte, error) { ExecutionPayload: b.ExecutionPayload, BLSToExecutionChanges: b.BLSToExecutionChanges, BlobKZGCommitments: blobKZGCommitments, + ExecutionRequests: b.ExecutionRequests, }, yaml.Flow(true)) if err != nil { return nil, err diff --git a/spec/electra/beaconstate.go b/spec/electra/beaconstate.go index 8b4a7d3b..a9ee8af2 100644 --- a/spec/electra/beaconstate.go +++ b/spec/electra/beaconstate.go @@ -18,6 +18,7 @@ import ( "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/capella" + "github.com/attestantio/go-eth2-client/spec/deneb" "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/goccy/go-yaml" bitfield "github.com/prysmaticlabs/go-bitfield" @@ -49,7 +50,7 @@ type BeaconState struct { InactivityScores []uint64 `ssz-max:"1099511627776"` CurrentSyncCommittee *altair.SyncCommittee NextSyncCommittee *altair.SyncCommittee - LatestExecutionPayloadHeader *ExecutionPayloadHeader + LatestExecutionPayloadHeader *deneb.ExecutionPayloadHeader NextWithdrawalIndex capella.WithdrawalIndex NextWithdrawalValidatorIndex phase0.ValidatorIndex HistoricalSummaries []*capella.HistoricalSummary `ssz-max:"16777216"` diff --git a/spec/electra/beaconstate_json.go b/spec/electra/beaconstate_json.go index 584b0595..ffe14955 100644 --- a/spec/electra/beaconstate_json.go +++ b/spec/electra/beaconstate_json.go @@ -23,6 +23,7 @@ import ( "github.com/attestantio/go-eth2-client/codecs" "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/capella" + "github.com/attestantio/go-eth2-client/spec/deneb" "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/pkg/errors" ) @@ -39,34 +40,34 @@ type beaconStateJSON struct { HistoricalRoots []phase0.Root `json:"historical_roots"` ETH1Data *phase0.ETH1Data `json:"eth1_data"` //nolint:staticcheck - ETH1DataVotes []*phase0.ETH1Data `json:"eth1_data_votes,allowempty"` - ETH1DepositIndex string `json:"eth1_deposit_index"` - Validators []*phase0.Validator `json:"validators"` - Balances []string `json:"balances"` - RANDAOMixes []string `json:"randao_mixes"` - Slashings []string `json:"slashings"` - PreviousEpochParticipation []string `json:"previous_epoch_participation"` - CurrentEpochParticipation []string `json:"current_epoch_participation"` - JustificationBits string `json:"justification_bits"` - PreviousJustifiedCheckpoint *phase0.Checkpoint `json:"previous_justified_checkpoint"` - CurrentJustifiedCheckpoint *phase0.Checkpoint `json:"current_justified_checkpoint"` - FinalizedCheckpoint *phase0.Checkpoint `json:"finalized_checkpoint"` - InactivityScores []string `json:"inactivity_scores"` - CurrentSyncCommittee *altair.SyncCommittee `json:"current_sync_committee"` - NextSyncCommittee *altair.SyncCommittee `json:"next_sync_committee"` - LatestExecutionPayloadHeader *ExecutionPayloadHeader `json:"latest_execution_payload_header"` - NextWithdrawalIndex string `json:"next_withdrawal_index"` - NextWithdrawalValidatorIndex string `json:"next_withdrawal_validator_index"` - HistoricalSummaries []*capella.HistoricalSummary `json:"historical_summaries"` - DepositRequestsStartIndex string `json:"deposit_requests_start_index"` - DepositBalanceToConsume phase0.Gwei `json:"deposit_balance_to_consume"` - ExitBalanceToConsume phase0.Gwei `json:"exit_balance_to_consume"` - EarliestExitEpoch phase0.Epoch `json:"earliest_exit_epoch"` - ConsolidationBalanceToConsume phase0.Gwei `json:"consolidation_balance_to_consume"` - EarliestConsolidationEpoch phase0.Epoch `json:"earliest_consolidation_epoch"` - PendingBalanceDeposits []*PendingBalanceDeposit `json:"pending_balance_deposits"` - PendingPartialWithdrawals []*PendingPartialWithdrawal `json:"pending_partial_withdrawals"` - PendingConsolidations []*PendingConsolidation `json:"pending_consolidations"` + ETH1DataVotes []*phase0.ETH1Data `json:"eth1_data_votes,allowempty"` + ETH1DepositIndex string `json:"eth1_deposit_index"` + Validators []*phase0.Validator `json:"validators"` + Balances []string `json:"balances"` + RANDAOMixes []string `json:"randao_mixes"` + Slashings []string `json:"slashings"` + PreviousEpochParticipation []string `json:"previous_epoch_participation"` + CurrentEpochParticipation []string `json:"current_epoch_participation"` + JustificationBits string `json:"justification_bits"` + PreviousJustifiedCheckpoint *phase0.Checkpoint `json:"previous_justified_checkpoint"` + CurrentJustifiedCheckpoint *phase0.Checkpoint `json:"current_justified_checkpoint"` + FinalizedCheckpoint *phase0.Checkpoint `json:"finalized_checkpoint"` + InactivityScores []string `json:"inactivity_scores"` + CurrentSyncCommittee *altair.SyncCommittee `json:"current_sync_committee"` + NextSyncCommittee *altair.SyncCommittee `json:"next_sync_committee"` + LatestExecutionPayloadHeader *deneb.ExecutionPayloadHeader `json:"latest_execution_payload_header"` + NextWithdrawalIndex string `json:"next_withdrawal_index"` + NextWithdrawalValidatorIndex string `json:"next_withdrawal_validator_index"` + HistoricalSummaries []*capella.HistoricalSummary `json:"historical_summaries"` + DepositRequestsStartIndex string `json:"deposit_requests_start_index"` + DepositBalanceToConsume phase0.Gwei `json:"deposit_balance_to_consume"` + ExitBalanceToConsume phase0.Gwei `json:"exit_balance_to_consume"` + EarliestExitEpoch phase0.Epoch `json:"earliest_exit_epoch"` + ConsolidationBalanceToConsume phase0.Gwei `json:"consolidation_balance_to_consume"` + EarliestConsolidationEpoch phase0.Epoch `json:"earliest_consolidation_epoch"` + PendingBalanceDeposits []*PendingBalanceDeposit `json:"pending_balance_deposits"` + PendingPartialWithdrawals []*PendingPartialWithdrawal `json:"pending_partial_withdrawals"` + PendingConsolidations []*PendingConsolidation `json:"pending_consolidations"` } // MarshalJSON implements json.Marshaler. @@ -273,7 +274,7 @@ func (b *BeaconState) UnmarshalJSON(input []byte) error { return errors.Wrap(err, "next_sync_committee") } - b.LatestExecutionPayloadHeader = &ExecutionPayloadHeader{} + b.LatestExecutionPayloadHeader = &deneb.ExecutionPayloadHeader{} if err := b.LatestExecutionPayloadHeader.UnmarshalJSON(raw["latest_execution_payload_header"]); err != nil { return errors.Wrap(err, "latest_execution_payload_header") } diff --git a/spec/electra/beaconstate_ssz.go b/spec/electra/beaconstate_ssz.go index 96a26112..b93a61d5 100644 --- a/spec/electra/beaconstate_ssz.go +++ b/spec/electra/beaconstate_ssz.go @@ -7,6 +7,7 @@ import ( "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/capella" "github.com/attestantio/go-eth2-client/spec/phase0" + "github.com/attestantio/go-eth2-client/spec/deneb" ssz "github.com/ferranbt/fastssz" ) @@ -170,7 +171,7 @@ func (b *BeaconState) MarshalSSZTo(buf []byte) (dst []byte, err error) { // Offset (24) 'LatestExecutionPayloadHeader' dst = ssz.WriteOffset(dst, offset) if b.LatestExecutionPayloadHeader == nil { - b.LatestExecutionPayloadHeader = new(ExecutionPayloadHeader) + b.LatestExecutionPayloadHeader = new(deneb.ExecutionPayloadHeader) } offset += b.LatestExecutionPayloadHeader.SizeSSZ() @@ -643,7 +644,7 @@ func (b *BeaconState) UnmarshalSSZ(buf []byte) error { { buf = tail[o24:o27] if b.LatestExecutionPayloadHeader == nil { - b.LatestExecutionPayloadHeader = new(ExecutionPayloadHeader) + b.LatestExecutionPayloadHeader = new(deneb.ExecutionPayloadHeader) } if err = b.LatestExecutionPayloadHeader.UnmarshalSSZ(buf); err != nil { return err @@ -751,7 +752,7 @@ func (b *BeaconState) SizeSSZ() (size int) { // Field (24) 'LatestExecutionPayloadHeader' if b.LatestExecutionPayloadHeader == nil { - b.LatestExecutionPayloadHeader = new(ExecutionPayloadHeader) + b.LatestExecutionPayloadHeader = new(deneb.ExecutionPayloadHeader) } size += b.LatestExecutionPayloadHeader.SizeSSZ() diff --git a/spec/electra/beaconstate_yaml.go b/spec/electra/beaconstate_yaml.go index 75b24e0f..f159884a 100644 --- a/spec/electra/beaconstate_yaml.go +++ b/spec/electra/beaconstate_yaml.go @@ -20,6 +20,7 @@ import ( "github.com/attestantio/go-eth2-client/spec/altair" "github.com/attestantio/go-eth2-client/spec/capella" + "github.com/attestantio/go-eth2-client/spec/deneb" "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/goccy/go-yaml" "github.com/pkg/errors" @@ -27,43 +28,43 @@ import ( // beaconStateYAML is the spec representation of the struct. type beaconStateYAML struct { - GenesisTime uint64 `yaml:"genesis_time"` - GenesisValidatorsRoot phase0.Root `yaml:"genesis_validators_root"` - Slot phase0.Slot `yaml:"slot"` - Fork *phase0.Fork `yaml:"fork"` - LatestBlockHeader *phase0.BeaconBlockHeader `yaml:"latest_block_header"` - BlockRoots []phase0.Root `yaml:"block_roots"` - StateRoots []phase0.Root `yaml:"state_roots"` - HistoricalRoots []phase0.Root `yaml:"historical_roots"` - ETH1Data *phase0.ETH1Data `yaml:"eth1_data"` - ETH1DataVotes []*phase0.ETH1Data `yaml:"eth1_data_votes"` - ETH1DepositIndex uint64 `yaml:"eth1_deposit_index"` - Validators []*phase0.Validator `yaml:"validators"` - Balances []phase0.Gwei `yaml:"balances"` - RANDAOMixes []phase0.Root `yaml:"randao_mixes"` - Slashings []phase0.Gwei `yaml:"slashings"` - PreviousEpochParticipation []altair.ParticipationFlags `yaml:"previous_epoch_participation"` - CurrentEpochParticipation []altair.ParticipationFlags `yaml:"current_epoch_participation"` - JustificationBits string `yaml:"justification_bits"` - PreviousJustifiedCheckpoint *phase0.Checkpoint `yaml:"previous_justified_checkpoint"` - CurrentJustifiedCheckpoint *phase0.Checkpoint `yaml:"current_justified_checkpoint"` - FinalizedCheckpoint *phase0.Checkpoint `yaml:"finalized_checkpoint"` - InactivityScores []uint64 `yaml:"inactivity_scores"` - CurrentSyncCommittee *altair.SyncCommittee `yaml:"current_sync_committee"` - NextSyncCommittee *altair.SyncCommittee `yaml:"next_sync_committee"` - LatestExecutionPayloadHeader *ExecutionPayloadHeader `yaml:"latest_execution_payload_header"` - NextWithdrawalIndex capella.WithdrawalIndex `yaml:"next_withdrawal_index"` - NextWithdrawalValidatorIndex phase0.ValidatorIndex `yaml:"next_withdrawal_validator_index"` - HistoricalSummaries []*capella.HistoricalSummary `yaml:"historical_summaries"` - DepositRequestsStartIndex uint64 `yaml:"deposit_requests_start_index"` - DepositBalanceToConsume phase0.Gwei `yaml:"deposit_balance_to_consume"` - ExitBalanceToConsume phase0.Gwei `yaml:"exit_balance_to_consume"` - EarliestExitEpoch phase0.Epoch `yaml:"earliest_exit_epoch"` - ConsolidationBalanceToConsume phase0.Gwei `yaml:"consolidation_balance_to_consume"` - EarliestConsolidationEpoch phase0.Epoch `yaml:"earliest_consolidation_epoch"` - PendingBalanceDeposits []*PendingBalanceDeposit `yaml:"pending_balance_deposits"` - PendingPartialWithdrawals []*PendingPartialWithdrawal `yaml:"pending_partial_withdrawals"` - PendingConsolidations []*PendingConsolidation `yaml:"pending_consolidations"` + GenesisTime uint64 `yaml:"genesis_time"` + GenesisValidatorsRoot phase0.Root `yaml:"genesis_validators_root"` + Slot phase0.Slot `yaml:"slot"` + Fork *phase0.Fork `yaml:"fork"` + LatestBlockHeader *phase0.BeaconBlockHeader `yaml:"latest_block_header"` + BlockRoots []phase0.Root `yaml:"block_roots"` + StateRoots []phase0.Root `yaml:"state_roots"` + HistoricalRoots []phase0.Root `yaml:"historical_roots"` + ETH1Data *phase0.ETH1Data `yaml:"eth1_data"` + ETH1DataVotes []*phase0.ETH1Data `yaml:"eth1_data_votes"` + ETH1DepositIndex uint64 `yaml:"eth1_deposit_index"` + Validators []*phase0.Validator `yaml:"validators"` + Balances []phase0.Gwei `yaml:"balances"` + RANDAOMixes []phase0.Root `yaml:"randao_mixes"` + Slashings []phase0.Gwei `yaml:"slashings"` + PreviousEpochParticipation []altair.ParticipationFlags `yaml:"previous_epoch_participation"` + CurrentEpochParticipation []altair.ParticipationFlags `yaml:"current_epoch_participation"` + JustificationBits string `yaml:"justification_bits"` + PreviousJustifiedCheckpoint *phase0.Checkpoint `yaml:"previous_justified_checkpoint"` + CurrentJustifiedCheckpoint *phase0.Checkpoint `yaml:"current_justified_checkpoint"` + FinalizedCheckpoint *phase0.Checkpoint `yaml:"finalized_checkpoint"` + InactivityScores []uint64 `yaml:"inactivity_scores"` + CurrentSyncCommittee *altair.SyncCommittee `yaml:"current_sync_committee"` + NextSyncCommittee *altair.SyncCommittee `yaml:"next_sync_committee"` + LatestExecutionPayloadHeader *deneb.ExecutionPayloadHeader `yaml:"latest_execution_payload_header"` + NextWithdrawalIndex capella.WithdrawalIndex `yaml:"next_withdrawal_index"` + NextWithdrawalValidatorIndex phase0.ValidatorIndex `yaml:"next_withdrawal_validator_index"` + HistoricalSummaries []*capella.HistoricalSummary `yaml:"historical_summaries"` + DepositRequestsStartIndex uint64 `yaml:"deposit_requests_start_index"` + DepositBalanceToConsume phase0.Gwei `yaml:"deposit_balance_to_consume"` + ExitBalanceToConsume phase0.Gwei `yaml:"exit_balance_to_consume"` + EarliestExitEpoch phase0.Epoch `yaml:"earliest_exit_epoch"` + ConsolidationBalanceToConsume phase0.Gwei `yaml:"consolidation_balance_to_consume"` + EarliestConsolidationEpoch phase0.Epoch `yaml:"earliest_consolidation_epoch"` + PendingBalanceDeposits []*PendingBalanceDeposit `yaml:"pending_balance_deposits"` + PendingPartialWithdrawals []*PendingPartialWithdrawal `yaml:"pending_partial_withdrawals"` + PendingConsolidations []*PendingConsolidation `yaml:"pending_consolidations"` } // MarshalYAML implements yaml.Marshaler. diff --git a/spec/electra/consensusspec_test.go b/spec/electra/consensusspec_test.go index b771888f..fbb76b68 100644 --- a/spec/electra/consensusspec_test.go +++ b/spec/electra/consensusspec_test.go @@ -123,12 +123,8 @@ func TestConsensusSpec(t *testing.T) { s: &phase0.ETH1Data{}, }, { - name: "ExecutionPayload", - s: &electra.ExecutionPayload{}, - }, - { - name: "ExecutionPayloadHeader", - s: &electra.ExecutionPayloadHeader{}, + name: "ExecutionRequests", + s: &electra.ExecutionRequests{}, }, { name: "Fork", diff --git a/spec/electra/consolidationrequest_ssz.go b/spec/electra/consolidationrequest_ssz.go index 81b07980..51a0db22 100644 --- a/spec/electra/consolidationrequest_ssz.go +++ b/spec/electra/consolidationrequest_ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 17d4c9180818d70e873edf284079b326d586a16686d17c7c974a8a2fd19ec3e9 +// Hash: a0960436212943f5595c94087ee709d30a033a29aefc5236b2ea5582d783504c // Version: 0.1.3 package electra @@ -8,28 +8,28 @@ import ( ) // MarshalSSZ ssz marshals the ConsolidationRequest object -func (e *ConsolidationRequest) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(e) +func (c *ConsolidationRequest) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(c) } // MarshalSSZTo ssz marshals the ConsolidationRequest object to a target array -func (e *ConsolidationRequest) MarshalSSZTo(buf []byte) (dst []byte, err error) { +func (c *ConsolidationRequest) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf // Field (0) 'SourceAddress' - dst = append(dst, e.SourceAddress[:]...) + dst = append(dst, c.SourceAddress[:]...) // Field (1) 'SourcePubkey' - dst = append(dst, e.SourcePubkey[:]...) + dst = append(dst, c.SourcePubkey[:]...) // Field (2) 'TargetPubkey' - dst = append(dst, e.TargetPubkey[:]...) + dst = append(dst, c.TargetPubkey[:]...) return } // UnmarshalSSZ ssz unmarshals the ConsolidationRequest object -func (e *ConsolidationRequest) UnmarshalSSZ(buf []byte) error { +func (c *ConsolidationRequest) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) if size != 116 { @@ -37,46 +37,46 @@ func (e *ConsolidationRequest) UnmarshalSSZ(buf []byte) error { } // Field (0) 'SourceAddress' - copy(e.SourceAddress[:], buf[0:20]) + copy(c.SourceAddress[:], buf[0:20]) // Field (1) 'SourcePubkey' - copy(e.SourcePubkey[:], buf[20:68]) + copy(c.SourcePubkey[:], buf[20:68]) // Field (2) 'TargetPubkey' - copy(e.TargetPubkey[:], buf[68:116]) + copy(c.TargetPubkey[:], buf[68:116]) return err } // SizeSSZ returns the ssz encoded size in bytes for the ConsolidationRequest object -func (e *ConsolidationRequest) SizeSSZ() (size int) { +func (c *ConsolidationRequest) SizeSSZ() (size int) { size = 116 return } // HashTreeRoot ssz hashes the ConsolidationRequest object -func (e *ConsolidationRequest) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(e) +func (c *ConsolidationRequest) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(c) } // HashTreeRootWith ssz hashes the ConsolidationRequest object with a hasher -func (e *ConsolidationRequest) HashTreeRootWith(hh ssz.HashWalker) (err error) { +func (c *ConsolidationRequest) HashTreeRootWith(hh ssz.HashWalker) (err error) { indx := hh.Index() // Field (0) 'SourceAddress' - hh.PutBytes(e.SourceAddress[:]) + hh.PutBytes(c.SourceAddress[:]) // Field (1) 'SourcePubkey' - hh.PutBytes(e.SourcePubkey[:]) + hh.PutBytes(c.SourcePubkey[:]) // Field (2) 'TargetPubkey' - hh.PutBytes(e.TargetPubkey[:]) + hh.PutBytes(c.TargetPubkey[:]) hh.Merkleize(indx) return } // GetTree ssz hashes the ConsolidationRequest object -func (e *ConsolidationRequest) GetTree() (*ssz.Node, error) { - return ssz.ProofTree(e) +func (c *ConsolidationRequest) GetTree() (*ssz.Node, error) { + return ssz.ProofTree(c) } diff --git a/spec/electra/depositrequest_ssz.go b/spec/electra/depositrequest_ssz.go index 9b314cbf..3dbca129 100644 --- a/spec/electra/depositrequest_ssz.go +++ b/spec/electra/depositrequest_ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 0ba659c6f75c98d67fde663b42e7c0d93368dc54eb9bdec5d3b8cadf0f43e416 +// Hash: a0960436212943f5595c94087ee709d30a033a29aefc5236b2ea5582d783504c // Version: 0.1.3 package electra diff --git a/spec/electra/executionpayload.go b/spec/electra/executionpayload.go deleted file mode 100644 index d8c77b55..00000000 --- a/spec/electra/executionpayload.go +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright © 2024 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 electra - -import ( - "fmt" - - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/goccy/go-yaml" - "github.com/holiman/uint256" -) - -// ExecutionPayload represents an execution layer payload. -type ExecutionPayload struct { - ParentHash phase0.Hash32 `ssz-size:"32"` - FeeRecipient bellatrix.ExecutionAddress `ssz-size:"20"` - StateRoot phase0.Root `ssz-size:"32"` - ReceiptsRoot phase0.Root `ssz-size:"32"` - LogsBloom [256]byte `ssz-size:"256"` - PrevRandao [32]byte `ssz-size:"32"` - BlockNumber uint64 - GasLimit uint64 - GasUsed uint64 - Timestamp uint64 - ExtraData []byte `ssz-max:"32"` - BaseFeePerGas *uint256.Int `ssz-size:"32"` - BlockHash phase0.Hash32 `ssz-size:"32"` - Transactions []bellatrix.Transaction `ssz-max:"1048576,1073741824" ssz-size:"?,?"` - Withdrawals []*capella.Withdrawal `ssz-max:"16"` - BlobGasUsed uint64 - ExcessBlobGas uint64 - DepositRequests []*DepositRequest `ssz-max:"8192"` - WithdrawalRequests []*WithdrawalRequest `ssz-max:"16"` - ConsolidationRequests []*ConsolidationRequest `ssz-max:"1"` -} - -// String returns a string version of the structure. -func (e *ExecutionPayload) String() string { - data, err := yaml.Marshal(e) - if err != nil { - return fmt.Sprintf("ERR: %v", err) - } - - return string(data) -} diff --git a/spec/electra/executionpayload_json.go b/spec/electra/executionpayload_json.go deleted file mode 100644 index 40c821b1..00000000 --- a/spec/electra/executionpayload_json.go +++ /dev/null @@ -1,281 +0,0 @@ -// Copyright © 2024 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 electra - -import ( - "bytes" - "encoding/hex" - "encoding/json" - "fmt" - "strconv" - - "github.com/attestantio/go-eth2-client/codecs" - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/holiman/uint256" - "github.com/pkg/errors" -) - -// executionPayloadJSON is the spec representation of the struct. -type executionPayloadJSON struct { - ParentHash phase0.Hash32 `json:"parent_hash"` - FeeRecipient bellatrix.ExecutionAddress `json:"fee_recipient"` - StateRoot phase0.Root `json:"state_root"` - ReceiptsRoot phase0.Root `json:"receipts_root"` - LogsBloom string `json:"logs_bloom"` - PrevRandao string `json:"prev_randao"` - BlockNumber string `json:"block_number"` - GasLimit string `json:"gas_limit"` - GasUsed string `json:"gas_used"` - Timestamp string `json:"timestamp"` - ExtraData string `json:"extra_data"` - BaseFeePerGas string `json:"base_fee_per_gas"` - BlockHash phase0.Hash32 `json:"block_hash"` - Transactions []string `json:"transactions"` - Withdrawals []*capella.Withdrawal `json:"withdrawals"` - BlobGasUsed string `json:"blob_gas_used"` - ExcessBlobGas string `json:"excess_blob_gas"` - DepositRequests []*DepositRequest `json:"deposit_requests"` - WithdrawalRequests []*WithdrawalRequest `json:"withdrawal_requests"` - ConsolidationRequests []*ConsolidationRequest `json:"consolidation_requests"` -} - -// MarshalJSON implements json.Marshaler. -func (e *ExecutionPayload) MarshalJSON() ([]byte, error) { - transactions := make([]string, len(e.Transactions)) - for i := range e.Transactions { - transactions[i] = fmt.Sprintf("%#x", e.Transactions[i]) - } - - extraData := "0x" - if len(e.ExtraData) > 0 { - extraData = fmt.Sprintf("%#x", e.ExtraData) - } - - return json.Marshal(&executionPayloadJSON{ - ParentHash: e.ParentHash, - FeeRecipient: e.FeeRecipient, - StateRoot: e.StateRoot, - ReceiptsRoot: e.ReceiptsRoot, - LogsBloom: fmt.Sprintf("%#x", e.LogsBloom), - PrevRandao: fmt.Sprintf("%#x", e.PrevRandao), - BlockNumber: strconv.FormatUint(e.BlockNumber, 10), - GasLimit: strconv.FormatUint(e.GasLimit, 10), - GasUsed: strconv.FormatUint(e.GasUsed, 10), - Timestamp: strconv.FormatUint(e.Timestamp, 10), - ExtraData: extraData, - BaseFeePerGas: e.BaseFeePerGas.Dec(), - BlockHash: e.BlockHash, - Transactions: transactions, - Withdrawals: e.Withdrawals, - BlobGasUsed: strconv.FormatUint(e.BlobGasUsed, 10), - ExcessBlobGas: strconv.FormatUint(e.ExcessBlobGas, 10), - DepositRequests: e.DepositRequests, - WithdrawalRequests: e.WithdrawalRequests, - }) -} - -// UnmarshalJSON implements json.Unmarshaler. -// -//nolint:gocyclo -func (e *ExecutionPayload) UnmarshalJSON(input []byte) error { - raw, err := codecs.RawJSON(&executionPayloadJSON{}, input) - if err != nil { - return err - } - - if err := e.ParentHash.UnmarshalJSON(raw["parent_hash"]); err != nil { - return errors.Wrap(err, "parent_hash") - } - - if err := e.FeeRecipient.UnmarshalJSON(raw["fee_recipient"]); err != nil { - return errors.Wrap(err, "fee_recipient") - } - - if err := e.StateRoot.UnmarshalJSON(raw["state_root"]); err != nil { - return errors.Wrap(err, "state_root") - } - - if err := e.ReceiptsRoot.UnmarshalJSON(raw["receipts_root"]); err != nil { - return errors.Wrap(err, "receipts_root") - } - - logsBloom := raw["logs_bloom"] - if !bytes.HasPrefix(logsBloom, []byte{'"', '0', 'x'}) { - return errors.New("logs_bloom: invalid prefix") - } - if !bytes.HasSuffix(logsBloom, []byte{'"'}) { - return errors.New("logs_bloom: invalid suffix") - } - if len(logsBloom) != 1+2+256*2+1 { - return errors.New("logs_bloom: incorrect length") - } - length, err := hex.Decode(e.LogsBloom[:], logsBloom[3:3+256*2]) - if err != nil { - return errors.Wrap(err, "logs_bloom") - } - if length != 256 { - return errors.New("logs_bloom: incorrect length") - } - - prevRandao := raw["prev_randao"] - if !bytes.HasPrefix(prevRandao, []byte{'"', '0', 'x'}) { - return errors.New("prev_randao: invalid prefix") - } - if !bytes.HasSuffix(prevRandao, []byte{'"'}) { - return errors.New("prev_randao: invalid suffix") - } - if len(prevRandao) != 1+2+32*2+1 { - return errors.New("prev_randao: incorrect length") - } - length, err = hex.Decode(e.PrevRandao[:], prevRandao[3:3+32*2]) - if err != nil { - return errors.Wrap(err, "prev_randao") - } - if length != 32 { - return errors.New("prev_randao: incorrect length") - } - - tmpUint, err := strconv.ParseUint(string(bytes.Trim(raw["block_number"], `"`)), 10, 64) - if err != nil { - return errors.Wrap(err, "block_number") - } - e.BlockNumber = tmpUint - - tmpUint, err = strconv.ParseUint(string(bytes.Trim(raw["gas_limit"], `"`)), 10, 64) - if err != nil { - return errors.Wrap(err, "gas_limit") - } - e.GasLimit = tmpUint - - tmpUint, err = strconv.ParseUint(string(bytes.Trim(raw["gas_used"], `"`)), 10, 64) - if err != nil { - return errors.Wrap(err, "gas_used") - } - e.GasUsed = tmpUint - - tmpUint, err = strconv.ParseUint(string(bytes.Trim(raw["timestamp"], `"`)), 10, 64) - if err != nil { - return errors.Wrap(err, "timestamp") - } - e.Timestamp = tmpUint - - var tmpBytes []byte - switch { - case bytes.Equal(raw["extra_data"], []byte{'0', 'x'}), bytes.Equal(raw["extra_data"], []byte{'0'}): - // Empty. - default: - tmpBytes = bytes.TrimPrefix(bytes.Trim(raw["extra_data"], `"`), []byte{'0', 'x'}) - if len(tmpBytes)%2 == 1 { - tmpBytes = []byte(fmt.Sprintf("0%s", string(tmpBytes))) - } - tmp, err := hex.DecodeString(string(tmpBytes)) - if err != nil { - return errors.Wrap(err, "extra_data") - } - if len(tmp) > 32 { - return errors.New("extra_data: incorrect length") - } - e.ExtraData = tmp - } - - tmpBytes = bytes.Trim(raw["base_fee_per_gas"], `"`) - tmpBytes = bytes.TrimPrefix(tmpBytes, []byte{'0', 'x'}) - if bytes.HasPrefix(tmpBytes, []byte{'0', 'x'}) { - e.BaseFeePerGas, err = uint256.FromHex(string(tmpBytes)) - } else { - e.BaseFeePerGas, err = uint256.FromDecimal(string(tmpBytes)) - } - if err != nil { - return errors.Wrap(err, "base_fee_per_gas") - } - - if err := e.BlockHash.UnmarshalJSON(raw["block_hash"]); err != nil { - return errors.Wrap(err, "block_hash") - } - - transactions := make([]json.RawMessage, 0) - if err := json.Unmarshal(raw["transactions"], &transactions); err != nil { - return errors.Wrap(err, "transactions") - } - if len(transactions) > bellatrix.MaxTransactionsPerPayload { - return errors.Wrap(err, "incorrect length for transactions") - } - e.Transactions = make([]bellatrix.Transaction, len(transactions)) - for i := range transactions { - if len(transactions[i]) == 0 || - bytes.Equal(transactions[i], []byte{'"', '"'}) || - bytes.Equal(transactions[i], []byte{'"', '0', 'x', '"'}) { - return fmt.Errorf("transaction %d: missing", i) - } - e.Transactions[i] = make([]byte, (len(transactions[i])-4)/2) - if err := json.Unmarshal(transactions[i], &e.Transactions[i]); err != nil { - return errors.Wrapf(err, "transaction %d", i) - } - if len(e.Transactions[i]) > bellatrix.MaxBytesPerTransaction { - return errors.Wrapf(err, "incorrect length for transaction %d", i) - } - } - - if err := json.Unmarshal(raw["withdrawals"], &e.Withdrawals); err != nil { - return errors.Wrap(err, "withdrawals") - } - for i := range e.Withdrawals { - if e.Withdrawals[i] == nil { - return fmt.Errorf("withdrawals entry %d missing", i) - } - } - - tmpUint, err = strconv.ParseUint(string(bytes.Trim(raw["blob_gas_used"], `"`)), 10, 64) - if err != nil { - return errors.Wrap(err, "blob_gas_used") - } - e.BlobGasUsed = tmpUint - - tmpUint, err = strconv.ParseUint(string(bytes.Trim(raw["excess_blob_gas"], `"`)), 10, 64) - if err != nil { - return errors.Wrap(err, "excess_blob_gas") - } - e.ExcessBlobGas = tmpUint - - if err := json.Unmarshal(raw["deposit_requests"], &e.DepositRequests); err != nil { - return errors.Wrap(err, "deposit_requests") - } - for i := range e.DepositRequests { - if e.DepositRequests[i] == nil { - return fmt.Errorf("deposit receipts entry %d missing", i) - } - } - - if err := json.Unmarshal(raw["withdrawal_requests"], &e.WithdrawalRequests); err != nil { - return errors.Wrap(err, "withdrawal_requests") - } - for i := range e.WithdrawalRequests { - if e.WithdrawalRequests[i] == nil { - return fmt.Errorf("withdraw requests entry %d missing", i) - } - } - - if err := json.Unmarshal(raw["consolidation_requests"], &e.ConsolidationRequests); err != nil { - return errors.Wrap(err, "consolidation_requests") - } - for i := range e.ConsolidationRequests { - if e.ConsolidationRequests[i] == nil { - return fmt.Errorf("consolidation requests entry %d missing", i) - } - } - - return nil -} diff --git a/spec/electra/executionpayload_ssz.go b/spec/electra/executionpayload_ssz.go deleted file mode 100644 index 0ab133d9..00000000 --- a/spec/electra/executionpayload_ssz.go +++ /dev/null @@ -1,560 +0,0 @@ -// Code generated by fastssz. DO NOT EDIT. -// Hash: 145f583ffefea9d2c418401980a7199f582dbe71558fe80f718fadd3931c034f -// Version: 0.1.3 -package electra - -import ( - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/capella" - ssz "github.com/ferranbt/fastssz" - "github.com/holiman/uint256" -) - -// MarshalSSZ ssz marshals the ExecutionPayload object -func (e *ExecutionPayload) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(e) -} - -// MarshalSSZTo ssz marshals the ExecutionPayload object to a target array -func (e *ExecutionPayload) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(540) - - // Field (0) 'ParentHash' - dst = append(dst, e.ParentHash[:]...) - - // Field (1) 'FeeRecipient' - dst = append(dst, e.FeeRecipient[:]...) - - // Field (2) 'StateRoot' - dst = append(dst, e.StateRoot[:]...) - - // Field (3) 'ReceiptsRoot' - dst = append(dst, e.ReceiptsRoot[:]...) - - // Field (4) 'LogsBloom' - dst = append(dst, e.LogsBloom[:]...) - - // Field (5) 'PrevRandao' - dst = append(dst, e.PrevRandao[:]...) - - // Field (6) 'BlockNumber' - dst = ssz.MarshalUint64(dst, e.BlockNumber) - - // Field (7) 'GasLimit' - dst = ssz.MarshalUint64(dst, e.GasLimit) - - // Field (8) 'GasUsed' - dst = ssz.MarshalUint64(dst, e.GasUsed) - - // Field (9) 'Timestamp' - dst = ssz.MarshalUint64(dst, e.Timestamp) - - // Offset (10) 'ExtraData' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.ExtraData) - - // Field (11) 'BaseFeePerGas' - baseFeePerGas := e.BaseFeePerGas.Bytes32() - for i := 0; i < 32; i++ { - dst = append(dst, baseFeePerGas[31-i]) - } - - // Field (12) 'BlockHash' - dst = append(dst, e.BlockHash[:]...) - - // Offset (13) 'Transactions' - dst = ssz.WriteOffset(dst, offset) - for ii := 0; ii < len(e.Transactions); ii++ { - offset += 4 - offset += len(e.Transactions[ii]) - } - - // Offset (14) 'Withdrawals' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.Withdrawals) * 44 - - // Field (15) 'BlobGasUsed' - dst = ssz.MarshalUint64(dst, e.BlobGasUsed) - - // Field (16) 'ExcessBlobGas' - dst = ssz.MarshalUint64(dst, e.ExcessBlobGas) - - // Offset (17) 'DepositRequests' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.DepositRequests) * 192 - - // Offset (18) 'WithdrawalRequests' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.WithdrawalRequests) * 76 - - // Offset (19) 'ConsolidationRequests' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.ConsolidationRequests) * 116 - - // Field (10) 'ExtraData' - if size := len(e.ExtraData); size > 32 { - err = ssz.ErrBytesLengthFn("ExecutionPayload.ExtraData", size, 32) - return - } - dst = append(dst, e.ExtraData...) - - // Field (13) 'Transactions' - if size := len(e.Transactions); size > 1073741824 { - err = ssz.ErrListTooBigFn("ExecutionPayload.Transactions", size, 1073741824) - return - } - { - offset = 4 * len(e.Transactions) - for ii := 0; ii < len(e.Transactions); ii++ { - dst = ssz.WriteOffset(dst, offset) - offset += len(e.Transactions[ii]) - } - } - for ii := 0; ii < len(e.Transactions); ii++ { - if size := len(e.Transactions[ii]); size > 1073741824 { - err = ssz.ErrBytesLengthFn("ExecutionPayload.Transactions[ii]", size, 1073741824) - return - } - dst = append(dst, e.Transactions[ii]...) - } - - // Field (14) 'Withdrawals' - if size := len(e.Withdrawals); size > 16 { - err = ssz.ErrListTooBigFn("ExecutionPayload.Withdrawals", size, 16) - return - } - for ii := 0; ii < len(e.Withdrawals); ii++ { - if dst, err = e.Withdrawals[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (17) 'DepositRequests' - if size := len(e.DepositRequests); size > 8192 { - err = ssz.ErrListTooBigFn("ExecutionPayload.DepositRequests", size, 8192) - return - } - for ii := 0; ii < len(e.DepositRequests); ii++ { - if dst, err = e.DepositRequests[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (18) 'WithdrawalRequests' - if size := len(e.WithdrawalRequests); size > 16 { - err = ssz.ErrListTooBigFn("ExecutionPayload.WithdrawalRequests", size, 16) - return - } - for ii := 0; ii < len(e.WithdrawalRequests); ii++ { - if dst, err = e.WithdrawalRequests[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - // Field (19) 'ConsolidationRequests' - if size := len(e.ConsolidationRequests); size > 1 { - err = ssz.ErrListTooBigFn("ExecutionPayload.ConsolidationRequests", size, 1) - return - } - for ii := 0; ii < len(e.ConsolidationRequests); ii++ { - if dst, err = e.ConsolidationRequests[ii].MarshalSSZTo(dst); err != nil { - return - } - } - - return -} - -// UnmarshalSSZ ssz unmarshals the ExecutionPayload object -func (e *ExecutionPayload) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 540 { - return ssz.ErrSize - } - - tail := buf - var o10, o13, o14, o17, o18, o19 uint64 - - // Field (0) 'ParentHash' - copy(e.ParentHash[:], buf[0:32]) - - // Field (1) 'FeeRecipient' - copy(e.FeeRecipient[:], buf[32:52]) - - // Field (2) 'StateRoot' - copy(e.StateRoot[:], buf[52:84]) - - // Field (3) 'ReceiptsRoot' - copy(e.ReceiptsRoot[:], buf[84:116]) - - // Field (4) 'LogsBloom' - copy(e.LogsBloom[:], buf[116:372]) - - // Field (5) 'PrevRandao' - copy(e.PrevRandao[:], buf[372:404]) - - // Field (6) 'BlockNumber' - e.BlockNumber = ssz.UnmarshallUint64(buf[404:412]) - - // Field (7) 'GasLimit' - e.GasLimit = ssz.UnmarshallUint64(buf[412:420]) - - // Field (8) 'GasUsed' - e.GasUsed = ssz.UnmarshallUint64(buf[420:428]) - - // Field (9) 'Timestamp' - e.Timestamp = ssz.UnmarshallUint64(buf[428:436]) - - // Offset (10) 'ExtraData' - if o10 = ssz.ReadOffset(buf[436:440]); o10 > size { - return ssz.ErrOffset - } - - if o10 < 540 { - return ssz.ErrInvalidVariableOffset - } - - // Field (11) 'BaseFeePerGas' - baseFeePerGasBE := make([]byte, 32) - for i := 0; i < 32; i++ { - baseFeePerGasBE[i] = buf[471-i] - } - e.BaseFeePerGas = &uint256.Int{} - e.BaseFeePerGas.SetBytes32(baseFeePerGasBE) - - // Field (12) 'BlockHash' - copy(e.BlockHash[:], buf[472:504]) - - // Offset (13) 'Transactions' - if o13 = ssz.ReadOffset(buf[504:508]); o13 > size || o10 > o13 { - return ssz.ErrOffset - } - - // Offset (14) 'Withdrawals' - if o14 = ssz.ReadOffset(buf[508:512]); o14 > size || o13 > o14 { - return ssz.ErrOffset - } - - // Field (15) 'BlobGasUsed' - e.BlobGasUsed = ssz.UnmarshallUint64(buf[512:520]) - - // Field (16) 'ExcessBlobGas' - e.ExcessBlobGas = ssz.UnmarshallUint64(buf[520:528]) - - // Offset (17) 'DepositRequests' - if o17 = ssz.ReadOffset(buf[528:532]); o17 > size || o14 > o17 { - return ssz.ErrOffset - } - - // Offset (18) 'WithdrawalRequests' - if o18 = ssz.ReadOffset(buf[532:536]); o18 > size || o17 > o18 { - return ssz.ErrOffset - } - - // Offset (19) 'ConsolidationRequests' - if o19 = ssz.ReadOffset(buf[536:540]); o19 > size || o18 > o19 { - return ssz.ErrOffset - } - - // Field (10) 'ExtraData' - { - buf = tail[o10:o13] - if len(buf) > 32 { - return ssz.ErrBytesLength - } - if cap(e.ExtraData) == 0 { - e.ExtraData = make([]byte, 0, len(buf)) - } - e.ExtraData = append(e.ExtraData, buf...) - } - - // Field (13) 'Transactions' - { - buf = tail[o13:o14] - num, err := ssz.DecodeDynamicLength(buf, 1073741824) - if err != nil { - return err - } - e.Transactions = make([]bellatrix.Transaction, num) - err = ssz.UnmarshalDynamic(buf, num, func(indx int, buf []byte) (err error) { - if len(buf) > 1073741824 { - return ssz.ErrBytesLength - } - if cap(e.Transactions[indx]) == 0 { - e.Transactions[indx] = bellatrix.Transaction(make([]byte, 0, len(buf))) - } - e.Transactions[indx] = append(e.Transactions[indx], buf...) - return nil - }) - if err != nil { - return err - } - } - - // Field (14) 'Withdrawals' - { - buf = tail[o14:o17] - num, err := ssz.DivideInt2(len(buf), 44, 16) - if err != nil { - return err - } - e.Withdrawals = make([]*capella.Withdrawal, num) - for ii := 0; ii < num; ii++ { - if e.Withdrawals[ii] == nil { - e.Withdrawals[ii] = new(capella.Withdrawal) - } - if err = e.Withdrawals[ii].UnmarshalSSZ(buf[ii*44 : (ii+1)*44]); err != nil { - return err - } - } - } - - // Field (17) 'DepositRequests' - { - buf = tail[o17:o18] - num, err := ssz.DivideInt2(len(buf), 192, 8192) - if err != nil { - return err - } - e.DepositRequests = make([]*DepositRequest, num) - for ii := 0; ii < num; ii++ { - if e.DepositRequests[ii] == nil { - e.DepositRequests[ii] = new(DepositRequest) - } - if err = e.DepositRequests[ii].UnmarshalSSZ(buf[ii*192 : (ii+1)*192]); err != nil { - return err - } - } - } - - // Field (18) 'WithdrawalRequests' - { - buf = tail[o18:o19] - num, err := ssz.DivideInt2(len(buf), 76, 16) - if err != nil { - return err - } - e.WithdrawalRequests = make([]*WithdrawalRequest, num) - for ii := 0; ii < num; ii++ { - if e.WithdrawalRequests[ii] == nil { - e.WithdrawalRequests[ii] = new(WithdrawalRequest) - } - if err = e.WithdrawalRequests[ii].UnmarshalSSZ(buf[ii*76 : (ii+1)*76]); err != nil { - return err - } - } - } - - // Field (19) 'ConsolidationRequests' - { - buf = tail[o19:] - num, err := ssz.DivideInt2(len(buf), 116, 1) - if err != nil { - return err - } - e.ConsolidationRequests = make([]*ConsolidationRequest, num) - for ii := 0; ii < num; ii++ { - if e.ConsolidationRequests[ii] == nil { - e.ConsolidationRequests[ii] = new(ConsolidationRequest) - } - if err = e.ConsolidationRequests[ii].UnmarshalSSZ(buf[ii*116 : (ii+1)*116]); err != nil { - return err - } - } - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayload object -func (e *ExecutionPayload) SizeSSZ() (size int) { - size = 540 - - // Field (10) 'ExtraData' - size += len(e.ExtraData) - - // Field (13) 'Transactions' - for ii := 0; ii < len(e.Transactions); ii++ { - size += 4 - size += len(e.Transactions[ii]) - } - - // Field (14) 'Withdrawals' - size += len(e.Withdrawals) * 44 - - // Field (17) 'DepositRequests' - size += len(e.DepositRequests) * 192 - - // Field (18) 'WithdrawalRequests' - size += len(e.WithdrawalRequests) * 76 - - // Field (19) 'ConsolidationRequests' - size += len(e.ConsolidationRequests) * 116 - - return -} - -// HashTreeRoot ssz hashes the ExecutionPayload object -func (e *ExecutionPayload) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(e) -} - -// HashTreeRootWith ssz hashes the ExecutionPayload object with a hasher -func (e *ExecutionPayload) HashTreeRootWith(hh ssz.HashWalker) (err error) { - indx := hh.Index() - - // Field (0) 'ParentHash' - hh.PutBytes(e.ParentHash[:]) - - // Field (1) 'FeeRecipient' - hh.PutBytes(e.FeeRecipient[:]) - - // Field (2) 'StateRoot' - hh.PutBytes(e.StateRoot[:]) - - // Field (3) 'ReceiptsRoot' - hh.PutBytes(e.ReceiptsRoot[:]) - - // Field (4) 'LogsBloom' - hh.PutBytes(e.LogsBloom[:]) - - // Field (5) 'PrevRandao' - hh.PutBytes(e.PrevRandao[:]) - - // Field (6) 'BlockNumber' - hh.PutUint64(e.BlockNumber) - - // Field (7) 'GasLimit' - hh.PutUint64(e.GasLimit) - - // Field (8) 'GasUsed' - hh.PutUint64(e.GasUsed) - - // Field (9) 'Timestamp' - hh.PutUint64(e.Timestamp) - - // Field (10) 'ExtraData' - { - elemIndx := hh.Index() - byteLen := uint64(len(e.ExtraData)) - if byteLen > 32 { - err = ssz.ErrIncorrectListSize - return - } - hh.Append(e.ExtraData) - hh.MerkleizeWithMixin(elemIndx, byteLen, (32+31)/32) - } - - // Field (11) 'BaseFeePerGas' - baseFeePerGas := make([]byte, 32) - baseFeePerGasBE := e.BaseFeePerGas.Bytes32() - for i := 0; i < 32; i++ { - baseFeePerGas[i] = baseFeePerGasBE[31-i] - } - hh.PutBytes(baseFeePerGas) - - // Field (12) 'BlockHash' - hh.PutBytes(e.BlockHash[:]) - - // Field (13) 'Transactions' - { - subIndx := hh.Index() - num := uint64(len(e.Transactions)) - if num > 1073741824 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.Transactions { - { - elemIndx := hh.Index() - byteLen := uint64(len(elem)) - if byteLen > 1073741824 { - err = ssz.ErrIncorrectListSize - return - } - hh.AppendBytes32(elem) - hh.MerkleizeWithMixin(elemIndx, byteLen, (1073741824+31)/32) - } - } - hh.MerkleizeWithMixin(subIndx, num, 1048576) - } - - // Field (14) 'Withdrawals' - { - subIndx := hh.Index() - num := uint64(len(e.Withdrawals)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.Withdrawals { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (15) 'BlobGasUsed' - hh.PutUint64(e.BlobGasUsed) - - // Field (16) 'ExcessBlobGas' - hh.PutUint64(e.ExcessBlobGas) - - // Field (17) 'DepositRequests' - { - subIndx := hh.Index() - num := uint64(len(e.DepositRequests)) - if num > 8192 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.DepositRequests { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 8192) - } - - // Field (18) 'WithdrawalRequests' - { - subIndx := hh.Index() - num := uint64(len(e.WithdrawalRequests)) - if num > 16 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.WithdrawalRequests { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 16) - } - - // Field (19) 'ConsolidationRequests' - { - subIndx := hh.Index() - num := uint64(len(e.ConsolidationRequests)) - if num > 1 { - err = ssz.ErrIncorrectListSize - return - } - for _, elem := range e.ConsolidationRequests { - if err = elem.HashTreeRootWith(hh); err != nil { - return - } - } - hh.MerkleizeWithMixin(subIndx, num, 1) - } - - hh.Merkleize(indx) - return -} - -// GetTree ssz hashes the ExecutionPayload object -func (e *ExecutionPayload) GetTree() (*ssz.Node, error) { - return ssz.ProofTree(e) -} diff --git a/spec/electra/executionpayload_yaml.go b/spec/electra/executionpayload_yaml.go deleted file mode 100644 index b9f8fedc..00000000 --- a/spec/electra/executionpayload_yaml.go +++ /dev/null @@ -1,105 +0,0 @@ -// Copyright © 2024 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 electra - -import ( - "bytes" - "encoding/json" - "fmt" - - "github.com/attestantio/go-eth2-client/spec/capella" - "github.com/goccy/go-yaml" - "github.com/pkg/errors" -) - -// executionPayloadYAML is the spec representation of the struct. -type executionPayloadYAML struct { - ParentHash string `yaml:"parent_hash"` - FeeRecipient string `yaml:"fee_recipient"` - StateRoot string `yaml:"state_root"` - ReceiptsRoot string `yaml:"receipts_root"` - LogsBloom string `yaml:"logs_bloom"` - PrevRandao string `yaml:"prev_randao"` - BlockNumber uint64 `yaml:"block_number"` - GasLimit uint64 `yaml:"gas_limit"` - GasUsed uint64 `yaml:"gas_used"` - Timestamp uint64 `yaml:"timestamp"` - ExtraData string `yaml:"extra_data"` - BaseFeePerGas string `yaml:"base_fee_per_gas"` - BlockHash string `yaml:"block_hash"` - Transactions []string `yaml:"transactions"` - Withdrawals []*capella.Withdrawal `yaml:"withdrawals"` - BlobGasUsed uint64 `yaml:"blob_gas_used"` - ExcessBlobGas uint64 `yaml:"excess_blob_gas"` - DepositRequests []*DepositRequest `yaml:"deposit_requests"` - WithdrawalRequests []*WithdrawalRequest `yaml:"withdrawal_requests"` - ConsolidationRequests []*ConsolidationRequest `yaml:"consolidation_requests"` -} - -// MarshalYAML implements yaml.Marshaler. -func (e *ExecutionPayload) MarshalYAML() ([]byte, error) { - transactions := make([]string, len(e.Transactions)) - for i := range e.Transactions { - transactions[i] = fmt.Sprintf("%#x", e.Transactions[i]) - } - - extraData := "0x" - if len(e.ExtraData) > 0 { - extraData = fmt.Sprintf("%#x", e.ExtraData) - } - - yamlBytes, err := yaml.MarshalWithOptions(&executionPayloadYAML{ - ParentHash: e.ParentHash.String(), - FeeRecipient: e.FeeRecipient.String(), - StateRoot: e.StateRoot.String(), - ReceiptsRoot: e.ReceiptsRoot.String(), - LogsBloom: fmt.Sprintf("%#x", e.LogsBloom), - PrevRandao: fmt.Sprintf("%#x", e.PrevRandao), - BlockNumber: e.BlockNumber, - GasLimit: e.GasLimit, - GasUsed: e.GasUsed, - Timestamp: e.Timestamp, - ExtraData: extraData, - BaseFeePerGas: e.BaseFeePerGas.Dec(), - BlockHash: fmt.Sprintf("%#x", e.BlockHash), - Transactions: transactions, - Withdrawals: e.Withdrawals, - BlobGasUsed: e.BlobGasUsed, - ExcessBlobGas: e.ExcessBlobGas, - DepositRequests: e.DepositRequests, - WithdrawalRequests: e.WithdrawalRequests, - ConsolidationRequests: e.ConsolidationRequests, - }, yaml.Flow(true)) - if err != nil { - return nil, err - } - - return bytes.ReplaceAll(yamlBytes, []byte(`"`), []byte(`'`)), nil -} - -// UnmarshalYAML implements yaml.Unmarshaler. -func (e *ExecutionPayload) UnmarshalYAML(input []byte) error { - // This is very inefficient, but YAML is only used for spec tests so we do this - // rather than maintain a custom YAML unmarshaller. - var unmarshaled executionPayloadJSON - if err := yaml.Unmarshal(input, &unmarshaled); err != nil { - return errors.Wrap(err, "failed to unmarshal YAML") - } - marshaled, err := json.Marshal(unmarshaled) - if err != nil { - return errors.Wrap(err, "failed to marshal JSON") - } - - return e.UnmarshalJSON(marshaled) -} diff --git a/spec/electra/executionpayloadheader.go b/spec/electra/executionpayloadheader.go deleted file mode 100644 index 473c6772..00000000 --- a/spec/electra/executionpayloadheader.go +++ /dev/null @@ -1,57 +0,0 @@ -// Copyright © 2024 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 electra - -import ( - "fmt" - - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/goccy/go-yaml" - "github.com/holiman/uint256" -) - -// ExecutionPayloadHeader represents an execution layer payload header. -type ExecutionPayloadHeader struct { - ParentHash phase0.Hash32 `ssz-size:"32"` - FeeRecipient bellatrix.ExecutionAddress `ssz-size:"20"` - StateRoot phase0.Root `ssz-size:"32"` - ReceiptsRoot phase0.Root `ssz-size:"32"` - LogsBloom [256]byte `ssz-size:"256"` - PrevRandao [32]byte `ssz-size:"32"` - BlockNumber uint64 - GasLimit uint64 - GasUsed uint64 - Timestamp uint64 - ExtraData []byte `ssz-max:"32"` - BaseFeePerGas *uint256.Int `ssz-size:"32"` - BlockHash phase0.Hash32 `ssz-size:"32"` - TransactionsRoot phase0.Root `ssz-size:"32"` - WithdrawalsRoot phase0.Root `ssz-size:"32"` - BlobGasUsed uint64 - ExcessBlobGas uint64 - DepositRequestsRoot phase0.Root `ssz-size:"32"` - WithdrawalRequestsRoot phase0.Root `ssz-size:"32"` - ConsolidationRequestsRoot phase0.Root `ssz-size:"32"` -} - -// String returns a string version of the structure. -func (e *ExecutionPayloadHeader) String() string { - data, err := yaml.Marshal(e) - if err != nil { - return fmt.Sprintf("ERR: %v", err) - } - - return string(data) -} diff --git a/spec/electra/executionpayloadheader_json.go b/spec/electra/executionpayloadheader_json.go deleted file mode 100644 index 193df437..00000000 --- a/spec/electra/executionpayloadheader_json.go +++ /dev/null @@ -1,238 +0,0 @@ -// Copyright © 2024 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 electra - -import ( - "bytes" - "encoding/hex" - "encoding/json" - "fmt" - "strconv" - - "github.com/attestantio/go-eth2-client/codecs" - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/holiman/uint256" - "github.com/pkg/errors" -) - -// executionPayloadHeaderJSON is the spec representation of the struct. -type executionPayloadHeaderJSON struct { - ParentHash phase0.Hash32 `json:"parent_hash"` - FeeRecipient bellatrix.ExecutionAddress `json:"fee_recipient"` - StateRoot phase0.Root `json:"state_root"` - ReceiptsRoot phase0.Root `json:"receipts_root"` - LogsBloom string `json:"logs_bloom"` - PrevRandao string `json:"prev_randao"` - BlockNumber string `json:"block_number"` - GasLimit string `json:"gas_limit"` - GasUsed string `json:"gas_used"` - Timestamp string `json:"timestamp"` - ExtraData string `json:"extra_data"` - BaseFeePerGas string `json:"base_fee_per_gas"` - BlockHash phase0.Hash32 `json:"block_hash"` - TransactionsRoot phase0.Root `json:"transactions_root"` - WithdrawalsRoot phase0.Root `json:"withdrawals_root"` - BlobGasUsed string `json:"blob_gas_used"` - ExcessBlobGas string `json:"excess_blob_gas"` - DepositRequestsRoot phase0.Root `json:"deposit_requests_root"` - WithdrawalRequestsRoot phase0.Root `json:"withdrawal_requests_root"` - ConsolidationRequestsRoot phase0.Root `json:"consolidation_requests_root"` -} - -// MarshalJSON implements json.Marshaler. -func (e *ExecutionPayloadHeader) MarshalJSON() ([]byte, error) { - extraData := "0x" - if len(e.ExtraData) > 0 { - extraData = fmt.Sprintf("%#x", e.ExtraData) - } - - return json.Marshal(&executionPayloadHeaderJSON{ - ParentHash: e.ParentHash, - FeeRecipient: e.FeeRecipient, - StateRoot: e.StateRoot, - ReceiptsRoot: e.ReceiptsRoot, - LogsBloom: fmt.Sprintf("%#x", e.LogsBloom), - PrevRandao: fmt.Sprintf("%#x", e.PrevRandao), - BlockNumber: strconv.FormatUint(e.BlockNumber, 10), - GasLimit: strconv.FormatUint(e.GasLimit, 10), - GasUsed: strconv.FormatUint(e.GasUsed, 10), - Timestamp: strconv.FormatUint(e.Timestamp, 10), - ExtraData: extraData, - BaseFeePerGas: e.BaseFeePerGas.Dec(), - BlockHash: e.BlockHash, - TransactionsRoot: e.TransactionsRoot, - WithdrawalsRoot: e.WithdrawalsRoot, - BlobGasUsed: strconv.FormatUint(e.BlobGasUsed, 10), - ExcessBlobGas: strconv.FormatUint(e.ExcessBlobGas, 10), - DepositRequestsRoot: e.DepositRequestsRoot, - WithdrawalRequestsRoot: e.WithdrawalRequestsRoot, - ConsolidationRequestsRoot: e.ConsolidationRequestsRoot, - }) -} - -// UnmarshalJSON implements json.Unmarshaler. -// -//nolint:gocyclo -func (e *ExecutionPayloadHeader) UnmarshalJSON(input []byte) error { - raw, err := codecs.RawJSON(&executionPayloadHeaderJSON{}, input) - if err != nil { - return err - } - - if err := e.ParentHash.UnmarshalJSON(raw["parent_hash"]); err != nil { - return errors.Wrap(err, "parent_hash") - } - - if err := e.FeeRecipient.UnmarshalJSON(raw["fee_recipient"]); err != nil { - return errors.Wrap(err, "fee_recipient") - } - - if err := e.StateRoot.UnmarshalJSON(raw["state_root"]); err != nil { - return errors.Wrap(err, "state_root") - } - - if err := e.ReceiptsRoot.UnmarshalJSON(raw["receipts_root"]); err != nil { - return errors.Wrap(err, "receipts_root") - } - - logsBloom := raw["logs_bloom"] - if !bytes.HasPrefix(logsBloom, []byte{'"', '0', 'x'}) { - return errors.New("logs_bloom: invalid prefix") - } - if !bytes.HasSuffix(logsBloom, []byte{'"'}) { - return errors.New("logs_bloom: invalid suffix") - } - if len(logsBloom) != 1+2+256*2+1 { - return errors.New("logs_bloom: incorrect length") - } - length, err := hex.Decode(e.LogsBloom[:], logsBloom[3:3+256*2]) - if err != nil { - return errors.Wrap(err, "logs_bloom") - } - if length != 256 { - return errors.New("logs_bloom: incorrect length") - } - - prevRandao := raw["prev_randao"] - if !bytes.HasPrefix(prevRandao, []byte{'"', '0', 'x'}) { - return errors.New("prev_randao: invalid prefix") - } - if !bytes.HasSuffix(prevRandao, []byte{'"'}) { - return errors.New("prev_randao: invalid suffix") - } - if len(prevRandao) != 1+2+32*2+1 { - return errors.New("prev_randao: incorrect length") - } - length, err = hex.Decode(e.PrevRandao[:], prevRandao[3:3+32*2]) - if err != nil { - return errors.Wrap(err, "prev_randao") - } - if length != 32 { - return errors.New("prev_randao: incorrect length") - } - - tmpUint, err := strconv.ParseUint(string(bytes.Trim(raw["block_number"], `"`)), 10, 64) - if err != nil { - return errors.Wrap(err, "block_number") - } - e.BlockNumber = tmpUint - - tmpUint, err = strconv.ParseUint(string(bytes.Trim(raw["gas_limit"], `"`)), 10, 64) - if err != nil { - return errors.Wrap(err, "gas_limit") - } - e.GasLimit = tmpUint - - tmpUint, err = strconv.ParseUint(string(bytes.Trim(raw["gas_used"], `"`)), 10, 64) - if err != nil { - return errors.Wrap(err, "gas_used") - } - e.GasUsed = tmpUint - - tmpUint, err = strconv.ParseUint(string(bytes.Trim(raw["timestamp"], `"`)), 10, 64) - if err != nil { - return errors.Wrap(err, "timestamp") - } - e.Timestamp = tmpUint - - var tmpBytes []byte - switch { - case bytes.Equal(raw["extra_data"], []byte{'0', 'x'}), - bytes.Equal(raw["extra_data"], []byte{'0'}), - bytes.Equal(raw["extra_data"], []byte{'"', '0', '"'}): - // Empty. - default: - tmpBytes = bytes.TrimPrefix(bytes.Trim(raw["extra_data"], `"`), []byte{'0', 'x'}) - if len(tmpBytes)%2 == 1 { - tmpBytes = []byte(fmt.Sprintf("0%s", string(tmpBytes))) - } - tmp, err := hex.DecodeString(string(tmpBytes)) - if err != nil { - return errors.Wrap(err, "extra_data") - } - if len(tmp) > 32 { - return errors.New("extra_data: incorrect length") - } - e.ExtraData = tmp - } - - tmpBytes = bytes.Trim(raw["base_fee_per_gas"], `"`) - if bytes.HasPrefix(tmpBytes, []byte{'0', 'x'}) { - e.BaseFeePerGas, err = uint256.FromHex(string(tmpBytes)) - } else { - e.BaseFeePerGas, err = uint256.FromDecimal(string(tmpBytes)) - } - if err != nil { - return errors.Wrap(err, "base_fee_per_gas") - } - - if err := e.BlockHash.UnmarshalJSON(raw["block_hash"]); err != nil { - return errors.Wrap(err, "block_hash") - } - - if err := e.TransactionsRoot.UnmarshalJSON(raw["transactions_root"]); err != nil { - return errors.Wrap(err, "transactions_root") - } - - if err := e.WithdrawalsRoot.UnmarshalJSON(raw["withdrawals_root"]); err != nil { - return errors.Wrap(err, "withdrawals_root") - } - - tmpUint, err = strconv.ParseUint(string(bytes.Trim(raw["blob_gas_used"], `"`)), 10, 64) - if err != nil { - return errors.Wrap(err, "blob_gas_used") - } - e.BlobGasUsed = tmpUint - - tmpUint, err = strconv.ParseUint(string(bytes.Trim(raw["excess_blob_gas"], `"`)), 10, 64) - if err != nil { - return errors.Wrap(err, "excess_blob_gas") - } - e.ExcessBlobGas = tmpUint - - if err := e.DepositRequestsRoot.UnmarshalJSON(raw["deposit_requests_root"]); err != nil { - return errors.Wrap(err, "deposit_requests_root") - } - - if err := e.WithdrawalRequestsRoot.UnmarshalJSON(raw["withdrawal_requests_root"]); err != nil { - return errors.Wrap(err, "withdrawal_requests_root") - } - - if err := e.ConsolidationRequestsRoot.UnmarshalJSON(raw["consolidation_requests_root"]); err != nil { - return errors.Wrap(err, "consolidation_requests_root") - } - - return nil -} diff --git a/spec/electra/executionpayloadheader_ssz.go b/spec/electra/executionpayloadheader_ssz.go deleted file mode 100644 index 98cd6a50..00000000 --- a/spec/electra/executionpayloadheader_ssz.go +++ /dev/null @@ -1,291 +0,0 @@ -// Code generated by fastssz. DO NOT EDIT. -// Hash: a63387b6d1f288be86bb43febdcd67174ea6fd3cbf23b63c8656748b54289b53 -// Version: 0.1.3 -package electra - -import ( - ssz "github.com/ferranbt/fastssz" - "github.com/holiman/uint256" -) - -// MarshalSSZ ssz marshals the ExecutionPayloadHeader object -func (e *ExecutionPayloadHeader) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(e) -} - -// MarshalSSZTo ssz marshals the ExecutionPayloadHeader object to a target array -func (e *ExecutionPayloadHeader) MarshalSSZTo(buf []byte) (dst []byte, err error) { - dst = buf - offset := int(680) - - // Field (0) 'ParentHash' - dst = append(dst, e.ParentHash[:]...) - - // Field (1) 'FeeRecipient' - dst = append(dst, e.FeeRecipient[:]...) - - // Field (2) 'StateRoot' - dst = append(dst, e.StateRoot[:]...) - - // Field (3) 'ReceiptsRoot' - dst = append(dst, e.ReceiptsRoot[:]...) - - // Field (4) 'LogsBloom' - dst = append(dst, e.LogsBloom[:]...) - - // Field (5) 'PrevRandao' - dst = append(dst, e.PrevRandao[:]...) - - // Field (6) 'BlockNumber' - dst = ssz.MarshalUint64(dst, e.BlockNumber) - - // Field (7) 'GasLimit' - dst = ssz.MarshalUint64(dst, e.GasLimit) - - // Field (8) 'GasUsed' - dst = ssz.MarshalUint64(dst, e.GasUsed) - - // Field (9) 'Timestamp' - dst = ssz.MarshalUint64(dst, e.Timestamp) - - // Offset (10) 'ExtraData' - dst = ssz.WriteOffset(dst, offset) - offset += len(e.ExtraData) - - // Field (11) 'BaseFeePerGas' - baseFeePerGas := e.BaseFeePerGas.Bytes32() - for i := 0; i < 32; i++ { - dst = append(dst, baseFeePerGas[31-i]) - } - - // Field (12) 'BlockHash' - dst = append(dst, e.BlockHash[:]...) - - // Field (13) 'TransactionsRoot' - dst = append(dst, e.TransactionsRoot[:]...) - - // Field (14) 'WithdrawalsRoot' - dst = append(dst, e.WithdrawalsRoot[:]...) - - // Field (15) 'BlobGasUsed' - dst = ssz.MarshalUint64(dst, e.BlobGasUsed) - - // Field (16) 'ExcessBlobGas' - dst = ssz.MarshalUint64(dst, e.ExcessBlobGas) - - // Field (17) 'DepositReceiptsRoot' - dst = append(dst, e.DepositRequestsRoot[:]...) - - // Field (18) 'WithdrawalRequestsRoot' - dst = append(dst, e.WithdrawalRequestsRoot[:]...) - - // Field (19) 'ConsolidationRequestsRoot' - dst = append(dst, e.ConsolidationRequestsRoot[:]...) - - // Field (10) 'ExtraData' - if size := len(e.ExtraData); size > 32 { - err = ssz.ErrBytesLengthFn("ExecutionPayloadHeader.ExtraData", size, 32) - return - } - dst = append(dst, e.ExtraData...) - - return -} - -// UnmarshalSSZ ssz unmarshals the ExecutionPayloadHeader object -func (e *ExecutionPayloadHeader) UnmarshalSSZ(buf []byte) error { - var err error - size := uint64(len(buf)) - if size < 680 { - return ssz.ErrSize - } - - tail := buf - var o10 uint64 - - // Field (0) 'ParentHash' - copy(e.ParentHash[:], buf[0:32]) - - // Field (1) 'FeeRecipient' - copy(e.FeeRecipient[:], buf[32:52]) - - // Field (2) 'StateRoot' - copy(e.StateRoot[:], buf[52:84]) - - // Field (3) 'ReceiptsRoot' - copy(e.ReceiptsRoot[:], buf[84:116]) - - // Field (4) 'LogsBloom' - copy(e.LogsBloom[:], buf[116:372]) - - // Field (5) 'PrevRandao' - copy(e.PrevRandao[:], buf[372:404]) - - // Field (6) 'BlockNumber' - e.BlockNumber = ssz.UnmarshallUint64(buf[404:412]) - - // Field (7) 'GasLimit' - e.GasLimit = ssz.UnmarshallUint64(buf[412:420]) - - // Field (8) 'GasUsed' - e.GasUsed = ssz.UnmarshallUint64(buf[420:428]) - - // Field (9) 'Timestamp' - e.Timestamp = ssz.UnmarshallUint64(buf[428:436]) - - // Offset (10) 'ExtraData' - if o10 = ssz.ReadOffset(buf[436:440]); o10 > size { - return ssz.ErrOffset - } - - if o10 < 680 { - return ssz.ErrInvalidVariableOffset - } - - // Field (11) 'BaseFeePerGas' - baseFeePerGasBE := make([]byte, 32) - for i := 0; i < 32; i++ { - baseFeePerGasBE[i] = buf[471-i] - } - e.BaseFeePerGas = &uint256.Int{} - e.BaseFeePerGas.SetBytes32(baseFeePerGasBE) - - // Field (12) 'BlockHash' - copy(e.BlockHash[:], buf[472:504]) - - // Field (13) 'TransactionsRoot' - copy(e.TransactionsRoot[:], buf[504:536]) - - // Field (14) 'WithdrawalsRoot' - copy(e.WithdrawalsRoot[:], buf[536:568]) - - // Field (15) 'BlobGasUsed' - e.BlobGasUsed = ssz.UnmarshallUint64(buf[568:576]) - - // Field (16) 'ExcessBlobGas' - e.ExcessBlobGas = ssz.UnmarshallUint64(buf[576:584]) - - // Field (17) 'DepositReceiptsRoot' - copy(e.DepositRequestsRoot[:], buf[584:616]) - - // Field (18) 'WithdrawalRequestsRoot' - copy(e.WithdrawalRequestsRoot[:], buf[616:648]) - - // Field (19) 'ConsolidationRequestsRoot' - copy(e.ConsolidationRequestsRoot[:], buf[648:680]) - - // Field (10) 'ExtraData' - { - buf = tail[o10:] - if len(buf) > 32 { - return ssz.ErrBytesLength - } - if cap(e.ExtraData) == 0 { - e.ExtraData = make([]byte, 0, len(buf)) - } - e.ExtraData = append(e.ExtraData, buf...) - } - return err -} - -// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadHeader object -func (e *ExecutionPayloadHeader) SizeSSZ() (size int) { - size = 680 - - // Field (10) 'ExtraData' - size += len(e.ExtraData) - - return -} - -// HashTreeRoot ssz hashes the ExecutionPayloadHeader object -func (e *ExecutionPayloadHeader) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(e) -} - -// HashTreeRootWith ssz hashes the ExecutionPayloadHeader object with a hasher -func (e *ExecutionPayloadHeader) HashTreeRootWith(hh ssz.HashWalker) (err error) { - indx := hh.Index() - - // Field (0) 'ParentHash' - hh.PutBytes(e.ParentHash[:]) - - // Field (1) 'FeeRecipient' - hh.PutBytes(e.FeeRecipient[:]) - - // Field (2) 'StateRoot' - hh.PutBytes(e.StateRoot[:]) - - // Field (3) 'ReceiptsRoot' - hh.PutBytes(e.ReceiptsRoot[:]) - - // Field (4) 'LogsBloom' - hh.PutBytes(e.LogsBloom[:]) - - // Field (5) 'PrevRandao' - hh.PutBytes(e.PrevRandao[:]) - - // Field (6) 'BlockNumber' - hh.PutUint64(e.BlockNumber) - - // Field (7) 'GasLimit' - hh.PutUint64(e.GasLimit) - - // Field (8) 'GasUsed' - hh.PutUint64(e.GasUsed) - - // Field (9) 'Timestamp' - hh.PutUint64(e.Timestamp) - - // Field (10) 'ExtraData' - { - elemIndx := hh.Index() - byteLen := uint64(len(e.ExtraData)) - if byteLen > 32 { - err = ssz.ErrIncorrectListSize - return - } - hh.Append(e.ExtraData) - hh.MerkleizeWithMixin(elemIndx, byteLen, (32+31)/32) - } - - // Field (11) 'BaseFeePerGas' - baseFeePerGas := make([]byte, 32) - baseFeePerGasBE := e.BaseFeePerGas.Bytes32() - for i := 0; i < 32; i++ { - baseFeePerGas[i] = baseFeePerGasBE[31-i] - } - hh.PutBytes(baseFeePerGas) - - // Field (12) 'BlockHash' - hh.PutBytes(e.BlockHash[:]) - - // Field (13) 'TransactionsRoot' - hh.PutBytes(e.TransactionsRoot[:]) - - // Field (14) 'WithdrawalsRoot' - hh.PutBytes(e.WithdrawalsRoot[:]) - - // Field (15) 'BlobGasUsed' - hh.PutUint64(e.BlobGasUsed) - - // Field (16) 'ExcessBlobGas' - hh.PutUint64(e.ExcessBlobGas) - - // Field (17) 'DepositReceiptsRoot' - hh.PutBytes(e.DepositRequestsRoot[:]) - - // Field (18) 'WithdrawalRequestsRoot' - hh.PutBytes(e.WithdrawalRequestsRoot[:]) - - // Field (19) 'ConsolidationRequestsRoot' - hh.PutBytes(e.ConsolidationRequestsRoot[:]) - - hh.Merkleize(indx) - return -} - -// GetTree ssz hashes the ExecutionPayloadHeader object -func (e *ExecutionPayloadHeader) GetTree() (*ssz.Node, error) { - return ssz.ProofTree(e) -} diff --git a/spec/electra/executionpayloadheader_yaml.go b/spec/electra/executionpayloadheader_yaml.go deleted file mode 100644 index 9a4eb0ee..00000000 --- a/spec/electra/executionpayloadheader_yaml.go +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright © 2024 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 electra - -import ( - "bytes" - "encoding/json" - "fmt" - - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/phase0" - "github.com/goccy/go-yaml" - "github.com/pkg/errors" -) - -// executionPayloadHeaderYAML is the spec representation of the struct. -type executionPayloadHeaderYAML struct { - ParentHash phase0.Hash32 `yaml:"parent_hash"` - FeeRecipient bellatrix.ExecutionAddress `yaml:"fee_recipient"` - StateRoot phase0.Root `yaml:"state_root"` - ReceiptsRoot phase0.Root `yaml:"receipts_root"` - LogsBloom string `yaml:"logs_bloom"` - PrevRandao string `yaml:"prev_randao"` - BlockNumber uint64 `yaml:"block_number"` - GasLimit uint64 `yaml:"gas_limit"` - GasUsed uint64 `yaml:"gas_used"` - Timestamp uint64 `yaml:"timestamp"` - ExtraData string `yaml:"extra_data"` - BaseFeePerGas string `yaml:"base_fee_per_gas"` - BlockHash phase0.Hash32 `yaml:"block_hash"` - TransactionsRoot phase0.Root `yaml:"transactions_root"` - WithdrawalsRoot phase0.Root `yaml:"withdrawals_root"` - BlobGasUsed uint64 `yaml:"blob_gas_used"` - ExcessBlobGas uint64 `yaml:"excess_blob_gas"` - DepositRequestsRoot phase0.Root `yaml:"deposit_requests_root"` - WithdrawalRequestsRoot phase0.Root `yaml:"withdrawal_requests_root"` - ConsolidationRequestsRoot phase0.Root `yaml:"consolidation_requests_root"` -} - -// MarshalYAML implements yaml.Marshaler. -func (e *ExecutionPayloadHeader) MarshalYAML() ([]byte, error) { - extraData := "0x" - if len(e.ExtraData) > 0 { - extraData = fmt.Sprintf("%#x", e.ExtraData) - } - - yamlBytes, err := yaml.MarshalWithOptions(&executionPayloadHeaderYAML{ - ParentHash: e.ParentHash, - FeeRecipient: e.FeeRecipient, - StateRoot: e.StateRoot, - ReceiptsRoot: e.ReceiptsRoot, - LogsBloom: fmt.Sprintf("%#x", e.LogsBloom), - PrevRandao: fmt.Sprintf("%#x", e.PrevRandao), - BlockNumber: e.BlockNumber, - GasLimit: e.GasLimit, - GasUsed: e.GasUsed, - Timestamp: e.Timestamp, - ExtraData: extraData, - BaseFeePerGas: e.BaseFeePerGas.Dec(), - BlockHash: e.BlockHash, - TransactionsRoot: e.TransactionsRoot, - WithdrawalsRoot: e.WithdrawalsRoot, - BlobGasUsed: e.BlobGasUsed, - ExcessBlobGas: e.ExcessBlobGas, - DepositRequestsRoot: e.DepositRequestsRoot, - WithdrawalRequestsRoot: e.WithdrawalRequestsRoot, - ConsolidationRequestsRoot: e.ConsolidationRequestsRoot, - }, yaml.Flow(true)) - if err != nil { - return nil, err - } - - return bytes.ReplaceAll(yamlBytes, []byte(`"`), []byte(`'`)), nil -} - -// UnmarshalYAML implements yaml.Unmarshaler. -func (e *ExecutionPayloadHeader) UnmarshalYAML(input []byte) error { - // This is very inefficient, but YAML is only used for spec tests so we do this - // rather than maintain a custom YAML unmarshaller. - var unmarshaled executionPayloadHeaderJSON - if err := yaml.Unmarshal(input, &unmarshaled); err != nil { - return errors.Wrap(err, "failed to unmarshal YAML") - } - marshaled, err := json.Marshal(unmarshaled) - if err != nil { - return errors.Wrap(err, "failed to marshal JSON") - } - - return e.UnmarshalJSON(marshaled) -} diff --git a/spec/electra/executionrequests.go b/spec/electra/executionrequests.go new file mode 100644 index 00000000..45bf9de1 --- /dev/null +++ b/spec/electra/executionrequests.go @@ -0,0 +1,37 @@ +// Copyright © 2024 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 electra + +import ( + "fmt" + + "github.com/goccy/go-yaml" +) + +// ExecutionRequests represents an execution layer payload. +type ExecutionRequests struct { + DepositRequests []*DepositRequest `ssz-max:"8192"` + WithdrawalRequests []*WithdrawalRequest `ssz-max:"16"` + ConsolidationRequests []*ConsolidationRequest `ssz-max:"1"` +} + +// String returns a string version of the structure. +func (e *ExecutionRequests) String() string { + data, err := yaml.Marshal(e) + if err != nil { + return fmt.Sprintf("ERR: %v", err) + } + + return string(data) +} diff --git a/spec/electra/executionrequests_json.go b/spec/electra/executionrequests_json.go new file mode 100644 index 00000000..8325841e --- /dev/null +++ b/spec/electra/executionrequests_json.go @@ -0,0 +1,77 @@ +// Copyright © 2024 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 electra + +import ( + "encoding/json" + "fmt" + + "github.com/attestantio/go-eth2-client/codecs" + "github.com/pkg/errors" +) + +// executionRequestsJSON is the spec representation of the struct. +type executionRequestsJSON struct { + DepositRequests []*DepositRequest `json:"deposit_requests"` + WithdrawalRequests []*WithdrawalRequest `json:"withdrawal_requests"` + ConsolidationRequests []*ConsolidationRequest `json:"consolidation_requests"` +} + +// MarshalJSON implements json.Marshaler. +func (e *ExecutionRequests) MarshalJSON() ([]byte, error) { + return json.Marshal(&executionRequestsJSON{ + DepositRequests: e.DepositRequests, + WithdrawalRequests: e.WithdrawalRequests, + ConsolidationRequests: e.ConsolidationRequests, + }) +} + +// UnmarshalJSON implements json.Unmarshaler. +// +//nolint:gocyclo +func (e *ExecutionRequests) UnmarshalJSON(input []byte) error { + raw, err := codecs.RawJSON(&executionRequestsJSON{}, input) + if err != nil { + return err + } + + if err := json.Unmarshal(raw["deposit_requests"], &e.DepositRequests); err != nil { + return errors.Wrap(err, "deposit_requests") + } + for i := range e.DepositRequests { + if e.DepositRequests[i] == nil { + return fmt.Errorf("deposit receipts entry %d missing", i) + } + } + + if err := json.Unmarshal(raw["withdrawal_requests"], &e.WithdrawalRequests); err != nil { + return errors.Wrap(err, "withdrawal_requests") + } + for i := range e.WithdrawalRequests { + if e.WithdrawalRequests[i] == nil { + return fmt.Errorf("withdraw requests entry %d missing", i) + } + } + + if err := json.Unmarshal(raw["consolidation_requests"], &e.ConsolidationRequests); err != nil { + return errors.Wrap(err, "consolidation_requests") + } + for i := range e.ConsolidationRequests { + if e.ConsolidationRequests[i] == nil { + return fmt.Errorf("consolidation requests entry %d missing", i) + } + } + + return nil +} diff --git a/spec/electra/executionrequests_ssz.go b/spec/electra/executionrequests_ssz.go new file mode 100644 index 00000000..b31640f9 --- /dev/null +++ b/spec/electra/executionrequests_ssz.go @@ -0,0 +1,234 @@ +// Code generated by fastssz. DO NOT EDIT. +// Hash: a0960436212943f5595c94087ee709d30a033a29aefc5236b2ea5582d783504c +// Version: 0.1.3 +package electra + +import ( + ssz "github.com/ferranbt/fastssz" +) + +// MarshalSSZ ssz marshals the ExecutionRequests object +func (e *ExecutionRequests) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(e) +} + +// MarshalSSZTo ssz marshals the ExecutionRequests object to a target array +func (e *ExecutionRequests) MarshalSSZTo(buf []byte) (dst []byte, err error) { + dst = buf + offset := int(12) + + // Offset (0) 'DepositRequests' + dst = ssz.WriteOffset(dst, offset) + offset += len(e.DepositRequests) * 192 + + // Offset (1) 'WithdrawalRequests' + dst = ssz.WriteOffset(dst, offset) + offset += len(e.WithdrawalRequests) * 76 + + // Offset (2) 'ConsolidationRequests' + dst = ssz.WriteOffset(dst, offset) + offset += len(e.ConsolidationRequests) * 116 + + // Field (0) 'DepositRequests' + if size := len(e.DepositRequests); size > 8192 { + err = ssz.ErrListTooBigFn("ExecutionRequests.DepositRequests", size, 8192) + return + } + for ii := 0; ii < len(e.DepositRequests); ii++ { + if dst, err = e.DepositRequests[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + // Field (1) 'WithdrawalRequests' + if size := len(e.WithdrawalRequests); size > 16 { + err = ssz.ErrListTooBigFn("ExecutionRequests.WithdrawalRequests", size, 16) + return + } + for ii := 0; ii < len(e.WithdrawalRequests); ii++ { + if dst, err = e.WithdrawalRequests[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + // Field (2) 'ConsolidationRequests' + if size := len(e.ConsolidationRequests); size > 1 { + err = ssz.ErrListTooBigFn("ExecutionRequests.ConsolidationRequests", size, 1) + return + } + for ii := 0; ii < len(e.ConsolidationRequests); ii++ { + if dst, err = e.ConsolidationRequests[ii].MarshalSSZTo(dst); err != nil { + return + } + } + + return +} + +// UnmarshalSSZ ssz unmarshals the ExecutionRequests object +func (e *ExecutionRequests) UnmarshalSSZ(buf []byte) error { + var err error + size := uint64(len(buf)) + if size < 12 { + return ssz.ErrSize + } + + tail := buf + var o0, o1, o2 uint64 + + // Offset (0) 'DepositRequests' + if o0 = ssz.ReadOffset(buf[0:4]); o0 > size { + return ssz.ErrOffset + } + + if o0 < 12 { + return ssz.ErrInvalidVariableOffset + } + + // Offset (1) 'WithdrawalRequests' + if o1 = ssz.ReadOffset(buf[4:8]); o1 > size || o0 > o1 { + return ssz.ErrOffset + } + + // Offset (2) 'ConsolidationRequests' + if o2 = ssz.ReadOffset(buf[8:12]); o2 > size || o1 > o2 { + return ssz.ErrOffset + } + + // Field (0) 'DepositRequests' + { + buf = tail[o0:o1] + num, err := ssz.DivideInt2(len(buf), 192, 8192) + if err != nil { + return err + } + e.DepositRequests = make([]*DepositRequest, num) + for ii := 0; ii < num; ii++ { + if e.DepositRequests[ii] == nil { + e.DepositRequests[ii] = new(DepositRequest) + } + if err = e.DepositRequests[ii].UnmarshalSSZ(buf[ii*192 : (ii+1)*192]); err != nil { + return err + } + } + } + + // Field (1) 'WithdrawalRequests' + { + buf = tail[o1:o2] + num, err := ssz.DivideInt2(len(buf), 76, 16) + if err != nil { + return err + } + e.WithdrawalRequests = make([]*WithdrawalRequest, num) + for ii := 0; ii < num; ii++ { + if e.WithdrawalRequests[ii] == nil { + e.WithdrawalRequests[ii] = new(WithdrawalRequest) + } + if err = e.WithdrawalRequests[ii].UnmarshalSSZ(buf[ii*76 : (ii+1)*76]); err != nil { + return err + } + } + } + + // Field (2) 'ConsolidationRequests' + { + buf = tail[o2:] + num, err := ssz.DivideInt2(len(buf), 116, 1) + if err != nil { + return err + } + e.ConsolidationRequests = make([]*ConsolidationRequest, num) + for ii := 0; ii < num; ii++ { + if e.ConsolidationRequests[ii] == nil { + e.ConsolidationRequests[ii] = new(ConsolidationRequest) + } + if err = e.ConsolidationRequests[ii].UnmarshalSSZ(buf[ii*116 : (ii+1)*116]); err != nil { + return err + } + } + } + return err +} + +// SizeSSZ returns the ssz encoded size in bytes for the ExecutionRequests object +func (e *ExecutionRequests) SizeSSZ() (size int) { + size = 12 + + // Field (0) 'DepositRequests' + size += len(e.DepositRequests) * 192 + + // Field (1) 'WithdrawalRequests' + size += len(e.WithdrawalRequests) * 76 + + // Field (2) 'ConsolidationRequests' + size += len(e.ConsolidationRequests) * 116 + + return +} + +// HashTreeRoot ssz hashes the ExecutionRequests object +func (e *ExecutionRequests) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(e) +} + +// HashTreeRootWith ssz hashes the ExecutionRequests object with a hasher +func (e *ExecutionRequests) HashTreeRootWith(hh ssz.HashWalker) (err error) { + indx := hh.Index() + + // Field (0) 'DepositRequests' + { + subIndx := hh.Index() + num := uint64(len(e.DepositRequests)) + if num > 8192 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range e.DepositRequests { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 8192) + } + + // Field (1) 'WithdrawalRequests' + { + subIndx := hh.Index() + num := uint64(len(e.WithdrawalRequests)) + if num > 16 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range e.WithdrawalRequests { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 16) + } + + // Field (2) 'ConsolidationRequests' + { + subIndx := hh.Index() + num := uint64(len(e.ConsolidationRequests)) + if num > 1 { + err = ssz.ErrIncorrectListSize + return + } + for _, elem := range e.ConsolidationRequests { + if err = elem.HashTreeRootWith(hh); err != nil { + return + } + } + hh.MerkleizeWithMixin(subIndx, num, 1) + } + + hh.Merkleize(indx) + return +} + +// GetTree ssz hashes the ExecutionRequests object +func (e *ExecutionRequests) GetTree() (*ssz.Node, error) { + return ssz.ProofTree(e) +} diff --git a/spec/electra/executionrequests_yaml.go b/spec/electra/executionrequests_yaml.go new file mode 100644 index 00000000..ede50558 --- /dev/null +++ b/spec/electra/executionrequests_yaml.go @@ -0,0 +1,59 @@ +// Copyright © 2024 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 electra + +import ( + "bytes" + "encoding/json" + + "github.com/goccy/go-yaml" + "github.com/pkg/errors" +) + +// executionRequestsYAML is the spec representation of the struct. +type executionRequestsYAML struct { + DepositRequests []*DepositRequest `yaml:"deposit_requests"` + WithdrawalRequests []*WithdrawalRequest `yaml:"withdrawal_requests"` + ConsolidationRequests []*ConsolidationRequest `yaml:"consolidation_requests"` +} + +// MarshalYAML implements yaml.Marshaler. +func (e *ExecutionRequests) MarshalYAML() ([]byte, error) { + yamlBytes, err := yaml.MarshalWithOptions(&executionRequestsYAML{ + DepositRequests: e.DepositRequests, + WithdrawalRequests: e.WithdrawalRequests, + ConsolidationRequests: e.ConsolidationRequests, + }, yaml.Flow(true)) + if err != nil { + return nil, err + } + + return bytes.ReplaceAll(yamlBytes, []byte(`"`), []byte(`'`)), nil +} + +// UnmarshalYAML implements yaml.Unmarshaler. +func (e *ExecutionRequests) UnmarshalYAML(input []byte) error { + // This is very inefficient, but YAML is only used for spec tests so we do this + // rather than maintain a custom YAML unmarshaller. + var unmarshaled executionRequestsJSON + if err := yaml.Unmarshal(input, &unmarshaled); err != nil { + return errors.Wrap(err, "failed to unmarshal YAML") + } + marshaled, err := json.Marshal(unmarshaled) + if err != nil { + return errors.Wrap(err, "failed to marshal JSON") + } + + return e.UnmarshalJSON(marshaled) +} diff --git a/spec/electra/generate.go b/spec/electra/generate.go index 5e654957..ab93b0d6 100644 --- a/spec/electra/generate.go +++ b/spec/electra/generate.go @@ -15,6 +15,6 @@ package electra //nolint:revive // Need to `go install github.com/ferranbt/fastssz/sszgen@latest` for this to work. -//go:generate rm -f aggregateandproof_ssz.go attestation_ssz.go attesterslashing_ssz.go beaconblockbody_ssz.go beaconblock_ssz.go beaconstate_ssz.go consolidation_ssz.go depositreceipt_ssz.go executionlayerwithdrawalrequest_ssz.go executionpayload_ssz.go executionpayloadheader_ssz.go pendingbalancedeposit_ssz.go pendingconsolidation_ssz.go pendingpartialwithdrawal_ssz.go signedaggregateandproof_ssz.go signedbeaconblock_ssz.go signedconsolidation_ssz.go -//go:generate sszgen --suffix=ssz --path . --include ../phase0,../altair,../bellatrix,../capella,../deneb --objs AggregateAndProof,Attestation,AttesterSlashing,BeaconBlockBody,BeaconBlock,BeaconState,Consolidation,DepositReceipt,ExecutionLayerWithdrawalRequest,ExecutionPayload,ExecutionPayloadHeader,PendingBalanceDeposit,PendingConsolidation,PendingPartialWithdrawal,SignedAggregateAndProof,SignedBeaconBlock,SignedConsolidation -//go:generate goimports -w aggregateandproof_ssz.go attestation_ssz.go attesterslashing_ssz.go beaconblockbody_ssz.go beaconblock_ssz.go beaconstate_ssz.go consolidation_ssz.go depositreceipt_ssz.go executionlayerwithdrawalrequest_ssz.go executionpayload_ssz.go executionpayloadheader_ssz.go pendingbalancedeposit_ssz.go pendingconsolidation_ssz.go pendingpartialwithdrawal_ssz.go signedaggregateandproof_ssz.go signedbeaconblock_ssz.go signedconsolidation_ssz.go +//go:generate rm -f aggregateandproof_ssz.go attestation_ssz.go attesterslashing_ssz.go beaconblockbody_ssz.go beaconblock_ssz.go beaconstate_ssz.go consolidation_ssz.go depositreceipt_ssz.go executionlayerwithdrawalrequest_ssz.go executionpayload_ssz.go executionpayloadheader_ssz.go pendingbalancedeposit_ssz.go pendingconsolidation_ssz.go pendingpartialwithdrawal_ssz.go signedaggregateandproof_ssz.go signedbeaconblock_ssz.go +//go:generate sszgen --suffix=ssz --path . --include ../phase0,../altair,../bellatrix,../capella,../deneb --objs AggregateAndProof,Attestation,AttesterSlashing,BeaconBlockBody,BeaconBlock,BeaconState,Consolidation,DepositReceipt,ExecutionLayerWithdrawalRequest,ExecutionRequests,PendingBalanceDeposit,PendingConsolidation,PendingPartialWithdrawal,SignedAggregateAndProof,SignedBeaconBlock +//go:generate goimports -w aggregateandproof_ssz.go attestation_ssz.go attesterslashing_ssz.go beaconblockbody_ssz.go beaconblock_ssz.go beaconstate_ssz.go consolidation_ssz.go depositreceipt_ssz.go executionlayerwithdrawalrequest_ssz.go executionpayload_ssz.go executionpayloadheader_ssz.go pendingbalancedeposit_ssz.go pendingconsolidation_ssz.go pendingpartialwithdrawal_ssz.go signedaggregateandproof_ssz.go signedbeaconblock_ssz.go diff --git a/spec/electra/withdrawalrequest_ssz.go b/spec/electra/withdrawalrequest_ssz.go index f9edd587..1a21ce85 100644 --- a/spec/electra/withdrawalrequest_ssz.go +++ b/spec/electra/withdrawalrequest_ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 17d4c9180818d70e873edf284079b326d586a16686d17c7c974a8a2fd19ec3e9 +// Hash: a0960436212943f5595c94087ee709d30a033a29aefc5236b2ea5582d783504c // Version: 0.1.3 package electra @@ -9,28 +9,28 @@ import ( ) // MarshalSSZ ssz marshals the WithdrawalRequest object -func (e *WithdrawalRequest) MarshalSSZ() ([]byte, error) { - return ssz.MarshalSSZ(e) +func (w *WithdrawalRequest) MarshalSSZ() ([]byte, error) { + return ssz.MarshalSSZ(w) } // MarshalSSZTo ssz marshals the WithdrawalRequest object to a target array -func (e *WithdrawalRequest) MarshalSSZTo(buf []byte) (dst []byte, err error) { +func (w *WithdrawalRequest) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf // Field (0) 'SourceAddress' - dst = append(dst, e.SourceAddress[:]...) + dst = append(dst, w.SourceAddress[:]...) // Field (1) 'ValidatorPubkey' - dst = append(dst, e.ValidatorPubkey[:]...) + dst = append(dst, w.ValidatorPubkey[:]...) // Field (2) 'Amount' - dst = ssz.MarshalUint64(dst, uint64(e.Amount)) + dst = ssz.MarshalUint64(dst, uint64(w.Amount)) return } // UnmarshalSSZ ssz unmarshals the WithdrawalRequest object -func (e *WithdrawalRequest) UnmarshalSSZ(buf []byte) error { +func (w *WithdrawalRequest) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) if size != 76 { @@ -38,46 +38,46 @@ func (e *WithdrawalRequest) UnmarshalSSZ(buf []byte) error { } // Field (0) 'SourceAddress' - copy(e.SourceAddress[:], buf[0:20]) + copy(w.SourceAddress[:], buf[0:20]) // Field (1) 'ValidatorPubkey' - copy(e.ValidatorPubkey[:], buf[20:68]) + copy(w.ValidatorPubkey[:], buf[20:68]) // Field (2) 'Amount' - e.Amount = phase0.Gwei(ssz.UnmarshallUint64(buf[68:76])) + w.Amount = phase0.Gwei(ssz.UnmarshallUint64(buf[68:76])) return err } // SizeSSZ returns the ssz encoded size in bytes for the WithdrawalRequest object -func (e *WithdrawalRequest) SizeSSZ() (size int) { +func (w *WithdrawalRequest) SizeSSZ() (size int) { size = 76 return } // HashTreeRoot ssz hashes the WithdrawalRequest object -func (e *WithdrawalRequest) HashTreeRoot() ([32]byte, error) { - return ssz.HashWithDefaultHasher(e) +func (w *WithdrawalRequest) HashTreeRoot() ([32]byte, error) { + return ssz.HashWithDefaultHasher(w) } // HashTreeRootWith ssz hashes the WithdrawalRequest object with a hasher -func (e *WithdrawalRequest) HashTreeRootWith(hh ssz.HashWalker) (err error) { +func (w *WithdrawalRequest) HashTreeRootWith(hh ssz.HashWalker) (err error) { indx := hh.Index() // Field (0) 'SourceAddress' - hh.PutBytes(e.SourceAddress[:]) + hh.PutBytes(w.SourceAddress[:]) // Field (1) 'ValidatorPubkey' - hh.PutBytes(e.ValidatorPubkey[:]) + hh.PutBytes(w.ValidatorPubkey[:]) // Field (2) 'Amount' - hh.PutUint64(uint64(e.Amount)) + hh.PutUint64(uint64(w.Amount)) hh.Merkleize(indx) return } // GetTree ssz hashes the WithdrawalRequest object -func (e *WithdrawalRequest) GetTree() (*ssz.Node, error) { - return ssz.ProofTree(e) +func (w *WithdrawalRequest) GetTree() (*ssz.Node, error) { + return ssz.ProofTree(w) } From b1dae21d0f05f74f7a907dfe5e62f36ed2ac8c52 Mon Sep 17 00:00:00 2001 From: pk910 Date: Mon, 23 Sep 2024 19:08:52 +0200 Subject: [PATCH 06/11] update `BlindedBeaconBlockBody` --- api/v1/electra/blindedbeaconblockbody.go | 3 +- api/v1/electra/blindedbeaconblockbody_json.go | 4 +- api/v1/electra/blindedbeaconblockbody_ssz.go | 59 +++++++++++++++---- api/v1/electra/blindedbeaconblockbody_yaml.go | 5 +- 4 files changed, 58 insertions(+), 13 deletions(-) diff --git a/api/v1/electra/blindedbeaconblockbody.go b/api/v1/electra/blindedbeaconblockbody.go index 033976da..a6b881a8 100644 --- a/api/v1/electra/blindedbeaconblockbody.go +++ b/api/v1/electra/blindedbeaconblockbody.go @@ -36,9 +36,10 @@ type BlindedBeaconBlockBody struct { Deposits []*phase0.Deposit `ssz-max:"16"` VoluntaryExits []*phase0.SignedVoluntaryExit `ssz-max:"16"` SyncAggregate *altair.SyncAggregate - ExecutionPayloadHeader *electra.ExecutionPayloadHeader + ExecutionPayloadHeader *deneb.ExecutionPayloadHeader BLSToExecutionChanges []*capella.SignedBLSToExecutionChange `ssz-max:"16"` BlobKZGCommitments []deneb.KZGCommitment `ssz-max:"4096" ssz-size:"?,48"` + ExecutionRequests *electra.ExecutionRequests } // String returns a string version of the structure. diff --git a/api/v1/electra/blindedbeaconblockbody_json.go b/api/v1/electra/blindedbeaconblockbody_json.go index fe86bedc..2e88f071 100644 --- a/api/v1/electra/blindedbeaconblockbody_json.go +++ b/api/v1/electra/blindedbeaconblockbody_json.go @@ -39,9 +39,10 @@ type blindedBeaconBlockBodyJSON struct { Deposits []*phase0.Deposit `json:"deposits"` VoluntaryExits []*phase0.SignedVoluntaryExit `json:"voluntary_exits"` SyncAggregate *altair.SyncAggregate `json:"sync_aggregate"` - ExecutionPayloadHeader *electra.ExecutionPayloadHeader `json:"execution_payload_header"` + ExecutionPayloadHeader *deneb.ExecutionPayloadHeader `json:"execution_payload_header"` BLSToExecutionChanges []*capella.SignedBLSToExecutionChange `json:"bls_to_execution_changes"` BlobKZGCommitments []string `json:"blob_kzg_commitments"` + ExecutionRequests *electra.ExecutionRequests `json:"execution_requests"` } // MarshalJSON implements json.Marshaler. @@ -64,6 +65,7 @@ func (b *BlindedBeaconBlockBody) MarshalJSON() ([]byte, error) { ExecutionPayloadHeader: b.ExecutionPayloadHeader, BLSToExecutionChanges: b.BLSToExecutionChanges, BlobKZGCommitments: blobKZGCommitments, + ExecutionRequests: b.ExecutionRequests, }) } diff --git a/api/v1/electra/blindedbeaconblockbody_ssz.go b/api/v1/electra/blindedbeaconblockbody_ssz.go index 38a4eae2..17b587b1 100644 --- a/api/v1/electra/blindedbeaconblockbody_ssz.go +++ b/api/v1/electra/blindedbeaconblockbody_ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 449c9e7b5e2698820a83b7fa31c569b206b83e7d5fc608ac39e5c95530999882 +// Hash: 4acc6e4c5284bf0d183f2452ef738334ce470925521b9d6870e54be14e4b9627 // Version: 0.1.3 package electra @@ -20,7 +20,7 @@ func (b *BlindedBeaconBlockBody) MarshalSSZ() ([]byte, error) { // MarshalSSZTo ssz marshals the BlindedBeaconBlockBody object to a target array func (b *BlindedBeaconBlockBody) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = buf - offset := int(392) + offset := int(396) // Field (0) 'RANDAOReveal' dst = append(dst, b.RANDAOReveal[:]...) @@ -73,7 +73,7 @@ func (b *BlindedBeaconBlockBody) MarshalSSZTo(buf []byte) (dst []byte, err error // Offset (9) 'ExecutionPayloadHeader' dst = ssz.WriteOffset(dst, offset) if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(electra.ExecutionPayloadHeader) + b.ExecutionPayloadHeader = new(deneb.ExecutionPayloadHeader) } offset += b.ExecutionPayloadHeader.SizeSSZ() @@ -85,6 +85,13 @@ func (b *BlindedBeaconBlockBody) MarshalSSZTo(buf []byte) (dst []byte, err error dst = ssz.WriteOffset(dst, offset) offset += len(b.BlobKZGCommitments) * 48 + // Offset (12) 'ExecutionRequests' + dst = ssz.WriteOffset(dst, offset) + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(electra.ExecutionRequests) + } + offset += b.ExecutionRequests.SizeSSZ() + // Field (3) 'ProposerSlashings' if size := len(b.ProposerSlashings); size > 16 { err = ssz.ErrListTooBigFn("BlindedBeaconBlockBody.ProposerSlashings", size, 16) @@ -179,6 +186,11 @@ func (b *BlindedBeaconBlockBody) MarshalSSZTo(buf []byte) (dst []byte, err error dst = append(dst, b.BlobKZGCommitments[ii][:]...) } + // Field (12) 'ExecutionRequests' + if dst, err = b.ExecutionRequests.MarshalSSZTo(dst); err != nil { + return + } + return } @@ -186,12 +198,12 @@ func (b *BlindedBeaconBlockBody) MarshalSSZTo(buf []byte) (dst []byte, err error func (b *BlindedBeaconBlockBody) UnmarshalSSZ(buf []byte) error { var err error size := uint64(len(buf)) - if size < 392 { + if size < 396 { return ssz.ErrSize } tail := buf - var o3, o4, o5, o6, o7, o9, o10, o11 uint64 + var o3, o4, o5, o6, o7, o9, o10, o11, o12 uint64 // Field (0) 'RANDAOReveal' copy(b.RANDAOReveal[:], buf[0:96]) @@ -212,7 +224,7 @@ func (b *BlindedBeaconBlockBody) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } - if o3 < 392 { + if o3 < 396 { return ssz.ErrInvalidVariableOffset } @@ -259,6 +271,11 @@ func (b *BlindedBeaconBlockBody) UnmarshalSSZ(buf []byte) error { return ssz.ErrOffset } + // Offset (12) 'ExecutionRequests' + if o12 = ssz.ReadOffset(buf[392:396]); o12 > size || o11 > o12 { + return ssz.ErrOffset + } + // Field (3) 'ProposerSlashings' { buf = tail[o3:o4] @@ -361,7 +378,7 @@ func (b *BlindedBeaconBlockBody) UnmarshalSSZ(buf []byte) error { { buf = tail[o9:o10] if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(electra.ExecutionPayloadHeader) + b.ExecutionPayloadHeader = new(deneb.ExecutionPayloadHeader) } if err = b.ExecutionPayloadHeader.UnmarshalSSZ(buf); err != nil { return err @@ -388,7 +405,7 @@ func (b *BlindedBeaconBlockBody) UnmarshalSSZ(buf []byte) error { // Field (11) 'BlobKZGCommitments' { - buf = tail[o11:] + buf = tail[o11:o12] num, err := ssz.DivideInt2(len(buf), 48, 4096) if err != nil { return err @@ -398,12 +415,23 @@ func (b *BlindedBeaconBlockBody) UnmarshalSSZ(buf []byte) error { copy(b.BlobKZGCommitments[ii][:], buf[ii*48:(ii+1)*48]) } } + + // Field (12) 'ExecutionRequests' + { + buf = tail[o12:] + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(electra.ExecutionRequests) + } + if err = b.ExecutionRequests.UnmarshalSSZ(buf); err != nil { + return err + } + } return err } // SizeSSZ returns the ssz encoded size in bytes for the BlindedBeaconBlockBody object func (b *BlindedBeaconBlockBody) SizeSSZ() (size int) { - size = 392 + size = 396 // Field (3) 'ProposerSlashings' size += len(b.ProposerSlashings) * 416 @@ -428,7 +456,7 @@ func (b *BlindedBeaconBlockBody) SizeSSZ() (size int) { // Field (9) 'ExecutionPayloadHeader' if b.ExecutionPayloadHeader == nil { - b.ExecutionPayloadHeader = new(electra.ExecutionPayloadHeader) + b.ExecutionPayloadHeader = new(deneb.ExecutionPayloadHeader) } size += b.ExecutionPayloadHeader.SizeSSZ() @@ -438,6 +466,12 @@ func (b *BlindedBeaconBlockBody) SizeSSZ() (size int) { // Field (11) 'BlobKZGCommitments' size += len(b.BlobKZGCommitments) * 48 + // Field (12) 'ExecutionRequests' + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(electra.ExecutionRequests) + } + size += b.ExecutionRequests.SizeSSZ() + return } @@ -587,6 +621,11 @@ func (b *BlindedBeaconBlockBody) HashTreeRootWith(hh ssz.HashWalker) (err error) hh.MerkleizeWithMixin(subIndx, numItems, 4096) } + // Field (12) 'ExecutionRequests' + if err = b.ExecutionRequests.HashTreeRootWith(hh); err != nil { + return + } + hh.Merkleize(indx) return } diff --git a/api/v1/electra/blindedbeaconblockbody_yaml.go b/api/v1/electra/blindedbeaconblockbody_yaml.go index c9094190..65f109c4 100644 --- a/api/v1/electra/blindedbeaconblockbody_yaml.go +++ b/api/v1/electra/blindedbeaconblockbody_yaml.go @@ -17,6 +17,7 @@ import ( "bytes" "fmt" + "github.com/attestantio/go-eth2-client/spec/deneb" "github.com/attestantio/go-eth2-client/spec/electra" "github.com/attestantio/go-eth2-client/spec/altair" @@ -36,9 +37,10 @@ type blindedBeaconBlockBodyYAML struct { Deposits []*phase0.Deposit `yaml:"deposits"` VoluntaryExits []*phase0.SignedVoluntaryExit `yaml:"voluntary_exits"` SyncAggregate *altair.SyncAggregate `yaml:"sync_aggregate"` - ExecutionPayloadHeader *electra.ExecutionPayloadHeader `yaml:"execution_payload_header"` + ExecutionPayloadHeader *deneb.ExecutionPayloadHeader `yaml:"execution_payload_header"` BLSToExecutionChanges []*capella.SignedBLSToExecutionChange `yaml:"bls_to_execution_changes"` BlobKZGCommitments []string `yaml:"blob_kzg_commitments"` + ExecutionRequests *electra.ExecutionRequests `yaml:"execution_requests"` } // MarshalYAML implements yaml.Marshaler. @@ -61,6 +63,7 @@ func (b *BlindedBeaconBlockBody) MarshalYAML() ([]byte, error) { ExecutionPayloadHeader: b.ExecutionPayloadHeader, BLSToExecutionChanges: b.BLSToExecutionChanges, BlobKZGCommitments: blobKZGCommitments, + ExecutionRequests: b.ExecutionRequests, }, yaml.Flow(true)) if err != nil { return nil, err From 82887e4ca7fc381456dfa1ab7d6ed7283a8f6944 Mon Sep 17 00:00:00 2001 From: pk910 Date: Mon, 23 Sep 2024 19:17:34 +0200 Subject: [PATCH 07/11] make linter happy --- spec/electra/beaconblockbody_json.go | 2 ++ spec/electra/executionrequests_json.go | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/electra/beaconblockbody_json.go b/spec/electra/beaconblockbody_json.go index 874859e8..3ee74d89 100644 --- a/spec/electra/beaconblockbody_json.go +++ b/spec/electra/beaconblockbody_json.go @@ -69,6 +69,8 @@ func (b *BeaconBlockBody) MarshalJSON() ([]byte, error) { } // UnmarshalJSON implements json.Unmarshaler. +// +//nolint:gocyclo func (b *BeaconBlockBody) UnmarshalJSON(input []byte) error { raw, err := codecs.RawJSON(&beaconBlockBodyJSON{}, input) if err != nil { diff --git a/spec/electra/executionrequests_json.go b/spec/electra/executionrequests_json.go index 8325841e..5fa7aa0a 100644 --- a/spec/electra/executionrequests_json.go +++ b/spec/electra/executionrequests_json.go @@ -38,8 +38,6 @@ func (e *ExecutionRequests) MarshalJSON() ([]byte, error) { } // UnmarshalJSON implements json.Unmarshaler. -// -//nolint:gocyclo func (e *ExecutionRequests) UnmarshalJSON(input []byte) error { raw, err := codecs.RawJSON(&executionRequestsJSON{}, input) if err != nil { From 824cbc694cb9f0cd29b53010e00cb6e2b5971aa6 Mon Sep 17 00:00:00 2001 From: pk910 Date: Mon, 23 Sep 2024 19:37:08 +0200 Subject: [PATCH 08/11] add `VersionedSignedBeaconBlock.ExecutionRequests()` --- spec/versionedsignedbeaconblock.go | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/spec/versionedsignedbeaconblock.go b/spec/versionedsignedbeaconblock.go index 69a7ce51..d05fcd69 100644 --- a/spec/versionedsignedbeaconblock.go +++ b/spec/versionedsignedbeaconblock.go @@ -1017,6 +1017,32 @@ func (v *VersionedSignedBeaconBlock) BlobKZGCommitments() ([]deneb.KZGCommitment } } +// ExecutionRequests returs the execution requests for the block. +func (v *VersionedSignedBeaconBlock) ExecutionRequests() (*electra.ExecutionRequests, error) { + switch v.Version { + case DataVersionPhase0: + return nil, errors.New("phase0 block does not have execution requests") + case DataVersionAltair: + return nil, errors.New("altair block does not have execution requests") + case DataVersionBellatrix: + return nil, errors.New("bellatrix block does not have execution requests") + case DataVersionCapella: + return nil, errors.New("capella block does not have execution requests") + case DataVersionDeneb: + return nil, errors.New("deneb block does not have execution requests") + case DataVersionElectra: + if v.Electra == nil || + v.Electra.Message == nil || + v.Electra.Message.Body == nil { + return nil, errors.New("no electra block") + } + + return v.Electra.Message.Body.ExecutionRequests, nil + default: + return nil, errors.New("unknown version") + } +} + // String returns a string version of the structure. func (v *VersionedSignedBeaconBlock) String() string { switch v.Version { From 1de34c7df4bf726636fa3dc670f539a49f7dd588 Mon Sep 17 00:00:00 2001 From: pk910 Date: Mon, 23 Sep 2024 19:48:07 +0200 Subject: [PATCH 09/11] regenerate ssz for `electra.BeaconBlockBody` --- spec/electra/attestation_ssz.go | 4 ++-- spec/electra/attesterslashing_ssz.go | 2 +- spec/electra/beaconblockbody_ssz.go | 15 +++++++++++++-- spec/electra/consolidationrequest_ssz.go | 4 +++- spec/electra/depositrequest_ssz.go | 2 +- spec/electra/executionrequests_ssz.go | 2 +- spec/electra/indexedattestation_ssz.go | 2 +- spec/electra/withdrawalrequest_ssz.go | 3 ++- 8 files changed, 24 insertions(+), 10 deletions(-) diff --git a/spec/electra/attestation_ssz.go b/spec/electra/attestation_ssz.go index 462fb9fe..899f6eb9 100644 --- a/spec/electra/attestation_ssz.go +++ b/spec/electra/attestation_ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 5a2d052da32c0d16b124cd692d1cc933fcbfc680beed934cdfa374656ab41afe +// Hash: 3a9a3226e05c9a4f4fe19244999dacfbc39962ae1ff5d0ae99f7634afef8ea5c // Version: 0.1.3 package electra @@ -135,7 +135,7 @@ func (a *Attestation) HashTreeRootWith(hh ssz.HashWalker) (err error) { return } - // Field (3) 'Signature' + // Field (2) 'Signature' hh.PutBytes(a.Signature[:]) // Field (3) 'CommitteeBits' diff --git a/spec/electra/attesterslashing_ssz.go b/spec/electra/attesterslashing_ssz.go index a5a6cad2..50cef347 100644 --- a/spec/electra/attesterslashing_ssz.go +++ b/spec/electra/attesterslashing_ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 7cf8a9d246b40208a079cd3bae3821d8d3f9b41f2c3852cf2b94f0cf8568b4c1 +// Hash: 3a9a3226e05c9a4f4fe19244999dacfbc39962ae1ff5d0ae99f7634afef8ea5c // Version: 0.1.3 package electra diff --git a/spec/electra/beaconblockbody_ssz.go b/spec/electra/beaconblockbody_ssz.go index 19a2a06a..2c0d8f7e 100644 --- a/spec/electra/beaconblockbody_ssz.go +++ b/spec/electra/beaconblockbody_ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 145f583ffefea9d2c418401980a7199f582dbe71558fe80f718fadd3931c034f +// Hash: 3a9a3226e05c9a4f4fe19244999dacfbc39962ae1ff5d0ae99f7634afef8ea5c // Version: 0.1.3 package electra @@ -84,6 +84,13 @@ func (b *BeaconBlockBody) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = ssz.WriteOffset(dst, offset) offset += len(b.BlobKZGCommitments) * 48 + // Offset (12) 'ExecutionRequests' + dst = ssz.WriteOffset(dst, offset) + if b.ExecutionRequests == nil { + b.ExecutionRequests = new(ExecutionRequests) + } + offset += b.ExecutionRequests.SizeSSZ() + // Field (3) 'ProposerSlashings' if size := len(b.ProposerSlashings); size > 16 { err = ssz.ErrListTooBigFn("BeaconBlockBody.ProposerSlashings", size, 16) @@ -178,6 +185,11 @@ func (b *BeaconBlockBody) MarshalSSZTo(buf []byte) (dst []byte, err error) { dst = append(dst, b.BlobKZGCommitments[ii][:]...) } + // Field (12) 'ExecutionRequests' + if dst, err = b.ExecutionRequests.MarshalSSZTo(dst); err != nil { + return + } + return } @@ -413,7 +425,6 @@ func (b *BeaconBlockBody) UnmarshalSSZ(buf []byte) error { return err } } - return err } diff --git a/spec/electra/consolidationrequest_ssz.go b/spec/electra/consolidationrequest_ssz.go index 51a0db22..7c5eeb90 100644 --- a/spec/electra/consolidationrequest_ssz.go +++ b/spec/electra/consolidationrequest_ssz.go @@ -1,9 +1,11 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: a0960436212943f5595c94087ee709d30a033a29aefc5236b2ea5582d783504c +// Hash: 3a9a3226e05c9a4f4fe19244999dacfbc39962ae1ff5d0ae99f7634afef8ea5c // Version: 0.1.3 package electra import ( + "github.com/attestantio/go-eth2-client/spec/bellatrix" + "github.com/attestantio/go-eth2-client/spec/phase0" ssz "github.com/ferranbt/fastssz" ) diff --git a/spec/electra/depositrequest_ssz.go b/spec/electra/depositrequest_ssz.go index 3dbca129..f8dbba47 100644 --- a/spec/electra/depositrequest_ssz.go +++ b/spec/electra/depositrequest_ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: a0960436212943f5595c94087ee709d30a033a29aefc5236b2ea5582d783504c +// Hash: 3a9a3226e05c9a4f4fe19244999dacfbc39962ae1ff5d0ae99f7634afef8ea5c // Version: 0.1.3 package electra diff --git a/spec/electra/executionrequests_ssz.go b/spec/electra/executionrequests_ssz.go index b31640f9..8f3f94fa 100644 --- a/spec/electra/executionrequests_ssz.go +++ b/spec/electra/executionrequests_ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: a0960436212943f5595c94087ee709d30a033a29aefc5236b2ea5582d783504c +// Hash: 3a9a3226e05c9a4f4fe19244999dacfbc39962ae1ff5d0ae99f7634afef8ea5c // Version: 0.1.3 package electra diff --git a/spec/electra/indexedattestation_ssz.go b/spec/electra/indexedattestation_ssz.go index 9ca0e7cc..f73f51cb 100644 --- a/spec/electra/indexedattestation_ssz.go +++ b/spec/electra/indexedattestation_ssz.go @@ -1,5 +1,5 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: 7cf8a9d246b40208a079cd3bae3821d8d3f9b41f2c3852cf2b94f0cf8568b4c1 +// Hash: 3a9a3226e05c9a4f4fe19244999dacfbc39962ae1ff5d0ae99f7634afef8ea5c // Version: 0.1.3 package electra diff --git a/spec/electra/withdrawalrequest_ssz.go b/spec/electra/withdrawalrequest_ssz.go index 1a21ce85..11b72f9f 100644 --- a/spec/electra/withdrawalrequest_ssz.go +++ b/spec/electra/withdrawalrequest_ssz.go @@ -1,9 +1,10 @@ // Code generated by fastssz. DO NOT EDIT. -// Hash: a0960436212943f5595c94087ee709d30a033a29aefc5236b2ea5582d783504c +// Hash: 3a9a3226e05c9a4f4fe19244999dacfbc39962ae1ff5d0ae99f7634afef8ea5c // Version: 0.1.3 package electra import ( + "github.com/attestantio/go-eth2-client/spec/bellatrix" "github.com/attestantio/go-eth2-client/spec/phase0" ssz "github.com/ferranbt/fastssz" ) From 8d64565c83cab91b2023fb889fcf2f48af466933 Mon Sep 17 00:00:00 2001 From: pk910 Date: Mon, 23 Sep 2024 19:49:43 +0200 Subject: [PATCH 10/11] fix unused imports --- spec/electra/consolidationrequest_ssz.go | 2 -- spec/electra/withdrawalrequest_ssz.go | 1 - 2 files changed, 3 deletions(-) diff --git a/spec/electra/consolidationrequest_ssz.go b/spec/electra/consolidationrequest_ssz.go index 7c5eeb90..e494e96b 100644 --- a/spec/electra/consolidationrequest_ssz.go +++ b/spec/electra/consolidationrequest_ssz.go @@ -4,8 +4,6 @@ package electra import ( - "github.com/attestantio/go-eth2-client/spec/bellatrix" - "github.com/attestantio/go-eth2-client/spec/phase0" ssz "github.com/ferranbt/fastssz" ) diff --git a/spec/electra/withdrawalrequest_ssz.go b/spec/electra/withdrawalrequest_ssz.go index 11b72f9f..7db570e9 100644 --- a/spec/electra/withdrawalrequest_ssz.go +++ b/spec/electra/withdrawalrequest_ssz.go @@ -4,7 +4,6 @@ package electra import ( - "github.com/attestantio/go-eth2-client/spec/bellatrix" "github.com/attestantio/go-eth2-client/spec/phase0" ssz "github.com/ferranbt/fastssz" ) From 01a8d4d899bb4f801918447bb14c18b123c4a8b2 Mon Sep 17 00:00:00 2001 From: pk910 Date: Wed, 25 Sep 2024 21:38:23 +0200 Subject: [PATCH 11/11] add missing files to generate.go --- spec/electra/generate.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/spec/electra/generate.go b/spec/electra/generate.go index ab93b0d6..f7536d21 100644 --- a/spec/electra/generate.go +++ b/spec/electra/generate.go @@ -15,6 +15,6 @@ package electra //nolint:revive // Need to `go install github.com/ferranbt/fastssz/sszgen@latest` for this to work. -//go:generate rm -f aggregateandproof_ssz.go attestation_ssz.go attesterslashing_ssz.go beaconblockbody_ssz.go beaconblock_ssz.go beaconstate_ssz.go consolidation_ssz.go depositreceipt_ssz.go executionlayerwithdrawalrequest_ssz.go executionpayload_ssz.go executionpayloadheader_ssz.go pendingbalancedeposit_ssz.go pendingconsolidation_ssz.go pendingpartialwithdrawal_ssz.go signedaggregateandproof_ssz.go signedbeaconblock_ssz.go -//go:generate sszgen --suffix=ssz --path . --include ../phase0,../altair,../bellatrix,../capella,../deneb --objs AggregateAndProof,Attestation,AttesterSlashing,BeaconBlockBody,BeaconBlock,BeaconState,Consolidation,DepositReceipt,ExecutionLayerWithdrawalRequest,ExecutionRequests,PendingBalanceDeposit,PendingConsolidation,PendingPartialWithdrawal,SignedAggregateAndProof,SignedBeaconBlock -//go:generate goimports -w aggregateandproof_ssz.go attestation_ssz.go attesterslashing_ssz.go beaconblockbody_ssz.go beaconblock_ssz.go beaconstate_ssz.go consolidation_ssz.go depositreceipt_ssz.go executionlayerwithdrawalrequest_ssz.go executionpayload_ssz.go executionpayloadheader_ssz.go pendingbalancedeposit_ssz.go pendingconsolidation_ssz.go pendingpartialwithdrawal_ssz.go signedaggregateandproof_ssz.go signedbeaconblock_ssz.go +//go:generate rm -f aggregateandproof_ssz.go attestation_ssz.go attesterslashing_ssz.go beaconblockbody_ssz.go beaconblock_ssz.go beaconstate_ssz.go consolidation_ssz.go consolidationrequest_ssz.go depositrequest_ssz.go withdrawalrequest_ssz.go executionrequests_ssz.go pendingbalancedeposit_ssz.go pendingconsolidation_ssz.go pendingpartialwithdrawal_ssz.go signedaggregateandproof_ssz.go signedbeaconblock_ssz.go +//go:generate sszgen --suffix=ssz --path . --include ../phase0,../altair,../bellatrix,../capella,../deneb --objs AggregateAndProof,Attestation,AttesterSlashing,BeaconBlockBody,BeaconBlock,BeaconState,Consolidation,ConsolidationRequest,DepositRequest,WithdrawalRequest,ExecutionRequests,PendingBalanceDeposit,PendingConsolidation,PendingPartialWithdrawal,SignedAggregateAndProof,SignedBeaconBlock +//go:generate goimports -w aggregateandproof_ssz.go attestation_ssz.go attesterslashing_ssz.go beaconblockbody_ssz.go beaconblock_ssz.go beaconstate_ssz.go consolidation_ssz.go consolidationrequest_ssz.go depositrequest_ssz.go withdrawalrequest_ssz.go executionrequests_ssz.go pendingbalancedeposit_ssz.go pendingconsolidation_ssz.go pendingpartialwithdrawal_ssz.go signedaggregateandproof_ssz.go signedbeaconblock_ssz.go