Skip to content
Draft
Show file tree
Hide file tree
Changes from all 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
12 changes: 3 additions & 9 deletions api/epbsproposalopts.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
package api

import (
"github.com/attestantio/go-eth2-client/spec/gloas"
"github.com/attestantio/go-eth2-client/spec/phase0"
)

Expand All @@ -35,6 +36,8 @@ type EPBSProposalOpts struct {
// SkipRandaoVerification is true if we do not want the server to verify our RANDAO reveal.
// If this is set then the RANDAO reveal should be passed as the point at infinity (0xc0…00)
SkipRandaoVerification bool
// BuilderConfig supplies the required P2P and direct-builder bid policy.
BuilderConfig *gloas.BuilderConfig
// IncludePayload selects whether a self-built proposal carries its execution
// payload envelope and blobs.
//
Expand All @@ -59,13 +62,4 @@ type EPBSProposalOpts struct {
// there is no safe value to assume on the caller's behalf, and leaving it
// unset is rejected rather than silently resolved to the constraining mode.
IncludePayload *bool
// BuilderBoostFactor is the relative weight of the builder payload versus a locally-produced
// payload, as per https://ethereum.github.io/beacon-APIs/#/Validator/produceBlockV4
//
// This is optional, and when it is not supplied the parameter is left off the
// request entirely, leaving the choice to the node. Note that differs from
// ProposalOpts, which materialises 100 client-side: the spec states no
// default for either endpoint, so sending nothing is what actually leaves the
// decision where the caller left it.
BuilderBoostFactor *uint64
}
3 changes: 3 additions & 0 deletions api/submitproposalopts.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,7 @@ type SubmitProposalOpts struct {

// BroadcastValidation is the validation required of the consensus node before broadcasting the proposal.
BroadcastValidation *apiv2.BroadcastValidation

// BuilderURL is the optional direct-builder route returned by block production.
BuilderURL string
}
19 changes: 9 additions & 10 deletions api/versionedepbsproposal.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ type VersionedEPBSProposal struct {
Version spec.DataVersion
// ExecutionPayloadIncluded selects which arm below carries the proposal.
ExecutionPayloadIncluded bool
BuilderIndex *gloas.BuilderIndex
ConsensusValue *big.Int
ExecutionValue *big.Int
// Gloas is the proposal when the execution payload is not included.
Expand Down Expand Up @@ -202,21 +203,19 @@ func (v *VersionedEPBSProposal) Blobs() ([]deneb.Blob, error) {
return contents.Blobs, nil
}

// Value returns the total value of the proposal: the consensus rewards plus the
// execution payload value. Both components are populated from response headers
// that a node may omit, so both are treated as zero when absent.
// Value returns the total value of the proposal, or nil when its execution
// value was not supplied by the beacon node.
func (v *VersionedEPBSProposal) Value() *big.Int {
value := big.NewInt(0)

if v.ConsensusValue != nil {
value = value.Add(value, v.ConsensusValue)
if v.ExecutionValue == nil {
return nil
}

if v.ExecutionValue != nil {
value = value.Add(value, v.ExecutionValue)
value := big.NewInt(0)
if v.ConsensusValue != nil {
value.Add(value, v.ConsensusValue)
}

return value
return value.Add(value, v.ExecutionValue)
}

// IsEmpty returns true if no proposal is populated.
Expand Down
26 changes: 14 additions & 12 deletions api/versionedepbsproposal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -408,40 +408,40 @@ func TestVersionedEPBSProposalBodyRoot(t *testing.T) {
block := newBlock(0x01)
wantBodyRoot, err := block.Body.HashTreeRoot()
require.NoError(t, err)
bodyRoot := phase0.Root(wantBodyRoot)
blockRoot, err := block.HashTreeRoot()
require.NoError(t, err)
require.NotEqual(t, bodyRoot, phase0.Root(blockRoot))
require.NotEqual(t, phase0.Root(wantBodyRoot), phase0.Root(blockRoot))

root := phase0.Root(wantBodyRoot)
got, err := (&api.VersionedEPBSProposal{
Version: spec.DataVersionGloas,
Gloas: block,
BeaconBlockBodyRoot: &bodyRoot,
BeaconBlockBodyRoot: &root,
}).BodyRoot()
require.NoError(t, err)
require.NotEqual(t, phase0.Root{}, got)
require.Equal(t, bodyRoot, got)
require.Equal(t, phase0.Root(wantBodyRoot), got)
require.NotEqual(t, phase0.Root(blockRoot), got)
})

t.Run("PayloadIncluded", func(t *testing.T) {
block := newBlock(0x02)
wantBodyRoot, err := block.Body.HashTreeRoot()
require.NoError(t, err)
bodyRoot := phase0.Root(wantBodyRoot)
blockRoot, err := block.HashTreeRoot()
require.NoError(t, err)
require.NotEqual(t, bodyRoot, phase0.Root(blockRoot))
require.NotEqual(t, phase0.Root(wantBodyRoot), phase0.Root(blockRoot))

root := phase0.Root(wantBodyRoot)
got, err := (&api.VersionedEPBSProposal{
Version: spec.DataVersionGloas,
ExecutionPayloadIncluded: true,
GloasContents: &apiv1gloas.BlockContents{Block: block},
BeaconBlockBodyRoot: &bodyRoot,
BeaconBlockBodyRoot: &root,
}).BodyRoot()
require.NoError(t, err)
require.NotEqual(t, phase0.Root{}, got)
require.Equal(t, bodyRoot, got)
require.Equal(t, phase0.Root(wantBodyRoot), got)
require.NotEqual(t, phase0.Root(blockRoot), got)
})

Expand Down Expand Up @@ -677,8 +677,10 @@ func TestVersionedEPBSProposalContents(t *testing.T) {
})
}

// TestVersionedEPBSProposalValue verifies the two reward components are summed
// nil-safely. Both are populated from response headers that a node may omit.
// TestVersionedEPBSProposalValue verifies the total is unknown -- nil -- unless
// the execution value arrived, and that a missing consensus value counts as
// zero rather than poisoning a known execution value. Both components are
// populated from response headers that a node may omit.
func TestVersionedEPBSProposalValue(t *testing.T) {
tests := []struct {
name string
Expand All @@ -687,8 +689,8 @@ func TestVersionedEPBSProposalValue(t *testing.T) {
expected *big.Int
}{
{name: "Both", consensus: big.NewInt(3), execution: big.NewInt(4), expected: big.NewInt(7)},
{name: "NeitherSet", expected: big.NewInt(0)},
{name: "ConsensusOnly", consensus: big.NewInt(5), expected: big.NewInt(5)},
{name: "NeitherSet"},
{name: "ConsensusOnly", consensus: big.NewInt(5)},
{name: "ExecutionOnly", execution: big.NewInt(6), expected: big.NewInt(6)},
}

Expand Down
2 changes: 2 additions & 0 deletions http/epbsguardwiring_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import (

client "github.com/attestantio/go-eth2-client"
"github.com/attestantio/go-eth2-client/api"
"github.com/attestantio/go-eth2-client/spec/gloas"
"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -99,6 +100,7 @@ func TestEPBSProposalRejectsADisagreeingNode(t *testing.T) {
_, err := s.EPBSProposal(ctx, &api.EPBSProposalOpts{
Slot: slot,
RandaoReveal: reveal,
BuilderConfig: &gloas.BuilderConfig{Builders: []*gloas.BuilderEntry{}},
IncludePayload: &includePayload,
})
require.ErrorIs(t, err, client.ErrInconsistentResult)
Expand Down
Loading