mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-22 03:30:35 +00:00
5a66807989
* First take at updating everything to v5 * Patch gRPC gateway to use prysm v5 Fix patch * Update go ssz --------- Co-authored-by: Preston Van Loon <pvanloon@offchainlabs.com>
235 lines
7.4 KiB
Go
235 lines
7.4 KiB
Go
package util
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/prysmaticlabs/go-bitfield"
|
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing"
|
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time"
|
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/transition"
|
|
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
|
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
|
"github.com/prysmaticlabs/prysm/v5/config/params"
|
|
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
|
"github.com/prysmaticlabs/prysm/v5/crypto/bls"
|
|
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
|
v1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
|
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
|
)
|
|
|
|
// GenerateFullBlockCapella generates a fully valid Capella block with the requested parameters.
|
|
// Use BlockGenConfig to declare the conditions you would like the block generated under.
|
|
// This function modifies the passed state as follows:
|
|
|
|
func GenerateFullBlockCapella(
|
|
bState state.BeaconState,
|
|
privs []bls.SecretKey,
|
|
conf *BlockGenConfig,
|
|
slot primitives.Slot,
|
|
) (*ethpb.SignedBeaconBlockCapella, error) {
|
|
ctx := context.Background()
|
|
currentSlot := bState.Slot()
|
|
if currentSlot > slot {
|
|
return nil, fmt.Errorf("current slot in state is larger than given slot. %d > %d", currentSlot, slot)
|
|
}
|
|
bState = bState.Copy()
|
|
|
|
if conf == nil {
|
|
conf = &BlockGenConfig{}
|
|
}
|
|
|
|
var err error
|
|
var pSlashings []*ethpb.ProposerSlashing
|
|
numToGen := conf.NumProposerSlashings
|
|
if numToGen > 0 {
|
|
pSlashings, err = generateProposerSlashings(bState, privs, numToGen)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed generating %d proposer slashings:", numToGen)
|
|
}
|
|
}
|
|
|
|
numToGen = conf.NumAttesterSlashings
|
|
var aSlashings []*ethpb.AttesterSlashing
|
|
if numToGen > 0 {
|
|
aSlashings, err = generateAttesterSlashings(bState, privs, numToGen)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed generating %d attester slashings:", numToGen)
|
|
}
|
|
}
|
|
|
|
numToGen = conf.NumAttestations
|
|
var atts []*ethpb.Attestation
|
|
if numToGen > 0 {
|
|
atts, err = GenerateAttestations(bState, privs, numToGen, slot, false)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed generating %d attestations:", numToGen)
|
|
}
|
|
}
|
|
|
|
numToGen = conf.NumDeposits
|
|
var newDeposits []*ethpb.Deposit
|
|
eth1Data := bState.Eth1Data()
|
|
if numToGen > 0 {
|
|
newDeposits, eth1Data, err = generateDepositsAndEth1Data(bState, numToGen)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed generating %d deposits:", numToGen)
|
|
}
|
|
}
|
|
|
|
numToGen = conf.NumVoluntaryExits
|
|
var exits []*ethpb.SignedVoluntaryExit
|
|
if numToGen > 0 {
|
|
exits, err = generateVoluntaryExits(bState, privs, numToGen)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "failed generating %d attester slashings:", numToGen)
|
|
}
|
|
}
|
|
|
|
numToGen = conf.NumTransactions
|
|
newTransactions := make([][]byte, numToGen)
|
|
for i := uint64(0); i < numToGen; i++ {
|
|
newTransactions[i] = bytesutil.Uint64ToBytesLittleEndian(i)
|
|
}
|
|
newWithdrawals := make([]*v1.Withdrawal, 0)
|
|
|
|
random, err := helpers.RandaoMix(bState, time.CurrentEpoch(bState))
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process randao mix")
|
|
}
|
|
|
|
timestamp, err := slots.ToTime(bState.GenesisTime(), slot)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not get current timestamp")
|
|
}
|
|
|
|
stCopy := bState.Copy()
|
|
stCopy, err = transition.ProcessSlots(context.Background(), stCopy, slot)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
parentExecution, err := stCopy.LatestExecutionPayloadHeader()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
blockHash := indexToHash(uint64(slot))
|
|
newExecutionPayloadCapella := &v1.ExecutionPayloadCapella{
|
|
ParentHash: parentExecution.BlockHash(),
|
|
FeeRecipient: make([]byte, 20),
|
|
StateRoot: params.BeaconConfig().ZeroHash[:],
|
|
ReceiptsRoot: params.BeaconConfig().ZeroHash[:],
|
|
LogsBloom: make([]byte, 256),
|
|
PrevRandao: random,
|
|
BlockNumber: uint64(slot),
|
|
ExtraData: params.BeaconConfig().ZeroHash[:],
|
|
BaseFeePerGas: params.BeaconConfig().ZeroHash[:],
|
|
BlockHash: blockHash[:],
|
|
Timestamp: uint64(timestamp.Unix()),
|
|
Transactions: newTransactions,
|
|
Withdrawals: newWithdrawals,
|
|
}
|
|
var syncCommitteeBits []byte
|
|
currSize := new(ethpb.SyncAggregate).SyncCommitteeBits.Len()
|
|
switch currSize {
|
|
case 512:
|
|
syncCommitteeBits = bitfield.NewBitvector512()
|
|
case 32:
|
|
syncCommitteeBits = bitfield.NewBitvector32()
|
|
default:
|
|
return nil, errors.New("invalid bit vector size")
|
|
}
|
|
newSyncAggregate := ðpb.SyncAggregate{
|
|
SyncCommitteeBits: syncCommitteeBits,
|
|
SyncCommitteeSignature: append([]byte{0xC0}, make([]byte, 95)...),
|
|
}
|
|
|
|
newHeader := bState.LatestBlockHeader()
|
|
prevStateRoot, err := bState.HashTreeRoot(ctx)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not hash state")
|
|
}
|
|
newHeader.StateRoot = prevStateRoot[:]
|
|
parentRoot, err := newHeader.HashTreeRoot()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not hash the new header")
|
|
}
|
|
|
|
if slot == currentSlot {
|
|
slot = currentSlot + 1
|
|
}
|
|
|
|
reveal, err := RandaoReveal(stCopy, time.CurrentEpoch(stCopy), privs)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not compute randao reveal")
|
|
}
|
|
|
|
idx, err := helpers.BeaconProposerIndex(ctx, stCopy)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not compute beacon proposer index")
|
|
}
|
|
|
|
changes := make([]*ethpb.SignedBLSToExecutionChange, conf.NumBLSChanges)
|
|
for i := uint64(0); i < conf.NumBLSChanges; i++ {
|
|
changes[i], err = GenerateBLSToExecutionChange(bState, privs[i+1], primitives.ValidatorIndex(i))
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
block := ðpb.BeaconBlockCapella{
|
|
Slot: slot,
|
|
ParentRoot: parentRoot[:],
|
|
ProposerIndex: idx,
|
|
Body: ðpb.BeaconBlockBodyCapella{
|
|
Eth1Data: eth1Data,
|
|
RandaoReveal: reveal,
|
|
ProposerSlashings: pSlashings,
|
|
AttesterSlashings: aSlashings,
|
|
Attestations: atts,
|
|
VoluntaryExits: exits,
|
|
Deposits: newDeposits,
|
|
Graffiti: make([]byte, fieldparams.RootLength),
|
|
SyncAggregate: newSyncAggregate,
|
|
ExecutionPayload: newExecutionPayloadCapella,
|
|
BlsToExecutionChanges: changes,
|
|
},
|
|
}
|
|
|
|
// The fork can change after processing the state
|
|
signature, err := BlockSignature(bState, block, privs)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not compute block signature")
|
|
}
|
|
|
|
return ðpb.SignedBeaconBlockCapella{Block: block, Signature: signature.Marshal()}, nil
|
|
}
|
|
|
|
// GenerateBLSToExecutionChange generates a valid bls to exec changae for validator `val` and its private key `priv` with the given beacon state `st`.
|
|
func GenerateBLSToExecutionChange(st state.BeaconState, priv bls.SecretKey, val primitives.ValidatorIndex) (*ethpb.SignedBLSToExecutionChange, error) {
|
|
cred := indexToHash(uint64(val))
|
|
pubkey := priv.PublicKey().Marshal()
|
|
message := ðpb.BLSToExecutionChange{
|
|
ToExecutionAddress: cred[12:],
|
|
ValidatorIndex: val,
|
|
FromBlsPubkey: pubkey,
|
|
}
|
|
c := params.BeaconConfig()
|
|
domain, err := signing.ComputeDomain(c.DomainBLSToExecutionChange, c.GenesisForkVersion, st.GenesisValidatorsRoot())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
sr, err := signing.ComputeSigningRoot(message, domain)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
signature := priv.Sign(sr[:]).Marshal()
|
|
return ðpb.SignedBLSToExecutionChange{
|
|
Message: message,
|
|
Signature: signature,
|
|
}, nil
|
|
}
|