package validator import ( "context" "fmt" types "github.com/prysmaticlabs/eth2-types" "github.com/prysmaticlabs/prysm/beacon-chain/core/transition/interop" "github.com/prysmaticlabs/prysm/config/params" "github.com/prysmaticlabs/prysm/crypto/bls" "github.com/prysmaticlabs/prysm/encoding/bytesutil" ethpb "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1" synccontribution "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/attestation/aggregation/sync_contribution" "github.com/prysmaticlabs/prysm/proto/prysm/v1alpha1/wrapper" "go.opencensus.io/trace" ) func (vs *Server) getAltairBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (*ethpb.BeaconBlockAltair, error) { ctx, span := trace.StartSpan(ctx, "ProposerServer.getAltairBeaconBlock") defer span.End() blkData, err := vs.buildPhase0BlockData(ctx, req) if err != nil { return nil, fmt.Errorf("could not build block data: %v", err) } // Use zero hash as stub for state root to compute later. stateRoot := params.BeaconConfig().ZeroHash[:] // No need for safe sub as req.Slot cannot be 0 if requesting Altair blocks. If 0, we will be throwing // an error in the first validity check of this endpoint. syncAggregate, err := vs.getSyncAggregate(ctx, req.Slot-1, bytesutil.ToBytes32(blkData.ParentRoot)) if err != nil { return nil, err } blk := ðpb.BeaconBlockAltair{ Slot: req.Slot, ParentRoot: blkData.ParentRoot, StateRoot: stateRoot, ProposerIndex: blkData.ProposerIdx, Body: ðpb.BeaconBlockBodyAltair{ Eth1Data: blkData.Eth1Data, Deposits: blkData.Deposits, Attestations: blkData.Attestations, RandaoReveal: req.RandaoReveal, ProposerSlashings: blkData.ProposerSlashings, AttesterSlashings: blkData.AttesterSlashings, VoluntaryExits: blkData.VoluntaryExits, Graffiti: blkData.Graffiti[:], SyncAggregate: syncAggregate, }, } // Compute state root with the newly constructed block. wsb, err := wrapper.WrappedAltairSignedBeaconBlock( ðpb.SignedBeaconBlockAltair{Block: blk, Signature: make([]byte, 96)}, ) if err != nil { return nil, err } stateRoot, err = vs.computeStateRoot(ctx, wsb) if err != nil { interop.WriteBlockToDisk(wsb, true /*failed*/) return nil, fmt.Errorf("could not compute state root: %v", err) } blk.StateRoot = stateRoot return blk, nil } // getSyncAggregate retrieves the sync contributions from the pool to construct the sync aggregate object. // The contributions are filtered based on matching of the input root and slot then profitability. func (vs *Server) getSyncAggregate(ctx context.Context, slot types.Slot, root [32]byte) (*ethpb.SyncAggregate, error) { _, span := trace.StartSpan(ctx, "ProposerServer.getSyncAggregate") defer span.End() // Contributions have to match the input root contributions, err := vs.SyncCommitteePool.SyncCommitteeContributions(slot) if err != nil { return nil, err } proposerContributions := proposerSyncContributions(contributions).filterByBlockRoot(root) // Each sync subcommittee is 128 bits and the sync committee is 512 bits for mainnet. var bitsHolder [][]byte for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSubnetCount; i++ { bitsHolder = append(bitsHolder, ethpb.NewSyncCommitteeAggregationBits()) } sigsHolder := make([]bls.Signature, 0, params.BeaconConfig().SyncCommitteeSize/params.BeaconConfig().SyncCommitteeSubnetCount) for i := uint64(0); i < params.BeaconConfig().SyncCommitteeSubnetCount; i++ { cs := proposerContributions.filterBySubIndex(i) aggregates, err := synccontribution.Aggregate(cs) if err != nil { return nil, err } // Retrieve the most profitable contribution deduped, err := proposerSyncContributions(aggregates).dedup() if err != nil { return nil, err } c := deduped.mostProfitable() if c == nil { continue } bitsHolder[i] = c.AggregationBits sig, err := bls.SignatureFromBytes(c.Signature) if err != nil { return nil, err } sigsHolder = append(sigsHolder, sig) } // Aggregate all the contribution bits and signatures. var syncBits []byte for _, b := range bitsHolder { syncBits = append(syncBits, b...) } syncSig := bls.AggregateSignatures(sigsHolder) var syncSigBytes [96]byte if syncSig == nil { syncSigBytes = [96]byte{0xC0} // Infinity signature if itself is nil. } else { syncSigBytes = bytesutil.ToBytes96(syncSig.Marshal()) } return ðpb.SyncAggregate{ SyncCommitteeBits: syncBits, SyncCommitteeSignature: syncSigBytes[:], }, nil }