Compare commits

...

1 Commits

Author SHA1 Message Date
terence
27b45bdc7b Edit to validator self build 2026-02-17 13:13:03 -08:00
4 changed files with 50 additions and 53 deletions

View File

@@ -393,7 +393,6 @@ func (c *grpcValidatorClient) EnsureReady(ctx context.Context) bool {
}
// Gloas Fork Methods
func (c *grpcValidatorClient) GetExecutionPayloadEnvelope(ctx context.Context, slot primitives.Slot, builderIndex primitives.BuilderIndex) (*ethpb.ExecutionPayloadEnvelope, error) {
req := &ethpb.ExecutionPayloadEnvelopeRequest{
Slot: slot,

View File

@@ -177,29 +177,9 @@ func (v *validator) ProposeBlock(ctx context.Context, slot primitives.Slot, pubK
return
}
// For Gloas, retrieve, sign, and publish the execution payload envelope after
// broadcasting the block. The envelope's state root is lazily computed by the
// beacon node using the post-block state, so the block must be submitted first.
if blk.Version() >= version.Gloas {
envelope, err := v.getExecutionPayloadEnvelope(ctx, slot, b)
if err != nil {
log.WithError(err).Error("Failed to get execution payload envelope")
if v.emitAccountMetrics {
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
}
return
}
signedEnvelope, err := v.signExecutionPayloadEnvelope(ctx, pubKey, slot, envelope)
if err != nil {
log.WithError(err).Error("Failed to sign execution payload envelope")
if v.emitAccountMetrics {
ValidatorProposeFailVec.WithLabelValues(fmtKey).Inc()
}
return
}
if _, err := v.validatorClient.PublishExecutionPayloadEnvelope(ctx, signedEnvelope); err != nil {
log.WithError(err).Error("Failed to publish execution payload envelope")
}
if err := v.proposeSelfBuildEnvelope(ctx, slot, pubKey, blk); err != nil {
log.WithError(err).Error("Failed to propose self-build envelope")
return
}
span.SetAttributes(

View File

@@ -6,38 +6,18 @@ import (
"github.com/OffchainLabs/prysm/v7/beacon-chain/core/signing"
fieldparams "github.com/OffchainLabs/prysm/v7/config/fieldparams"
"github.com/OffchainLabs/prysm/v7/config/params"
"github.com/OffchainLabs/prysm/v7/consensus-types/interfaces"
"github.com/OffchainLabs/prysm/v7/consensus-types/primitives"
"github.com/OffchainLabs/prysm/v7/monitoring/tracing/trace"
ethpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1"
validatorpb "github.com/OffchainLabs/prysm/v7/proto/prysm/v1alpha1/validator-client"
"github.com/OffchainLabs/prysm/v7/runtime/version"
"github.com/OffchainLabs/prysm/v7/time/slots"
"github.com/pkg/errors"
)
// getExecutionPayloadEnvelope retrieves the execution payload envelope from the
// beacon node for the given block's builder index and slot.
func (v *validator) getExecutionPayloadEnvelope(
ctx context.Context,
slot primitives.Slot,
b *ethpb.GenericBeaconBlock,
) (*ethpb.ExecutionPayloadEnvelope, error) {
ctx, span := trace.StartSpan(ctx, "validator.getExecutionPayloadEnvelope")
defer span.End()
gloasBlock := b.GetGloas()
if gloasBlock == nil {
return nil, errors.New("expected Gloas block but got nil")
}
if gloasBlock.Body == nil || gloasBlock.Body.SignedExecutionPayloadBid == nil || gloasBlock.Body.SignedExecutionPayloadBid.Message == nil {
return nil, errors.New("block missing signed execution payload bid")
}
builderIndex := gloasBlock.Body.SignedExecutionPayloadBid.Message.BuilderIndex
return v.validatorClient.GetExecutionPayloadEnvelope(ctx, slot, builderIndex)
}
// signExecutionPayloadEnvelope signs the execution payload envelope using the
// builder's key. The envelope is signed with DomainBeaconBuilder since it is
// proposer's key. The envelope is signed with DomainBeaconBuilder since it is
// a builder artifact — even in the self-build case where the proposer acts as
// their own builder.
func (v *validator) signExecutionPayloadEnvelope(
@@ -82,3 +62,41 @@ func (v *validator) signExecutionPayloadEnvelope(
Signature: sig.Marshal(),
}, nil
}
func (v *validator) proposeSelfBuildEnvelope(
ctx context.Context,
slot primitives.Slot,
pubKey [fieldparams.BLSPubkeyLength]byte,
blk interfaces.SignedBeaconBlock,
) error {
if blk.Version() < version.Gloas {
return nil
}
bid, err := blk.Block().Body().SignedExecutionPayloadBid()
if err != nil {
return err
}
if bid == nil || bid.Message == nil {
return errors.New("no execution payload bid found in block body")
}
if bid.Message.BuilderIndex != params.BeaconConfig().BuilderIndexSelfBuild {
return nil
}
envelope, err := v.validatorClient.GetExecutionPayloadEnvelope(ctx, slot, params.BeaconConfig().BuilderIndexSelfBuild)
if err != nil {
return errors.Wrap(err, "failed to get execution payload envelope for self-build")
}
signedEnvelope, err := v.signExecutionPayloadEnvelope(ctx, pubKey, slot, envelope)
if err != nil {
return errors.Wrap(err, "could not sign execution payload envelope")
}
if _, err := v.validatorClient.PublishExecutionPayloadEnvelope(ctx, signedEnvelope); err != nil {
return errors.Wrap(err, "failed to publish execution payload envelope")
}
return nil
}

View File

@@ -44,7 +44,7 @@ func TestExecutionPayloadEnvelope(t *testing.T) {
defer finish()
slot := primitives.Slot(100)
builderIndex := primitives.BuilderIndex(42)
builderIndex := params.BeaconConfig().BuilderIndexSelfBuild
expectedEnvelope := testExecutionPayloadEnvelope(slot, builderIndex)
@@ -68,7 +68,7 @@ func TestExecutionPayloadEnvelope(t *testing.T) {
},
}
envelope, err := validator.getExecutionPayloadEnvelope(t.Context(), slot, b)
envelope, err := validator.getSelfBuildExecutionPayloadEnvelope(t.Context(), slot, b)
require.NoError(t, err)
require.DeepEqual(t, expectedEnvelope, envelope)
}
@@ -81,7 +81,7 @@ func TestExecutionPayloadEnvelope_NilBlock(t *testing.T) {
Block: &ethpb.GenericBeaconBlock_Gloas{},
}
_, err := validator.getExecutionPayloadEnvelope(t.Context(), 1, b)
_, err := validator.getSelfBuildExecutionPayloadEnvelope(t.Context(), 1, b)
require.ErrorContains(t, "expected Gloas block but got nil", err)
}
@@ -98,7 +98,7 @@ func TestExecutionPayloadEnvelope_MissingBid(t *testing.T) {
},
}
_, err := validator.getExecutionPayloadEnvelope(t.Context(), 1, b)
_, err := validator.getSelfBuildExecutionPayloadEnvelope(t.Context(), 1, b)
require.ErrorContains(t, "block missing signed execution payload bid", err)
}
@@ -124,7 +124,7 @@ func TestExecutionPayloadEnvelope_ClientError(t *testing.T) {
},
}
_, err := validator.getExecutionPayloadEnvelope(t.Context(), 1, b)
_, err := validator.getSelfBuildExecutionPayloadEnvelope(t.Context(), 1, b)
require.ErrorContains(t, "connection refused", err)
}
@@ -250,7 +250,7 @@ func TestProposeBlock_Gloas_EnvelopeAfterBlock(t *testing.T) {
copy(pubKey[:], validatorKey.PublicKey().Marshal())
blk := util.NewBeaconBlockGloas()
builderIndex := blk.Block.Body.SignedExecutionPayloadBid.Message.BuilderIndex
builderIndex := params.BeaconConfig().BuilderIndexSelfBuild
gloasBlock := &ethpb.GenericBeaconBlock{
Block: &ethpb.GenericBeaconBlock_Gloas{