Skip to content

Commit

Permalink
core: unsigned data implementation for duty builder proposer (#817)
Browse files Browse the repository at this point in the history
- unsigned data implementation of blinded blocker proposer
- implementation of clone test
- Addition to random.go to generate random blinded block body and blinded block (required for clone test)

This touches core & testutil not sure on convention for PR header when this is the case - have gone with core for now

category: feature
ticket: #809
  • Loading branch information
ciaranmcveigh5 authored Jul 19, 2022
1 parent cdbf821 commit 97add9c
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 6 deletions.
86 changes: 86 additions & 0 deletions core/unsigneddata.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package core
import (
"encoding/json"

eth2api "github.com/attestantio/go-eth2-client/api"
eth2v1 "github.com/attestantio/go-eth2-client/api/v1"
"github.com/attestantio/go-eth2-client/spec"
"github.com/attestantio/go-eth2-client/spec/altair"
Expand All @@ -30,6 +31,7 @@ import (
var (
_ UnsignedData = AttestationData{}
_ UnsignedData = VersionedBeaconBlock{}
_ UnsignedData = VersionedBlindedBeaconBlock{}
)

// AttestationData wraps the eth2 attestation data and adds the original duty.
Expand Down Expand Up @@ -180,6 +182,83 @@ func (b *VersionedBeaconBlock) UnmarshalJSON(input []byte) error {
return nil
}

type VersionedBlindedBeaconBlock struct {
eth2api.VersionedBlindedBeaconBlock
}

// NewVersionedBlindedBeaconBlock validates and returns a new wrapped VersionedBlindedBeaconBlock.
func NewVersionedBlindedBeaconBlock(block *eth2api.VersionedBlindedBeaconBlock) (VersionedBlindedBeaconBlock, error) {
switch block.Version {
case spec.DataVersionBellatrix:
if block.Bellatrix == nil {
return VersionedBlindedBeaconBlock{}, errors.New("no bellatrix block")
}
default:
return VersionedBlindedBeaconBlock{}, errors.New("unknown version")
}

return VersionedBlindedBeaconBlock{VersionedBlindedBeaconBlock: *block}, nil
}

func (b VersionedBlindedBeaconBlock) Clone() (UnsignedData, error) {
var resp VersionedBlindedBeaconBlock
err := cloneJSONMarshaler(b, &resp)
if err != nil {
return nil, errors.Wrap(err, "clone block")
}

return resp, nil
}

func (b VersionedBlindedBeaconBlock) MarshalJSON() ([]byte, error) {
var marshaller json.Marshaler
switch b.Version {
// No block nil checks since `NewVersionedSignedBlindedBeaconBlock` assumed.
case spec.DataVersionBellatrix:
marshaller = b.Bellatrix
default:
return nil, errors.New("unknown version")
}

block, err := marshaller.MarshalJSON()
if err != nil {
return nil, errors.Wrap(err, "marshal block")
}

resp, err := json.Marshal(versionedRawBlockJSON{
Version: int(b.Version),
Block: block,
})
if err != nil {
return nil, errors.Wrap(err, "marshal wrapper")
}

return resp, nil
}

func (b *VersionedBlindedBeaconBlock) UnmarshalJSON(input []byte) error {
var raw versionedRawBlockJSON
if err := json.Unmarshal(input, &raw); err != nil {
return errors.Wrap(err, "unmarshal block")
}

resp := eth2api.VersionedBlindedBeaconBlock{Version: spec.DataVersion(raw.Version)}
switch resp.Version {
case spec.DataVersionBellatrix:
block := new(eth2v1.BlindedBeaconBlock)
if err := json.Unmarshal(raw.Block, &block); err != nil {
return errors.Wrap(err, "unmarshal bellatrix")
}
resp.Bellatrix = block
default:
return errors.New("unknown version")
}

*b = VersionedBlindedBeaconBlock{VersionedBlindedBeaconBlock: resp}

return nil
}

// UnmarshalUnsignedData returns an instantiated unsigned data based on the duty type.
// TODO(corver): Unexport once leadercast is removed or uses protobufs.
func UnmarshalUnsignedData(typ DutyType, data []byte) (UnsignedData, error) {
Expand All @@ -197,6 +276,13 @@ func UnmarshalUnsignedData(typ DutyType, data []byte) (UnsignedData, error) {
return nil, errors.Wrap(err, "unmarshal block")
}

return resp, nil
case DutyBuilderProposer:
var resp VersionedBlindedBeaconBlock
if err := json.Unmarshal(data, &resp); err != nil {
return nil, errors.Wrap(err, "unmarshal block")
}

return resp, nil
default:
return nil, errors.New("unsupported unsigned data duty type")
Expand Down
14 changes: 14 additions & 0 deletions core/unsigneddata_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,17 @@ func TestCloneVersionedBeaconBlock(t *testing.T) {

require.Equal(t, slot1, slot2)
}

func TestCloneVersionedBlindedBeaconBlock(t *testing.T) {
block := testutil.RandomCoreVersionBlindedBeaconBlock(t)
slot1, err := block.Slot()
require.NoError(t, err)

clone, err := block.Clone()
require.NoError(t, err)
block2 := clone.(core.VersionedBlindedBeaconBlock)
slot2, err := block2.Slot()
require.NoError(t, err)

require.Equal(t, slot1, slot2)
}
64 changes: 58 additions & 6 deletions testutil/random.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"strings"
"testing"

eth2api "github.com/attestantio/go-eth2-client/api"
eth2v1 "github.com/attestantio/go-eth2-client/api/v1"
"github.com/attestantio/go-eth2-client/spec"
"github.com/attestantio/go-eth2-client/spec/altair"
Expand Down Expand Up @@ -194,6 +195,50 @@ func RandomCoreVersionBeaconBlock(t *testing.T) core.VersionedBeaconBlock {
}
}

func RandomBellatrixBlindedBeaconBlock(t *testing.T) *eth2v1.BlindedBeaconBlock {
t.Helper()

return &eth2v1.BlindedBeaconBlock{
Slot: RandomSlot(),
ProposerIndex: RandomVIdx(),
ParentRoot: RandomRoot(),
StateRoot: RandomRoot(),
Body: RandomBellatrixBlindedBeaconBlockBody(t),
}
}

func RandomBellatrixBlindedBeaconBlockBody(t *testing.T) *eth2v1.BlindedBeaconBlockBody {
t.Helper()

return &eth2v1.BlindedBeaconBlockBody{
RANDAOReveal: RandomEth2Signature(),
ETH1Data: &eth2p0.ETH1Data{
DepositRoot: RandomRoot(),
DepositCount: 0,
BlockHash: RandomBytes32(),
},
Graffiti: RandomBytes32(),
ProposerSlashings: []*eth2p0.ProposerSlashing{},
AttesterSlashings: []*eth2p0.AttesterSlashing{},
Attestations: []*eth2p0.Attestation{RandomAttestation(), RandomAttestation()},
Deposits: []*eth2p0.Deposit{},
VoluntaryExits: []*eth2p0.SignedVoluntaryExit{},
SyncAggregate: RandomSyncAggregate(t),
ExecutionPayloadHeader: RandomExecutionPayloadHeader(),
}
}

func RandomCoreVersionBlindedBeaconBlock(t *testing.T) core.VersionedBlindedBeaconBlock {
t.Helper()

return core.VersionedBlindedBeaconBlock{
VersionedBlindedBeaconBlock: eth2api.VersionedBlindedBeaconBlock{
Version: spec.DataVersionBellatrix,
Bellatrix: RandomBellatrixBlindedBeaconBlock(t),
},
}
}

func RandomSyncAggregate(t *testing.T) *altair.SyncAggregate {
t.Helper()

Expand All @@ -209,22 +254,29 @@ func RandomSyncAggregate(t *testing.T) *altair.SyncAggregate {
func RandomExecutionPayLoad() *bellatrix.ExecutionPayload {
return &bellatrix.ExecutionPayload{
ParentHash: RandomArray32(),
FeeRecipient: bellatrix.ExecutionAddress{},
StateRoot: RandomArray32(),
ReceiptsRoot: RandomArray32(),
LogsBloom: [256]byte{},
PrevRandao: RandomArray32(),
BlockNumber: 0,
GasLimit: 0,
GasUsed: 0,
Timestamp: 0,
ExtraData: RandomBytes32(),
BaseFeePerGas: RandomArray32(),
BlockHash: RandomArray32(),
Transactions: []bellatrix.Transaction{},
}
}

func RandomExecutionPayloadHeader() *bellatrix.ExecutionPayloadHeader {
return &bellatrix.ExecutionPayloadHeader{
ParentHash: RandomArray32(),
StateRoot: RandomArray32(),
ReceiptsRoot: RandomArray32(),
PrevRandao: RandomArray32(),
ExtraData: RandomBytes32(),
BaseFeePerGas: RandomArray32(),
BlockHash: RandomArray32(),
TransactionsRoot: RandomArray32(),
}
}

func RandomAttestationDuty(t *testing.T) *eth2v1.AttesterDuty {
t.Helper()
return &eth2v1.AttesterDuty{
Expand Down

0 comments on commit 97add9c

Please sign in to comment.