Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,5 @@ generate-jsons:

.PHONY: generate-ssz
generate-ssz:
@go generate ./qbft/
@go generate ./ssv/
@go generate ./types/
@bash ./scripts/generate_qbft_ssz.sh
@bash ./scripts/generate_types_ssz.sh
7 changes: 4 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ module github.com/ssvlabs/ssv-spec
go 1.22

require (
github.com/attestantio/go-eth2-client v0.24.0
// TODO: Update go-eth2-client when a stable version is released.
github.com/attestantio/go-eth2-client v0.26.1-0.20250829122455-ff89a2135a43
github.com/ethereum/go-ethereum v1.14.8
github.com/ferranbt/fastssz v0.1.4
github.com/google/go-cmp v0.6.0
Expand Down Expand Up @@ -49,9 +50,9 @@ require (
go.uber.org/multierr v1.11.0 // indirect
go.uber.org/zap v1.27.0 // indirect
golang.org/dl v0.0.0-20250116195134-55ca457114df // indirect
golang.org/x/crypto v0.32.0 // indirect
golang.org/x/crypto v0.33.0 // indirect
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 // indirect
golang.org/x/sys v0.29.0 // indirect
golang.org/x/sys v0.30.0 // indirect
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ github.com/attestantio/go-eth2-client v0.23.2-0.20250204090132-2e07a2cbc932 h1:J
github.com/attestantio/go-eth2-client v0.23.2-0.20250204090132-2e07a2cbc932/go.mod h1:/KTLN3WuH1xrJL7ZZrpBoWM1xCCihnFbzequD5L+83o=
github.com/attestantio/go-eth2-client v0.24.0 h1:lGVbcnhlBwRglt1Zs56JOCgXVyLWKFZOmZN8jKhE7Ws=
github.com/attestantio/go-eth2-client v0.24.0/go.mod h1:/KTLN3WuH1xrJL7ZZrpBoWM1xCCihnFbzequD5L+83o=
github.com/attestantio/go-eth2-client v0.26.1-0.20250829122455-ff89a2135a43 h1:v5l00W4U5WuYz6+Cux0URjN/VBKCupwzG6gCgRdn6Wo=
github.com/attestantio/go-eth2-client v0.26.1-0.20250829122455-ff89a2135a43/go.mod h1:fvULSL9WtNskkOB4i+Yyr6BKpNHXvmpGZj9969fCrfY=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o=
github.com/benbjohnson/clock v1.3.5/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
Expand Down Expand Up @@ -299,6 +301,8 @@ golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30=
golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M=
golang.org/x/crypto v0.32.0 h1:euUpcYgM8WcP71gNpTqQCn6rC2t6ULUPiOzfWaXVVfc=
golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus=
golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8=
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
Expand Down Expand Up @@ -335,6 +339,8 @@ golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
Expand Down
4 changes: 0 additions & 4 deletions qbft/generate.go

This file was deleted.

17 changes: 17 additions & 0 deletions scripts/generate_qbft_ssz.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/bash
set -e

echo "Generating SSZ encodings for qbft..."

cd qbft

# Remove old generated file
rm -f ./messages_encoding.go

# Generate messages encoding
echo "Generating messages_encoding.go..."
go run github.com/ferranbt/fastssz/sszgen --path messages.go \
--include ./types.go,../types/signer.go,../types/operator.go \
--exclude-objs OperatorID,ProcessingMessage

echo "QBFT SSZ generation complete!"
64 changes: 64 additions & 0 deletions scripts/generate_types_ssz.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#!/bin/bash
set -e

# Get the module directory dynamically
ETH2_CLIENT_DIR=$(go list -m -f '{{.Dir}}' github.com/attestantio/go-eth2-client)

if [ -z "$ETH2_CLIENT_DIR" ]; then
echo "Error: Could not find go-eth2-client module directory"
exit 1
fi

echo "Using go-eth2-client from: $ETH2_CLIENT_DIR"

cd types

# Remove old generated files
echo "Removing old generated files..."
rm -f ./operator_encoding.go
rm -f ./share_encoding.go
rm -f ./messages_encoding.go
rm -f ./beacon_types_encoding.go
rm -f ./partial_sig_message_encoding.go
rm -f ./consensus_data_encoding.go

# Generate operator encoding
echo "Generating operator_encoding.go..."
go run github.com/ferranbt/fastssz/sszgen --path operator.go \
--include ./committee_id.go,./domain_type.go \
--exclude-objs OperatorID

# Generate share encoding
echo "Generating share_encoding.go..."
go run github.com/ferranbt/fastssz/sszgen --path share.go \
--include "${ETH2_CLIENT_DIR}/spec/phase0,./operator.go,./messages.go,./signer.go,./domain_type.go"

# Generate messages encoding
echo "Generating messages_encoding.go..."
go run github.com/ferranbt/fastssz/sszgen --path messages.go \
--include ./operator.go \
--exclude-objs ValidatorPK,MessageID,MsgType,ShareValidatorPK

# Generate beacon types encoding
echo "Generating beacon_types_encoding.go..."
go run github.com/ferranbt/fastssz/sszgen --path beacon_types.go \
--include "${ETH2_CLIENT_DIR}/spec/phase0" \
--exclude-objs BeaconNetwork,BeaconRole,CommitteeDuty

# Generate partial sig message encoding
echo "Generating partial_sig_message_encoding.go..."
go run github.com/ferranbt/fastssz/sszgen --path partial_sig_message.go \
--include "${ETH2_CLIENT_DIR}/spec/phase0,./signer.go,./operator.go" \
--exclude-objs PartialSigMsgType

# Generate consensus data encoding
echo "Generating consensus_data_encoding.go..."
go run github.com/ferranbt/fastssz/sszgen --path consensus_data.go \
--include "./operator.go,./signer.go,./partial_sig_message.go,./beacon_types.go,${ETH2_CLIENT_DIR}/spec/phase0,${ETH2_CLIENT_DIR}/spec,${ETH2_CLIENT_DIR}/spec/altair" \
--exclude-objs Contributions,BeaconNetwork,BeaconRole

# Format the generated consensus data encoding
echo "Formatting consensus_data_encoding.go..."
go run golang.org/x/tools/cmd/goimports@latest -w consensus_data_encoding.go

echo "Types SSZ generation complete!"
6 changes: 6 additions & 0 deletions ssv/aggregator.go
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,12 @@ func constructVersionedSignedAggregateAndProof(aggregateAndProof spec.VersionedA
Message: aggregateAndProof.Electra,
Signature: signature,
}
case spec.DataVersionFulu:
ret.Fulu = &electra.SignedAggregateAndProof{
Message: aggregateAndProof.Fulu,
Signature: signature,
}

default:
return nil, errors.New("unknown version for signed aggregate and proof")
}
Expand Down
13 changes: 10 additions & 3 deletions ssv/committee_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
ssz "github.com/ferranbt/fastssz"
"github.com/pkg/errors"
"github.com/prysmaticlabs/go-bitfield"

"github.com/ssvlabs/ssv-spec/qbft"
"github.com/ssvlabs/ssv-spec/types"
)
Expand Down Expand Up @@ -511,7 +512,6 @@ func constructAttestationData(vote *types.BeaconVote, duty *types.ValidatorDuty,
}

func VersionedAttestationWithSignature(att *spec.VersionedAttestation, specSig phase0.BLSSignature) (*spec.VersionedAttestation, error) {

switch att.Version {
case spec.DataVersionPhase0:
if att.Phase0 == nil {
Expand Down Expand Up @@ -543,8 +543,13 @@ func VersionedAttestationWithSignature(att *spec.VersionedAttestation, specSig p
return att, errors.New("no Electra attestation")
}
att.Electra.Signature = specSig
case spec.DataVersionFulu:
if att.Fulu == nil {
return att, errors.New("no Fulu attestation")
}
att.Fulu.Signature = specSig
default:
return att, errors.New("unknown version")
return nil, errors.Errorf("unknown version: %s", att.Version)
}

return att, nil
Expand Down Expand Up @@ -574,7 +579,6 @@ func ConstructElectraAttestationWithoutSignature(attestationData *phase0.Attesta
}

func ConstructVersionedAttestationWithoutSignature(attestationData *phase0.AttestationData, dataVersion spec.DataVersion, validatorDuty *types.ValidatorDuty) (*spec.VersionedAttestation, error) {

ret := &spec.VersionedAttestation{
Version: dataVersion,
ValidatorIndex: &validatorDuty.ValidatorIndex,
Expand All @@ -599,6 +603,9 @@ func ConstructVersionedAttestationWithoutSignature(attestationData *phase0.Attes
case spec.DataVersionElectra:
ret.Electra = ConstructElectraAttestationWithoutSignature(attestationData, validatorDuty)
return ret, nil
case spec.DataVersionFulu:
ret.Fulu = ConstructElectraAttestationWithoutSignature(attestationData, validatorDuty)
return ret, nil
default:
return nil, errors.New("unknown version")
}
Expand Down
59 changes: 11 additions & 48 deletions ssv/proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ func (r *ProposerRunner) ProcessPreConsensus(signedMsg *types.PartialSignatureMe
duty := r.GetState().StartingDuty.(*types.ValidatorDuty)

// get block data
obj, ver, err := r.GetBeaconNode().GetBeaconBlock(duty.Slot, r.GetShare().Graffiti, fullSig)
vBlk, obj, err := r.GetBeaconNode().GetBeaconBlock(duty.Slot, r.GetShare().Graffiti, fullSig)
if err != nil {
return errors.Wrap(err, "failed to get Beacon block")
}
Expand All @@ -98,7 +98,7 @@ func (r *ProposerRunner) ProcessPreConsensus(signedMsg *types.PartialSignatureMe

input := &types.ValidatorConsensusData{
Duty: *duty,
Version: ver,
Version: vBlk.Version,
DataSSZ: byts,
}

Expand All @@ -124,16 +124,9 @@ func (r *ProposerRunner) ProcessConsensus(signedMsg *types.SignedSSVMessage) err
var blkToSign ssz.HashRoot

cd := decidedValue.(*types.ValidatorConsensusData)
if r.decidedBlindedBlock() {
_, blkToSign, err = cd.GetBlindedBlockData()
if err != nil {
return errors.Wrap(err, "could not get blinded block data")
}
} else {
_, blkToSign, err = cd.GetBlockData()
if err != nil {
return errors.Wrap(err, "could not get block data")
}
_, blkToSign, err = cd.GetBlockData()
if err != nil {
return errors.Wrap(err, "could not get block data")
}

msg, err := r.BaseRunner.signBeaconObject(r, r.BaseRunner.State.StartingDuty.(*types.ValidatorDuty), blkToSign,
Expand Down Expand Up @@ -206,42 +199,19 @@ func (r *ProposerRunner) ProcessPostConsensus(signedMsg *types.PartialSignatureM
if err != nil {
return errors.Wrap(err, "could not create consensus data")
}
if r.decidedBlindedBlock() {
vBlindedBlk, _, err := validatorConsensusData.GetBlindedBlockData()
if err != nil {
return errors.Wrap(err, "could not get blinded block")
}

if err := r.GetBeaconNode().SubmitBlindedBeaconBlock(vBlindedBlk, specSig); err != nil {
return errors.Wrap(err, "could not submit to Beacon chain reconstructed signed blinded Beacon block")
}
} else {
vBlk, _, err := validatorConsensusData.GetBlockData()
if err != nil {
return errors.Wrap(err, "could not get block")
}
vBlk, _, err := validatorConsensusData.GetBlockData()
if err != nil {
return errors.Wrap(err, "could not get block")
}

if err := r.GetBeaconNode().SubmitBeaconBlock(vBlk, specSig); err != nil {
return errors.Wrap(err, "could not submit to Beacon chain reconstructed signed Beacon block")
}
if err := r.GetBeaconNode().SubmitBeaconBlock(vBlk, specSig); err != nil {
return errors.Wrap(err, "could not submit to Beacon chain reconstructed signed Beacon block")
}
}
r.GetState().Finished = true
return nil
}

// decidedBlindedBlock returns true if decided value has a blinded block, false if regular block
// WARNING!! should be called after decided only
func (r *ProposerRunner) decidedBlindedBlock() bool {
validatorConsensusData := &types.ValidatorConsensusData{}
err := validatorConsensusData.Decode(r.GetState().DecidedValue)
if err != nil {
return false
}
_, _, err = validatorConsensusData.GetBlindedBlockData()
return err == nil
}

func (r *ProposerRunner) expectedPreConsensusRootsAndDomain() ([]ssz.HashRoot, phase0.DomainType, error) {
epoch := r.BaseRunner.BeaconNetwork.EstimatedEpochAtSlot(r.GetState().StartingDuty.DutySlot())
return []ssz.HashRoot{types.SSZUint64(epoch)}, types.DomainRandao, nil
Expand All @@ -254,13 +224,6 @@ func (r *ProposerRunner) expectedPostConsensusRootsAndDomain() ([]ssz.HashRoot,
if err != nil {
return nil, phase0.DomainType{}, errors.Wrap(err, "could not create consensus data")
}
if r.decidedBlindedBlock() {
_, data, err := validatorConsensusData.GetBlindedBlockData()
if err != nil {
return nil, phase0.DomainType{}, errors.Wrap(err, "could not get blinded block data")
}
return []ssz.HashRoot{data}, types.DomainProposer, nil
}

_, data, err := validatorConsensusData.GetBlockData()
if err != nil {
Expand Down
Loading