Proposer builds block in parallel. (Consensus vs Execution) (#12297)

* Proposer builds block in parallel. Cosensus vs Execution

* Update beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>

* Use feature flag

---------

Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com>
This commit is contained in:
terencechain
2023-05-01 07:37:26 -07:00
committed by GitHub
parent 83416f31a5
commit 5b8084b829
3 changed files with 103 additions and 33 deletions

View File

@@ -5,6 +5,7 @@ import (
"encoding/hex"
"fmt"
"strings"
"sync"
"time"
"github.com/ethereum/go-ethereum/common"
@@ -18,6 +19,8 @@ import (
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/transition"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/db/kv"
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v4/config/features"
"github.com/prysmaticlabs/prysm/v4/config/params"
"github.com/prysmaticlabs/prysm/v4/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v4/consensus-types/interfaces"
@@ -82,25 +85,6 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
sBlk.SetRandaoReveal(req.RandaoReveal)
sBlk.SetParentRoot(parentRoot[:])
// Set eth1 data.
eth1Data, err := vs.eth1DataMajorityVote(ctx, head)
if err != nil {
eth1Data = &ethpb.Eth1Data{DepositRoot: params.BeaconConfig().ZeroHash[:], BlockHash: params.BeaconConfig().ZeroHash[:]}
log.WithError(err).Error("Could not get eth1data")
}
sBlk.SetEth1Data(eth1Data)
// Set deposit and attestation.
deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data) // TODO: split attestations and deposits
if err != nil {
sBlk.SetDeposits([]*ethpb.Deposit{})
sBlk.SetAttestations([]*ethpb.Attestation{})
log.WithError(err).Error("Could not pack deposits and attestations")
} else {
sBlk.SetDeposits(deposits)
sBlk.SetAttestations(atts)
}
// Set proposer index.
idx, err := helpers.BeaconProposerIndex(ctx, head)
if err != nil {
@@ -108,25 +92,50 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
}
sBlk.SetProposerIndex(idx)
// Set slashings.
validProposerSlashings, validAttSlashings := vs.getSlashings(ctx, head)
sBlk.SetProposerSlashings(validProposerSlashings)
sBlk.SetAttesterSlashings(validAttSlashings)
if features.Get().BuildBlockParallel {
if err := vs.BuildBlockParallel(ctx, sBlk, head); err != nil {
return nil, errors.Wrap(err, "could not build block in parallel")
}
} else {
// Set eth1 data.
eth1Data, err := vs.eth1DataMajorityVote(ctx, head)
if err != nil {
eth1Data = &ethpb.Eth1Data{DepositRoot: params.BeaconConfig().ZeroHash[:], BlockHash: params.BeaconConfig().ZeroHash[:]}
log.WithError(err).Error("Could not get eth1data")
}
sBlk.SetEth1Data(eth1Data)
// Set exits.
sBlk.SetVoluntaryExits(vs.getExits(head, req.Slot))
// Set deposit and attestation.
deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data) // TODO: split attestations and deposits
if err != nil {
sBlk.SetDeposits([]*ethpb.Deposit{})
sBlk.SetAttestations([]*ethpb.Attestation{})
log.WithError(err).Error("Could not pack deposits and attestations")
} else {
sBlk.SetDeposits(deposits)
sBlk.SetAttestations(atts)
}
// Set sync aggregate. New in Altair.
vs.setSyncAggregate(ctx, sBlk)
// Set slashings.
validProposerSlashings, validAttSlashings := vs.getSlashings(ctx, head)
sBlk.SetProposerSlashings(validProposerSlashings)
sBlk.SetAttesterSlashings(validAttSlashings)
// Set execution data. New in Bellatrix.
if err := vs.setExecutionData(ctx, sBlk, head); err != nil {
return nil, status.Errorf(codes.Internal, "Could not set execution data: %v", err)
// Set exits.
sBlk.SetVoluntaryExits(vs.getExits(head, req.Slot))
// Set sync aggregate. New in Altair.
vs.setSyncAggregate(ctx, sBlk)
// Set execution data. New in Bellatrix.
if err := vs.setExecutionData(ctx, sBlk, head); err != nil {
return nil, status.Errorf(codes.Internal, "Could not set execution data: %v", err)
}
// Set bls to execution change. New in Capella.
vs.setBlsToExecData(sBlk, head)
}
// Set bls to execution change. New in Capella.
vs.setBlsToExecData(sBlk, head)
sr, err := vs.computeStateRoot(ctx, sBlk)
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not compute state root: %v", err)
@@ -155,6 +164,56 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
return &ethpb.GenericBeaconBlock{Block: &ethpb.GenericBeaconBlock_Phase0{Phase0: pb.(*ethpb.BeaconBlock)}}, nil
}
func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.SignedBeaconBlock, head state.BeaconState) error {
// Build consensus fields in background
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
// Set eth1 data.
eth1Data, err := vs.eth1DataMajorityVote(ctx, head)
if err != nil {
eth1Data = &ethpb.Eth1Data{DepositRoot: params.BeaconConfig().ZeroHash[:], BlockHash: params.BeaconConfig().ZeroHash[:]}
log.WithError(err).Error("Could not get eth1data")
}
sBlk.SetEth1Data(eth1Data)
// Set deposit and attestation.
deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data) // TODO: split attestations and deposits
if err != nil {
sBlk.SetDeposits([]*ethpb.Deposit{})
sBlk.SetAttestations([]*ethpb.Attestation{})
log.WithError(err).Error("Could not pack deposits and attestations")
} else {
sBlk.SetDeposits(deposits)
sBlk.SetAttestations(atts)
}
// Set slashings.
validProposerSlashings, validAttSlashings := vs.getSlashings(ctx, head)
sBlk.SetProposerSlashings(validProposerSlashings)
sBlk.SetAttesterSlashings(validAttSlashings)
// Set exits.
sBlk.SetVoluntaryExits(vs.getExits(head, sBlk.Block().Slot()))
// Set sync aggregate. New in Altair.
vs.setSyncAggregate(ctx, sBlk)
// Set bls to execution change. New in Capella.
vs.setBlsToExecData(sBlk, head)
}()
if err := vs.setExecutionData(ctx, sBlk, head); err != nil {
return status.Errorf(codes.Internal, "Could not set execution data: %v", err)
}
wg.Wait() // Wait until block is built via consensus and execution fields.
return nil
}
// ProposeBeaconBlock is called by a proposer during its assigned slot to create a block in an attempt
// to get it processed by the beacon node as the canonical head.
func (vs *Server) ProposeBeaconBlock(ctx context.Context, req *ethpb.GenericSignedBeaconBlock) (*ethpb.ProposeResponse, error) {

View File

@@ -67,6 +67,8 @@ type Flags struct {
PrepareAllPayloads bool // PrepareAllPayloads informs the engine to prepare a block on every slot.
BuildBlockParallel bool // BuildBlockParallel builds beacon block for proposer in parallel.
// KeystoreImportDebounceInterval specifies the time duration the validator waits to reload new keys if they have
// changed on disk. This feature is for advanced use cases only.
KeystoreImportDebounceInterval time.Duration
@@ -212,6 +214,10 @@ func ConfigureBeaconChain(ctx *cli.Context) error {
logEnabled(prepareAllPayloads)
cfg.PrepareAllPayloads = true
}
if ctx.IsSet(buildBlockParallel.Name) {
logEnabled(buildBlockParallel)
cfg.BuildBlockParallel = true
}
Init(cfg)
return nil
}

View File

@@ -118,6 +118,10 @@ var (
Name: "prepare-all-payloads",
Usage: "Informs the engine to prepare all local payloads. Useful for relayers and builders",
}
buildBlockParallel = &cli.BoolFlag{
Name: "build-block-parallel",
Usage: "Builds a beacon block in parallel for consensus and execution. It results in faster block construction time",
}
)
// devModeFlags holds list of flags that are set when development mode is on.
@@ -164,6 +168,7 @@ var BeaconChainFlags = append(deprecatedBeaconFlags, append(deprecatedFlags, []c
enableVerboseSigVerification,
enableOptionalEngineMethods,
prepareAllPayloads,
buildBlockParallel,
}...)...)
// E2EBeaconChainFlags contains a list of the beacon chain feature flags to be tested in E2E.