Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Start to add support for Electra #131

Merged
merged 9 commits into from
May 6, 2024
Merged
40 changes: 40 additions & 0 deletions api/v1/electra/blindedbeaconblock.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// 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/phase0"
"github.com/goccy/go-yaml"
)

// BlindedBeaconBlock represents a blinded beacon block.
type BlindedBeaconBlock struct {
Slot phase0.Slot
ProposerIndex phase0.ValidatorIndex
ParentRoot phase0.Root `ssz-size:"32"`
StateRoot phase0.Root `ssz-size:"32"`
Body *BlindedBeaconBlockBody
}

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

return string(data)
}
102 changes: 102 additions & 0 deletions api/v1/electra/blindedbeaconblock_json.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// 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/hex"
"encoding/json"
"fmt"
"strconv"
"strings"

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

// blindedBeaconBlockJSON is the spec representation of the struct.
type blindedBeaconBlockJSON struct {
Slot string `json:"slot"`
ProposerIndex string `json:"proposer_index"`
ParentRoot string `json:"parent_root"`
StateRoot string `json:"state_root"`
Body *BlindedBeaconBlockBody `json:"body"`
}

// MarshalJSON implements json.Marshaler.
func (b *BlindedBeaconBlock) MarshalJSON() ([]byte, error) {
return json.Marshal(&blindedBeaconBlockJSON{
Slot: fmt.Sprintf("%d", b.Slot),
ProposerIndex: fmt.Sprintf("%d", b.ProposerIndex),
ParentRoot: fmt.Sprintf("%#x", b.ParentRoot),
StateRoot: fmt.Sprintf("%#x", b.StateRoot),
Body: b.Body,
})
}

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

return b.unpack(&data)
}

func (b *BlindedBeaconBlock) unpack(data *blindedBeaconBlockJSON) error {
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")
}
b.Slot = phase0.Slot(slot)
if data.ProposerIndex == "" {
return errors.New("proposer index missing")
}
proposerIndex, err := strconv.ParseUint(data.ProposerIndex, 10, 64)
if err != nil {
return errors.Wrap(err, "invalid value for proposer index")
}
b.ProposerIndex = phase0.ValidatorIndex(proposerIndex)
if data.ParentRoot == "" {
return errors.New("parent root missing")
}
parentRoot, err := hex.DecodeString(strings.TrimPrefix(data.ParentRoot, "0x"))
if err != nil {
return errors.Wrap(err, "invalid value for parent root")
}
if len(parentRoot) != phase0.RootLength {
return errors.New("incorrect length for parent root")
}
copy(b.ParentRoot[:], parentRoot)
if data.StateRoot == "" {
return errors.New("state root missing")
}
stateRoot, err := hex.DecodeString(strings.TrimPrefix(data.StateRoot, "0x"))
if err != nil {
return errors.Wrap(err, "invalid value for state root")
}
if len(stateRoot) != phase0.RootLength {
return errors.New("incorrect length for state root")
}
copy(b.StateRoot[:], stateRoot)
if data.Body == nil {
return errors.New("body missing")
}
b.Body = data.Body

return nil
}
139 changes: 139 additions & 0 deletions api/v1/electra/blindedbeaconblock_ssz.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 57 additions & 0 deletions api/v1/electra/blindedbeaconblock_yaml.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// 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"
"fmt"

"github.com/goccy/go-yaml"
)

// blindedBeaconBlockYAML is the spec representation of the struct.
type blindedBeaconBlockYAML struct {
Slot uint64 `yaml:"slot"`
ProposerIndex uint64 `yaml:"proposer_index"`
ParentRoot string `yaml:"parent_root"`
StateRoot string `yaml:"state_root"`
Body *BlindedBeaconBlockBody `yaml:"body"`
}

// MarshalYAML implements yaml.Marshaler.
func (b *BlindedBeaconBlock) MarshalYAML() ([]byte, error) {
yamlBytes, err := yaml.MarshalWithOptions(&blindedBeaconBlockYAML{
Slot: uint64(b.Slot),
ProposerIndex: uint64(b.ProposerIndex),
ParentRoot: fmt.Sprintf("%#x", b.ParentRoot),
StateRoot: fmt.Sprintf("%#x", b.StateRoot),
Body: b.Body,
}, yaml.Flow(true))
if err != nil {
return nil, err
}

return bytes.ReplaceAll(yamlBytes, []byte(`"`), []byte(`'`)), nil
}

// UnmarshalYAML implements yaml.Unmarshaler.
func (b *BlindedBeaconBlock) UnmarshalYAML(input []byte) error {
// We unmarshal to the JSON struct to save on duplicate code.
var data blindedBeaconBlockJSON
if err := yaml.Unmarshal(input, &data); err != nil {
return err
}

return b.unpack(&data)
}
53 changes: 53 additions & 0 deletions api/v1/electra/blindedbeaconblockbody.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// 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/deneb"
"github.com/attestantio/go-eth2-client/spec/electra"

"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/goccy/go-yaml"
)

// BlindedBeaconBlockBody represents the body of a blinded beacon block.
type BlindedBeaconBlockBody struct {
RANDAOReveal phase0.BLSSignature `ssz-size:"96"`
ETH1Data *phase0.ETH1Data
Graffiti [32]byte `ssz-size:"32"`
ProposerSlashings []*phase0.ProposerSlashing `ssz-max:"16"`
AttesterSlashings []*phase0.AttesterSlashing `ssz-max:"1"`
Attestations []*electra.Attestation `ssz-max:"8"`
Deposits []*phase0.Deposit `ssz-max:"16"`
VoluntaryExits []*phase0.SignedVoluntaryExit `ssz-max:"16"`
SyncAggregate *altair.SyncAggregate
ExecutionPayloadHeader *electra.ExecutionPayloadHeader
BLSToExecutionChanges []*capella.SignedBLSToExecutionChange `ssz-max:"16"`
BlobKZGCommitments []deneb.KZGCommitment `ssz-max:"4096" ssz-size:"?,48"`
Consolidations []*electra.SignedConsolidation `ssz-max:"16"`
}

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

return string(data)
}
Loading
Loading