mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-10 22:07:59 -05:00
Compare commits
31 Commits
votes_in_p
...
readonly-p
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6791dd2367 | ||
|
|
a4d13611ad | ||
|
|
030bf62da3 | ||
|
|
fa6688c3ec | ||
|
|
f5799372b6 | ||
|
|
ab4a563bb1 | ||
|
|
7badaf7b4d | ||
|
|
572a9d3d65 | ||
|
|
02dce037dc | ||
|
|
f2a2189203 | ||
|
|
173dcab20c | ||
|
|
152612eaec | ||
|
|
9c452a6b0e | ||
|
|
720a9b7491 | ||
|
|
0b9169f42c | ||
|
|
6dfbdad1aa | ||
|
|
e5b25071f9 | ||
|
|
498ee635e1 | ||
|
|
c238c00630 | ||
|
|
3eacc37831 | ||
|
|
5267b4b4d4 | ||
|
|
ec84a1b49c | ||
|
|
afb7383225 | ||
|
|
a00b40fa81 | ||
|
|
365c6252ba | ||
|
|
7c81c7da90 | ||
|
|
f8950c8c40 | ||
|
|
18be899aef | ||
|
|
9dc3b645c4 | ||
|
|
318561999d | ||
|
|
ae5b0b4391 |
@@ -98,6 +98,8 @@ func ProcessVoluntaryExits(
|
||||
// assert get_current_epoch(state) >= voluntary_exit.epoch
|
||||
// # Verify the validator has been active long enough
|
||||
// assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
|
||||
// # Only exit validator if it has no pending withdrawals in the queue
|
||||
// assert get_pending_balance_to_withdraw(state, voluntary_exit.validator_index) == 0 # [New in Electra:EIP7251]
|
||||
// # Verify signature
|
||||
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
|
||||
// signing_root = compute_signing_root(voluntary_exit, domain)
|
||||
@@ -113,7 +115,6 @@ func VerifyExitAndSignature(
|
||||
return errors.New("nil exit")
|
||||
}
|
||||
|
||||
currentSlot := state.Slot()
|
||||
fork := state.Fork()
|
||||
genesisRoot := state.GenesisValidatorsRoot()
|
||||
|
||||
@@ -128,7 +129,7 @@ func VerifyExitAndSignature(
|
||||
}
|
||||
|
||||
exit := signed.Exit
|
||||
if err := verifyExitConditions(validator, currentSlot, exit); err != nil {
|
||||
if err := verifyExitConditions(state, validator, exit); err != nil {
|
||||
return err
|
||||
}
|
||||
domain, err := signing.Domain(fork, exit.Epoch, params.BeaconConfig().DomainVoluntaryExit, genesisRoot)
|
||||
@@ -157,14 +158,16 @@ func VerifyExitAndSignature(
|
||||
// assert get_current_epoch(state) >= voluntary_exit.epoch
|
||||
// # Verify the validator has been active long enough
|
||||
// assert get_current_epoch(state) >= validator.activation_epoch + SHARD_COMMITTEE_PERIOD
|
||||
// # Only exit validator if it has no pending withdrawals in the queue
|
||||
// assert get_pending_balance_to_withdraw(state, voluntary_exit.validator_index) == 0 # [New in Electra:EIP7251]
|
||||
// # Verify signature
|
||||
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
|
||||
// signing_root = compute_signing_root(voluntary_exit, domain)
|
||||
// assert bls.Verify(validator.pubkey, signing_root, signed_voluntary_exit.signature)
|
||||
// # Initiate exit
|
||||
// initiate_validator_exit(state, voluntary_exit.validator_index)
|
||||
func verifyExitConditions(validator state.ReadOnlyValidator, currentSlot primitives.Slot, exit *ethpb.VoluntaryExit) error {
|
||||
currentEpoch := slots.ToEpoch(currentSlot)
|
||||
func verifyExitConditions(st state.ReadOnlyBeaconState, validator state.ReadOnlyValidator, exit *ethpb.VoluntaryExit) error {
|
||||
currentEpoch := slots.ToEpoch(st.Slot())
|
||||
// Verify the validator is active.
|
||||
if !helpers.IsActiveValidatorUsingTrie(validator, currentEpoch) {
|
||||
return errors.New("non-active validator cannot exit")
|
||||
@@ -187,5 +190,17 @@ func verifyExitConditions(validator state.ReadOnlyValidator, currentSlot primiti
|
||||
validator.ActivationEpoch()+params.BeaconConfig().ShardCommitteePeriod,
|
||||
)
|
||||
}
|
||||
|
||||
if st.Version() >= version.Electra {
|
||||
// Only exit validator if it has no pending withdrawals in the queue.
|
||||
ok, err := st.HasPendingBalanceToWithdraw(exit.ValidatorIndex)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to retrieve pending balance to withdraw for validator %d: %w", exit.ValidatorIndex, err)
|
||||
}
|
||||
if ok {
|
||||
return fmt.Errorf("validator %d must have no pending balance to withdraw", exit.ValidatorIndex)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -135,6 +135,11 @@ func TestProcessVoluntaryExits_AppliesCorrectStatus(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestVerifyExitAndSignature(t *testing.T) {
|
||||
// Remove after electra fork epoch is defined.
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.ElectraForkEpoch = cfg.DenebForkEpoch * 2
|
||||
params.SetActiveTestCleanup(t, cfg)
|
||||
// End remove section.
|
||||
denebSlot, err := slots.EpochStart(params.BeaconConfig().DenebForkEpoch)
|
||||
require.NoError(t, err)
|
||||
tests := []struct {
|
||||
@@ -167,7 +172,7 @@ func TestVerifyExitAndSignature(t *testing.T) {
|
||||
wantErr: "nil exit",
|
||||
},
|
||||
{
|
||||
name: "Happy Path",
|
||||
name: "Happy Path phase0",
|
||||
setup: func() (*ethpb.Validator, *ethpb.SignedVoluntaryExit, state.ReadOnlyBeaconState, error) {
|
||||
fork := ðpb.Fork{
|
||||
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
|
||||
@@ -275,6 +280,52 @@ func TestVerifyExitAndSignature(t *testing.T) {
|
||||
return validator, signedExit, bs, nil
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "EIP-7251 - pending balance to withdraw must be zero",
|
||||
setup: func() (*ethpb.Validator, *ethpb.SignedVoluntaryExit, state.ReadOnlyBeaconState, error) {
|
||||
fork := ðpb.Fork{
|
||||
PreviousVersion: params.BeaconConfig().DenebForkVersion,
|
||||
CurrentVersion: params.BeaconConfig().ElectraForkVersion,
|
||||
Epoch: params.BeaconConfig().ElectraForkEpoch,
|
||||
}
|
||||
signedExit := ðpb.SignedVoluntaryExit{
|
||||
Exit: ðpb.VoluntaryExit{
|
||||
Epoch: params.BeaconConfig().DenebForkEpoch + 1,
|
||||
ValidatorIndex: 0,
|
||||
},
|
||||
}
|
||||
electraSlot, err := slots.EpochStart(params.BeaconConfig().ElectraForkEpoch)
|
||||
require.NoError(t, err)
|
||||
bs, keys := util.DeterministicGenesisState(t, 1)
|
||||
bs, err = state_native.InitializeFromProtoUnsafeElectra(ðpb.BeaconStateElectra{
|
||||
GenesisValidatorsRoot: bs.GenesisValidatorsRoot(),
|
||||
Fork: fork,
|
||||
Slot: electraSlot,
|
||||
Validators: bs.Validators(),
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
validator := bs.Validators()[0]
|
||||
validator.ActivationEpoch = 1
|
||||
err = bs.UpdateValidatorAtIndex(0, validator)
|
||||
require.NoError(t, err)
|
||||
sb, err := signing.ComputeDomainAndSign(bs, signedExit.Exit.Epoch, signedExit.Exit, params.BeaconConfig().DomainVoluntaryExit, keys[0])
|
||||
require.NoError(t, err)
|
||||
sig, err := bls.SignatureFromBytes(sb)
|
||||
require.NoError(t, err)
|
||||
signedExit.Signature = sig.Marshal()
|
||||
|
||||
// Give validator a pending balance to withdraw.
|
||||
require.NoError(t, bs.AppendPendingPartialWithdrawal(ðpb.PendingPartialWithdrawal{
|
||||
Index: 0,
|
||||
Amount: 500,
|
||||
}))
|
||||
|
||||
return validator, signedExit, bs, nil
|
||||
},
|
||||
wantErr: "validator 0 must have no pending balance to withdraw",
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
|
||||
@@ -120,32 +120,35 @@ func ValidateBLSToExecutionChange(st state.ReadOnlyBeaconState, signed *ethpb.Si
|
||||
//
|
||||
// Spec pseudocode definition:
|
||||
//
|
||||
// def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
|
||||
// def process_withdrawals(state: BeaconState, payload: ExecutionPayload) -> None:
|
||||
// expected_withdrawals, partial_withdrawals_count = get_expected_withdrawals(state) # [Modified in Electra:EIP7251]
|
||||
//
|
||||
// expected_withdrawals = get_expected_withdrawals(state)
|
||||
// assert len(payload.withdrawals) == len(expected_withdrawals)
|
||||
// assert len(payload.withdrawals) == len(expected_withdrawals)
|
||||
//
|
||||
// for expected_withdrawal, withdrawal in zip(expected_withdrawals, payload.withdrawals):
|
||||
// assert withdrawal == expected_withdrawal
|
||||
// decrease_balance(state, withdrawal.validator_index, withdrawal.amount)
|
||||
// for expected_withdrawal, withdrawal in zip(expected_withdrawals, payload.withdrawals):
|
||||
// assert withdrawal == expected_withdrawal
|
||||
// decrease_balance(state, withdrawal.validator_index, withdrawal.amount)
|
||||
//
|
||||
// # Update the next withdrawal index if this block contained withdrawals
|
||||
// if len(expected_withdrawals) != 0:
|
||||
// latest_withdrawal = expected_withdrawals[-1]
|
||||
// state.next_withdrawal_index = WithdrawalIndex(latest_withdrawal.index + 1)
|
||||
// # Update pending partial withdrawals [New in Electra:EIP7251]
|
||||
// state.pending_partial_withdrawals = state.pending_partial_withdrawals[partial_withdrawals_count:]
|
||||
//
|
||||
// # Update the next validator index to start the next withdrawal sweep
|
||||
// if len(expected_withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
||||
// # Next sweep starts after the latest withdrawal's validator index
|
||||
// next_validator_index = ValidatorIndex((expected_withdrawals[-1].validator_index + 1) % len(state.validators))
|
||||
// state.next_withdrawal_validator_index = next_validator_index
|
||||
// else:
|
||||
// # Advance sweep by the max length of the sweep if there was not a full set of withdrawals
|
||||
// next_index = state.next_withdrawal_validator_index + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP
|
||||
// next_validator_index = ValidatorIndex(next_index % len(state.validators))
|
||||
// state.next_withdrawal_validator_index = next_validator_index
|
||||
// # Update the next withdrawal index if this block contained withdrawals
|
||||
// if len(expected_withdrawals) != 0:
|
||||
// latest_withdrawal = expected_withdrawals[-1]
|
||||
// state.next_withdrawal_index = WithdrawalIndex(latest_withdrawal.index + 1)
|
||||
//
|
||||
// # Update the next validator index to start the next withdrawal sweep
|
||||
// if len(expected_withdrawals) == MAX_WITHDRAWALS_PER_PAYLOAD:
|
||||
// # Next sweep starts after the latest withdrawal's validator index
|
||||
// next_validator_index = ValidatorIndex((expected_withdrawals[-1].validator_index + 1) % len(state.validators))
|
||||
// state.next_withdrawal_validator_index = next_validator_index
|
||||
// else:
|
||||
// # Advance sweep by the max length of the sweep if there was not a full set of withdrawals
|
||||
// next_index = state.next_withdrawal_validator_index + MAX_VALIDATORS_PER_WITHDRAWALS_SWEEP
|
||||
// next_validator_index = ValidatorIndex(next_index % len(state.validators))
|
||||
// state.next_withdrawal_validator_index = next_validator_index
|
||||
func ProcessWithdrawals(st state.BeaconState, executionData interfaces.ExecutionData) (state.BeaconState, error) {
|
||||
expectedWithdrawals, _, err := st.ExpectedWithdrawals()
|
||||
expectedWithdrawals, partialWithdrawalsCount, err := st.ExpectedWithdrawals()
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get expected withdrawals")
|
||||
}
|
||||
@@ -162,6 +165,11 @@ func ProcessWithdrawals(st state.BeaconState, executionData interfaces.Execution
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get withdrawals")
|
||||
}
|
||||
|
||||
if len(wds) != len(expectedWithdrawals) {
|
||||
return nil, fmt.Errorf("execution payload header has %d withdrawals when %d were expected", len(wds), len(expectedWithdrawals))
|
||||
}
|
||||
|
||||
wdRoot, err = ssz.WithdrawalSliceRoot(wds, fieldparams.MaxWithdrawalsPerPayload)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not get withdrawals root")
|
||||
@@ -182,6 +190,13 @@ func ProcessWithdrawals(st state.BeaconState, executionData interfaces.Execution
|
||||
return nil, errors.Wrap(err, "could not decrease balance")
|
||||
}
|
||||
}
|
||||
|
||||
if st.Version() >= version.Electra {
|
||||
if err := st.DequeuePartialWithdrawals(partialWithdrawalsCount); err != nil {
|
||||
return nil, fmt.Errorf("unable to dequeue partial withdrawals from state: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if len(expectedWithdrawals) > 0 {
|
||||
if err := st.SetNextWithdrawalIndex(expectedWithdrawals[len(expectedWithdrawals)-1].Index + 1); err != nil {
|
||||
return nil, errors.Wrap(err, "could not set next withdrawal index")
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
consensusblocks "github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/crypto/bls"
|
||||
"github.com/prysmaticlabs/prysm/v5/crypto/bls/common"
|
||||
@@ -19,6 +20,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
)
|
||||
@@ -675,6 +677,7 @@ func TestProcessWithdrawals(t *testing.T) {
|
||||
FullWithdrawalIndices []primitives.ValidatorIndex
|
||||
PendingPartialWithdrawalIndices []primitives.ValidatorIndex
|
||||
Withdrawals []*enginev1.Withdrawal
|
||||
PendingPartialWithdrawals []*ethpb.PendingPartialWithdrawal // Electra
|
||||
}
|
||||
type control struct {
|
||||
NextWithdrawalValidatorIndex primitives.ValidatorIndex
|
||||
@@ -772,7 +775,7 @@ func TestProcessWithdrawals(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Args: args{
|
||||
Name: "Less than max sweep at end",
|
||||
Name: "less than max sweep at end",
|
||||
NextWithdrawalIndex: 22,
|
||||
NextWithdrawalValidatorIndex: 4,
|
||||
FullWithdrawalIndices: []primitives.ValidatorIndex{80, 81, 82, 83},
|
||||
@@ -789,7 +792,7 @@ func TestProcessWithdrawals(t *testing.T) {
|
||||
},
|
||||
{
|
||||
Args: args{
|
||||
Name: "Less than max sweep and beginning",
|
||||
Name: "less than max sweep and beginning",
|
||||
NextWithdrawalIndex: 22,
|
||||
NextWithdrawalValidatorIndex: 4,
|
||||
FullWithdrawalIndices: []primitives.ValidatorIndex{4, 5, 6},
|
||||
@@ -846,6 +849,36 @@ func TestProcessWithdrawals(t *testing.T) {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Args: args{
|
||||
Name: "success many withdrawals with pending partial withdrawals in state",
|
||||
NextWithdrawalIndex: 22,
|
||||
NextWithdrawalValidatorIndex: 88,
|
||||
FullWithdrawalIndices: []primitives.ValidatorIndex{7, 19, 28},
|
||||
PendingPartialWithdrawalIndices: []primitives.ValidatorIndex{2, 1, 89, 15},
|
||||
Withdrawals: []*enginev1.Withdrawal{
|
||||
PendingPartialWithdrawal(89, 22), PendingPartialWithdrawal(1, 23), PendingPartialWithdrawal(2, 24),
|
||||
fullWithdrawal(7, 25), PendingPartialWithdrawal(15, 26), fullWithdrawal(19, 27),
|
||||
fullWithdrawal(28, 28),
|
||||
},
|
||||
PendingPartialWithdrawals: []*ethpb.PendingPartialWithdrawal{
|
||||
{
|
||||
Index: 11,
|
||||
Amount: withdrawalAmount(11) - maxEffectiveBalance,
|
||||
},
|
||||
},
|
||||
},
|
||||
Control: control{
|
||||
NextWithdrawalValidatorIndex: 40,
|
||||
NextWithdrawalIndex: 29,
|
||||
Balances: map[uint64]uint64{
|
||||
7: 0, 19: 0, 28: 0,
|
||||
2: maxEffectiveBalance, 1: maxEffectiveBalance, 89: maxEffectiveBalance,
|
||||
15: maxEffectiveBalance,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
{
|
||||
Args: args{
|
||||
Name: "success more than max fully withdrawals",
|
||||
@@ -1011,65 +1044,97 @@ func TestProcessWithdrawals(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
prepareValidators := func(st *ethpb.BeaconStateCapella, arguments args) (state.BeaconState, error) {
|
||||
prepareValidators := func(st state.BeaconState, arguments args) error {
|
||||
validators := make([]*ethpb.Validator, numValidators)
|
||||
st.Balances = make([]uint64, numValidators)
|
||||
if err := st.SetBalances(make([]uint64, numValidators)); err != nil {
|
||||
return err
|
||||
}
|
||||
for i := range validators {
|
||||
v := ðpb.Validator{}
|
||||
v.EffectiveBalance = maxEffectiveBalance
|
||||
v.WithdrawableEpoch = epochInFuture
|
||||
v.WithdrawalCredentials = make([]byte, 32)
|
||||
v.WithdrawalCredentials[31] = byte(i)
|
||||
st.Balances[i] = v.EffectiveBalance - uint64(rand.Intn(1000))
|
||||
if err := st.UpdateBalancesAtIndex(primitives.ValidatorIndex(i), v.EffectiveBalance-uint64(rand.Intn(1000))); err != nil {
|
||||
return err
|
||||
}
|
||||
validators[i] = v
|
||||
}
|
||||
for _, idx := range arguments.FullWithdrawalIndices {
|
||||
if idx != notWithdrawableIndex {
|
||||
validators[idx].WithdrawableEpoch = epochInPast
|
||||
}
|
||||
st.Balances[idx] = withdrawalAmount(idx)
|
||||
if err := st.UpdateBalancesAtIndex(idx, withdrawalAmount(idx)); err != nil {
|
||||
return err
|
||||
}
|
||||
validators[idx].WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
}
|
||||
for _, idx := range arguments.PendingPartialWithdrawalIndices {
|
||||
validators[idx].WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
st.Balances[idx] = withdrawalAmount(idx)
|
||||
if err := st.UpdateBalancesAtIndex(idx, withdrawalAmount(idx)); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
st.Validators = validators
|
||||
return state_native.InitializeFromProtoCapella(st)
|
||||
return st.SetValidators(validators)
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.Args.Name, func(t *testing.T) {
|
||||
saved := params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep
|
||||
params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep = maxSweep
|
||||
if test.Args.Withdrawals == nil {
|
||||
test.Args.Withdrawals = make([]*enginev1.Withdrawal, 0)
|
||||
for _, fork := range []int{version.Capella, version.Electra} {
|
||||
t.Run(version.String(fork), func(t *testing.T) {
|
||||
saved := params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep
|
||||
params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep = maxSweep
|
||||
if test.Args.Withdrawals == nil {
|
||||
test.Args.Withdrawals = make([]*enginev1.Withdrawal, 0)
|
||||
}
|
||||
if test.Args.FullWithdrawalIndices == nil {
|
||||
test.Args.FullWithdrawalIndices = make([]primitives.ValidatorIndex, 0)
|
||||
}
|
||||
if test.Args.PendingPartialWithdrawalIndices == nil {
|
||||
test.Args.PendingPartialWithdrawalIndices = make([]primitives.ValidatorIndex, 0)
|
||||
}
|
||||
slot, err := slots.EpochStart(currentEpoch)
|
||||
require.NoError(t, err)
|
||||
var st state.BeaconState
|
||||
var p interfaces.ExecutionData
|
||||
switch fork {
|
||||
case version.Capella:
|
||||
spb := ðpb.BeaconStateCapella{
|
||||
Slot: slot,
|
||||
NextWithdrawalValidatorIndex: test.Args.NextWithdrawalValidatorIndex,
|
||||
NextWithdrawalIndex: test.Args.NextWithdrawalIndex,
|
||||
}
|
||||
st, err = state_native.InitializeFromProtoUnsafeCapella(spb)
|
||||
require.NoError(t, err)
|
||||
p, err = consensusblocks.WrappedExecutionPayloadCapella(&enginev1.ExecutionPayloadCapella{Withdrawals: test.Args.Withdrawals})
|
||||
require.NoError(t, err)
|
||||
case version.Electra:
|
||||
spb := ðpb.BeaconStateElectra{
|
||||
Slot: slot,
|
||||
NextWithdrawalValidatorIndex: test.Args.NextWithdrawalValidatorIndex,
|
||||
NextWithdrawalIndex: test.Args.NextWithdrawalIndex,
|
||||
PendingPartialWithdrawals: test.Args.PendingPartialWithdrawals,
|
||||
}
|
||||
st, err = state_native.InitializeFromProtoUnsafeElectra(spb)
|
||||
require.NoError(t, err)
|
||||
p, err = consensusblocks.WrappedExecutionPayloadElectra(&enginev1.ExecutionPayloadElectra{Withdrawals: test.Args.Withdrawals})
|
||||
require.NoError(t, err)
|
||||
default:
|
||||
t.Fatalf("Add a beacon state setup for version %s", version.String(fork))
|
||||
}
|
||||
err = prepareValidators(st, test.Args)
|
||||
require.NoError(t, err)
|
||||
post, err := blocks.ProcessWithdrawals(st, p)
|
||||
if test.Control.ExpectedError {
|
||||
require.NotNil(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
checkPostState(t, test.Control, post)
|
||||
}
|
||||
params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep = saved
|
||||
|
||||
})
|
||||
}
|
||||
if test.Args.FullWithdrawalIndices == nil {
|
||||
test.Args.FullWithdrawalIndices = make([]primitives.ValidatorIndex, 0)
|
||||
}
|
||||
if test.Args.PendingPartialWithdrawalIndices == nil {
|
||||
test.Args.PendingPartialWithdrawalIndices = make([]primitives.ValidatorIndex, 0)
|
||||
}
|
||||
slot, err := slots.EpochStart(currentEpoch)
|
||||
require.NoError(t, err)
|
||||
spb := ðpb.BeaconStateCapella{
|
||||
Slot: slot,
|
||||
NextWithdrawalValidatorIndex: test.Args.NextWithdrawalValidatorIndex,
|
||||
NextWithdrawalIndex: test.Args.NextWithdrawalIndex,
|
||||
}
|
||||
st, err := prepareValidators(spb, test.Args)
|
||||
require.NoError(t, err)
|
||||
p, err := consensusblocks.WrappedExecutionPayloadCapella(&enginev1.ExecutionPayloadCapella{Withdrawals: test.Args.Withdrawals})
|
||||
require.NoError(t, err)
|
||||
post, err := blocks.ProcessWithdrawals(st, p)
|
||||
if test.Control.ExpectedError {
|
||||
require.NotNil(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
checkPostState(t, test.Control, post)
|
||||
}
|
||||
params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep = saved
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package electra
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks"
|
||||
@@ -13,7 +14,9 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/contracts/deposit"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
@@ -190,12 +193,27 @@ func verifyDepositDataSigningRoot(obj *ethpb.Deposit_Data, domain []byte) error
|
||||
// available_for_processing = state.deposit_balance_to_consume + get_activation_exit_churn_limit(state)
|
||||
// processed_amount = 0
|
||||
// next_deposit_index = 0
|
||||
// deposits_to_postpone = []
|
||||
//
|
||||
// for deposit in state.pending_balance_deposits:
|
||||
// if processed_amount + deposit.amount > available_for_processing:
|
||||
// break
|
||||
// increase_balance(state, deposit.index, deposit.amount)
|
||||
// processed_amount += deposit.amount
|
||||
// validator = state.validators[deposit.index]
|
||||
// # Validator is exiting, postpone the deposit until after withdrawable epoch
|
||||
// if validator.exit_epoch < FAR_FUTURE_EPOCH:
|
||||
// if get_current_epoch(state) <= validator.withdrawable_epoch:
|
||||
// deposits_to_postpone.append(deposit)
|
||||
// # Deposited balance will never become active. Increase balance but do not consume churn
|
||||
// else:
|
||||
// increase_balance(state, deposit.index, deposit.amount)
|
||||
// # Validator is not exiting, attempt to process deposit
|
||||
// else:
|
||||
// # Deposit does not fit in the churn, no more deposit processing in this epoch.
|
||||
// if processed_amount + deposit.amount > available_for_processing:
|
||||
// break
|
||||
// # Deposit fits in the churn, process it. Increase balance and consume churn.
|
||||
// else:
|
||||
// increase_balance(state, deposit.index, deposit.amount)
|
||||
// processed_amount += deposit.amount
|
||||
// # Regardless of how the deposit was handled, we move on in the queue.
|
||||
// next_deposit_index += 1
|
||||
//
|
||||
// state.pending_balance_deposits = state.pending_balance_deposits[next_deposit_index:]
|
||||
@@ -204,6 +222,8 @@ func verifyDepositDataSigningRoot(obj *ethpb.Deposit_Data, domain []byte) error
|
||||
// state.deposit_balance_to_consume = Gwei(0)
|
||||
// else:
|
||||
// state.deposit_balance_to_consume = available_for_processing - processed_amount
|
||||
//
|
||||
// state.pending_balance_deposits += deposits_to_postpone
|
||||
func ProcessPendingBalanceDeposits(ctx context.Context, st state.BeaconState, activeBalance primitives.Gwei) error {
|
||||
_, span := trace.StartSpan(ctx, "electra.ProcessPendingBalanceDeposits")
|
||||
defer span.End()
|
||||
@@ -216,35 +236,69 @@ func ProcessPendingBalanceDeposits(ctx context.Context, st state.BeaconState, ac
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
availableForProcessing := depBalToConsume + helpers.ActivationExitChurnLimit(activeBalance)
|
||||
processedAmount := uint64(0)
|
||||
nextDepositIndex := 0
|
||||
var depositsToPostpone []*eth.PendingBalanceDeposit
|
||||
|
||||
deposits, err := st.PendingBalanceDeposits()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// constants
|
||||
ffe := params.BeaconConfig().FarFutureEpoch
|
||||
curEpoch := slots.ToEpoch(st.Slot())
|
||||
|
||||
for _, balanceDeposit := range deposits {
|
||||
if primitives.Gwei(balanceDeposit.Amount) > availableForProcessing {
|
||||
break
|
||||
v, err := st.ValidatorAtIndexReadOnly(balanceDeposit.Index)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to fetch validator at index: %w", err)
|
||||
}
|
||||
if err := helpers.IncreaseBalance(st, balanceDeposit.Index, balanceDeposit.Amount); err != nil {
|
||||
return err
|
||||
|
||||
// If the validator is currently exiting, postpone the deposit until after the withdrawable
|
||||
// epoch.
|
||||
if v.ExitEpoch() < ffe {
|
||||
if curEpoch <= v.WithdrawableEpoch() {
|
||||
depositsToPostpone = append(depositsToPostpone, balanceDeposit)
|
||||
} else {
|
||||
// The deposited balance will never become active. Therefore, we increase the balance but do
|
||||
// not consume the churn.
|
||||
if err := helpers.IncreaseBalance(st, balanceDeposit.Index, balanceDeposit.Amount); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Validator is not exiting, attempt to process deposit.
|
||||
if primitives.Gwei(processedAmount+balanceDeposit.Amount) > availableForProcessing {
|
||||
break
|
||||
}
|
||||
// Deposit fits in churn, process it. Increase balance and consume churn.
|
||||
if err := helpers.IncreaseBalance(st, balanceDeposit.Index, balanceDeposit.Amount); err != nil {
|
||||
return err
|
||||
}
|
||||
processedAmount += balanceDeposit.Amount
|
||||
}
|
||||
availableForProcessing -= primitives.Gwei(balanceDeposit.Amount)
|
||||
|
||||
// Regardless of how the deposit was handled, we move on in the queue.
|
||||
nextDepositIndex++
|
||||
}
|
||||
|
||||
deposits = deposits[nextDepositIndex:]
|
||||
// Combined operation:
|
||||
// - state.pending_balance_deposits = state.pending_balance_deposits[next_deposit_index:]
|
||||
// - state.pending_balance_deposits += deposits_to_postpone
|
||||
// However, the number of remaining deposits must be maintained to properly update the deposit
|
||||
// balance to consume.
|
||||
numRemainingDeposits := len(deposits[nextDepositIndex:])
|
||||
deposits = append(deposits[nextDepositIndex:], depositsToPostpone...)
|
||||
if err := st.SetPendingBalanceDeposits(deposits); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(deposits) == 0 {
|
||||
if numRemainingDeposits == 0 {
|
||||
return st.SetDepositBalanceToConsume(0)
|
||||
} else {
|
||||
return st.SetDepositBalanceToConsume(availableForProcessing)
|
||||
return st.SetDepositBalanceToConsume(availableForProcessing - primitives.Gwei(processedAmount))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -107,6 +107,80 @@ func TestProcessPendingBalanceDeposits(t *testing.T) {
|
||||
require.Equal(t, params.BeaconConfig().MinActivationBalance+uint64(amountAvailForProcessing)/5, b)
|
||||
}
|
||||
|
||||
// All of the balance deposits should have been processed.
|
||||
remaining, err := st.PendingBalanceDeposits()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 0, len(remaining))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "exiting validator deposit postponed",
|
||||
state: func() state.BeaconState {
|
||||
st := stateWithActiveBalanceETH(t, 1_000)
|
||||
require.NoError(t, st.SetDepositBalanceToConsume(0))
|
||||
amountAvailForProcessing := helpers.ActivationExitChurnLimit(1_000 * 1e9)
|
||||
deps := make([]*eth.PendingBalanceDeposit, 5)
|
||||
for i := 0; i < len(deps); i += 1 {
|
||||
deps[i] = ð.PendingBalanceDeposit{
|
||||
Amount: uint64(amountAvailForProcessing) / 5,
|
||||
Index: primitives.ValidatorIndex(i),
|
||||
}
|
||||
}
|
||||
require.NoError(t, st.SetPendingBalanceDeposits(deps))
|
||||
v, err := st.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
v.ExitEpoch = 10
|
||||
v.WithdrawableEpoch = 20
|
||||
require.NoError(t, st.UpdateValidatorAtIndex(0, v))
|
||||
return st
|
||||
}(),
|
||||
check: func(t *testing.T, st state.BeaconState) {
|
||||
amountAvailForProcessing := helpers.ActivationExitChurnLimit(1_000 * 1e9)
|
||||
res, err := st.DepositBalanceToConsume()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, primitives.Gwei(0), res)
|
||||
// Validators 1..4 should have their balance increased
|
||||
for i := primitives.ValidatorIndex(1); i < 4; i++ {
|
||||
b, err := st.BalanceAtIndex(i)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, params.BeaconConfig().MinActivationBalance+uint64(amountAvailForProcessing)/5, b)
|
||||
}
|
||||
|
||||
// All of the balance deposits should have been processed, except validator index 0 was
|
||||
// added back to the pending deposits queue.
|
||||
remaining, err := st.PendingBalanceDeposits()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(remaining))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "exited validator balance increased",
|
||||
state: func() state.BeaconState {
|
||||
st := stateWithActiveBalanceETH(t, 1_000)
|
||||
deps := make([]*eth.PendingBalanceDeposit, 1)
|
||||
for i := 0; i < len(deps); i += 1 {
|
||||
deps[i] = ð.PendingBalanceDeposit{
|
||||
Amount: 1_000_000,
|
||||
Index: primitives.ValidatorIndex(i),
|
||||
}
|
||||
}
|
||||
require.NoError(t, st.SetPendingBalanceDeposits(deps))
|
||||
v, err := st.ValidatorAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
v.ExitEpoch = 2
|
||||
v.WithdrawableEpoch = 8
|
||||
require.NoError(t, st.UpdateValidatorAtIndex(0, v))
|
||||
require.NoError(t, st.UpdateBalancesAtIndex(0, 100_000))
|
||||
return st
|
||||
}(),
|
||||
check: func(t *testing.T, st state.BeaconState) {
|
||||
res, err := st.DepositBalanceToConsume()
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, primitives.Gwei(0), res)
|
||||
b, err := st.BalanceAtIndex(0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(1_100_000), b)
|
||||
|
||||
// All of the balance deposits should have been processed.
|
||||
remaining, err := st.PendingBalanceDeposits()
|
||||
require.NoError(t, err)
|
||||
|
||||
@@ -56,7 +56,7 @@ func ProcessEffectiveBalanceUpdates(state state.BeaconState) error {
|
||||
if balance+downwardThreshold < val.EffectiveBalance || val.EffectiveBalance+upwardThreshold < balance {
|
||||
effectiveBal := min(balance-balance%effBalanceInc, effectiveBalanceLimit)
|
||||
val.EffectiveBalance = effectiveBal
|
||||
return false, val, nil
|
||||
return true, val, nil
|
||||
}
|
||||
return false, val, nil
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ func ProcessRegistryUpdates(ctx context.Context, st state.BeaconState) error {
|
||||
}
|
||||
|
||||
// Collect validators eligible for activation and not yet dequeued for activation.
|
||||
if helpers.IsEligibleForActivationUsingTrie(st, val) {
|
||||
if helpers.IsEligibleForActivationUsingROVal(st, val) {
|
||||
eligibleForActivation = append(eligibleForActivation, primitives.ValidatorIndex(idx))
|
||||
}
|
||||
|
||||
|
||||
@@ -26,66 +26,67 @@ import (
|
||||
//
|
||||
// def process_withdrawal_request(
|
||||
//
|
||||
// state: BeaconState,
|
||||
// withdrawal_request: WithdrawalRequest
|
||||
// state: BeaconState,
|
||||
// withdrawal_request: WithdrawalRequest
|
||||
//
|
||||
// ) -> None:
|
||||
// amount = execution_layer_withdrawal_request.amount
|
||||
// is_full_exit_request = amount == FULL_EXIT_REQUEST_AMOUNT
|
||||
// ) -> None:
|
||||
//
|
||||
// # If partial withdrawal queue is full, only full exits are processed
|
||||
// if len(state.pending_partial_withdrawals) == PENDING_PARTIAL_WITHDRAWALS_LIMIT and not is_full_exit_request:
|
||||
// return
|
||||
// amount = withdrawal_request.amount
|
||||
// is_full_exit_request = amount == FULL_EXIT_REQUEST_AMOUNT
|
||||
//
|
||||
// validator_pubkeys = [v.pubkey for v in state.validators]
|
||||
// # Verify pubkey exists
|
||||
// request_pubkey = execution_layer_withdrawal_request.validator_pubkey
|
||||
// if request_pubkey not in validator_pubkeys:
|
||||
// return
|
||||
// index = ValidatorIndex(validator_pubkeys.index(request_pubkey))
|
||||
// validator = state.validators[index]
|
||||
// # If partial withdrawal queue is full, only full exits are processed
|
||||
// if len(state.pending_partial_withdrawals) == PENDING_PARTIAL_WITHDRAWALS_LIMIT and not is_full_exit_request:
|
||||
// return
|
||||
//
|
||||
// # Verify withdrawal credentials
|
||||
// has_correct_credential = has_execution_withdrawal_credential(validator)
|
||||
// is_correct_source_address = (
|
||||
// validator.withdrawal_credentials[12:] == execution_layer_withdrawal_request.source_address
|
||||
// )
|
||||
// if not (has_correct_credential and is_correct_source_address):
|
||||
// return
|
||||
// # Verify the validator is active
|
||||
// if not is_active_validator(validator, get_current_epoch(state)):
|
||||
// return
|
||||
// # Verify exit has not been initiated
|
||||
// if validator.exit_epoch != FAR_FUTURE_EPOCH:
|
||||
// return
|
||||
// # Verify the validator has been active long enough
|
||||
// if get_current_epoch(state) < validator.activation_epoch + SHARD_COMMITTEE_PERIOD:
|
||||
// return
|
||||
// validator_pubkeys = [v.pubkey for v in state.validators]
|
||||
// # Verify pubkey exists
|
||||
// request_pubkey = withdrawal_request.validator_pubkey
|
||||
// if request_pubkey not in validator_pubkeys:
|
||||
// return
|
||||
// index = ValidatorIndex(validator_pubkeys.index(request_pubkey))
|
||||
// validator = state.validators[index]
|
||||
//
|
||||
// pending_balance_to_withdraw = get_pending_balance_to_withdraw(state, index)
|
||||
// # Verify withdrawal credentials
|
||||
// has_correct_credential = has_execution_withdrawal_credential(validator)
|
||||
// is_correct_source_address = (
|
||||
// validator.withdrawal_credentials[12:] == withdrawal_request.source_address
|
||||
// )
|
||||
// if not (has_correct_credential and is_correct_source_address):
|
||||
// return
|
||||
// # Verify the validator is active
|
||||
// if not is_active_validator(validator, get_current_epoch(state)):
|
||||
// return
|
||||
// # Verify exit has not been initiated
|
||||
// if validator.exit_epoch != FAR_FUTURE_EPOCH:
|
||||
// return
|
||||
// # Verify the validator has been active long enough
|
||||
// if get_current_epoch(state) < validator.activation_epoch + SHARD_COMMITTEE_PERIOD:
|
||||
// return
|
||||
//
|
||||
// if is_full_exit_request:
|
||||
// # Only exit validator if it has no pending withdrawals in the queue
|
||||
// if pending_balance_to_withdraw == 0:
|
||||
// initiate_validator_exit(state, index)
|
||||
// return
|
||||
// pending_balance_to_withdraw = get_pending_balance_to_withdraw(state, index)
|
||||
//
|
||||
// has_sufficient_effective_balance = validator.effective_balance >= MIN_ACTIVATION_BALANCE
|
||||
// has_excess_balance = state.balances[index] > MIN_ACTIVATION_BALANCE + pending_balance_to_withdraw
|
||||
// if is_full_exit_request:
|
||||
// # Only exit validator if it has no pending withdrawals in the queue
|
||||
// if pending_balance_to_withdraw == 0:
|
||||
// initiate_validator_exit(state, index)
|
||||
// return
|
||||
//
|
||||
// # Only allow partial withdrawals with compounding withdrawal credentials
|
||||
// if has_compounding_withdrawal_credential(validator) and has_sufficient_effective_balance and has_excess_balance:
|
||||
// to_withdraw = min(
|
||||
// state.balances[index] - MIN_ACTIVATION_BALANCE - pending_balance_to_withdraw,
|
||||
// amount
|
||||
// )
|
||||
// exit_queue_epoch = compute_exit_epoch_and_update_churn(state, to_withdraw)
|
||||
// withdrawable_epoch = Epoch(exit_queue_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
|
||||
// state.pending_partial_withdrawals.append(PendingPartialWithdrawal(
|
||||
// index=index,
|
||||
// amount=to_withdraw,
|
||||
// withdrawable_epoch=withdrawable_epoch,
|
||||
// ))
|
||||
// has_sufficient_effective_balance = validator.effective_balance >= MIN_ACTIVATION_BALANCE
|
||||
// has_excess_balance = state.balances[index] > MIN_ACTIVATION_BALANCE + pending_balance_to_withdraw
|
||||
//
|
||||
// # Only allow partial withdrawals with compounding withdrawal credentials
|
||||
// if has_compounding_withdrawal_credential(validator) and has_sufficient_effective_balance and has_excess_balance:
|
||||
// to_withdraw = min(
|
||||
// state.balances[index] - MIN_ACTIVATION_BALANCE - pending_balance_to_withdraw,
|
||||
// amount
|
||||
// )
|
||||
// exit_queue_epoch = compute_exit_epoch_and_update_churn(state, to_withdraw)
|
||||
// withdrawable_epoch = Epoch(exit_queue_epoch + MIN_VALIDATOR_WITHDRAWABILITY_DELAY)
|
||||
// state.pending_partial_withdrawals.append(PendingPartialWithdrawal(
|
||||
// index=index,
|
||||
// amount=to_withdraw,
|
||||
// withdrawable_epoch=withdrawable_epoch,
|
||||
// ))
|
||||
func ProcessWithdrawalRequests(ctx context.Context, st state.BeaconState, wrs []*enginev1.WithdrawalRequest) (state.BeaconState, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "electra.ProcessWithdrawalRequests")
|
||||
defer span.End()
|
||||
|
||||
@@ -96,7 +96,7 @@ func ProcessRegistryUpdates(ctx context.Context, st state.BeaconState) (state.Be
|
||||
}
|
||||
|
||||
// Collect validators eligible for activation and not yet dequeued for activation.
|
||||
if helpers.IsEligibleForActivationUsingTrie(st, val) {
|
||||
if helpers.IsEligibleForActivationUsingROVal(st, val) {
|
||||
eligibleForActivation = append(eligibleForActivation, primitives.ValidatorIndex(idx))
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ go_library(
|
||||
"block.go",
|
||||
"genesis.go",
|
||||
"metrics.go",
|
||||
"payload_attestation.go",
|
||||
"randao.go",
|
||||
"rewards_penalties.go",
|
||||
"shuffle.go",
|
||||
@@ -53,6 +54,8 @@ go_test(
|
||||
"attestation_test.go",
|
||||
"beacon_committee_test.go",
|
||||
"block_test.go",
|
||||
"exports_test.go",
|
||||
"payload_attestation_test.go",
|
||||
"private_access_fuzz_noop_test.go", # keep
|
||||
"private_access_test.go",
|
||||
"randao_test.go",
|
||||
@@ -78,10 +81,13 @@ go_test(
|
||||
"//container/slice:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
"//encoding/bytesutil:go_default_library",
|
||||
"//math:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"//testing/util/random:go_default_library",
|
||||
"//time:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
|
||||
@@ -172,6 +172,7 @@ type CommitteeAssignment struct {
|
||||
Committee []primitives.ValidatorIndex
|
||||
AttesterSlot primitives.Slot
|
||||
CommitteeIndex primitives.CommitteeIndex
|
||||
PtcSlot primitives.Slot
|
||||
}
|
||||
|
||||
// verifyAssignmentEpoch verifies if the given epoch is valid for assignment based on the provided state.
|
||||
@@ -274,6 +275,8 @@ func CommitteeAssignments(ctx context.Context, state state.BeaconState, epoch pr
|
||||
vals[v] = struct{}{}
|
||||
}
|
||||
|
||||
ptcPerSlot, PtcMembersPerCommittee := PtcAllocation(activeValidatorCount)
|
||||
|
||||
// Compute committee assignments for each slot in the epoch.
|
||||
for slot := startSlot; slot < startSlot+params.BeaconConfig().SlotsPerEpoch; slot++ {
|
||||
// Compute committees for the current slot.
|
||||
@@ -294,12 +297,53 @@ func CommitteeAssignments(ctx context.Context, state state.BeaconState, epoch pr
|
||||
assignments[vIndex].AttesterSlot = slot
|
||||
assignments[vIndex].CommitteeIndex = primitives.CommitteeIndex(j)
|
||||
}
|
||||
|
||||
// We only need to assign PTC slots for the first `PTCPerSlot` committees of a given slot.
|
||||
if j < ptcPerSlot {
|
||||
assignments = PTCAssignments(committee, assignments, PtcMembersPerCommittee, slot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return assignments, nil
|
||||
}
|
||||
|
||||
// PTCAssignments updates the PTC slot assignments for the given committee members.
|
||||
// committee: a slice of ValidatorIndex representing committee members.
|
||||
// assignments: a map of ValidatorIndex to CommitteeAssignment where assignments will be updated.
|
||||
// membersPerCommittee: the number of members to be assigned to the PTC committee.
|
||||
// slot: the slot to be assigned for PTC assignment.
|
||||
// Returns the updated assignments map.
|
||||
func PTCAssignments(committee []primitives.ValidatorIndex,
|
||||
assignments map[primitives.ValidatorIndex]*CommitteeAssignment,
|
||||
membersPerCommittee uint64,
|
||||
slot primitives.Slot) map[primitives.ValidatorIndex]*CommitteeAssignment {
|
||||
committeeLength := uint64(len(committee))
|
||||
// If the number of PTC members is greater than Beacon members,
|
||||
// return the current assignments without changes.
|
||||
if membersPerCommittee > committeeLength {
|
||||
return assignments
|
||||
}
|
||||
|
||||
// Calculate the starting index for PTC committee.
|
||||
ptcStartIndex := committeeLength - membersPerCommittee
|
||||
|
||||
// Loop through the selected committee members for PTC assignments.
|
||||
for i := ptcStartIndex; i < committeeLength; i++ {
|
||||
vIndex := committee[i]
|
||||
|
||||
assignment, exists := assignments[vIndex]
|
||||
if !exists {
|
||||
assignment = &CommitteeAssignment{}
|
||||
assignments[vIndex] = assignment
|
||||
}
|
||||
|
||||
assignment.PtcSlot = slot
|
||||
}
|
||||
|
||||
return assignments
|
||||
}
|
||||
|
||||
// VerifyBitfieldLength verifies that a bitfield length matches the given committee size.
|
||||
func VerifyBitfieldLength(bf bitfield.Bitfield, committeeSize uint64) error {
|
||||
if bf.Len() != committeeSize {
|
||||
|
||||
@@ -3,6 +3,7 @@ package helpers_test
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"slices"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
@@ -10,6 +11,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/time"
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
field_params "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/container/slice"
|
||||
@@ -716,15 +718,26 @@ func TestCommitteeIndices(t *testing.T) {
|
||||
assert.DeepEqual(t, []primitives.CommitteeIndex{0, 1, 3}, indices)
|
||||
}
|
||||
|
||||
func TestAttestationCommittees(t *testing.T) {
|
||||
validators := make([]*ethpb.Validator, params.BeaconConfig().SlotsPerEpoch.Mul(params.BeaconConfig().TargetCommitteeSize))
|
||||
func TestCommitteeAssignments_PTC(t *testing.T) {
|
||||
helpers.ClearCache()
|
||||
// Create 10 committees. Total 40960 validators.
|
||||
committeeCount := uint64(10)
|
||||
validatorCount := committeeCount * params.BeaconConfig().TargetCommitteeSize * uint64(params.BeaconConfig().SlotsPerEpoch)
|
||||
validators := make([]*ethpb.Validator, validatorCount)
|
||||
validatorIndices := make([]primitives.ValidatorIndex, validatorCount)
|
||||
|
||||
for i := 0; i < len(validators); i++ {
|
||||
k := make([]byte, 48)
|
||||
copy(k, strconv.Itoa(i))
|
||||
validators[i] = ðpb.Validator{
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
PublicKey: k,
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
}
|
||||
validatorIndices[i] = primitives.ValidatorIndex(i)
|
||||
}
|
||||
|
||||
state, err := state_native.InitializeFromProtoPhase0(ðpb.BeaconState{
|
||||
state, err := state_native.InitializeFromProtoEpbs(ðpb.BeaconStateEPBS{
|
||||
Validators: validators,
|
||||
RandaoMixes: make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector),
|
||||
})
|
||||
@@ -748,4 +761,29 @@ func TestAttestationCommittees(t *testing.T) {
|
||||
assert.Equal(t, params.BeaconConfig().TargetCommitteeSize, uint64(len(committees[0])))
|
||||
assert.Equal(t, params.BeaconConfig().TargetCommitteeSize, uint64(len(committees[1])))
|
||||
})
|
||||
as, err := helpers.CommitteeAssignments(context.Background(), state, 1, validatorIndices)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Capture all the slots and all the validator index that belonged in a PTC using a map for verification later.
|
||||
slotValidatorMap := make(map[primitives.Slot][]primitives.ValidatorIndex)
|
||||
for i, a := range as {
|
||||
slotValidatorMap[a.PtcSlot] = append(slotValidatorMap[a.PtcSlot], i)
|
||||
}
|
||||
|
||||
// Verify that all the slots have the correct number of PTC.
|
||||
for s, v := range slotValidatorMap {
|
||||
if s == 0 {
|
||||
continue
|
||||
}
|
||||
// Make sure all the PTC are the correct size from the map.
|
||||
require.Equal(t, len(v), field_params.PTCSize)
|
||||
|
||||
// Get the actual PTC from the beacon state using the helper function
|
||||
ptc, err := helpers.GetPayloadTimelinessCommittee(context.Background(), state, s)
|
||||
require.NoError(t, err)
|
||||
for _, index := range ptc {
|
||||
i := slices.Index(v, index)
|
||||
require.NotEqual(t, -1, i) // PTC not found from the assignment map
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
12
beacon-chain/core/helpers/exports_test.go
Normal file
12
beacon-chain/core/helpers/exports_test.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package helpers
|
||||
|
||||
var (
|
||||
ErrNilMessage = errNilMessage
|
||||
ErrNilData = errNilData
|
||||
ErrNilBeaconBlockRoot = errNilBeaconBlockRoot
|
||||
ErrNilPayloadAttestation = errNilPayloadAttestation
|
||||
ErrNilSignature = errNilSignature
|
||||
ErrNilAggregationBits = errNilAggregationBits
|
||||
ErrPreEPBSState = errPreEPBSState
|
||||
ErrCommitteeOverflow = errCommitteeOverflow
|
||||
)
|
||||
100
beacon-chain/core/helpers/payload_attestation.go
Normal file
100
beacon-chain/core/helpers/payload_attestation.go
Normal file
@@ -0,0 +1,100 @@
|
||||
package helpers
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
)
|
||||
|
||||
var (
|
||||
errNilMessage = errors.New("nil PayloadAttestationMessage")
|
||||
errNilData = errors.New("nil PayloadAttestationData")
|
||||
errNilBeaconBlockRoot = errors.New("nil BeaconBlockRoot")
|
||||
errNilPayloadAttestation = errors.New("nil PayloadAttestation")
|
||||
errNilSignature = errors.New("nil Signature")
|
||||
errNilAggregationBits = errors.New("nil AggregationBits")
|
||||
errPreEPBSState = errors.New("beacon state pre ePBS fork")
|
||||
errCommitteeOverflow = errors.New("beacon committee of insufficient size")
|
||||
)
|
||||
|
||||
// ValidateNilPayloadAttestationData checks if any composite field of the
|
||||
// payload attestation data is nil
|
||||
func ValidateNilPayloadAttestationData(data *eth.PayloadAttestationData) error {
|
||||
if data == nil {
|
||||
return errNilData
|
||||
}
|
||||
if data.BeaconBlockRoot == nil {
|
||||
return errNilBeaconBlockRoot
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ValidateNilPayloadAttestationMessage checks if any composite field of the
|
||||
// payload attestation message is nil
|
||||
func ValidateNilPayloadAttestationMessage(att *eth.PayloadAttestationMessage) error {
|
||||
if att == nil {
|
||||
return errNilMessage
|
||||
}
|
||||
if att.Signature == nil {
|
||||
return errNilSignature
|
||||
}
|
||||
return ValidateNilPayloadAttestationData(att.Data)
|
||||
}
|
||||
|
||||
// ValidateNilPayloadAttestation checks if any composite field of the
|
||||
// payload attestation is nil
|
||||
func ValidateNilPayloadAttestation(att *eth.PayloadAttestation) error {
|
||||
if att == nil {
|
||||
return errNilPayloadAttestation
|
||||
}
|
||||
if att.AggregationBits == nil {
|
||||
return errNilAggregationBits
|
||||
}
|
||||
if att.Signature == nil {
|
||||
return errNilSignature
|
||||
}
|
||||
return ValidateNilPayloadAttestationData(att.Data)
|
||||
}
|
||||
|
||||
// GetPayloadTimelinessCommittee returns the PTC for the given slot, computed from the passed state as in the
|
||||
// spec function `get_ptc`.
|
||||
func GetPayloadTimelinessCommittee(ctx context.Context, state state.ReadOnlyBeaconState, slot primitives.Slot) (indices []primitives.ValidatorIndex, err error) {
|
||||
if state.Version() < version.EPBS {
|
||||
return nil, errPreEPBSState
|
||||
}
|
||||
epoch := slots.ToEpoch(slot)
|
||||
activeCount, err := ActiveValidatorCount(ctx, state, epoch)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "could not compute active validator count")
|
||||
}
|
||||
committeesPerSlot, membersPerCommittee := PtcAllocation(activeCount)
|
||||
for i := uint64(0); i < committeesPerSlot; i++ {
|
||||
committee, err := BeaconCommitteeFromState(ctx, state, slot, primitives.CommitteeIndex(i))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uint64(len(committee)) < membersPerCommittee {
|
||||
return nil, errCommitteeOverflow
|
||||
}
|
||||
start := uint64(len(committee)) - membersPerCommittee
|
||||
indices = append(indices, committee[start:]...)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// PtcAllocation returns:
|
||||
// 1. The number of beacon committees that PTC will borrow from in a slot.
|
||||
// 2. The number of validators that PTC will borrow from in a beacon committee.
|
||||
func PtcAllocation(totalActive uint64) (committeesPerSlot, membersPerCommittee uint64) {
|
||||
slotCommittees := SlotCommitteeCount(totalActive)
|
||||
committeesPerSlot = math.LargestPowerOfTwo(math.Min(slotCommittees, fieldparams.PTCSize))
|
||||
membersPerCommittee = fieldparams.PTCSize / committeesPerSlot
|
||||
return
|
||||
}
|
||||
117
beacon-chain/core/helpers/payload_attestation_test.go
Normal file
117
beacon-chain/core/helpers/payload_attestation_test.go
Normal file
@@ -0,0 +1,117 @@
|
||||
package helpers_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util/random"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
)
|
||||
|
||||
func TestValidateNilPayloadAttestation(t *testing.T) {
|
||||
require.ErrorIs(t, helpers.ErrNilData, helpers.ValidateNilPayloadAttestationData(nil))
|
||||
data := ð.PayloadAttestationData{}
|
||||
require.ErrorIs(t, helpers.ErrNilBeaconBlockRoot, helpers.ValidateNilPayloadAttestationData(data))
|
||||
data.BeaconBlockRoot = make([]byte, 32)
|
||||
require.NoError(t, helpers.ValidateNilPayloadAttestationData(data))
|
||||
|
||||
require.ErrorIs(t, helpers.ErrNilMessage, helpers.ValidateNilPayloadAttestationMessage(nil))
|
||||
message := ð.PayloadAttestationMessage{}
|
||||
require.ErrorIs(t, helpers.ErrNilSignature, helpers.ValidateNilPayloadAttestationMessage(message))
|
||||
message.Signature = make([]byte, 96)
|
||||
require.ErrorIs(t, helpers.ErrNilData, helpers.ValidateNilPayloadAttestationMessage(message))
|
||||
message.Data = data
|
||||
require.NoError(t, helpers.ValidateNilPayloadAttestationMessage(message))
|
||||
|
||||
require.ErrorIs(t, helpers.ErrNilPayloadAttestation, helpers.ValidateNilPayloadAttestation(nil))
|
||||
att := ð.PayloadAttestation{}
|
||||
require.ErrorIs(t, helpers.ErrNilAggregationBits, helpers.ValidateNilPayloadAttestation(att))
|
||||
att.AggregationBits = bitfield.NewBitvector512()
|
||||
require.ErrorIs(t, helpers.ErrNilSignature, helpers.ValidateNilPayloadAttestation(att))
|
||||
att.Signature = message.Signature
|
||||
require.ErrorIs(t, helpers.ErrNilData, helpers.ValidateNilPayloadAttestation(att))
|
||||
att.Data = data
|
||||
require.NoError(t, helpers.ValidateNilPayloadAttestation(att))
|
||||
}
|
||||
|
||||
func TestGetPayloadTimelinessCommittee(t *testing.T) {
|
||||
helpers.ClearCache()
|
||||
|
||||
// Create 10 committees
|
||||
committeeCount := uint64(10)
|
||||
validatorCount := committeeCount * params.BeaconConfig().TargetCommitteeSize * uint64(params.BeaconConfig().SlotsPerEpoch)
|
||||
validators := make([]*ethpb.Validator, validatorCount)
|
||||
|
||||
for i := 0; i < len(validators); i++ {
|
||||
k := make([]byte, 48)
|
||||
copy(k, strconv.Itoa(i))
|
||||
validators[i] = ðpb.Validator{
|
||||
PublicKey: k,
|
||||
WithdrawalCredentials: make([]byte, 32),
|
||||
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
}
|
||||
}
|
||||
|
||||
state, err := state_native.InitializeFromProtoEpbs(random.BeaconState(t))
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
require.NoError(t, state.SetSlot(200))
|
||||
|
||||
ctx := context.Background()
|
||||
indices, err := helpers.BeaconCommitteeFromState(ctx, state, state.Slot(), 1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 128, len(indices))
|
||||
|
||||
epoch := slots.ToEpoch(state.Slot())
|
||||
activeCount, err := helpers.ActiveValidatorCount(ctx, state, epoch)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, uint64(40960), activeCount)
|
||||
|
||||
computedCommitteeCount := helpers.SlotCommitteeCount(activeCount)
|
||||
require.Equal(t, committeeCount, computedCommitteeCount)
|
||||
committeesPerSlot := math.LargestPowerOfTwo(math.Min(committeeCount, fieldparams.PTCSize))
|
||||
require.Equal(t, uint64(8), committeesPerSlot)
|
||||
|
||||
ptc, err := helpers.GetPayloadTimelinessCommittee(ctx, state, state.Slot())
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, fieldparams.PTCSize, len(ptc))
|
||||
|
||||
committee1, err := helpers.BeaconCommitteeFromState(ctx, state, state.Slot(), 0)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.DeepEqual(t, committee1[len(committee1)-64:], ptc[:64])
|
||||
}
|
||||
|
||||
func Test_PtcAllocation(t *testing.T) {
|
||||
tests := []struct {
|
||||
totalActive uint64
|
||||
memberPerCommittee uint64
|
||||
committeesPerSlot uint64
|
||||
}{
|
||||
{64, 512, 1},
|
||||
{params.BeaconConfig().MinGenesisActiveValidatorCount, 128, 4},
|
||||
{25600, 128, 4},
|
||||
{256000, 16, 32},
|
||||
{1024000, 8, 64},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
committeesPerSlot, memberPerCommittee := helpers.PtcAllocation(test.totalActive)
|
||||
if memberPerCommittee != test.memberPerCommittee {
|
||||
t.Errorf("memberPerCommittee(%d) = %d; expected %d", test.totalActive, memberPerCommittee, test.memberPerCommittee)
|
||||
}
|
||||
if committeesPerSlot != test.committeesPerSlot {
|
||||
t.Errorf("committeesPerSlot(%d) = %d; expected %d", test.totalActive, committeesPerSlot, test.committeesPerSlot)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -470,13 +470,9 @@ func IsEligibleForActivation(state state.ReadOnlyCheckpoint, validator *ethpb.Va
|
||||
return isEligibleForActivation(validator.ActivationEligibilityEpoch, validator.ActivationEpoch, finalizedEpoch)
|
||||
}
|
||||
|
||||
// IsEligibleForActivationUsingTrie checks if the validator is eligible for activation.
|
||||
func IsEligibleForActivationUsingTrie(state state.ReadOnlyCheckpoint, validator state.ReadOnlyValidator) bool {
|
||||
cpt := state.FinalizedCheckpoint()
|
||||
if cpt == nil {
|
||||
return false
|
||||
}
|
||||
return isEligibleForActivation(validator.ActivationEligibilityEpoch(), validator.ActivationEpoch(), cpt.Epoch)
|
||||
// IsEligibleForActivationUsingROVal checks if the validator is eligible for activation using the provided read only validator.
|
||||
func IsEligibleForActivationUsingROVal(state state.ReadOnlyCheckpoint, validator state.ReadOnlyValidator) bool {
|
||||
return isEligibleForActivation(validator.ActivationEligibilityEpoch(), validator.ActivationEpoch(), state.FinalizedCheckpointEpoch())
|
||||
}
|
||||
|
||||
// isEligibleForActivation carries out the logic for IsEligibleForActivation*
|
||||
@@ -588,13 +584,13 @@ func IsSameWithdrawalCredentials(a, b *ethpb.Validator) bool {
|
||||
// and validator.withdrawable_epoch <= epoch
|
||||
// and balance > 0
|
||||
// )
|
||||
func IsFullyWithdrawableValidator(val *ethpb.Validator, balance uint64, epoch primitives.Epoch) bool {
|
||||
func IsFullyWithdrawableValidator(val *ethpb.Validator, balance uint64, epoch primitives.Epoch, fork int) bool {
|
||||
if val == nil || balance <= 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
// Electra / EIP-7251 logic
|
||||
if epoch >= params.BeaconConfig().ElectraForkEpoch {
|
||||
if fork >= version.Electra {
|
||||
return HasExecutionWithdrawalCredentials(val) && val.WithdrawableEpoch <= epoch
|
||||
}
|
||||
|
||||
@@ -604,12 +600,12 @@ func IsFullyWithdrawableValidator(val *ethpb.Validator, balance uint64, epoch pr
|
||||
// IsPartiallyWithdrawableValidator returns whether the validator is able to perform a
|
||||
// partial withdrawal. This function assumes that the caller has a lock on the state.
|
||||
// This method conditionally calls the fork appropriate implementation based on the epoch argument.
|
||||
func IsPartiallyWithdrawableValidator(val *ethpb.Validator, balance uint64, epoch primitives.Epoch) bool {
|
||||
func IsPartiallyWithdrawableValidator(val *ethpb.Validator, balance uint64, epoch primitives.Epoch, fork int) bool {
|
||||
if val == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if epoch < params.BeaconConfig().ElectraForkEpoch {
|
||||
if fork < version.Electra {
|
||||
return isPartiallyWithdrawableValidatorCapella(val, balance, epoch)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/crypto/hash"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
@@ -970,6 +971,7 @@ func TestIsFullyWithdrawableValidator(t *testing.T) {
|
||||
validator *ethpb.Validator
|
||||
balance uint64
|
||||
epoch primitives.Epoch
|
||||
fork int
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
@@ -1027,13 +1029,14 @@ func TestIsFullyWithdrawableValidator(t *testing.T) {
|
||||
},
|
||||
balance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
epoch: params.BeaconConfig().ElectraForkEpoch,
|
||||
fork: version.Electra,
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.want, helpers.IsFullyWithdrawableValidator(tt.validator, tt.balance, tt.epoch))
|
||||
assert.Equal(t, tt.want, helpers.IsFullyWithdrawableValidator(tt.validator, tt.balance, tt.epoch, tt.fork))
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1044,6 +1047,7 @@ func TestIsPartiallyWithdrawableValidator(t *testing.T) {
|
||||
validator *ethpb.Validator
|
||||
balance uint64
|
||||
epoch primitives.Epoch
|
||||
fork int
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
@@ -1091,6 +1095,7 @@ func TestIsPartiallyWithdrawableValidator(t *testing.T) {
|
||||
},
|
||||
balance: params.BeaconConfig().MinActivationBalance * 2,
|
||||
epoch: params.BeaconConfig().ElectraForkEpoch,
|
||||
fork: version.Electra,
|
||||
want: true,
|
||||
},
|
||||
{
|
||||
@@ -1101,13 +1106,14 @@ func TestIsPartiallyWithdrawableValidator(t *testing.T) {
|
||||
},
|
||||
balance: params.BeaconConfig().MaxEffectiveBalanceElectra * 2,
|
||||
epoch: params.BeaconConfig().ElectraForkEpoch,
|
||||
fork: version.Electra,
|
||||
want: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert.Equal(t, tt.want, helpers.IsPartiallyWithdrawableValidator(tt.validator, tt.balance, tt.epoch))
|
||||
assert.Equal(t, tt.want, helpers.IsPartiallyWithdrawableValidator(tt.validator, tt.balance, tt.epoch, tt.fork))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ func SlashingParamsPerVersion(v int) (slashingQuotient, proposerRewardQuotient,
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientBellatrix
|
||||
proposerRewardQuotient = cfg.ProposerRewardQuotient
|
||||
whistleblowerRewardQuotient = cfg.WhistleBlowerRewardQuotient
|
||||
case version.Electra:
|
||||
case version.Electra, version.EPBS:
|
||||
slashingQuotient = cfg.MinSlashingPenaltyQuotientElectra
|
||||
proposerRewardQuotient = cfg.ProposerRewardQuotient
|
||||
whistleblowerRewardQuotient = cfg.WhistleBlowerRewardQuotientElectra
|
||||
|
||||
@@ -53,6 +53,7 @@ type ReadOnlyDatabase interface {
|
||||
DepositContractAddress(ctx context.Context) ([]byte, error)
|
||||
// ExecutionChainData operations.
|
||||
ExecutionChainData(ctx context.Context) (*ethpb.ETH1ChainData, error)
|
||||
SignedBlindPayloadEnvelope(ctx context.Context, blockRoot []byte) (*ethpb.SignedBlindPayloadEnvelope, error)
|
||||
// Fee recipients operations.
|
||||
FeeRecipientByValidatorID(ctx context.Context, id primitives.ValidatorIndex) (common.Address, error)
|
||||
RegistrationByValidatorID(ctx context.Context, id primitives.ValidatorIndex) (*ethpb.ValidatorRegistrationV1, error)
|
||||
@@ -87,6 +88,7 @@ type NoHeadAccessDatabase interface {
|
||||
SaveDepositContractAddress(ctx context.Context, addr common.Address) error
|
||||
// SaveExecutionChainData operations.
|
||||
SaveExecutionChainData(ctx context.Context, data *ethpb.ETH1ChainData) error
|
||||
SaveBlindPayloadEnvelope(ctx context.Context, envelope *ethpb.SignedBlindPayloadEnvelope) error
|
||||
// Run any required database migrations.
|
||||
RunMigrations(ctx context.Context) error
|
||||
// Fee recipients operations.
|
||||
|
||||
@@ -6,6 +6,7 @@ go_library(
|
||||
"archived_point.go",
|
||||
"backfill.go",
|
||||
"backup.go",
|
||||
"blind_payload_envelope.go",
|
||||
"blocks.go",
|
||||
"checkpoint.go",
|
||||
"deposit_contract.go",
|
||||
@@ -78,6 +79,7 @@ go_test(
|
||||
"archived_point_test.go",
|
||||
"backfill_test.go",
|
||||
"backup_test.go",
|
||||
"blind_payload_envelope_test.go",
|
||||
"blocks_test.go",
|
||||
"checkpoint_test.go",
|
||||
"deposit_contract_test.go",
|
||||
@@ -119,6 +121,7 @@ go_test(
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"//testing/util/random:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common:go_default_library",
|
||||
"@com_github_golang_snappy//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
|
||||
45
beacon-chain/db/kv/blind_payload_envelope.go
Normal file
45
beacon-chain/db/kv/blind_payload_envelope.go
Normal file
@@ -0,0 +1,45 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
// SaveBlindPayloadEnvelope saves a signed execution payload envelope blind in the database.
|
||||
func (s *Store) SaveBlindPayloadEnvelope(ctx context.Context, env *ethpb.SignedBlindPayloadEnvelope) error {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.SaveBlindPayloadEnvelope")
|
||||
defer span.End()
|
||||
|
||||
enc, err := encode(ctx, env)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r := env.Message.BeaconBlockRoot
|
||||
err = s.db.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(executionPayloadEnvelopeBucket)
|
||||
return bucket.Put(r, enc)
|
||||
})
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SignedBlindPayloadEnvelope retrieves a signed execution payload envelope blind from the database.
|
||||
func (s *Store) SignedBlindPayloadEnvelope(ctx context.Context, blockRoot []byte) (*ethpb.SignedBlindPayloadEnvelope, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "BeaconDB.SignedBlindPayloadEnvelope")
|
||||
defer span.End()
|
||||
|
||||
env := ðpb.SignedBlindPayloadEnvelope{}
|
||||
err := s.db.View(func(tx *bolt.Tx) error {
|
||||
bkt := tx.Bucket(executionPayloadEnvelopeBucket)
|
||||
enc := bkt.Get(blockRoot)
|
||||
if enc == nil {
|
||||
return ErrNotFound
|
||||
}
|
||||
return decode(ctx, enc, env)
|
||||
})
|
||||
return env, err
|
||||
}
|
||||
23
beacon-chain/db/kv/blind_payload_envelope_test.go
Normal file
23
beacon-chain/db/kv/blind_payload_envelope_test.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package kv
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util/random"
|
||||
)
|
||||
|
||||
func TestStore_SignedBlindPayloadEnvelope(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
ctx := context.Background()
|
||||
_, err := db.SignedBlindPayloadEnvelope(ctx, []byte("test"))
|
||||
require.ErrorIs(t, err, ErrNotFound)
|
||||
|
||||
env := random.SignedBlindPayloadEnvelope(t)
|
||||
err = db.SaveBlindPayloadEnvelope(ctx, env)
|
||||
require.NoError(t, err)
|
||||
got, err := db.SignedBlindPayloadEnvelope(ctx, env.Message.BeaconBlockRoot)
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, got, env)
|
||||
}
|
||||
@@ -823,6 +823,11 @@ func unmarshalBlock(_ context.Context, enc []byte) (interfaces.ReadOnlySignedBea
|
||||
if err := rawBlock.UnmarshalSSZ(enc[len(electraBlindKey):]); err != nil {
|
||||
return nil, errors.Wrap(err, "could not unmarshal blinded Electra block")
|
||||
}
|
||||
case hasEpbsKey(enc):
|
||||
rawBlock = ðpb.SignedBeaconBlockEpbs{}
|
||||
if err := rawBlock.UnmarshalSSZ(enc[len(epbsKey):]); err != nil {
|
||||
return nil, errors.Wrap(err, "could not unmarshal EPBS block")
|
||||
}
|
||||
default:
|
||||
// Marshal block bytes to phase 0 beacon block.
|
||||
rawBlock = ðpb.SignedBeaconBlock{}
|
||||
@@ -852,6 +857,8 @@ func encodeBlock(blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) {
|
||||
|
||||
func keyForBlock(blk interfaces.ReadOnlySignedBeaconBlock) ([]byte, error) {
|
||||
switch blk.Version() {
|
||||
case version.EPBS:
|
||||
return epbsKey, nil
|
||||
case version.Electra:
|
||||
if blk.IsBlinded() {
|
||||
return electraBlindKey, nil
|
||||
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util/random"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
@@ -146,6 +147,17 @@ var blockTests = []struct {
|
||||
}
|
||||
return blocks.NewSignedBeaconBlock(b)
|
||||
}},
|
||||
{
|
||||
name: "epbs",
|
||||
newBlock: func(slot primitives.Slot, root []byte) (interfaces.ReadOnlySignedBeaconBlock, error) {
|
||||
b := random.SignedBeaconBlock(&testing.T{})
|
||||
b.Block.Slot = slot
|
||||
if root != nil {
|
||||
b.Block.ParentRoot = root
|
||||
}
|
||||
return blocks.NewSignedBeaconBlock(b)
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
func TestStore_SaveBlock_NoDuplicates(t *testing.T) {
|
||||
@@ -202,7 +214,7 @@ func TestStore_BlocksCRUD(t *testing.T) {
|
||||
retrievedBlock, err = db.Block(ctx, blockRoot)
|
||||
require.NoError(t, err)
|
||||
wanted := retrievedBlock
|
||||
if retrievedBlock.Version() >= version.Bellatrix {
|
||||
if retrievedBlock.Version() >= version.Bellatrix && retrievedBlock.Version() < version.EPBS {
|
||||
wanted, err = retrievedBlock.ToBlinded()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -390,7 +402,7 @@ func TestStore_BlocksCRUD_NoCache(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
wanted := blk
|
||||
if blk.Version() >= version.Bellatrix {
|
||||
if blk.Version() >= version.Bellatrix && blk.Version() < version.EPBS {
|
||||
wanted, err = blk.ToBlinded()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -609,7 +621,7 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) {
|
||||
b, err := db.Block(ctx, root)
|
||||
require.NoError(t, err)
|
||||
wanted := block1
|
||||
if block1.Version() >= version.Bellatrix {
|
||||
if block1.Version() >= version.Bellatrix && block1.Version() < version.EPBS {
|
||||
wanted, err = wanted.ToBlinded()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -627,7 +639,7 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) {
|
||||
b, err = db.Block(ctx, root)
|
||||
require.NoError(t, err)
|
||||
wanted2 := block2
|
||||
if block2.Version() >= version.Bellatrix {
|
||||
if block2.Version() >= version.Bellatrix && block2.Version() < version.EPBS {
|
||||
wanted2, err = block2.ToBlinded()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -645,7 +657,7 @@ func TestStore_SaveBlock_CanGetHighestAt(t *testing.T) {
|
||||
b, err = db.Block(ctx, root)
|
||||
require.NoError(t, err)
|
||||
wanted = block3
|
||||
if block3.Version() >= version.Bellatrix {
|
||||
if block3.Version() >= version.Bellatrix && block3.Version() < version.EPBS {
|
||||
wanted, err = wanted.ToBlinded()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -681,7 +693,7 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) {
|
||||
b, err := db.Block(ctx, root)
|
||||
require.NoError(t, err)
|
||||
wanted := block1
|
||||
if block1.Version() >= version.Bellatrix {
|
||||
if block1.Version() >= version.Bellatrix && block1.Version() < version.EPBS {
|
||||
wanted, err = block1.ToBlinded()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -698,7 +710,7 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) {
|
||||
b, err = db.Block(ctx, root)
|
||||
require.NoError(t, err)
|
||||
wanted = genesisBlock
|
||||
if genesisBlock.Version() >= version.Bellatrix {
|
||||
if genesisBlock.Version() >= version.Bellatrix && genesisBlock.Version() < version.EPBS {
|
||||
wanted, err = genesisBlock.ToBlinded()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -715,7 +727,7 @@ func TestStore_GenesisBlock_CanGetHighestAt(t *testing.T) {
|
||||
b, err = db.Block(ctx, root)
|
||||
require.NoError(t, err)
|
||||
wanted = genesisBlock
|
||||
if genesisBlock.Version() >= version.Bellatrix {
|
||||
if genesisBlock.Version() >= version.Bellatrix && genesisBlock.Version() < version.EPBS {
|
||||
wanted, err = genesisBlock.ToBlinded()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -811,7 +823,7 @@ func TestStore_BlocksBySlot_BlockRootsBySlot(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
|
||||
wanted := b1
|
||||
if b1.Version() >= version.Bellatrix {
|
||||
if b1.Version() >= version.Bellatrix && b1.Version() < version.EPBS {
|
||||
wanted, err = b1.ToBlinded()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -827,7 +839,7 @@ func TestStore_BlocksBySlot_BlockRootsBySlot(t *testing.T) {
|
||||
t.Fatalf("Expected 2 blocks, received %d blocks", len(retrievedBlocks))
|
||||
}
|
||||
wanted = b2
|
||||
if b2.Version() >= version.Bellatrix {
|
||||
if b2.Version() >= version.Bellatrix && b2.Version() < version.EPBS {
|
||||
wanted, err = b2.ToBlinded()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -837,7 +849,7 @@ func TestStore_BlocksBySlot_BlockRootsBySlot(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, true, proto.Equal(wantedPb, retrieved0Pb), "Wanted: %v, received: %v", retrievedBlocks[0], wanted)
|
||||
wanted = b3
|
||||
if b3.Version() >= version.Bellatrix {
|
||||
if b3.Version() >= version.Bellatrix && b3.Version() < version.EPBS {
|
||||
wanted, err = b3.ToBlinded()
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
@@ -78,6 +78,8 @@ func isSSZStorageFormat(obj interface{}) bool {
|
||||
return true
|
||||
case *ethpb.VoluntaryExit:
|
||||
return true
|
||||
case *ethpb.SignedBlindPayloadEnvelope:
|
||||
return true
|
||||
case *ethpb.ValidatorRegistrationV1:
|
||||
return true
|
||||
default:
|
||||
|
||||
@@ -65,3 +65,10 @@ func hasElectraBlindKey(enc []byte) bool {
|
||||
}
|
||||
return bytes.Equal(enc[:len(electraBlindKey)], electraBlindKey)
|
||||
}
|
||||
|
||||
func hasEpbsKey(enc []byte) bool {
|
||||
if len(epbsKey) >= len(enc) {
|
||||
return false
|
||||
}
|
||||
return bytes.Equal(enc[:len(epbsKey)], epbsKey)
|
||||
}
|
||||
|
||||
@@ -118,6 +118,9 @@ var Buckets = [][]byte{
|
||||
|
||||
feeRecipientBucket,
|
||||
registrationBucket,
|
||||
|
||||
// ePBS
|
||||
executionPayloadEnvelopeBucket,
|
||||
}
|
||||
|
||||
// KVStoreOption is a functional option that modifies a kv.Store.
|
||||
|
||||
@@ -7,15 +7,16 @@ package kv
|
||||
// it easy to scan for keys that have a certain shard number as a prefix and return those
|
||||
// corresponding attestations.
|
||||
var (
|
||||
blocksBucket = []byte("blocks")
|
||||
stateBucket = []byte("state")
|
||||
stateSummaryBucket = []byte("state-summary")
|
||||
chainMetadataBucket = []byte("chain-metadata")
|
||||
checkpointBucket = []byte("check-point")
|
||||
powchainBucket = []byte("powchain")
|
||||
stateValidatorsBucket = []byte("state-validators")
|
||||
feeRecipientBucket = []byte("fee-recipient")
|
||||
registrationBucket = []byte("registration")
|
||||
blocksBucket = []byte("blocks")
|
||||
stateBucket = []byte("state")
|
||||
stateSummaryBucket = []byte("state-summary")
|
||||
chainMetadataBucket = []byte("chain-metadata")
|
||||
checkpointBucket = []byte("check-point")
|
||||
powchainBucket = []byte("powchain")
|
||||
stateValidatorsBucket = []byte("state-validators")
|
||||
feeRecipientBucket = []byte("fee-recipient")
|
||||
registrationBucket = []byte("registration")
|
||||
executionPayloadEnvelopeBucket = []byte("execution-payload-envelope")
|
||||
|
||||
// Deprecated: This bucket was migrated in PR 6461. Do not use, except for migrations.
|
||||
slotsHasObjectBucket = []byte("slots-has-objects")
|
||||
@@ -50,6 +51,7 @@ var (
|
||||
denebBlindKey = []byte("blind-deneb")
|
||||
electraKey = []byte("electra")
|
||||
electraBlindKey = []byte("blind-electra")
|
||||
epbsKey = []byte("epbs")
|
||||
|
||||
// block root included in the beacon state used by weak subjectivity initial sync
|
||||
originCheckpointBlockRootKey = []byte("origin-checkpoint-block-root")
|
||||
|
||||
@@ -252,6 +252,10 @@ func (s *Store) saveStatesEfficientInternal(ctx context.Context, tx *bolt.Tx, bl
|
||||
if err := s.processElectra(ctx, rawType, rt[:], bucket, valIdxBkt, validatorKeys[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
case *ethpb.BeaconStateEPBS:
|
||||
if err := s.processEPBS(ctx, rawType, rt[:], bucket, valIdxBkt, validatorKeys[i]); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return errors.New("invalid state type")
|
||||
}
|
||||
@@ -367,6 +371,24 @@ func (s *Store) processElectra(ctx context.Context, pbState *ethpb.BeaconStateEl
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) processEPBS(ctx context.Context, pbState *ethpb.BeaconStateEPBS, rootHash []byte, bucket, valIdxBkt *bolt.Bucket, validatorKey []byte) error {
|
||||
valEntries := pbState.Validators
|
||||
pbState.Validators = make([]*ethpb.Validator, 0)
|
||||
rawObj, err := pbState.MarshalSSZ()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
encodedState := snappy.Encode(nil, append(epbsKey, rawObj...))
|
||||
if err := bucket.Put(rootHash, encodedState); err != nil {
|
||||
return err
|
||||
}
|
||||
pbState.Validators = valEntries
|
||||
if err := valIdxBkt.Put(rootHash, validatorKey); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Store) storeValidatorEntriesSeparately(ctx context.Context, tx *bolt.Tx, validatorsEntries map[string]*ethpb.Validator) error {
|
||||
valBkt := tx.Bucket(stateValidatorsBucket)
|
||||
for hashStr, validatorEntry := range validatorsEntries {
|
||||
@@ -516,6 +538,19 @@ func (s *Store) unmarshalState(_ context.Context, enc []byte, validatorEntries [
|
||||
}
|
||||
|
||||
switch {
|
||||
case hasEpbsKey(enc):
|
||||
protoState := ðpb.BeaconStateEPBS{}
|
||||
if err := protoState.UnmarshalSSZ(enc[len(epbsKey):]); err != nil {
|
||||
return nil, errors.Wrap(err, "failed to unmarshal encoding for EPBS")
|
||||
}
|
||||
ok, err := s.isStateValidatorMigrationOver()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ok {
|
||||
protoState.Validators = validatorEntries
|
||||
}
|
||||
return statenative.InitializeFromProtoEpbs(protoState)
|
||||
case hasElectraKey(enc):
|
||||
protoState := ðpb.BeaconStateElectra{}
|
||||
if err := protoState.UnmarshalSSZ(enc[len(electraKey):]); err != nil {
|
||||
@@ -675,6 +710,19 @@ func marshalState(ctx context.Context, st state.ReadOnlyBeaconState) ([]byte, er
|
||||
return nil, err
|
||||
}
|
||||
return snappy.Encode(nil, append(electraKey, rawObj...)), nil
|
||||
case *ethpb.BeaconStateEPBS:
|
||||
rState, ok := st.ToProtoUnsafe().(*ethpb.BeaconStateEPBS)
|
||||
if !ok {
|
||||
return nil, errors.New("non valid inner state")
|
||||
}
|
||||
if rState == nil {
|
||||
return nil, errors.New("nil state")
|
||||
}
|
||||
rawObj, err := rState.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snappy.Encode(nil, append(epbsKey, rawObj...)), nil
|
||||
default:
|
||||
return nil, errors.New("invalid inner state")
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
statenative "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
|
||||
@@ -20,6 +21,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util/random"
|
||||
bolt "go.etcd.io/bbolt"
|
||||
)
|
||||
|
||||
@@ -159,6 +161,16 @@ func TestState_CanSaveRetrieve(t *testing.T) {
|
||||
},
|
||||
rootSeed: 'E',
|
||||
},
|
||||
{
|
||||
name: "epbs",
|
||||
s: func() state.BeaconState {
|
||||
stPb := random.BeaconState(t)
|
||||
st, err := statenative.InitializeFromProtoUnsafeEpbs(stPb)
|
||||
require.NoError(t, err)
|
||||
return st
|
||||
},
|
||||
rootSeed: 'F',
|
||||
},
|
||||
}
|
||||
|
||||
db := setupDB(t)
|
||||
@@ -1113,6 +1125,26 @@ func TestDenebState_CanDelete(t *testing.T) {
|
||||
require.Equal(t, state.ReadOnlyBeaconState(nil), savedS, "Unsaved state should've been nil")
|
||||
}
|
||||
|
||||
func TestEpbsState_CanDelete(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
|
||||
r := [32]byte{'A'}
|
||||
|
||||
require.Equal(t, false, db.HasState(context.Background(), r))
|
||||
|
||||
s := random.BeaconState(t)
|
||||
st, err := statenative.InitializeFromProtoUnsafeEpbs(s)
|
||||
require.NoError(t, err)
|
||||
|
||||
require.NoError(t, db.SaveState(context.Background(), st, r))
|
||||
require.Equal(t, true, db.HasState(context.Background(), r))
|
||||
|
||||
require.NoError(t, db.DeleteState(context.Background(), r))
|
||||
savedS, err := db.State(context.Background(), r)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, state.ReadOnlyBeaconState(nil), savedS, "Unsaved state should've been nil")
|
||||
}
|
||||
|
||||
func TestStateDeneb_CanSaveRetrieveValidatorEntries(t *testing.T) {
|
||||
db := setupDB(t)
|
||||
|
||||
|
||||
@@ -267,11 +267,12 @@ func (f *ForkChoice) updateBalances() error {
|
||||
newBalances := f.justifiedBalances
|
||||
zHash := params.BeaconConfig().ZeroHash
|
||||
|
||||
for index, vote := range f.votes {
|
||||
for index := 0; index < len(f.votes); index++ {
|
||||
// Skip if validator has been slashed
|
||||
if f.store.slashedIndices[primitives.ValidatorIndex(index)] {
|
||||
continue
|
||||
}
|
||||
vote := &f.votes[index]
|
||||
// Skip if validator has never voted for current root and next root (i.e. if the
|
||||
// votes are zero hash aka genesis block), there's nothing to compute.
|
||||
if vote.currentRoot == zHash && vote.nextRoot == zHash {
|
||||
|
||||
@@ -11,17 +11,17 @@ import (
|
||||
|
||||
// gossipTopicMappings represent the protocol ID to protobuf message type map for easy
|
||||
// lookup.
|
||||
var gossipTopicMappings = map[string]proto.Message{
|
||||
BlockSubnetTopicFormat: ðpb.SignedBeaconBlock{},
|
||||
AttestationSubnetTopicFormat: ðpb.Attestation{},
|
||||
ExitSubnetTopicFormat: ðpb.SignedVoluntaryExit{},
|
||||
ProposerSlashingSubnetTopicFormat: ðpb.ProposerSlashing{},
|
||||
AttesterSlashingSubnetTopicFormat: ðpb.AttesterSlashing{},
|
||||
AggregateAndProofSubnetTopicFormat: ðpb.SignedAggregateAttestationAndProof{},
|
||||
SyncContributionAndProofSubnetTopicFormat: ðpb.SignedContributionAndProof{},
|
||||
SyncCommitteeSubnetTopicFormat: ðpb.SyncCommitteeMessage{},
|
||||
BlsToExecutionChangeSubnetTopicFormat: ðpb.SignedBLSToExecutionChange{},
|
||||
BlobSubnetTopicFormat: ðpb.BlobSidecar{},
|
||||
var gossipTopicMappings = map[string]func() proto.Message{
|
||||
BlockSubnetTopicFormat: func() proto.Message { return ðpb.SignedBeaconBlock{} },
|
||||
AttestationSubnetTopicFormat: func() proto.Message { return ðpb.Attestation{} },
|
||||
ExitSubnetTopicFormat: func() proto.Message { return ðpb.SignedVoluntaryExit{} },
|
||||
ProposerSlashingSubnetTopicFormat: func() proto.Message { return ðpb.ProposerSlashing{} },
|
||||
AttesterSlashingSubnetTopicFormat: func() proto.Message { return ðpb.AttesterSlashing{} },
|
||||
AggregateAndProofSubnetTopicFormat: func() proto.Message { return ðpb.SignedAggregateAttestationAndProof{} },
|
||||
SyncContributionAndProofSubnetTopicFormat: func() proto.Message { return ðpb.SignedContributionAndProof{} },
|
||||
SyncCommitteeSubnetTopicFormat: func() proto.Message { return ðpb.SyncCommitteeMessage{} },
|
||||
BlsToExecutionChangeSubnetTopicFormat: func() proto.Message { return ðpb.SignedBLSToExecutionChange{} },
|
||||
BlobSubnetTopicFormat: func() proto.Message { return ðpb.BlobSidecar{} },
|
||||
}
|
||||
|
||||
// GossipTopicMappings is a function to return the assigned data type
|
||||
@@ -44,27 +44,35 @@ func GossipTopicMappings(topic string, epoch primitives.Epoch) proto.Message {
|
||||
if epoch >= params.BeaconConfig().AltairForkEpoch {
|
||||
return ðpb.SignedBeaconBlockAltair{}
|
||||
}
|
||||
return gossipTopicMappings[topic]
|
||||
return gossipMessage(topic)
|
||||
case AttestationSubnetTopicFormat:
|
||||
if epoch >= params.BeaconConfig().ElectraForkEpoch {
|
||||
return ðpb.AttestationElectra{}
|
||||
}
|
||||
return gossipTopicMappings[topic]
|
||||
return gossipMessage(topic)
|
||||
case AttesterSlashingSubnetTopicFormat:
|
||||
if epoch >= params.BeaconConfig().ElectraForkEpoch {
|
||||
return ðpb.AttesterSlashingElectra{}
|
||||
}
|
||||
return gossipTopicMappings[topic]
|
||||
return gossipMessage(topic)
|
||||
case AggregateAndProofSubnetTopicFormat:
|
||||
if epoch >= params.BeaconConfig().ElectraForkEpoch {
|
||||
return ðpb.SignedAggregateAttestationAndProofElectra{}
|
||||
}
|
||||
return gossipTopicMappings[topic]
|
||||
return gossipMessage(topic)
|
||||
default:
|
||||
return gossipTopicMappings[topic]
|
||||
return gossipMessage(topic)
|
||||
}
|
||||
}
|
||||
|
||||
func gossipMessage(topic string) proto.Message {
|
||||
msgGen, ok := gossipTopicMappings[topic]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return msgGen()
|
||||
}
|
||||
|
||||
// AllTopics returns all topics stored in our
|
||||
// gossip mapping.
|
||||
func AllTopics() []string {
|
||||
@@ -81,7 +89,7 @@ var GossipTypeMapping = make(map[reflect.Type]string, len(gossipTopicMappings))
|
||||
|
||||
func init() {
|
||||
for k, v := range gossipTopicMappings {
|
||||
GossipTypeMapping[reflect.TypeOf(v)] = k
|
||||
GossipTypeMapping[reflect.TypeOf(v())] = k
|
||||
}
|
||||
// Specially handle Altair objects.
|
||||
GossipTypeMapping[reflect.TypeOf(ðpb.SignedBeaconBlockAltair{})] = BlockSubnetTopicFormat
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestMappingHasNoDuplicates(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
m := make(map[reflect.Type]bool)
|
||||
for _, v := range gossipTopicMappings {
|
||||
if _, ok := m[reflect.TypeOf(v)]; ok {
|
||||
if _, ok := m[reflect.TypeOf(v())]; ok {
|
||||
t.Errorf("%T is duplicated in the topic mapping", v)
|
||||
}
|
||||
m[reflect.TypeOf(v)] = true
|
||||
|
||||
@@ -20,6 +20,10 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
// Variables defined in the placeholderFields will not be tested in `TestGetSpec`.
|
||||
// These are variables that we don't use in Prysm. (i.e. future hardfork, light client... etc)
|
||||
var placeholderFields = []string{"DOMAIN_BEACON_BUILDER", "DOMAIN_PTC_ATTESTER"}
|
||||
|
||||
func TestGetDepositContract(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
config := params.BeaconConfig().Copy()
|
||||
@@ -192,7 +196,7 @@ func TestGetSpec(t *testing.T) {
|
||||
data, ok := resp.Data.(map[string]interface{})
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
assert.Equal(t, 155, len(data))
|
||||
assert.Equal(t, 157, len(data))
|
||||
for k, v := range data {
|
||||
t.Run(k, func(t *testing.T) {
|
||||
switch k {
|
||||
@@ -530,6 +534,12 @@ func TestGetSpec(t *testing.T) {
|
||||
case "MAX_DEPOSIT_REQUESTS_PER_PAYLOAD":
|
||||
assert.Equal(t, "93", v)
|
||||
default:
|
||||
for _, pf := range placeholderFields {
|
||||
if k == pf {
|
||||
t.Logf("Skipping placeholder field: %s", k)
|
||||
return
|
||||
}
|
||||
}
|
||||
t.Errorf("Incorrect key: %s", k)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -459,7 +459,7 @@ func (s *Server) sendPayloadAttributes(ctx context.Context, w http.ResponseWrite
|
||||
SuggestedFeeRecipient: hexutil.Encode(headPayload.FeeRecipient()),
|
||||
Withdrawals: structs.WithdrawalsFromConsensus(withdrawals),
|
||||
}
|
||||
case version.Deneb:
|
||||
case version.Deneb, version.Electra:
|
||||
withdrawals, _, err := headState.ExpectedWithdrawals()
|
||||
if err != nil {
|
||||
return write(w, flusher, "Could not get head state expected withdrawals: "+err.Error())
|
||||
|
||||
@@ -24,6 +24,7 @@ go_library(
|
||||
"proposer_exits.go",
|
||||
"proposer_slashings.go",
|
||||
"proposer_sync_aggregate.go",
|
||||
"ptc_attester.go",
|
||||
"server.go",
|
||||
"status.go",
|
||||
"sync_committee.go",
|
||||
@@ -82,6 +83,7 @@ go_library(
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//proto/prysm/v1alpha1/attestation:go_default_library",
|
||||
"//proto/prysm/v1alpha1/attestation/aggregation:go_default_library",
|
||||
"//proto/prysm/v1alpha1/attestation/aggregation/attestations:go_default_library",
|
||||
"//proto/prysm/v1alpha1/attestation/aggregation/sync_contribution:go_default_library",
|
||||
|
||||
@@ -39,54 +39,59 @@ func (vs *Server) GetAttestationData(ctx context.Context, req *ethpb.Attestation
|
||||
}
|
||||
|
||||
// ProposeAttestation is a function called by an attester to vote
|
||||
// on a block via an attestation object as defined in the Ethereum Serenity specification.
|
||||
// on a block via an attestation object as defined in the Ethereum specification.
|
||||
func (vs *Server) ProposeAttestation(ctx context.Context, att *ethpb.Attestation) (*ethpb.AttestResponse, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "AttesterServer.ProposeAttestation")
|
||||
defer span.End()
|
||||
|
||||
if _, err := bls.SignatureFromBytes(att.Signature); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Incorrect attestation signature")
|
||||
}
|
||||
|
||||
root, err := att.Data.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not tree hash attestation: %v", err)
|
||||
}
|
||||
|
||||
// Broadcast the unaggregated attestation on a feed to notify other services in the beacon node
|
||||
// of a received unaggregated attestation.
|
||||
vs.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: operation.UnaggregatedAttReceived,
|
||||
Data: &operation.UnAggregatedAttReceivedData{
|
||||
Attestation: att,
|
||||
},
|
||||
})
|
||||
|
||||
// Determine subnet to broadcast attestation to
|
||||
wantedEpoch := slots.ToEpoch(att.Data.Slot)
|
||||
vals, err := vs.HeadFetcher.HeadValidatorsIndices(ctx, wantedEpoch)
|
||||
resp, err := vs.proposeAtt(ctx, att, att.GetData().CommitteeIndex)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subnet := helpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), att.Data.CommitteeIndex, att.Data.Slot)
|
||||
|
||||
// Broadcast the new attestation to the network.
|
||||
if err := vs.P2P.BroadcastAttestation(ctx, subnet, att); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not broadcast attestation: %v", err)
|
||||
}
|
||||
|
||||
go func() {
|
||||
ctx = trace.NewContext(context.Background(), trace.FromContext(ctx))
|
||||
attCopy := ethpb.CopyAttestation(att)
|
||||
if err := vs.AttPool.SaveUnaggregatedAttestation(attCopy); err != nil {
|
||||
log.WithError(err).Error("Could not handle attestation in operations service")
|
||||
log.WithError(err).Error("Could not save unaggregated attestation")
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
return ðpb.AttestResponse{
|
||||
AttestationDataRoot: root[:],
|
||||
}, nil
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// ProposeAttestationElectra is a function called by an attester to vote
|
||||
// on a block via an attestation object as defined in the Ethereum specification.
|
||||
func (vs *Server) ProposeAttestationElectra(ctx context.Context, att *ethpb.AttestationElectra) (*ethpb.AttestResponse, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "AttesterServer.ProposeAttestationElectra")
|
||||
defer span.End()
|
||||
|
||||
if att.GetData().CommitteeIndex != 0 {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Committee index must be set to 0")
|
||||
}
|
||||
committeeIndices := helpers.CommitteeIndices(att.CommitteeBits)
|
||||
if len(committeeIndices) == 0 {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Committee bits has no bit set")
|
||||
}
|
||||
if len(committeeIndices) > 1 {
|
||||
return nil, status.Errorf(codes.InvalidArgument, "Committee bits has more than one bit set")
|
||||
}
|
||||
|
||||
resp, err := vs.proposeAtt(ctx, att, committeeIndices[0])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
go func() {
|
||||
ctx = trace.NewContext(context.Background(), trace.FromContext(ctx))
|
||||
attCopy := ethpb.CopyAttestationElectra(att)
|
||||
if err := vs.AttPool.SaveUnaggregatedAttestation(attCopy); err != nil {
|
||||
log.WithError(err).Error("Could not save unaggregated attestation")
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// SubscribeCommitteeSubnets subscribes to the committee ID subnet given subscribe request.
|
||||
@@ -136,3 +141,40 @@ func (vs *Server) SubscribeCommitteeSubnets(ctx context.Context, req *ethpb.Comm
|
||||
|
||||
return &emptypb.Empty{}, nil
|
||||
}
|
||||
|
||||
func (vs *Server) proposeAtt(ctx context.Context, att ethpb.Att, committee primitives.CommitteeIndex) (*ethpb.AttestResponse, error) {
|
||||
if _, err := bls.SignatureFromBytes(att.GetSignature()); err != nil {
|
||||
return nil, status.Error(codes.InvalidArgument, "Incorrect attestation signature")
|
||||
}
|
||||
|
||||
root, err := att.GetData().HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not tree hash attestation: %v", err)
|
||||
}
|
||||
|
||||
// Broadcast the unaggregated attestation on a feed to notify other services in the beacon node
|
||||
// of a received unaggregated attestation.
|
||||
vs.OperationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: operation.UnaggregatedAttReceived,
|
||||
Data: &operation.UnAggregatedAttReceivedData{
|
||||
Attestation: att,
|
||||
},
|
||||
})
|
||||
|
||||
// Determine subnet to broadcast attestation to
|
||||
wantedEpoch := slots.ToEpoch(att.GetData().Slot)
|
||||
vals, err := vs.HeadFetcher.HeadValidatorsIndices(ctx, wantedEpoch)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
subnet := helpers.ComputeSubnetFromCommitteeAndSlot(uint64(len(vals)), committee, att.GetData().Slot)
|
||||
|
||||
// Broadcast the new attestation to the network.
|
||||
if err := vs.P2P.BroadcastAttestation(ctx, subnet, att); err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Could not broadcast attestation: %v", err)
|
||||
}
|
||||
|
||||
return ðpb.AttestResponse{
|
||||
AttestationDataRoot: root[:],
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import (
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func TestProposeAttestation_OK(t *testing.T) {
|
||||
func TestProposeAttestation(t *testing.T) {
|
||||
attesterServer := &Server{
|
||||
HeadFetcher: &mock.ChainService{},
|
||||
P2P: &mockp2p.MockBroadcaster{},
|
||||
@@ -53,24 +53,107 @@ func TestProposeAttestation_OK(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
state, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1))
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
|
||||
sk, err := bls.RandKey()
|
||||
require.NoError(t, err)
|
||||
sig := sk.Sign([]byte("dummy_test_data"))
|
||||
req := ðpb.Attestation{
|
||||
Signature: sig.Marshal(),
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: root[:],
|
||||
Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Target: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
},
|
||||
}
|
||||
_, err = attesterServer.ProposeAttestation(context.Background(), req)
|
||||
assert.NoError(t, err)
|
||||
|
||||
t.Run("Phase 0", func(t *testing.T) {
|
||||
state, err := util.NewBeaconState()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1))
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
|
||||
req := ðpb.Attestation{
|
||||
Signature: sig.Marshal(),
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: root[:],
|
||||
Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Target: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
},
|
||||
}
|
||||
_, err = attesterServer.ProposeAttestation(context.Background(), req)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("Electra", func(t *testing.T) {
|
||||
state, err := util.NewBeaconStateElectra()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1))
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
|
||||
cb := primitives.NewAttestationCommitteeBits()
|
||||
cb.SetBitAt(0, true)
|
||||
req := ðpb.AttestationElectra{
|
||||
Signature: sig.Marshal(),
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: root[:],
|
||||
Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Target: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
},
|
||||
CommitteeBits: cb,
|
||||
}
|
||||
_, err = attesterServer.ProposeAttestationElectra(context.Background(), req)
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
t.Run("Electra - non-zero committee index", func(t *testing.T) {
|
||||
state, err := util.NewBeaconStateElectra()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1))
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
|
||||
cb := primitives.NewAttestationCommitteeBits()
|
||||
cb.SetBitAt(0, true)
|
||||
req := ðpb.AttestationElectra{
|
||||
Signature: sig.Marshal(),
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: root[:],
|
||||
Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Target: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
CommitteeIndex: 1,
|
||||
},
|
||||
CommitteeBits: cb,
|
||||
}
|
||||
_, err = attesterServer.ProposeAttestationElectra(context.Background(), req)
|
||||
assert.ErrorContains(t, "Committee index must be set to 0", err)
|
||||
})
|
||||
t.Run("Electra - no committee bit set", func(t *testing.T) {
|
||||
state, err := util.NewBeaconStateElectra()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1))
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
|
||||
req := ðpb.AttestationElectra{
|
||||
Signature: sig.Marshal(),
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: root[:],
|
||||
Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Target: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
},
|
||||
CommitteeBits: primitives.NewAttestationCommitteeBits(),
|
||||
}
|
||||
_, err = attesterServer.ProposeAttestationElectra(context.Background(), req)
|
||||
assert.ErrorContains(t, "Committee bits has no bit set", err)
|
||||
})
|
||||
t.Run("Electra - multiple committee bits set", func(t *testing.T) {
|
||||
state, err := util.NewBeaconStateElectra()
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, state.SetSlot(params.BeaconConfig().SlotsPerEpoch+1))
|
||||
require.NoError(t, state.SetValidators(validators))
|
||||
|
||||
cb := primitives.NewAttestationCommitteeBits()
|
||||
cb.SetBitAt(0, true)
|
||||
cb.SetBitAt(1, true)
|
||||
req := ðpb.AttestationElectra{
|
||||
Signature: sig.Marshal(),
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: root[:],
|
||||
Source: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
Target: ðpb.Checkpoint{Root: make([]byte, 32)},
|
||||
},
|
||||
CommitteeBits: cb,
|
||||
}
|
||||
_, err = attesterServer.ProposeAttestationElectra(context.Background(), req)
|
||||
assert.ErrorContains(t, "Committee bits has more than one bit set", err)
|
||||
})
|
||||
}
|
||||
|
||||
func TestProposeAttestation_IncorrectSignature(t *testing.T) {
|
||||
|
||||
@@ -108,6 +108,7 @@ func (vs *Server) duties(ctx context.Context, req *ethpb.DutiesRequest) (*ethpb.
|
||||
assignment.Committee = ca.Committee
|
||||
assignment.AttesterSlot = ca.AttesterSlot
|
||||
assignment.CommitteeIndex = ca.CommitteeIndex
|
||||
assignment.PtcSlot = ca.PtcSlot
|
||||
}
|
||||
// Save the next epoch assignments.
|
||||
ca, ok = nextEpochAssignments[idx]
|
||||
@@ -115,6 +116,7 @@ func (vs *Server) duties(ctx context.Context, req *ethpb.DutiesRequest) (*ethpb.
|
||||
nextAssignment.Committee = ca.Committee
|
||||
nextAssignment.AttesterSlot = ca.AttesterSlot
|
||||
nextAssignment.CommitteeIndex = ca.CommitteeIndex
|
||||
nextAssignment.PtcSlot = ca.PtcSlot
|
||||
}
|
||||
} else {
|
||||
// If the validator isn't in the beacon state, try finding their deposit to determine their status.
|
||||
|
||||
@@ -194,7 +194,7 @@ func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.Signed
|
||||
sBlk.SetEth1Data(eth1Data)
|
||||
|
||||
// Set deposit and attestation.
|
||||
deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, eth1Data) // TODO: split attestations and deposits
|
||||
deposits, atts, err := vs.packDepositsAndAttestations(ctx, head, sBlk.Block().Slot(), eth1Data) // TODO: split attestations and deposits
|
||||
if err != nil {
|
||||
sBlk.SetDeposits([]*ethpb.Deposit{})
|
||||
if err := sBlk.SetAttestations([]ethpb.Att{}); err != nil {
|
||||
|
||||
@@ -12,14 +12,17 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation"
|
||||
"github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation/aggregation"
|
||||
attaggregation "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/attestation/aggregation/attestations"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/time/slots"
|
||||
"go.opencensus.io/trace"
|
||||
)
|
||||
|
||||
type proposerAtts []ethpb.Att
|
||||
|
||||
func (vs *Server) packAttestations(ctx context.Context, latestState state.BeaconState) ([]ethpb.Att, error) {
|
||||
func (vs *Server) packAttestations(ctx context.Context, latestState state.BeaconState, blkSlot primitives.Slot) ([]ethpb.Att, error) {
|
||||
ctx, span := trace.StartSpan(ctx, "ProposerServer.packAttestations")
|
||||
defer span.End()
|
||||
|
||||
@@ -39,20 +42,37 @@ func (vs *Server) packAttestations(ctx context.Context, latestState state.Beacon
|
||||
}
|
||||
atts = append(atts, uAtts...)
|
||||
|
||||
postElectra := slots.ToEpoch(blkSlot) >= params.BeaconConfig().ElectraForkEpoch
|
||||
|
||||
versionAtts := make([]ethpb.Att, 0, len(atts))
|
||||
if postElectra {
|
||||
for _, a := range atts {
|
||||
if a.Version() == version.Electra {
|
||||
versionAtts = append(versionAtts, a)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for _, a := range atts {
|
||||
if a.Version() == version.Phase0 {
|
||||
versionAtts = append(versionAtts, a)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove duplicates from both aggregated/unaggregated attestations. This
|
||||
// prevents inefficient aggregates being created.
|
||||
atts, err = proposerAtts(atts).dedup()
|
||||
versionAtts, err = proposerAtts(versionAtts).dedup()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
attsByDataRoot := make(map[[32]byte][]ethpb.Att, len(atts))
|
||||
for _, att := range atts {
|
||||
attDataRoot, err := att.GetData().HashTreeRoot()
|
||||
attsByDataRoot := make(map[attestation.Id][]ethpb.Att, len(versionAtts))
|
||||
for _, att := range versionAtts {
|
||||
id, err := attestation.NewId(att, attestation.Data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, errors.Wrap(err, "could not create attestation ID")
|
||||
}
|
||||
attsByDataRoot[attDataRoot] = append(attsByDataRoot[attDataRoot], att)
|
||||
attsByDataRoot[id] = append(attsByDataRoot[id], att)
|
||||
}
|
||||
|
||||
attsForInclusion := proposerAtts(make([]ethpb.Att, 0))
|
||||
@@ -169,8 +189,18 @@ func (a proposerAtts) sortByProfitabilityUsingMaxCover() (proposerAtts, error) {
|
||||
|
||||
// limitToMaxAttestations limits attestations to maximum attestations per block.
|
||||
func (a proposerAtts) limitToMaxAttestations() proposerAtts {
|
||||
if uint64(len(a)) > params.BeaconConfig().MaxAttestations {
|
||||
return a[:params.BeaconConfig().MaxAttestations]
|
||||
if len(a) == 0 {
|
||||
return a
|
||||
}
|
||||
|
||||
var limit uint64
|
||||
if a[0].Version() == version.Phase0 {
|
||||
limit = params.BeaconConfig().MaxAttestations
|
||||
} else {
|
||||
limit = params.BeaconConfig().MaxAttestationsElectra
|
||||
}
|
||||
if uint64(len(a)) > limit {
|
||||
return a[:limit]
|
||||
}
|
||||
return a
|
||||
}
|
||||
@@ -182,13 +212,13 @@ func (a proposerAtts) dedup() (proposerAtts, error) {
|
||||
if len(a) < 2 {
|
||||
return a, nil
|
||||
}
|
||||
attsByDataRoot := make(map[[32]byte][]ethpb.Att, len(a))
|
||||
attsByDataRoot := make(map[attestation.Id][]ethpb.Att, len(a))
|
||||
for _, att := range a {
|
||||
attDataRoot, err := att.GetData().HashTreeRoot()
|
||||
id, err := attestation.NewId(att, attestation.Data)
|
||||
if err != nil {
|
||||
continue
|
||||
return nil, errors.Wrap(err, "failed to create attestation ID")
|
||||
}
|
||||
attsByDataRoot[attDataRoot] = append(attsByDataRoot[attDataRoot], att)
|
||||
attsByDataRoot[id] = append(attsByDataRoot[id], att)
|
||||
}
|
||||
|
||||
uniqAtts := make([]ethpb.Att, 0, len(a))
|
||||
|
||||
@@ -2,10 +2,13 @@ package validator
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"sort"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/operations/attestations"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
@@ -423,3 +426,106 @@ func TestProposer_ProposerAtts_dedup(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_packAttestations(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
phase0Att := ðpb.Attestation{
|
||||
AggregationBits: bitfield.Bitlist{0b11111},
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: make([]byte, 32),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
Root: make([]byte, 32),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
Root: make([]byte, 32),
|
||||
},
|
||||
},
|
||||
Signature: make([]byte, 96),
|
||||
}
|
||||
cb := primitives.NewAttestationCommitteeBits()
|
||||
cb.SetBitAt(0, true)
|
||||
electraAtt := ðpb.AttestationElectra{
|
||||
AggregationBits: bitfield.Bitlist{0b11111},
|
||||
CommitteeBits: cb,
|
||||
Data: ðpb.AttestationData{
|
||||
BeaconBlockRoot: make([]byte, 32),
|
||||
Source: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
Root: make([]byte, 32),
|
||||
},
|
||||
Target: ðpb.Checkpoint{
|
||||
Epoch: 0,
|
||||
Root: make([]byte, 32),
|
||||
},
|
||||
},
|
||||
Signature: make([]byte, 96),
|
||||
}
|
||||
pool := attestations.NewPool()
|
||||
require.NoError(t, pool.SaveAggregatedAttestations([]ethpb.Att{phase0Att, electraAtt}))
|
||||
s := &Server{AttPool: pool}
|
||||
|
||||
t.Run("Phase 0", func(t *testing.T) {
|
||||
st, _ := util.DeterministicGenesisState(t, 64)
|
||||
require.NoError(t, st.SetSlot(1))
|
||||
|
||||
atts, err := s.packAttestations(ctx, st, 0)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(atts))
|
||||
assert.DeepEqual(t, phase0Att, atts[0])
|
||||
})
|
||||
t.Run("Electra", func(t *testing.T) {
|
||||
params.SetupTestConfigCleanup(t)
|
||||
cfg := params.BeaconConfig().Copy()
|
||||
cfg.ElectraForkEpoch = 1
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
st, _ := util.DeterministicGenesisStateElectra(t, 64)
|
||||
require.NoError(t, st.SetSlot(params.BeaconConfig().SlotsPerEpoch+1))
|
||||
|
||||
atts, err := s.packAttestations(ctx, st, params.BeaconConfig().SlotsPerEpoch)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, len(atts))
|
||||
assert.DeepEqual(t, electraAtt, atts[0])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_limitToMaxAttestations(t *testing.T) {
|
||||
t.Run("Phase 0", func(t *testing.T) {
|
||||
atts := make([]ethpb.Att, params.BeaconConfig().MaxAttestations+1)
|
||||
for i := range atts {
|
||||
atts[i] = ðpb.Attestation{}
|
||||
}
|
||||
|
||||
// 1 less than limit
|
||||
pAtts := proposerAtts(atts[:len(atts)-3])
|
||||
assert.Equal(t, len(pAtts), len(pAtts.limitToMaxAttestations()))
|
||||
|
||||
// equal to limit
|
||||
pAtts = atts[:len(atts)-2]
|
||||
assert.Equal(t, len(pAtts), len(pAtts.limitToMaxAttestations()))
|
||||
|
||||
// 1 more than limit
|
||||
pAtts = atts
|
||||
assert.Equal(t, len(pAtts)-1, len(pAtts.limitToMaxAttestations()))
|
||||
})
|
||||
t.Run("Electra", func(t *testing.T) {
|
||||
atts := make([]ethpb.Att, params.BeaconConfig().MaxAttestationsElectra+1)
|
||||
for i := range atts {
|
||||
atts[i] = ðpb.AttestationElectra{}
|
||||
}
|
||||
|
||||
// 1 less than limit
|
||||
pAtts := proposerAtts(atts[:len(atts)-3])
|
||||
assert.Equal(t, len(pAtts), len(pAtts.limitToMaxAttestations()))
|
||||
|
||||
// equal to limit
|
||||
pAtts = atts[:len(atts)-2]
|
||||
assert.Equal(t, len(pAtts), len(pAtts.limitToMaxAttestations()))
|
||||
|
||||
// 1 more than limit
|
||||
pAtts = atts
|
||||
assert.Equal(t, len(pAtts)-1, len(pAtts.limitToMaxAttestations()))
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/container/trie"
|
||||
"github.com/prysmaticlabs/prysm/v5/math"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
@@ -20,7 +21,12 @@ import (
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
func (vs *Server) packDepositsAndAttestations(ctx context.Context, head state.BeaconState, eth1Data *ethpb.Eth1Data) ([]*ethpb.Deposit, []ethpb.Att, error) {
|
||||
func (vs *Server) packDepositsAndAttestations(
|
||||
ctx context.Context,
|
||||
head state.BeaconState,
|
||||
blkSlot primitives.Slot,
|
||||
eth1Data *ethpb.Eth1Data,
|
||||
) ([]*ethpb.Deposit, []ethpb.Att, error) {
|
||||
eg, egctx := errgroup.WithContext(ctx)
|
||||
var deposits []*ethpb.Deposit
|
||||
var atts []ethpb.Att
|
||||
@@ -43,7 +49,7 @@ func (vs *Server) packDepositsAndAttestations(ctx context.Context, head state.Be
|
||||
|
||||
eg.Go(func() error {
|
||||
// Pack aggregated attestations which have not been included in the beacon chain.
|
||||
localAtts, err := vs.packAttestations(egctx, head)
|
||||
localAtts, err := vs.packAttestations(egctx, head, blkSlot)
|
||||
if err != nil {
|
||||
return status.Errorf(codes.Internal, "Could not get attestations to pack into block: %v", err)
|
||||
}
|
||||
|
||||
17
beacon-chain/rpc/prysm/v1alpha1/validator/ptc_attester.go
Normal file
17
beacon-chain/rpc/prysm/v1alpha1/validator/ptc_attester.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package validator
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/golang/protobuf/ptypes/empty"
|
||||
"github.com/pkg/errors"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func (vs *Server) GetPayloadAttestationData(ctx context.Context, req *ethpb.GetPayloadAttestationDataRequest) (*ethpb.PayloadAttestationData, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
|
||||
func (vs *Server) SubmitPayloadAttestation(ctx context.Context, in *ethpb.PayloadAttestationMessage) (*empty.Empty, error) {
|
||||
return nil, errors.New("not implemented")
|
||||
}
|
||||
@@ -5,6 +5,7 @@ go_library(
|
||||
srcs = [
|
||||
"error.go",
|
||||
"interfaces.go",
|
||||
"interfaces_epbs.go",
|
||||
"prometheus.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/state",
|
||||
|
||||
@@ -60,6 +60,7 @@ type ReadOnlyBeaconState interface {
|
||||
ReadOnlySyncCommittee
|
||||
ReadOnlyDeposits
|
||||
ReadOnlyConsolidations
|
||||
ReadOnlyEpbsFields
|
||||
ToProtoUnsafe() interface{}
|
||||
ToProto() interface{}
|
||||
GenesisTime() uint64
|
||||
@@ -94,6 +95,7 @@ type WriteOnlyBeaconState interface {
|
||||
WriteOnlyConsolidations
|
||||
WriteOnlyWithdrawals
|
||||
WriteOnlyDeposits
|
||||
WriteOnlyEpbsFields
|
||||
SetGenesisTime(val uint64) error
|
||||
SetGenesisValidatorsRoot(val []byte) error
|
||||
SetSlot(val primitives.Slot) error
|
||||
@@ -200,6 +202,7 @@ type ReadOnlyWithdrawals interface {
|
||||
NextWithdrawalIndex() (uint64, error)
|
||||
PendingBalanceToWithdraw(idx primitives.ValidatorIndex) (uint64, error)
|
||||
NumPendingPartialWithdrawals() (uint64, error)
|
||||
HasPendingBalanceToWithdraw(idx primitives.ValidatorIndex) (bool, error)
|
||||
}
|
||||
|
||||
// ReadOnlyParticipation defines a struct which only has read access to participation methods.
|
||||
|
||||
21
beacon-chain/state/interfaces_epbs.go
Normal file
21
beacon-chain/state/interfaces_epbs.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package state
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
)
|
||||
|
||||
type ReadOnlyEpbsFields interface {
|
||||
IsParentBlockFull() bool
|
||||
ExecutionPayloadHeader() *enginev1.ExecutionPayloadHeaderEPBS
|
||||
LatestBlockHash() []byte
|
||||
LatestFullSlot() primitives.Slot
|
||||
LastWithdrawalsRoot() []byte
|
||||
}
|
||||
|
||||
type WriteOnlyEpbsFields interface {
|
||||
SetExecutionPayloadHeader(val *enginev1.ExecutionPayloadHeaderEPBS)
|
||||
SetLatestBlockHash(val []byte)
|
||||
SetLatestFullSlot(val primitives.Slot)
|
||||
SetLastWithdrawalsRoot(val []byte)
|
||||
}
|
||||
@@ -13,11 +13,13 @@ go_library(
|
||||
"getters_checkpoint.go",
|
||||
"getters_consolidation.go",
|
||||
"getters_deposit_requests.go",
|
||||
"getters_epbs.go",
|
||||
"getters_eth1.go",
|
||||
"getters_exit.go",
|
||||
"getters_misc.go",
|
||||
"getters_participation.go",
|
||||
"getters_payload_header.go",
|
||||
"getters_payload_header_epbs.go",
|
||||
"getters_randao.go",
|
||||
"getters_state.go",
|
||||
"getters_sync_committee.go",
|
||||
@@ -34,6 +36,7 @@ go_library(
|
||||
"setters_churn.go",
|
||||
"setters_consolidation.go",
|
||||
"setters_deposit_requests.go",
|
||||
"setters_epbs.go",
|
||||
"setters_eth1.go",
|
||||
"setters_misc.go",
|
||||
"setters_participation.go",
|
||||
@@ -46,6 +49,7 @@ go_library(
|
||||
"spec_parameters.go",
|
||||
"ssz.go",
|
||||
"state_trie.go",
|
||||
"state_trie_epbs.go",
|
||||
"types.go",
|
||||
"validator_index_cache.go",
|
||||
],
|
||||
@@ -98,6 +102,7 @@ go_test(
|
||||
"getters_deposit_requests_test.go",
|
||||
"getters_exit_test.go",
|
||||
"getters_participation_test.go",
|
||||
"getters_setters_epbs_test.go",
|
||||
"getters_test.go",
|
||||
"getters_validator_test.go",
|
||||
"getters_withdrawal_test.go",
|
||||
@@ -119,6 +124,7 @@ go_test(
|
||||
"setters_withdrawal_test.go",
|
||||
"state_fuzz_test.go",
|
||||
"state_test.go",
|
||||
"state_trie_epbs_test.go",
|
||||
"state_trie_test.go",
|
||||
"types_test.go",
|
||||
"validator_index_cache_test.go",
|
||||
@@ -152,6 +158,7 @@ go_test(
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"//testing/util/random:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
|
||||
"@com_github_golang_snappy//:go_default_library",
|
||||
|
||||
@@ -60,6 +60,11 @@ type BeaconState struct {
|
||||
latestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra
|
||||
nextWithdrawalIndex uint64
|
||||
nextWithdrawalValidatorIndex primitives.ValidatorIndex
|
||||
// ePBS fields
|
||||
latestBlockHash [32]byte
|
||||
latestFullSlot primitives.Slot
|
||||
executionPayloadHeader *enginev1.ExecutionPayloadHeaderEPBS
|
||||
lastWithdrawalsRoot [32]byte
|
||||
|
||||
// Electra fields
|
||||
depositRequestsStartIndex uint64
|
||||
|
||||
@@ -60,6 +60,11 @@ type BeaconState struct {
|
||||
latestExecutionPayloadHeaderElectra *enginev1.ExecutionPayloadHeaderElectra
|
||||
nextWithdrawalIndex uint64
|
||||
nextWithdrawalValidatorIndex primitives.ValidatorIndex
|
||||
// ePBS fields
|
||||
latestBlockHash [32]byte
|
||||
latestFullSlot primitives.Slot
|
||||
executionPayloadHeader *enginev1.ExecutionPayloadHeaderEPBS
|
||||
lastWithdrawalsRoot [32]byte
|
||||
|
||||
// Electra fields
|
||||
depositRequestsStartIndex uint64
|
||||
|
||||
51
beacon-chain/state/state-native/getters_epbs.go
Normal file
51
beacon-chain/state/state-native/getters_epbs.go
Normal file
@@ -0,0 +1,51 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
)
|
||||
|
||||
// ExecutionPayloadHeader retrieves a copy of the execution payload header.
|
||||
// It returns an error if the operation is not supported for the beacon state's version.
|
||||
func (b *BeaconState) ExecutionPayloadHeader() *enginev1.ExecutionPayloadHeaderEPBS {
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.executionPayloadHeaderVal()
|
||||
}
|
||||
|
||||
// IsParentBlockFull checks if the last committed payload header was fulfilled.
|
||||
// Returns true if both the beacon block and payload were present.
|
||||
// Call this function on a beacon state before processing the execution payload header.
|
||||
func (b *BeaconState) IsParentBlockFull() bool {
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
headerBlockHash := bytesutil.ToBytes32(b.executionPayloadHeader.BlockHash)
|
||||
return headerBlockHash == b.latestBlockHash
|
||||
}
|
||||
|
||||
// LatestBlockHash returns the latest block hash.
|
||||
func (b *BeaconState) LatestBlockHash() []byte {
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.latestBlockHash[:]
|
||||
}
|
||||
|
||||
// LatestFullSlot returns the slot of the latest full block.
|
||||
func (b *BeaconState) LatestFullSlot() primitives.Slot {
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.latestFullSlot
|
||||
}
|
||||
|
||||
// LastWithdrawalsRoot returns the latest withdrawal root.
|
||||
func (b *BeaconState) LastWithdrawalsRoot() []byte {
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
return b.lastWithdrawalsRoot[:]
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
func (b *BeaconState) executionPayloadHeaderVal() *enginev1.ExecutionPayloadHeaderEPBS {
|
||||
return eth.CopyExecutionPayloadHeaderEPBS(b.executionPayloadHeader)
|
||||
}
|
||||
67
beacon-chain/state/state-native/getters_setters_epbs_test.go
Normal file
67
beacon-chain/state/state-native/getters_setters_epbs_test.go
Normal file
@@ -0,0 +1,67 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util/random"
|
||||
)
|
||||
|
||||
func Test_LatestExecutionPayloadHeader(t *testing.T) {
|
||||
s := &BeaconState{version: version.EPBS}
|
||||
_, err := s.LatestExecutionPayloadHeader()
|
||||
require.ErrorContains(t, "unsupported version (epbs) for latest execution payload header", err)
|
||||
}
|
||||
|
||||
func Test_SetLatestExecutionPayloadHeader(t *testing.T) {
|
||||
s := &BeaconState{version: version.EPBS}
|
||||
require.ErrorContains(t, "SetLatestExecutionPayloadHeader is not supported for epbs", s.SetLatestExecutionPayloadHeader(nil))
|
||||
}
|
||||
|
||||
func Test_SetExecutionPayloadHeader(t *testing.T) {
|
||||
s := &BeaconState{version: version.EPBS, dirtyFields: make(map[types.FieldIndex]bool)}
|
||||
header := random.ExecutionPayloadHeader(t)
|
||||
s.SetExecutionPayloadHeader(header)
|
||||
require.Equal(t, true, s.dirtyFields[types.ExecutionPayloadHeader])
|
||||
|
||||
got := s.ExecutionPayloadHeader()
|
||||
require.DeepEqual(t, got, header)
|
||||
}
|
||||
|
||||
func Test_SetLatestBlockHash(t *testing.T) {
|
||||
s := &BeaconState{version: version.EPBS, dirtyFields: make(map[types.FieldIndex]bool)}
|
||||
b := make([]byte, fieldparams.RootLength)
|
||||
_, err := rand.Read(b)
|
||||
require.NoError(t, err)
|
||||
s.SetLatestBlockHash(b)
|
||||
require.Equal(t, true, s.dirtyFields[types.LatestBlockHash])
|
||||
|
||||
got := s.LatestBlockHash()
|
||||
require.DeepEqual(t, got, b)
|
||||
}
|
||||
|
||||
func Test_SetLatestFullSlot(t *testing.T) {
|
||||
s := &BeaconState{version: version.EPBS, dirtyFields: make(map[types.FieldIndex]bool)}
|
||||
s.SetLatestFullSlot(3)
|
||||
require.Equal(t, true, s.dirtyFields[types.LatestFullSlot])
|
||||
|
||||
got := s.LatestFullSlot()
|
||||
require.Equal(t, primitives.Slot(3), got)
|
||||
}
|
||||
|
||||
func Test_SetLastWithdrawalsRoot(t *testing.T) {
|
||||
s := &BeaconState{version: version.EPBS, dirtyFields: make(map[types.FieldIndex]bool)}
|
||||
b := make([]byte, fieldparams.RootLength)
|
||||
_, err := rand.Read(b)
|
||||
require.NoError(t, err)
|
||||
s.SetLastWithdrawalsRoot(b)
|
||||
require.Equal(t, true, s.dirtyFields[types.LastWithdrawalsRoot])
|
||||
|
||||
got := s.LastWithdrawalsRoot()
|
||||
require.DeepEqual(t, got, b)
|
||||
}
|
||||
@@ -212,6 +212,49 @@ func (b *BeaconState) ToProtoUnsafe() interface{} {
|
||||
PendingPartialWithdrawals: b.pendingPartialWithdrawals,
|
||||
PendingConsolidations: b.pendingConsolidations,
|
||||
}
|
||||
case version.EPBS:
|
||||
return ðpb.BeaconStateEPBS{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
Slot: b.slot,
|
||||
Fork: b.fork,
|
||||
LatestBlockHeader: b.latestBlockHeader,
|
||||
BlockRoots: br,
|
||||
StateRoots: sr,
|
||||
HistoricalRoots: b.historicalRoots.Slice(),
|
||||
Eth1Data: b.eth1Data,
|
||||
Eth1DataVotes: b.eth1DataVotes,
|
||||
Eth1DepositIndex: b.eth1DepositIndex,
|
||||
Validators: vals,
|
||||
Balances: bals,
|
||||
RandaoMixes: rm,
|
||||
Slashings: b.slashings,
|
||||
PreviousEpochParticipation: b.previousEpochParticipation,
|
||||
CurrentEpochParticipation: b.currentEpochParticipation,
|
||||
JustificationBits: b.justificationBits,
|
||||
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpoint,
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpoint,
|
||||
FinalizedCheckpoint: b.finalizedCheckpoint,
|
||||
InactivityScores: b.inactivityScoresVal(),
|
||||
CurrentSyncCommittee: b.currentSyncCommittee,
|
||||
NextSyncCommittee: b.nextSyncCommittee,
|
||||
NextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
HistoricalSummaries: b.historicalSummaries,
|
||||
DepositRequestsStartIndex: b.depositRequestsStartIndex,
|
||||
DepositBalanceToConsume: b.depositBalanceToConsume,
|
||||
ExitBalanceToConsume: b.exitBalanceToConsume,
|
||||
EarliestExitEpoch: b.earliestExitEpoch,
|
||||
ConsolidationBalanceToConsume: b.consolidationBalanceToConsume,
|
||||
EarliestConsolidationEpoch: b.earliestConsolidationEpoch,
|
||||
PendingBalanceDeposits: b.pendingBalanceDeposits,
|
||||
PendingPartialWithdrawals: b.pendingPartialWithdrawals,
|
||||
PendingConsolidations: b.pendingConsolidations,
|
||||
LatestBlockHash: b.latestBlockHash[:],
|
||||
LatestFullSlot: b.latestFullSlot,
|
||||
LatestExecutionPayloadHeader: b.executionPayloadHeader,
|
||||
LastWithdrawalsRoot: b.lastWithdrawalsRoot[:],
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
@@ -236,6 +279,9 @@ func (b *BeaconState) ToProto() interface{} {
|
||||
inactivityScores = b.inactivityScoresVal()
|
||||
}
|
||||
|
||||
LatestBlockHashCopy := b.latestBlockHash
|
||||
lastWithdrawalsRootCopy := b.lastWithdrawalsRoot
|
||||
|
||||
switch b.version {
|
||||
case version.Phase0:
|
||||
return ðpb.BeaconState{
|
||||
@@ -418,6 +464,49 @@ func (b *BeaconState) ToProto() interface{} {
|
||||
PendingPartialWithdrawals: b.pendingPartialWithdrawalsVal(),
|
||||
PendingConsolidations: b.pendingConsolidationsVal(),
|
||||
}
|
||||
case version.EPBS:
|
||||
return ðpb.BeaconStateEPBS{
|
||||
GenesisTime: b.genesisTime,
|
||||
GenesisValidatorsRoot: gvrCopy[:],
|
||||
Slot: b.slot,
|
||||
Fork: b.forkVal(),
|
||||
LatestBlockHeader: b.latestBlockHeaderVal(),
|
||||
BlockRoots: br,
|
||||
StateRoots: sr,
|
||||
HistoricalRoots: b.historicalRoots.Slice(),
|
||||
Eth1Data: b.eth1DataVal(),
|
||||
Eth1DataVotes: b.eth1DataVotesVal(),
|
||||
Eth1DepositIndex: b.eth1DepositIndex,
|
||||
Validators: b.validatorsVal(),
|
||||
Balances: b.balancesVal(),
|
||||
RandaoMixes: rm,
|
||||
Slashings: b.slashingsVal(),
|
||||
PreviousEpochParticipation: b.previousEpochParticipationVal(),
|
||||
CurrentEpochParticipation: b.currentEpochParticipationVal(),
|
||||
JustificationBits: b.justificationBitsVal(),
|
||||
PreviousJustifiedCheckpoint: b.previousJustifiedCheckpointVal(),
|
||||
CurrentJustifiedCheckpoint: b.currentJustifiedCheckpointVal(),
|
||||
FinalizedCheckpoint: b.finalizedCheckpointVal(),
|
||||
InactivityScores: b.inactivityScoresVal(),
|
||||
CurrentSyncCommittee: b.currentSyncCommitteeVal(),
|
||||
NextSyncCommittee: b.nextSyncCommitteeVal(),
|
||||
NextWithdrawalIndex: b.nextWithdrawalIndex,
|
||||
NextWithdrawalValidatorIndex: b.nextWithdrawalValidatorIndex,
|
||||
HistoricalSummaries: b.historicalSummariesVal(),
|
||||
DepositRequestsStartIndex: b.depositRequestsStartIndex,
|
||||
DepositBalanceToConsume: b.depositBalanceToConsume,
|
||||
ExitBalanceToConsume: b.exitBalanceToConsume,
|
||||
EarliestExitEpoch: b.earliestExitEpoch,
|
||||
ConsolidationBalanceToConsume: b.consolidationBalanceToConsume,
|
||||
EarliestConsolidationEpoch: b.earliestConsolidationEpoch,
|
||||
PendingBalanceDeposits: b.pendingBalanceDepositsVal(),
|
||||
PendingPartialWithdrawals: b.pendingPartialWithdrawalsVal(),
|
||||
PendingConsolidations: b.pendingConsolidationsVal(),
|
||||
LatestBlockHash: LatestBlockHashCopy[:],
|
||||
LatestFullSlot: b.latestFullSlot,
|
||||
LatestExecutionPayloadHeader: b.executionPayloadHeaderVal(),
|
||||
LastWithdrawalsRoot: lastWithdrawalsRootCopy[:],
|
||||
}
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -501,3 +501,24 @@ func (b *BeaconState) PendingBalanceToWithdraw(idx primitives.ValidatorIndex) (u
|
||||
}
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
func (b *BeaconState) HasPendingBalanceToWithdraw(idx primitives.ValidatorIndex) (bool, error) {
|
||||
if b.version < version.Electra {
|
||||
return false, errNotSupported("HasPendingBalanceToWithdraw", b.version)
|
||||
}
|
||||
|
||||
b.lock.RLock()
|
||||
defer b.lock.RUnlock()
|
||||
|
||||
// TODO: Consider maintaining this value in the state, if it's a potential bottleneck.
|
||||
// This is n*m complexity, but this method can only be called
|
||||
// MAX_WITHDRAWAL_REQUESTS_PER_PAYLOAD per slot. A more optimized storage indexing such as a
|
||||
// lookup map could be used to reduce the complexity marginally.
|
||||
for _, w := range b.pendingPartialWithdrawals {
|
||||
if w.Index == idx {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -162,3 +162,32 @@ func TestAggregateKeyFromIndices(t *testing.T) {
|
||||
|
||||
assert.Equal(t, true, aggKey.Equals(retKey), "unequal aggregated keys")
|
||||
}
|
||||
|
||||
func TestHasPendingBalanceToWithdraw(t *testing.T) {
|
||||
pb := ðpb.BeaconStateElectra{
|
||||
PendingPartialWithdrawals: []*ethpb.PendingPartialWithdrawal{
|
||||
{
|
||||
Amount: 100,
|
||||
Index: 1,
|
||||
},
|
||||
{
|
||||
Amount: 200,
|
||||
Index: 2,
|
||||
},
|
||||
{
|
||||
Amount: 300,
|
||||
Index: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
state, err := statenative.InitializeFromProtoUnsafeElectra(pb)
|
||||
require.NoError(t, err)
|
||||
|
||||
ok, err := state.HasPendingBalanceToWithdraw(1)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, ok)
|
||||
|
||||
ok, err = state.HasPendingBalanceToWithdraw(5)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, ok)
|
||||
}
|
||||
|
||||
@@ -154,7 +154,7 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, err
|
||||
if err != nil {
|
||||
return nil, 0, errors.Wrapf(err, "could not retrieve balance at index %d", validatorIndex)
|
||||
}
|
||||
if helpers.IsFullyWithdrawableValidator(val, balance, epoch) {
|
||||
if helpers.IsFullyWithdrawableValidator(val, balance, epoch, b.version) {
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: validatorIndex,
|
||||
@@ -162,7 +162,7 @@ func (b *BeaconState) ExpectedWithdrawals() ([]*enginev1.Withdrawal, uint64, err
|
||||
Amount: balance,
|
||||
})
|
||||
withdrawalIndex++
|
||||
} else if helpers.IsPartiallyWithdrawableValidator(val, balance, epoch) {
|
||||
} else if helpers.IsPartiallyWithdrawableValidator(val, balance, epoch, b.version) {
|
||||
withdrawals = append(withdrawals, &enginev1.Withdrawal{
|
||||
Index: withdrawalIndex,
|
||||
ValidatorIndex: validatorIndex,
|
||||
|
||||
@@ -41,6 +41,8 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
|
||||
fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateDenebFieldCount)
|
||||
case version.Electra:
|
||||
fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateElectraFieldCount)
|
||||
case version.EPBS:
|
||||
fieldRoots = make([][]byte, params.BeaconConfig().BeaconStateEpbsFieldCount)
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown state version %s", version.String(state.version))
|
||||
}
|
||||
@@ -260,6 +262,14 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
|
||||
}
|
||||
fieldRoots[types.LatestExecutionPayloadHeaderElectra.RealPosition()] = executionPayloadRoot[:]
|
||||
}
|
||||
if state.version == version.EPBS {
|
||||
// Execution payload header root.
|
||||
executionPayloadRoot, err := state.executionPayloadHeader.HashTreeRoot()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
fieldRoots[types.ExecutionPayloadHeader.RealPosition()] = executionPayloadRoot[:]
|
||||
}
|
||||
|
||||
if state.version >= version.Capella {
|
||||
// Next withdrawal index root.
|
||||
@@ -327,5 +337,19 @@ func ComputeFieldRootsWithHasher(ctx context.Context, state *BeaconState) ([][]b
|
||||
fieldRoots[types.PendingConsolidations.RealPosition()] = pcRoot[:]
|
||||
}
|
||||
|
||||
if state.version >= version.EPBS {
|
||||
// Latest block hash root.
|
||||
latestBlockHashRoot := state.latestBlockHash[:]
|
||||
fieldRoots[types.LatestBlockHash.RealPosition()] = latestBlockHashRoot
|
||||
|
||||
// Latest full slot root.
|
||||
latestFullSlotRoot := ssz.Uint64Root(uint64(state.latestFullSlot))
|
||||
fieldRoots[types.LatestFullSlot.RealPosition()] = latestFullSlotRoot[:]
|
||||
|
||||
// Last withdrawals root.
|
||||
lastWithdrawalsRoot := state.lastWithdrawalsRoot[:]
|
||||
fieldRoots[types.LastWithdrawalsRoot.RealPosition()] = lastWithdrawalsRoot
|
||||
}
|
||||
|
||||
return fieldRoots, nil
|
||||
}
|
||||
|
||||
44
beacon-chain/state/state-native/setters_epbs.go
Normal file
44
beacon-chain/state/state-native/setters_epbs.go
Normal file
@@ -0,0 +1,44 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
)
|
||||
|
||||
// SetExecutionPayloadHeader sets the execution payload header for the beacon state.
|
||||
func (b *BeaconState) SetExecutionPayloadHeader(h *enginev1.ExecutionPayloadHeaderEPBS) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.executionPayloadHeader = h
|
||||
b.markFieldAsDirty(types.ExecutionPayloadHeader)
|
||||
}
|
||||
|
||||
// SetLatestBlockHash sets the latest block hash for the beacon state.
|
||||
func (b *BeaconState) SetLatestBlockHash(h []byte) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.latestBlockHash = bytesutil.ToBytes32(h)
|
||||
b.markFieldAsDirty(types.LatestBlockHash)
|
||||
}
|
||||
|
||||
// SetLatestFullSlot sets the latest full slot for the beacon state.
|
||||
func (b *BeaconState) SetLatestFullSlot(s primitives.Slot) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.latestFullSlot = s
|
||||
b.markFieldAsDirty(types.LatestFullSlot)
|
||||
}
|
||||
|
||||
// SetLastWithdrawalsRoot sets the latest withdrawals root for the beacon state.
|
||||
func (b *BeaconState) SetLastWithdrawalsRoot(r []byte) {
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
b.lastWithdrawalsRoot = bytesutil.ToBytes32(r)
|
||||
b.markFieldAsDirty(types.LastWithdrawalsRoot)
|
||||
}
|
||||
@@ -17,7 +17,7 @@ func (b *BeaconState) SetLatestExecutionPayloadHeader(val interfaces.ExecutionDa
|
||||
b.lock.Lock()
|
||||
defer b.lock.Unlock()
|
||||
|
||||
if b.version < version.Bellatrix {
|
||||
if b.version < version.Bellatrix || b.version >= version.EPBS {
|
||||
return errNotSupported("SetLatestExecutionPayloadHeader", b.version)
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
func (b *BeaconState) ProportionalSlashingMultiplier() (uint64, error) {
|
||||
switch b.version {
|
||||
case version.Bellatrix, version.Capella, version.Deneb, version.Electra:
|
||||
case version.Bellatrix, version.Capella, version.Deneb, version.Electra, version.EPBS:
|
||||
return params.BeaconConfig().ProportionalSlashingMultiplierBellatrix, nil
|
||||
case version.Altair:
|
||||
return params.BeaconConfig().ProportionalSlashingMultiplierAltair, nil
|
||||
@@ -19,7 +19,7 @@ func (b *BeaconState) ProportionalSlashingMultiplier() (uint64, error) {
|
||||
|
||||
func (b *BeaconState) InactivityPenaltyQuotient() (uint64, error) {
|
||||
switch b.version {
|
||||
case version.Bellatrix, version.Capella, version.Deneb, version.Electra:
|
||||
case version.Bellatrix, version.Capella, version.Deneb, version.Electra, version.EPBS:
|
||||
return params.BeaconConfig().InactivityPenaltyQuotientBellatrix, nil
|
||||
case version.Altair:
|
||||
return params.BeaconConfig().InactivityPenaltyQuotientAltair, nil
|
||||
|
||||
@@ -111,6 +111,27 @@ var electraFields = append(
|
||||
types.PendingConsolidations,
|
||||
)
|
||||
|
||||
var epbsFields = append(
|
||||
altairFields,
|
||||
types.NextWithdrawalIndex,
|
||||
types.NextWithdrawalValidatorIndex,
|
||||
types.HistoricalSummaries,
|
||||
types.ExecutionPayloadHeader, // new in ePBS
|
||||
types.DepositRequestsStartIndex, // electra fields start here
|
||||
types.DepositBalanceToConsume,
|
||||
types.ExitBalanceToConsume,
|
||||
types.EarliestExitEpoch,
|
||||
types.ConsolidationBalanceToConsume,
|
||||
types.EarliestConsolidationEpoch,
|
||||
types.PendingBalanceDeposits,
|
||||
types.PendingPartialWithdrawals,
|
||||
types.PendingConsolidations,
|
||||
types.LatestBlockHash, // ePBS fields start here
|
||||
types.LatestFullSlot,
|
||||
types.ExecutionPayloadHeader,
|
||||
types.LastWithdrawalsRoot,
|
||||
)
|
||||
|
||||
const (
|
||||
phase0SharedFieldRefCount = 10
|
||||
altairSharedFieldRefCount = 11
|
||||
@@ -118,12 +139,14 @@ const (
|
||||
capellaSharedFieldRefCount = 14
|
||||
denebSharedFieldRefCount = 14
|
||||
electraSharedFieldRefCount = 17
|
||||
epbsSharedFieldRefCount = 17
|
||||
experimentalStatePhase0SharedFieldRefCount = 5
|
||||
experimentalStateAltairSharedFieldRefCount = 5
|
||||
experimentalStateBellatrixSharedFieldRefCount = 6
|
||||
experimentalStateCapellaSharedFieldRefCount = 8
|
||||
experimentalStateDenebSharedFieldRefCount = 8
|
||||
experimentalStateElectraSharedFieldRefCount = 11
|
||||
experimentalStateEpbsSharedFieldRefCount = 11
|
||||
)
|
||||
|
||||
// InitializeFromProtoPhase0 the beacon state from a protobuf representation.
|
||||
@@ -155,6 +178,11 @@ func InitializeFromProtoElectra(st *ethpb.BeaconStateElectra) (state.BeaconState
|
||||
return InitializeFromProtoUnsafeElectra(proto.Clone(st).(*ethpb.BeaconStateElectra))
|
||||
}
|
||||
|
||||
// InitializeFromProtoEpbs initializes the beacon state from its protobuf representation.
|
||||
func InitializeFromProtoEpbs(st *ethpb.BeaconStateEPBS) (state.BeaconState, error) {
|
||||
return InitializeFromProtoUnsafeEpbs(proto.Clone(st).(*ethpb.BeaconStateEPBS))
|
||||
}
|
||||
|
||||
// InitializeFromProtoUnsafePhase0 directly uses the beacon state protobuf fields
|
||||
// and sets them as fields of the BeaconState type.
|
||||
func InitializeFromProtoUnsafePhase0(st *ethpb.BeaconState) (state.BeaconState, error) {
|
||||
@@ -851,6 +879,8 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
fieldCount = params.BeaconConfig().BeaconStateDenebFieldCount
|
||||
case version.Electra:
|
||||
fieldCount = params.BeaconConfig().BeaconStateElectraFieldCount
|
||||
case version.EPBS:
|
||||
fieldCount = params.BeaconConfig().BeaconStateEpbsFieldCount
|
||||
}
|
||||
|
||||
dst := &BeaconState{
|
||||
@@ -868,6 +898,9 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
earliestExitEpoch: b.earliestExitEpoch,
|
||||
consolidationBalanceToConsume: b.consolidationBalanceToConsume,
|
||||
earliestConsolidationEpoch: b.earliestConsolidationEpoch,
|
||||
latestBlockHash: b.latestBlockHash,
|
||||
latestFullSlot: b.latestFullSlot,
|
||||
lastWithdrawalsRoot: b.lastWithdrawalsRoot,
|
||||
|
||||
// Large arrays, infrequently changed, constant size.
|
||||
blockRoots: b.blockRoots,
|
||||
@@ -911,6 +944,7 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
latestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapellaVal(),
|
||||
latestExecutionPayloadHeaderDeneb: b.latestExecutionPayloadHeaderDenebVal(),
|
||||
latestExecutionPayloadHeaderElectra: b.latestExecutionPayloadHeaderElectraVal(),
|
||||
executionPayloadHeader: b.executionPayloadHeaderVal(),
|
||||
|
||||
id: types.Enumerator.Inc(),
|
||||
|
||||
@@ -949,6 +983,8 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateDenebSharedFieldRefCount)
|
||||
case version.Electra:
|
||||
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateElectraSharedFieldRefCount)
|
||||
case version.EPBS:
|
||||
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateEpbsSharedFieldRefCount)
|
||||
}
|
||||
} else {
|
||||
switch b.version {
|
||||
@@ -964,6 +1000,8 @@ func (b *BeaconState) Copy() state.BeaconState {
|
||||
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, denebSharedFieldRefCount)
|
||||
case version.Electra:
|
||||
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, electraSharedFieldRefCount)
|
||||
case version.EPBS:
|
||||
dst.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, epbsSharedFieldRefCount)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1058,6 +1096,8 @@ func (b *BeaconState) initializeMerkleLayers(ctx context.Context) error {
|
||||
b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateDenebFieldCount)
|
||||
case version.Electra:
|
||||
b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateElectraFieldCount)
|
||||
case version.EPBS:
|
||||
b.dirtyFields = make(map[types.FieldIndex]bool, params.BeaconConfig().BeaconStateEpbsFieldCount)
|
||||
default:
|
||||
return fmt.Errorf("unknown state version (%s) when computing dirty fields in merklization", version.String(b.version))
|
||||
}
|
||||
@@ -1304,6 +1344,14 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
|
||||
return stateutil.PendingPartialWithdrawalsRoot(b.pendingPartialWithdrawals)
|
||||
case types.PendingConsolidations:
|
||||
return stateutil.PendingConsolidationsRoot(b.pendingConsolidations)
|
||||
case types.LatestBlockHash:
|
||||
return b.latestBlockHash, nil
|
||||
case types.LatestFullSlot:
|
||||
return ssz.Uint64Root(uint64(b.latestFullSlot)), nil
|
||||
case types.ExecutionPayloadHeader:
|
||||
return b.executionPayloadHeader.HashTreeRoot()
|
||||
case types.LastWithdrawalsRoot:
|
||||
return b.lastWithdrawalsRoot, nil
|
||||
}
|
||||
return [32]byte{}, errors.New("invalid field index provided")
|
||||
}
|
||||
|
||||
147
beacon-chain/state/state-native/state_trie_epbs.go
Normal file
147
beacon-chain/state/state-native/state_trie_epbs.go
Normal file
@@ -0,0 +1,147 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"runtime"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/fieldtrie"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native/types"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state/stateutil"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/features"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
// InitializeFromProtoUnsafeEpbs constructs a BeaconState from its protobuf representation.
|
||||
func InitializeFromProtoUnsafeEpbs(st *ethpb.BeaconStateEPBS) (*BeaconState, error) {
|
||||
if st == nil {
|
||||
return nil, errors.New("received nil state")
|
||||
}
|
||||
|
||||
// Process historical roots.
|
||||
hRoots := make([][32]byte, len(st.HistoricalRoots))
|
||||
for i, root := range st.HistoricalRoots {
|
||||
hRoots[i] = bytesutil.ToBytes32(root)
|
||||
}
|
||||
|
||||
// Define the number of fields to track changes.
|
||||
fieldCount := params.BeaconConfig().BeaconStateEpbsFieldCount
|
||||
b := &BeaconState{
|
||||
version: version.EPBS,
|
||||
genesisTime: st.GenesisTime,
|
||||
genesisValidatorsRoot: bytesutil.ToBytes32(st.GenesisValidatorsRoot),
|
||||
slot: st.Slot,
|
||||
fork: st.Fork,
|
||||
latestBlockHeader: st.LatestBlockHeader,
|
||||
historicalRoots: hRoots,
|
||||
eth1Data: st.Eth1Data,
|
||||
eth1DataVotes: st.Eth1DataVotes,
|
||||
eth1DepositIndex: st.Eth1DepositIndex,
|
||||
slashings: st.Slashings,
|
||||
previousEpochParticipation: st.PreviousEpochParticipation,
|
||||
currentEpochParticipation: st.CurrentEpochParticipation,
|
||||
justificationBits: st.JustificationBits,
|
||||
previousJustifiedCheckpoint: st.PreviousJustifiedCheckpoint,
|
||||
currentJustifiedCheckpoint: st.CurrentJustifiedCheckpoint,
|
||||
finalizedCheckpoint: st.FinalizedCheckpoint,
|
||||
currentSyncCommittee: st.CurrentSyncCommittee,
|
||||
nextSyncCommittee: st.NextSyncCommittee,
|
||||
nextWithdrawalIndex: st.NextWithdrawalIndex,
|
||||
nextWithdrawalValidatorIndex: st.NextWithdrawalValidatorIndex,
|
||||
historicalSummaries: st.HistoricalSummaries,
|
||||
depositRequestsStartIndex: st.DepositRequestsStartIndex,
|
||||
depositBalanceToConsume: st.DepositBalanceToConsume,
|
||||
exitBalanceToConsume: st.ExitBalanceToConsume,
|
||||
earliestExitEpoch: st.EarliestExitEpoch,
|
||||
consolidationBalanceToConsume: st.ConsolidationBalanceToConsume,
|
||||
earliestConsolidationEpoch: st.EarliestConsolidationEpoch,
|
||||
pendingBalanceDeposits: st.PendingBalanceDeposits,
|
||||
pendingPartialWithdrawals: st.PendingPartialWithdrawals,
|
||||
pendingConsolidations: st.PendingConsolidations,
|
||||
|
||||
// ePBS fields
|
||||
latestBlockHash: bytesutil.ToBytes32(st.LatestBlockHash),
|
||||
latestFullSlot: st.LatestFullSlot,
|
||||
executionPayloadHeader: st.LatestExecutionPayloadHeader,
|
||||
lastWithdrawalsRoot: bytesutil.ToBytes32(st.LastWithdrawalsRoot),
|
||||
|
||||
dirtyFields: make(map[types.FieldIndex]bool, fieldCount),
|
||||
dirtyIndices: make(map[types.FieldIndex][]uint64, fieldCount),
|
||||
stateFieldLeaves: make(map[types.FieldIndex]*fieldtrie.FieldTrie, fieldCount),
|
||||
rebuildTrie: make(map[types.FieldIndex]bool, fieldCount),
|
||||
valMapHandler: stateutil.NewValMapHandler(st.Validators),
|
||||
}
|
||||
|
||||
if features.Get().EnableExperimentalState {
|
||||
b.blockRootsMultiValue = NewMultiValueBlockRoots(st.BlockRoots)
|
||||
b.stateRootsMultiValue = NewMultiValueStateRoots(st.StateRoots)
|
||||
b.randaoMixesMultiValue = NewMultiValueRandaoMixes(st.RandaoMixes)
|
||||
b.balancesMultiValue = NewMultiValueBalances(st.Balances)
|
||||
b.validatorsMultiValue = NewMultiValueValidators(st.Validators)
|
||||
b.inactivityScoresMultiValue = NewMultiValueInactivityScores(st.InactivityScores)
|
||||
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, experimentalStateEpbsSharedFieldRefCount)
|
||||
} else {
|
||||
bRoots := make([][32]byte, fieldparams.BlockRootsLength)
|
||||
for i, r := range st.BlockRoots {
|
||||
bRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
b.blockRoots = bRoots
|
||||
|
||||
sRoots := make([][32]byte, fieldparams.StateRootsLength)
|
||||
for i, r := range st.StateRoots {
|
||||
sRoots[i] = bytesutil.ToBytes32(r)
|
||||
}
|
||||
b.stateRoots = sRoots
|
||||
|
||||
mixes := make([][32]byte, fieldparams.RandaoMixesLength)
|
||||
for i, m := range st.RandaoMixes {
|
||||
mixes[i] = bytesutil.ToBytes32(m)
|
||||
}
|
||||
b.randaoMixes = mixes
|
||||
|
||||
b.balances = st.Balances
|
||||
b.validators = st.Validators
|
||||
b.inactivityScores = st.InactivityScores
|
||||
|
||||
b.sharedFieldReferences = make(map[types.FieldIndex]*stateutil.Reference, epbsSharedFieldRefCount)
|
||||
}
|
||||
|
||||
for _, f := range epbsFields {
|
||||
b.dirtyFields[f] = true
|
||||
b.rebuildTrie[f] = true
|
||||
b.dirtyIndices[f] = []uint64{}
|
||||
trie, err := fieldtrie.NewFieldTrie(f, types.BasicArray, nil, 0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b.stateFieldLeaves[f] = trie
|
||||
}
|
||||
|
||||
// Initialize field reference tracking for shared data.
|
||||
b.sharedFieldReferences[types.HistoricalRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.Eth1DataVotes] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.Slashings] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.PreviousEpochParticipationBits] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.CurrentEpochParticipationBits] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.HistoricalSummaries] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.PendingBalanceDeposits] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.PendingPartialWithdrawals] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.PendingConsolidations] = stateutil.NewRef(1)
|
||||
if !features.Get().EnableExperimentalState {
|
||||
b.sharedFieldReferences[types.BlockRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.StateRoots] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.RandaoMixes] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.Balances] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.Validators] = stateutil.NewRef(1)
|
||||
b.sharedFieldReferences[types.InactivityScores] = stateutil.NewRef(1)
|
||||
}
|
||||
|
||||
state.Count.Inc()
|
||||
// Finalizer runs when dst is being destroyed in garbage collection.
|
||||
runtime.SetFinalizer(b, finalizerCleanup)
|
||||
return b, nil
|
||||
}
|
||||
65
beacon-chain/state/state-native/state_trie_epbs_test.go
Normal file
65
beacon-chain/state/state-native/state_trie_epbs_test.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package state_native
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util/random"
|
||||
)
|
||||
|
||||
func Test_InitializeFromProtoEpbs(t *testing.T) {
|
||||
st := random.BeaconState(t)
|
||||
|
||||
// Cache initial values to check against after initialization.
|
||||
latestBlockHash := st.LatestBlockHash
|
||||
latestFullSlot := st.LatestFullSlot
|
||||
header := st.LatestExecutionPayloadHeader
|
||||
lastWithdrawalsRoot := st.LastWithdrawalsRoot
|
||||
|
||||
s, err := InitializeFromProtoEpbs(st)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Assert that initial values match those in the new state.
|
||||
gotLatestBlockHash := s.LatestBlockHash()
|
||||
require.DeepEqual(t, latestBlockHash, gotLatestBlockHash)
|
||||
gotLatestFullSlot := s.LatestFullSlot()
|
||||
require.Equal(t, latestFullSlot, gotLatestFullSlot)
|
||||
gotHeader := s.ExecutionPayloadHeader()
|
||||
require.DeepEqual(t, header, gotHeader)
|
||||
gotLastWithdrawalsRoot := s.LastWithdrawalsRoot()
|
||||
require.DeepEqual(t, lastWithdrawalsRoot, gotLastWithdrawalsRoot)
|
||||
}
|
||||
|
||||
func Test_CopyEpbs(t *testing.T) {
|
||||
st := random.BeaconState(t)
|
||||
s, err := InitializeFromProtoUnsafeEpbs(st)
|
||||
require.NoError(t, err)
|
||||
|
||||
// Test shallow copy.
|
||||
sNoCopy := s
|
||||
require.DeepEqual(t, s.executionPayloadHeader, sNoCopy.executionPayloadHeader)
|
||||
|
||||
// Modify a field to check if it reflects in the shallow copy.
|
||||
s.executionPayloadHeader.Slot = 100
|
||||
require.Equal(t, s.executionPayloadHeader, sNoCopy.executionPayloadHeader)
|
||||
|
||||
// Copy the state
|
||||
sCopy := s.Copy()
|
||||
require.NoError(t, err)
|
||||
header := sCopy.ExecutionPayloadHeader()
|
||||
require.DeepEqual(t, s.executionPayloadHeader, header)
|
||||
|
||||
// Modify the original to check if the copied state is independent.
|
||||
s.executionPayloadHeader.Slot = 200
|
||||
require.DeepNotEqual(t, s.executionPayloadHeader, header)
|
||||
}
|
||||
|
||||
func Test_HashTreeRootEpbs(t *testing.T) {
|
||||
st := random.BeaconState(t)
|
||||
s, err := InitializeFromProtoUnsafeEpbs(st)
|
||||
require.NoError(t, err)
|
||||
|
||||
_, err = s.HashTreeRoot(context.Background())
|
||||
require.NoError(t, err)
|
||||
}
|
||||
@@ -114,6 +114,14 @@ func (f FieldIndex) String() string {
|
||||
return "pendingPartialWithdrawals"
|
||||
case PendingConsolidations:
|
||||
return "pendingConsolidations"
|
||||
case LatestBlockHash: // ePBS fields start here
|
||||
return "LatestBlockHash"
|
||||
case LatestFullSlot:
|
||||
return "LatestFullSlot"
|
||||
case ExecutionPayloadHeader:
|
||||
return "ExecutionPayloadHeader"
|
||||
case LastWithdrawalsRoot:
|
||||
return "LastWithdrawalsRoot"
|
||||
default:
|
||||
return fmt.Sprintf("unknown field index number: %d", f)
|
||||
}
|
||||
@@ -171,7 +179,8 @@ func (f FieldIndex) RealPosition() int {
|
||||
return 22
|
||||
case NextSyncCommittee:
|
||||
return 23
|
||||
case LatestExecutionPayloadHeader, LatestExecutionPayloadHeaderCapella, LatestExecutionPayloadHeaderDeneb, LatestExecutionPayloadHeaderElectra:
|
||||
// ExecutionPayloadHeader is from ePBS.
|
||||
case LatestExecutionPayloadHeader, LatestExecutionPayloadHeaderCapella, LatestExecutionPayloadHeaderDeneb, LatestExecutionPayloadHeaderElectra, ExecutionPayloadHeader:
|
||||
return 24
|
||||
case NextWithdrawalIndex:
|
||||
return 25
|
||||
@@ -197,6 +206,12 @@ func (f FieldIndex) RealPosition() int {
|
||||
return 35
|
||||
case PendingConsolidations:
|
||||
return 36
|
||||
case LatestBlockHash: // ePBS fields start here
|
||||
return 41
|
||||
case LatestFullSlot:
|
||||
return 42
|
||||
case LastWithdrawalsRoot:
|
||||
return 43
|
||||
default:
|
||||
return -1
|
||||
}
|
||||
@@ -250,6 +265,7 @@ const (
|
||||
LatestExecutionPayloadHeaderCapella
|
||||
LatestExecutionPayloadHeaderDeneb
|
||||
LatestExecutionPayloadHeaderElectra
|
||||
ExecutionPayloadHeader
|
||||
NextWithdrawalIndex
|
||||
NextWithdrawalValidatorIndex
|
||||
HistoricalSummaries
|
||||
@@ -262,6 +278,9 @@ const (
|
||||
PendingBalanceDeposits // Electra: EIP-7251
|
||||
PendingPartialWithdrawals // Electra: EIP-7251
|
||||
PendingConsolidations // Electra: EIP-7251
|
||||
LatestBlockHash // ePBS fields start here
|
||||
LatestFullSlot
|
||||
LastWithdrawalsRoot
|
||||
)
|
||||
|
||||
// Enumerator keeps track of the number of states created since the node's start.
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
var errNilPubsubMessage = errors.New("nil pubsub message")
|
||||
@@ -52,7 +51,7 @@ func (s *Service) decodePubsubMessage(msg *pubsub.Message) (ssz.Unmarshaler, err
|
||||
if base == nil {
|
||||
return nil, p2p.ErrMessageNotMapped
|
||||
}
|
||||
m, ok := proto.Clone(base).(ssz.Unmarshaler)
|
||||
m, ok := base.(ssz.Unmarshaler)
|
||||
if !ok {
|
||||
return nil, errors.Errorf("message of %T does not support marshaller interface", base)
|
||||
}
|
||||
|
||||
@@ -403,6 +403,26 @@ func TestSidecarInclusionProven(t *testing.T) {
|
||||
require.NotNil(t, v.results.result(RequireSidecarInclusionProven))
|
||||
}
|
||||
|
||||
func TestSidecarInclusionProvenElectra(t *testing.T) {
|
||||
// GenerateTestDenebBlockWithSidecar is supposed to generate valid inclusion proofs
|
||||
_, blobs := util.GenerateTestElectraBlockWithSidecar(t, [32]byte{}, 1, 1)
|
||||
b := blobs[0]
|
||||
|
||||
ini := Initializer{}
|
||||
v := ini.NewBlobVerifier(b, GossipSidecarRequirements)
|
||||
require.NoError(t, v.SidecarInclusionProven())
|
||||
require.Equal(t, true, v.results.executed(RequireSidecarInclusionProven))
|
||||
require.NoError(t, v.results.result(RequireSidecarInclusionProven))
|
||||
|
||||
// Invert bits of the first byte of the body root to mess up the proof
|
||||
byte0 := b.SignedBlockHeader.Header.BodyRoot[0]
|
||||
b.SignedBlockHeader.Header.BodyRoot[0] = byte0 ^ 255
|
||||
v = ini.NewBlobVerifier(b, GossipSidecarRequirements)
|
||||
require.ErrorIs(t, v.SidecarInclusionProven(), ErrSidecarInclusionProofInvalid)
|
||||
require.Equal(t, true, v.results.executed(RequireSidecarInclusionProven))
|
||||
require.NotNil(t, v.results.result(RequireSidecarInclusionProven))
|
||||
}
|
||||
|
||||
func TestSidecarKzgProofVerified(t *testing.T) {
|
||||
// GenerateTestDenebBlockWithSidecar is supposed to generate valid commitments
|
||||
_, blobs := util.GenerateTestDenebBlockWithSidecar(t, [32]byte{}, 1, 1)
|
||||
|
||||
@@ -212,6 +212,10 @@ func before(ctx *cli.Context) error {
|
||||
return errors.Wrap(err, "failed to set max fd limits")
|
||||
}
|
||||
|
||||
if err := features.ValidateNetworkFlags(ctx); err != nil {
|
||||
return errors.Wrap(err, "provided multiple network flags")
|
||||
}
|
||||
|
||||
return cmd.ValidateNoArgs(ctx)
|
||||
}
|
||||
|
||||
|
||||
@@ -175,6 +175,9 @@ var Commands = []*cli.Command{
|
||||
if err := cmd.LoadFlagsFromConfig(cliCtx, cliCtx.Command.Flags); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := features.ValidateNetworkFlags(cliCtx); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := tos.VerifyTosAcceptedOrPrompt(cliCtx); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -193,6 +193,10 @@ func main() {
|
||||
return errors.Wrap(err, "failed to setup debug")
|
||||
}
|
||||
|
||||
if err := features.ValidateNetworkFlags(ctx); err != nil {
|
||||
return errors.Wrap(err, "provided multiple network flags")
|
||||
}
|
||||
|
||||
return cmd.ValidateNoArgs(ctx)
|
||||
},
|
||||
After: func(ctx *cli.Context) error {
|
||||
|
||||
@@ -20,6 +20,8 @@ The process for implementing new features using this package is as follows:
|
||||
package features
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -337,3 +339,25 @@ func logDisabled(flag cli.DocGenerationFlag) {
|
||||
}
|
||||
log.WithField(name, flag.GetUsage()).Warn(disabledFeatureFlag)
|
||||
}
|
||||
|
||||
// ValidateNetworkFlags validates provided flags and
|
||||
// prevents beacon node or validator to start
|
||||
// if more than one network flag is provided
|
||||
func ValidateNetworkFlags(ctx *cli.Context) error {
|
||||
networkFlagsCount := 0
|
||||
for _, flag := range NetworkFlags {
|
||||
if ctx.IsSet(flag.Names()[0]) {
|
||||
networkFlagsCount++
|
||||
if networkFlagsCount > 1 {
|
||||
// using a forLoop so future addition
|
||||
// doesn't require changes in this function
|
||||
var flagNames []string
|
||||
for _, flag := range NetworkFlags {
|
||||
flagNames = append(flagNames, "--"+flag.Names()[0])
|
||||
}
|
||||
return fmt.Errorf("cannot use more than one network flag at the same time. Possible network flags are: %s", strings.Join(flagNames, ", "))
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -46,3 +46,50 @@ func TestConfigureBeaconConfig(t *testing.T) {
|
||||
c := Get()
|
||||
assert.Equal(t, true, c.EnableSlasher)
|
||||
}
|
||||
|
||||
func TestValidateNetworkFlags(t *testing.T) {
|
||||
// Define the test cases
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "No network flags",
|
||||
args: []string{"command"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "One network flag",
|
||||
args: []string{"command", "--sepolia"},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "Two network flags",
|
||||
args: []string{"command", "--sepolia", "--holesky"},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "All network flags",
|
||||
args: []string{"command", "--sepolia", "--holesky", "--mainnet"},
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
// Create a new CLI app with the ValidateNetworkFlags function as the Before action
|
||||
app := &cli.App{
|
||||
Before: ValidateNetworkFlags,
|
||||
Action: func(c *cli.Context) error {
|
||||
return nil
|
||||
},
|
||||
// Set the network flags for the app
|
||||
Flags: NetworkFlags,
|
||||
}
|
||||
err := app.Run(tt.args)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("ValidateNetworkFlags() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ const (
|
||||
CurrentEpochAttestationsLength = 4096 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
SlashingsLength = 8192 // EPOCHS_PER_SLASHINGS_VECTOR
|
||||
SyncCommitteeLength = 512 // SYNC_COMMITTEE_SIZE
|
||||
PTCSize = 512 // PTC_SIZE [New in ePBS]
|
||||
RootLength = 32 // RootLength defines the byte length of a Merkle root.
|
||||
BLSSignatureLength = 96 // BLSSignatureLength defines the byte length of a BLSSignature.
|
||||
BLSPubkeyLength = 48 // BLSPubkeyLength defines the byte length of a BLSSignature.
|
||||
@@ -28,6 +29,7 @@ const (
|
||||
MaxWithdrawalsPerPayload = 16 // MaxWithdrawalsPerPayloadLength defines the maximum number of withdrawals that can be included in a payload.
|
||||
MaxBlobsPerBlock = 6 // MaxBlobsPerBlock defines the maximum number of blobs with respect to consensus rule can be included in a block.
|
||||
MaxBlobCommitmentsPerBlock = 4096 // MaxBlobCommitmentsPerBlock defines the theoretical limit of blobs can be included in a block.
|
||||
MaxPayloadAttestationsPerBlock = 4 // MAX_PAYLOAD_ATTESTATIONS [New in ePBS]
|
||||
LogMaxBlobCommitments = 12 // Log_2 of MaxBlobCommitmentsPerBlock
|
||||
BlobLength = 131072 // BlobLength defines the byte length of a blob.
|
||||
BlobSize = 131072 // defined to match blob.size in bazel ssz codegen
|
||||
|
||||
@@ -14,6 +14,7 @@ const (
|
||||
CurrentEpochAttestationsLength = 1024 // MAX_ATTESTATIONS * SLOTS_PER_EPOCH
|
||||
SlashingsLength = 64 // EPOCHS_PER_SLASHINGS_VECTOR
|
||||
SyncCommitteeLength = 32 // SYNC_COMMITTEE_SIZE
|
||||
PTCSize = 32 // PTC_SIZE [New in ePBS]
|
||||
RootLength = 32 // RootLength defines the byte length of a Merkle root.
|
||||
BLSSignatureLength = 96 // BLSSignatureLength defines the byte length of a BLSSignature.
|
||||
BLSPubkeyLength = 48 // BLSPubkeyLength defines the byte length of a BLSSignature.
|
||||
@@ -28,6 +29,7 @@ const (
|
||||
MaxWithdrawalsPerPayload = 4 // MaxWithdrawalsPerPayloadLength defines the maximum number of withdrawals that can be included in a payload.
|
||||
MaxBlobsPerBlock = 6 // MaxBlobsPerBlock defines the maximum number of blobs with respect to consensus rule can be included in a block.
|
||||
MaxBlobCommitmentsPerBlock = 16 // MaxBlobCommitmentsPerBlock defines the theoretical limit of blobs can be included in a block.
|
||||
MaxPayloadAttestationsPerBlock = 4 // MAX_PAYLOAD_ATTESTATIONS [New in ePBS]
|
||||
LogMaxBlobCommitments = 4 // Log_2 of MaxBlobCommitmentsPerBlock
|
||||
BlobLength = 131072 // BlobLength defines the byte length of a blob.
|
||||
BlobSize = 131072 // defined to match blob.size in bazel ssz codegen
|
||||
|
||||
@@ -126,6 +126,8 @@ type BeaconChainConfig struct {
|
||||
DomainApplicationBuilder [4]byte `yaml:"DOMAIN_APPLICATION_BUILDER" spec:"true"` // DomainApplicationBuilder defines the BLS signature domain for application builder.
|
||||
DomainBLSToExecutionChange [4]byte `yaml:"DOMAIN_BLS_TO_EXECUTION_CHANGE" spec:"true"` // DomainBLSToExecutionChange defines the BLS signature domain to change withdrawal addresses to ETH1 prefix
|
||||
DomainConsolidation [4]byte `yaml:"DOMAIN_CONSOLIDATION" spec:"true"`
|
||||
DomainBeaconBuilder [4]byte `yaml:"DOMAIN_BEACON_BUILDER" spec:"false"` // DomainBeaconBuilder defines the BLS signature domain used by builders [New in ePBS]
|
||||
DomainPTCAttester [4]byte `yaml:"DOMAIN_PTC_ATTESTER" spec:"false"` // DomainPTCAttester defines the BLS signature domain used by PTC members [New in ePBS]
|
||||
|
||||
// Prysm constants.
|
||||
GweiPerEth uint64 // GweiPerEth is the amount of gwei corresponding to 1 eth.
|
||||
@@ -146,6 +148,7 @@ type BeaconChainConfig struct {
|
||||
BeaconStateCapellaFieldCount int // BeaconStateCapellaFieldCount defines how many fields are in beacon state post upgrade to Capella.
|
||||
BeaconStateDenebFieldCount int // BeaconStateDenebFieldCount defines how many fields are in beacon state post upgrade to Deneb.
|
||||
BeaconStateElectraFieldCount int // BeaconStateElectraFieldCount defines how many fields are in beacon state post upgrade to Electra.
|
||||
BeaconStateEpbsFieldCount int // BeaconStateEpbsFieldCount defines how many fields are in beacon state post upgrade to ePBS.
|
||||
|
||||
// Slasher constants.
|
||||
WeakSubjectivityPeriod primitives.Epoch // WeakSubjectivityPeriod defines the time period expressed in number of epochs were proof of stake network should validate block headers and attestations for slashable events.
|
||||
@@ -166,6 +169,8 @@ type BeaconChainConfig struct {
|
||||
DenebForkEpoch primitives.Epoch `yaml:"DENEB_FORK_EPOCH" spec:"true"` // DenebForkEpoch is used to represent the assigned fork epoch for deneb.
|
||||
ElectraForkVersion []byte `yaml:"ELECTRA_FORK_VERSION" spec:"true"` // ElectraForkVersion is used to represent the fork version for deneb.
|
||||
ElectraForkEpoch primitives.Epoch `yaml:"ELECTRA_FORK_EPOCH" spec:"true"` // ElectraForkEpoch is used to represent the assigned fork epoch for deneb.
|
||||
EPBSForkVersion []byte // EPBSForkVersion is used to represent the fork version for ePBS.
|
||||
EPBSForkEpoch primitives.Epoch // EPBSForkEpoch is used to represent the assigned fork epoch for ePBS.
|
||||
|
||||
ForkVersionSchedule map[[fieldparams.VersionLength]byte]primitives.Epoch // Schedule of fork epochs by version.
|
||||
ForkVersionNames map[[fieldparams.VersionLength]byte]string // Human-readable names of fork versions.
|
||||
@@ -313,6 +318,7 @@ func ConfigForkVersions(b *BeaconChainConfig) map[[fieldparams.VersionLength]byt
|
||||
bytesutil.ToBytes4(b.CapellaForkVersion): version.Capella,
|
||||
bytesutil.ToBytes4(b.DenebForkVersion): version.Deneb,
|
||||
bytesutil.ToBytes4(b.ElectraForkVersion): version.Electra,
|
||||
bytesutil.ToBytes4(b.EPBSForkVersion): version.EPBS,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ const (
|
||||
mainnetDenebForkEpoch = 269568 // March 13, 2024, 13:55:35 UTC
|
||||
// Electra Fork Epoch for mainnet config
|
||||
mainnetElectraForkEpoch = math.MaxUint64 // Far future / to be defined
|
||||
// ePBS Fork Epoch for mainnet config.
|
||||
mainnetEPBSForkEpoch = math.MaxUint64
|
||||
)
|
||||
|
||||
var mainnetNetworkConfig = &NetworkConfig{
|
||||
@@ -194,6 +196,7 @@ var mainnetBeaconConfig = &BeaconChainConfig{
|
||||
BeaconStateCapellaFieldCount: 28,
|
||||
BeaconStateDenebFieldCount: 28,
|
||||
BeaconStateElectraFieldCount: 37,
|
||||
BeaconStateEpbsFieldCount: 44,
|
||||
|
||||
// Slasher related values.
|
||||
WeakSubjectivityPeriod: 54000,
|
||||
@@ -216,6 +219,8 @@ var mainnetBeaconConfig = &BeaconChainConfig{
|
||||
DenebForkEpoch: mainnetDenebForkEpoch,
|
||||
ElectraForkVersion: []byte{5, 0, 0, 0},
|
||||
ElectraForkEpoch: mainnetElectraForkEpoch,
|
||||
EPBSForkVersion: []byte{6, 0, 0, 0},
|
||||
EPBSForkEpoch: mainnetEPBSForkEpoch,
|
||||
|
||||
// New values introduced in Altair hard fork 1.
|
||||
// Participation flag indices.
|
||||
@@ -335,6 +340,7 @@ func FillTestVersions(c *BeaconChainConfig, b byte) {
|
||||
c.CapellaForkVersion = make([]byte, fieldparams.VersionLength)
|
||||
c.DenebForkVersion = make([]byte, fieldparams.VersionLength)
|
||||
c.ElectraForkVersion = make([]byte, fieldparams.VersionLength)
|
||||
c.EPBSForkVersion = make([]byte, fieldparams.VersionLength)
|
||||
|
||||
c.GenesisForkVersion[fieldparams.VersionLength-1] = b
|
||||
c.AltairForkVersion[fieldparams.VersionLength-1] = b
|
||||
@@ -342,6 +348,7 @@ func FillTestVersions(c *BeaconChainConfig, b byte) {
|
||||
c.CapellaForkVersion[fieldparams.VersionLength-1] = b
|
||||
c.DenebForkVersion[fieldparams.VersionLength-1] = b
|
||||
c.ElectraForkVersion[fieldparams.VersionLength-1] = b
|
||||
c.EPBSForkVersion[fieldparams.VersionLength-1] = b
|
||||
|
||||
c.GenesisForkVersion[0] = 0
|
||||
c.AltairForkVersion[0] = 1
|
||||
@@ -349,4 +356,5 @@ func FillTestVersions(c *BeaconChainConfig, b byte) {
|
||||
c.CapellaForkVersion[0] = 3
|
||||
c.DenebForkVersion[0] = 4
|
||||
c.ElectraForkVersion[0] = 5
|
||||
c.EPBSForkVersion[0] = 6
|
||||
}
|
||||
|
||||
@@ -41,11 +41,14 @@ go_test(
|
||||
srcs = [
|
||||
"execution_test.go",
|
||||
"factory_test.go",
|
||||
"getters_epbs_test.go",
|
||||
"getters_test.go",
|
||||
"kzg_test.go",
|
||||
"proto_epbs_test.go",
|
||||
"proto_test.go",
|
||||
"roblob_test.go",
|
||||
"roblock_test.go",
|
||||
"setters_test.go",
|
||||
],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
|
||||
@@ -74,6 +74,10 @@ func NewSignedBeaconBlock(i interface{}) (interfaces.SignedBeaconBlock, error) {
|
||||
return initBlindedSignedBlockFromProtoElectra(b)
|
||||
case *eth.GenericSignedBeaconBlock_BlindedElectra:
|
||||
return initBlindedSignedBlockFromProtoElectra(b.BlindedElectra)
|
||||
case *eth.GenericSignedBeaconBlock_Epbs:
|
||||
return initSignedBlockFromProtoEPBS(b.Epbs)
|
||||
case *eth.SignedBeaconBlockEpbs:
|
||||
return initSignedBlockFromProtoEPBS(b)
|
||||
default:
|
||||
return nil, errors.Wrapf(ErrUnsupportedSignedBeaconBlock, "unable to create block from type %T", i)
|
||||
}
|
||||
@@ -124,6 +128,10 @@ func NewBeaconBlock(i interface{}) (interfaces.ReadOnlyBeaconBlock, error) {
|
||||
return initBlindedBlockFromProtoElectra(b)
|
||||
case *eth.GenericBeaconBlock_BlindedElectra:
|
||||
return initBlindedBlockFromProtoElectra(b.BlindedElectra)
|
||||
case *eth.GenericBeaconBlock_Epbs:
|
||||
return initBlockFromProtoEpbs(b.Epbs)
|
||||
case *eth.BeaconBlockEpbs:
|
||||
return initBlockFromProtoEpbs(b)
|
||||
default:
|
||||
return nil, errors.Wrapf(errUnsupportedBeaconBlock, "unable to create block from type %T", i)
|
||||
}
|
||||
@@ -154,6 +162,8 @@ func NewBeaconBlockBody(i interface{}) (interfaces.ReadOnlyBeaconBlockBody, erro
|
||||
return initBlockBodyFromProtoElectra(b)
|
||||
case *eth.BlindedBeaconBlockBodyElectra:
|
||||
return initBlindedBlockBodyFromProtoElectra(b)
|
||||
case *eth.BeaconBlockBodyEpbs:
|
||||
return initBlockBodyFromProtoEpbs(b)
|
||||
default:
|
||||
return nil, errors.Wrapf(errUnsupportedBeaconBlockBody, "unable to create block body from type %T", i)
|
||||
}
|
||||
@@ -233,6 +243,12 @@ func BuildSignedBeaconBlock(blk interfaces.ReadOnlyBeaconBlock, signature []byte
|
||||
return nil, errIncorrectBlockVersion
|
||||
}
|
||||
return NewSignedBeaconBlock(ð.SignedBeaconBlockElectra{Block: pb, Signature: signature})
|
||||
case version.EPBS:
|
||||
pb, ok := pb.(*eth.BeaconBlockEpbs)
|
||||
if !ok {
|
||||
return nil, errIncorrectBlockVersion
|
||||
}
|
||||
return NewSignedBeaconBlock(ð.SignedBeaconBlockEpbs{Block: pb, Signature: signature})
|
||||
default:
|
||||
return nil, errUnsupportedBeaconBlock
|
||||
}
|
||||
@@ -247,6 +263,9 @@ func BuildSignedBeaconBlockFromExecutionPayload(blk interfaces.ReadOnlySignedBea
|
||||
if !blk.IsBlinded() {
|
||||
return nil, errNonBlindedSignedBeaconBlock
|
||||
}
|
||||
if blk.Version() >= version.EPBS {
|
||||
return nil, errors.Wrap(errUnsupportedBeaconBlock, "post epbs blocks no longer need to be unblind")
|
||||
}
|
||||
b := blk.Block()
|
||||
payloadHeader, err := b.Body().Execution()
|
||||
if err != nil {
|
||||
|
||||
@@ -161,6 +161,26 @@ func Test_NewSignedBeaconBlock(t *testing.T) {
|
||||
assert.Equal(t, version.Deneb, b.Version())
|
||||
assert.Equal(t, true, b.IsBlinded())
|
||||
})
|
||||
t.Run("GenericSignedBeaconBlock_Epbs", func(t *testing.T) {
|
||||
pb := ð.GenericSignedBeaconBlock_Epbs{
|
||||
Epbs: ð.SignedBeaconBlockEpbs{
|
||||
Block: ð.BeaconBlockEpbs{
|
||||
Body: ð.BeaconBlockBodyEpbs{},
|
||||
},
|
||||
},
|
||||
}
|
||||
b, err := NewSignedBeaconBlock(pb)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, version.EPBS, b.Version())
|
||||
})
|
||||
t.Run("SignedBeaconBlockEpbs", func(t *testing.T) {
|
||||
pb := ð.SignedBeaconBlockEpbs{
|
||||
Block: ð.BeaconBlockEpbs{
|
||||
Body: ð.BeaconBlockBodyEpbs{}}}
|
||||
b, err := NewSignedBeaconBlock(pb)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, version.EPBS, b.Version())
|
||||
})
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
_, err := NewSignedBeaconBlock(nil)
|
||||
assert.ErrorContains(t, "received nil object", err)
|
||||
@@ -276,6 +296,18 @@ func Test_NewBeaconBlock(t *testing.T) {
|
||||
assert.Equal(t, version.Deneb, b.Version())
|
||||
assert.Equal(t, true, b.IsBlinded())
|
||||
})
|
||||
t.Run("GenericBeaconBlock_Epbs", func(t *testing.T) {
|
||||
pb := ð.GenericBeaconBlock_Epbs{Epbs: ð.BeaconBlockEpbs{Body: ð.BeaconBlockBodyEpbs{}}}
|
||||
b, err := NewBeaconBlock(pb)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, version.EPBS, b.Version())
|
||||
})
|
||||
t.Run("BeaconBlockEpbs", func(t *testing.T) {
|
||||
pb := ð.BeaconBlockEpbs{Body: ð.BeaconBlockBodyEpbs{}}
|
||||
b, err := NewBeaconBlock(pb)
|
||||
require.NoError(t, err)
|
||||
assert.Equal(t, version.EPBS, b.Version())
|
||||
})
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
_, err := NewBeaconBlock(nil)
|
||||
assert.ErrorContains(t, "received nil object", err)
|
||||
@@ -354,6 +386,14 @@ func Test_NewBeaconBlockBody(t *testing.T) {
|
||||
assert.Equal(t, version.Deneb, b.version)
|
||||
assert.Equal(t, true, b.IsBlinded())
|
||||
})
|
||||
t.Run("BeaconBlockBodyEpbs", func(t *testing.T) {
|
||||
pb := ð.BeaconBlockBodyEpbs{}
|
||||
i, err := NewBeaconBlockBody(pb)
|
||||
require.NoError(t, err)
|
||||
b, ok := i.(*BeaconBlockBody)
|
||||
require.Equal(t, true, ok)
|
||||
assert.Equal(t, version.EPBS, b.version)
|
||||
})
|
||||
t.Run("nil", func(t *testing.T) {
|
||||
_, err := NewBeaconBlockBody(nil)
|
||||
assert.ErrorContains(t, "received nil object", err)
|
||||
@@ -425,6 +465,13 @@ func Test_BuildSignedBeaconBlock(t *testing.T) {
|
||||
assert.Equal(t, version.Deneb, sb.Version())
|
||||
assert.Equal(t, true, sb.IsBlinded())
|
||||
})
|
||||
t.Run("Epbs", func(t *testing.T) {
|
||||
b := &BeaconBlock{version: version.EPBS, body: &BeaconBlockBody{version: version.EPBS}}
|
||||
sb, err := BuildSignedBeaconBlock(b, sig[:])
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, sig, sb.Signature())
|
||||
assert.Equal(t, version.EPBS, sb.Version())
|
||||
})
|
||||
}
|
||||
|
||||
func TestBuildSignedBeaconBlockFromExecutionPayload(t *testing.T) {
|
||||
|
||||
@@ -15,6 +15,11 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrAlreadyUnblinded is returned when trying to unblind a full block.
|
||||
ErrAlreadyUnblinded = errors.New("cannot unblind if a full block")
|
||||
)
|
||||
|
||||
// BeaconBlockIsNil checks if any composite field of input signed beacon block is nil.
|
||||
// Access to these nil fields will result in run time panic,
|
||||
// it is recommended to run these checks as first line of defense.
|
||||
@@ -85,7 +90,9 @@ func (b *SignedBeaconBlock) Copy() (interfaces.SignedBeaconBlock, error) {
|
||||
}
|
||||
cp := eth.CopySignedBeaconBlockElectra(pb.(*eth.SignedBeaconBlockElectra))
|
||||
return initSignedBlockFromProtoElectra(cp)
|
||||
|
||||
case version.EPBS:
|
||||
cp := eth.CopySignedBeaconBlockEPBS(pb.(*eth.SignedBeaconBlockEpbs))
|
||||
return initSignedBlockFromProtoEPBS(cp)
|
||||
default:
|
||||
return nil, errIncorrectBlockVersion
|
||||
}
|
||||
@@ -142,6 +149,10 @@ func (b *SignedBeaconBlock) PbGenericBlock() (*eth.GenericSignedBeaconBlock, err
|
||||
return ð.GenericSignedBeaconBlock{
|
||||
Block: ð.GenericSignedBeaconBlock_Electra{Electra: pb.(*eth.SignedBeaconBlockContentsElectra)},
|
||||
}, nil
|
||||
case version.EPBS:
|
||||
return ð.GenericSignedBeaconBlock{
|
||||
Block: ð.GenericSignedBeaconBlock_Epbs{Epbs: pb.(*eth.SignedBeaconBlockEpbs)},
|
||||
}, nil
|
||||
default:
|
||||
return nil, errIncorrectBlockVersion
|
||||
}
|
||||
@@ -149,7 +160,7 @@ func (b *SignedBeaconBlock) PbGenericBlock() (*eth.GenericSignedBeaconBlock, err
|
||||
|
||||
// ToBlinded converts a non-blinded block to its blinded equivalent.
|
||||
func (b *SignedBeaconBlock) ToBlinded() (interfaces.ReadOnlySignedBeaconBlock, error) {
|
||||
if b.version < version.Bellatrix {
|
||||
if b.version < version.Bellatrix || b.version >= version.EPBS {
|
||||
return nil, ErrUnsupportedVersion
|
||||
}
|
||||
if b.IsBlinded() {
|
||||
@@ -287,11 +298,11 @@ func (b *SignedBeaconBlock) ToBlinded() (interfaces.ReadOnlySignedBeaconBlock, e
|
||||
}
|
||||
|
||||
func (b *SignedBeaconBlock) Unblind(e interfaces.ExecutionData) error {
|
||||
if e.IsNil() {
|
||||
if e == nil || e.IsNil() {
|
||||
return errors.New("cannot unblind with nil execution data")
|
||||
}
|
||||
if !b.IsBlinded() {
|
||||
return errors.New("cannot unblind if the block is already unblinded")
|
||||
return ErrAlreadyUnblinded
|
||||
}
|
||||
payloadRoot, err := e.HashTreeRoot()
|
||||
if err != nil {
|
||||
@@ -321,7 +332,8 @@ func (b *SignedBeaconBlock) Version() int {
|
||||
|
||||
// IsBlinded metadata on whether a block is blinded
|
||||
func (b *SignedBeaconBlock) IsBlinded() bool {
|
||||
return b.version >= version.Bellatrix && b.block.body.executionPayload == nil
|
||||
preEPBS := b.version < version.EPBS
|
||||
return preEPBS && b.version >= version.Bellatrix && b.block.body.executionPayload == nil
|
||||
}
|
||||
|
||||
// Header converts the underlying protobuf object from blinded block to header format.
|
||||
@@ -377,6 +389,8 @@ func (b *SignedBeaconBlock) MarshalSSZ() ([]byte, error) {
|
||||
return pb.(*eth.SignedBlindedBeaconBlockElectra).MarshalSSZ()
|
||||
}
|
||||
return pb.(*eth.SignedBeaconBlockElectra).MarshalSSZ()
|
||||
case version.EPBS:
|
||||
return pb.(*eth.SignedBeaconBlockEpbs).MarshalSSZ()
|
||||
default:
|
||||
return []byte{}, errIncorrectBlockVersion
|
||||
}
|
||||
@@ -414,6 +428,8 @@ func (b *SignedBeaconBlock) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return pb.(*eth.SignedBlindedBeaconBlockElectra).MarshalSSZTo(dst)
|
||||
}
|
||||
return pb.(*eth.SignedBeaconBlockElectra).MarshalSSZTo(dst)
|
||||
case version.EPBS:
|
||||
return pb.(*eth.SignedBeaconBlockEpbs).MarshalSSZTo(dst)
|
||||
default:
|
||||
return []byte{}, errIncorrectBlockVersion
|
||||
}
|
||||
@@ -455,6 +471,8 @@ func (b *SignedBeaconBlock) SizeSSZ() int {
|
||||
return pb.(*eth.SignedBlindedBeaconBlockElectra).SizeSSZ()
|
||||
}
|
||||
return pb.(*eth.SignedBeaconBlockElectra).SizeSSZ()
|
||||
case version.EPBS:
|
||||
return pb.(*eth.SignedBeaconBlockEpbs).SizeSSZ()
|
||||
default:
|
||||
panic(incorrectBlockVersion)
|
||||
}
|
||||
@@ -572,6 +590,16 @@ func (b *SignedBeaconBlock) UnmarshalSSZ(buf []byte) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case version.EPBS:
|
||||
pb := ð.SignedBeaconBlockEpbs{}
|
||||
if err := pb.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
var err error
|
||||
newBlock, err = initSignedBlockFromProtoEPBS(pb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return errIncorrectBlockVersion
|
||||
}
|
||||
@@ -611,7 +639,8 @@ func (b *BeaconBlock) IsNil() bool {
|
||||
|
||||
// IsBlinded checks if the beacon block is a blinded block.
|
||||
func (b *BeaconBlock) IsBlinded() bool {
|
||||
return b.version >= version.Bellatrix && b.body.executionPayload == nil
|
||||
preEPBS := b.version < version.EPBS
|
||||
return preEPBS && b.version >= version.Bellatrix && b.body.executionPayload == nil
|
||||
}
|
||||
|
||||
// Version of the underlying protobuf object.
|
||||
@@ -650,6 +679,8 @@ func (b *BeaconBlock) HashTreeRoot() ([field_params.RootLength]byte, error) {
|
||||
return pb.(*eth.BlindedBeaconBlockElectra).HashTreeRoot()
|
||||
}
|
||||
return pb.(*eth.BeaconBlockElectra).HashTreeRoot()
|
||||
case version.EPBS:
|
||||
return pb.(*eth.BeaconBlockEpbs).HashTreeRoot()
|
||||
default:
|
||||
return [field_params.RootLength]byte{}, errIncorrectBlockVersion
|
||||
}
|
||||
@@ -686,6 +717,8 @@ func (b *BeaconBlock) HashTreeRootWith(h *ssz.Hasher) error {
|
||||
return pb.(*eth.BlindedBeaconBlockElectra).HashTreeRootWith(h)
|
||||
}
|
||||
return pb.(*eth.BeaconBlockElectra).HashTreeRootWith(h)
|
||||
case version.EPBS:
|
||||
return pb.(*eth.BeaconBlockEpbs).HashTreeRootWith(h)
|
||||
default:
|
||||
return errIncorrectBlockVersion
|
||||
}
|
||||
@@ -723,6 +756,8 @@ func (b *BeaconBlock) MarshalSSZ() ([]byte, error) {
|
||||
return pb.(*eth.BlindedBeaconBlockElectra).MarshalSSZ()
|
||||
}
|
||||
return pb.(*eth.BeaconBlockElectra).MarshalSSZ()
|
||||
case version.EPBS:
|
||||
return pb.(*eth.BeaconBlockEpbs).MarshalSSZ()
|
||||
default:
|
||||
return []byte{}, errIncorrectBlockVersion
|
||||
}
|
||||
@@ -760,6 +795,8 @@ func (b *BeaconBlock) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
return pb.(*eth.BlindedBeaconBlockElectra).MarshalSSZTo(dst)
|
||||
}
|
||||
return pb.(*eth.BeaconBlockElectra).MarshalSSZTo(dst)
|
||||
case version.EPBS:
|
||||
return pb.(*eth.BeaconBlockEpbs).MarshalSSZTo(dst)
|
||||
default:
|
||||
return []byte{}, errIncorrectBlockVersion
|
||||
}
|
||||
@@ -801,6 +838,8 @@ func (b *BeaconBlock) SizeSSZ() int {
|
||||
return pb.(*eth.BlindedBeaconBlockElectra).SizeSSZ()
|
||||
}
|
||||
return pb.(*eth.BeaconBlockElectra).SizeSSZ()
|
||||
case version.EPBS:
|
||||
return pb.(*eth.BeaconBlockEpbs).SizeSSZ()
|
||||
default:
|
||||
panic(incorrectBodyVersion)
|
||||
}
|
||||
@@ -918,6 +957,16 @@ func (b *BeaconBlock) UnmarshalSSZ(buf []byte) error {
|
||||
return err
|
||||
}
|
||||
}
|
||||
case version.EPBS:
|
||||
pb := ð.BeaconBlockEpbs{}
|
||||
if err := pb.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
var err error
|
||||
newBlock, err = initBlockFromProtoEpbs(pb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return errIncorrectBlockVersion
|
||||
}
|
||||
@@ -956,6 +1005,8 @@ func (b *BeaconBlock) AsSignRequestObject() (validatorpb.SignRequestObject, erro
|
||||
return &validatorpb.SignRequest_BlindedBlockElectra{BlindedBlockElectra: pb.(*eth.BlindedBeaconBlockElectra)}, nil
|
||||
}
|
||||
return &validatorpb.SignRequest_BlockElectra{BlockElectra: pb.(*eth.BeaconBlockElectra)}, nil
|
||||
case version.EPBS:
|
||||
return &validatorpb.SignRequest_BlockEpbs{BlockEpbs: pb.(*eth.BeaconBlockEpbs)}, nil
|
||||
default:
|
||||
return nil, errIncorrectBlockVersion
|
||||
}
|
||||
@@ -1005,6 +1056,9 @@ func (b *BeaconBlock) Copy() (interfaces.ReadOnlyBeaconBlock, error) {
|
||||
}
|
||||
cp := eth.CopyBeaconBlockElectra(pb.(*eth.BeaconBlockElectra))
|
||||
return initBlockFromProtoElectra(cp)
|
||||
case version.EPBS:
|
||||
cp := eth.CopyBeaconBlockEPBS(pb.(*eth.BeaconBlockEpbs))
|
||||
return initBlockFromProtoEpbs(cp)
|
||||
default:
|
||||
return nil, errIncorrectBlockVersion
|
||||
}
|
||||
@@ -1102,7 +1156,7 @@ func (b *BeaconBlockBody) SyncAggregate() (*eth.SyncAggregate, error) {
|
||||
// Execution returns the execution payload of the block body.
|
||||
func (b *BeaconBlockBody) Execution() (interfaces.ExecutionData, error) {
|
||||
switch b.version {
|
||||
case version.Phase0, version.Altair:
|
||||
case version.Phase0, version.Altair, version.EPBS:
|
||||
return nil, consensus_types.ErrNotSupported("Execution", b.version)
|
||||
default:
|
||||
if b.IsBlinded() {
|
||||
@@ -1131,6 +1185,16 @@ func (b *BeaconBlockBody) BlobKzgCommitments() ([][]byte, error) {
|
||||
}
|
||||
}
|
||||
|
||||
// PayloadAttestations returns the payload attestations in the block.
|
||||
func (b *BeaconBlockBody) PayloadAttestations() []*eth.PayloadAttestation {
|
||||
return b.payloadAttestations
|
||||
}
|
||||
|
||||
// SignedExecutionPayloadHeader returns the signed execution payload header in the block.
|
||||
func (b *BeaconBlockBody) SignedExecutionPayloadHeader() *enginev1.SignedExecutionPayloadHeader {
|
||||
return b.signedExecutionPayloadHeader
|
||||
}
|
||||
|
||||
// Version returns the version of the beacon block body
|
||||
func (b *BeaconBlockBody) Version() int {
|
||||
return b.version
|
||||
@@ -1167,6 +1231,8 @@ func (b *BeaconBlockBody) HashTreeRoot() ([field_params.RootLength]byte, error)
|
||||
return pb.(*eth.BlindedBeaconBlockBodyElectra).HashTreeRoot()
|
||||
}
|
||||
return pb.(*eth.BeaconBlockBodyElectra).HashTreeRoot()
|
||||
case version.EPBS:
|
||||
return pb.(*eth.BeaconBlockBodyEpbs).HashTreeRoot()
|
||||
default:
|
||||
return [field_params.RootLength]byte{}, errIncorrectBodyVersion
|
||||
}
|
||||
@@ -1174,5 +1240,6 @@ func (b *BeaconBlockBody) HashTreeRoot() ([field_params.RootLength]byte, error)
|
||||
|
||||
// IsBlinded checks if the beacon block body is a blinded block body.
|
||||
func (b *BeaconBlockBody) IsBlinded() bool {
|
||||
return b.version >= version.Bellatrix && b.executionPayload == nil
|
||||
preEPBS := b.version < version.EPBS
|
||||
return preEPBS && b.version >= version.Bellatrix && b.executionPayload == nil
|
||||
}
|
||||
|
||||
95
consensus-types/blocks/getters_epbs_test.go
Normal file
95
consensus-types/blocks/getters_epbs_test.go
Normal file
@@ -0,0 +1,95 @@
|
||||
package blocks
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
pb "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
func Test_EpbsBlock_Copy(t *testing.T) {
|
||||
signedHeader := &pb.SignedExecutionPayloadHeader{
|
||||
Message: &pb.ExecutionPayloadHeaderEPBS{
|
||||
ParentBlockHash: bytesutil.PadTo([]byte("parentblockhash"), fieldparams.RootLength),
|
||||
ParentBlockRoot: bytesutil.PadTo([]byte("parentblockroot"), fieldparams.RootLength),
|
||||
BlockHash: bytesutil.PadTo([]byte("blockhash"), fieldparams.RootLength),
|
||||
BuilderIndex: 1,
|
||||
Slot: 2,
|
||||
Value: 3,
|
||||
BlobKzgCommitmentsRoot: bytesutil.PadTo([]byte("blobkzgcommitmentsroot"), fieldparams.RootLength),
|
||||
GasLimit: 4,
|
||||
},
|
||||
Signature: bytesutil.PadTo([]byte("signature"), fieldparams.BLSSignatureLength),
|
||||
}
|
||||
aggregationBits := bitfield.NewBitvector512()
|
||||
aggregationBits.SetBitAt(1, true)
|
||||
aggregationBits.SetBitAt(2, true)
|
||||
|
||||
payloadAttestations := []*eth.PayloadAttestation{
|
||||
{
|
||||
AggregationBits: aggregationBits,
|
||||
Data: ð.PayloadAttestationData{
|
||||
BeaconBlockRoot: []byte("beaconblockroot"),
|
||||
Slot: 1,
|
||||
PayloadStatus: 2,
|
||||
},
|
||||
Signature: []byte("signature"),
|
||||
},
|
||||
{
|
||||
AggregationBits: aggregationBits,
|
||||
Data: ð.PayloadAttestationData{
|
||||
BeaconBlockRoot: []byte("beaconblockroot"),
|
||||
Slot: 1,
|
||||
PayloadStatus: 1,
|
||||
},
|
||||
Signature: []byte("signature"),
|
||||
},
|
||||
}
|
||||
|
||||
epbsBlockProto := ð.BeaconBlockEpbs{
|
||||
Body: ð.BeaconBlockBodyEpbs{
|
||||
SignedExecutionPayloadHeader: signedHeader,
|
||||
PayloadAttestations: payloadAttestations,
|
||||
},
|
||||
}
|
||||
|
||||
epbsBlock, err := NewBeaconBlock(epbsBlockProto)
|
||||
require.NoError(t, err)
|
||||
copiedEpbsBlock, err := epbsBlock.Copy()
|
||||
require.NoError(t, err)
|
||||
copiedBody, ok := copiedEpbsBlock.Body().(interfaces.ROBlockBodyEpbs)
|
||||
require.Equal(t, true, ok)
|
||||
require.DeepEqual(t, copiedBody.SignedExecutionPayloadHeader(), signedHeader)
|
||||
|
||||
copiedPayloadAtts := copiedBody.PayloadAttestations()
|
||||
require.DeepEqual(t, copiedPayloadAtts, payloadAttestations)
|
||||
}
|
||||
|
||||
func Test_EpbsBlock_ToBlinded(t *testing.T) {
|
||||
b := &SignedBeaconBlock{version: version.EPBS}
|
||||
_, err := b.ToBlinded()
|
||||
require.ErrorIs(t, err, ErrUnsupportedVersion)
|
||||
}
|
||||
|
||||
func Test_EpbsBlock_Unblind(t *testing.T) {
|
||||
b := &SignedBeaconBlock{version: version.EPBS}
|
||||
e, err := WrappedExecutionPayload(&pb.ExecutionPayload{})
|
||||
require.NoError(t, err)
|
||||
err = b.Unblind(e)
|
||||
require.ErrorIs(t, err, ErrAlreadyUnblinded)
|
||||
}
|
||||
|
||||
func Test_EpbsBlock_IsBlinded(t *testing.T) {
|
||||
b := &SignedBeaconBlock{version: version.EPBS}
|
||||
require.Equal(t, false, b.IsBlinded())
|
||||
bb := &BeaconBlock{version: version.EPBS}
|
||||
require.Equal(t, false, bb.IsBlinded())
|
||||
bd := &BeaconBlockBody{version: version.EPBS}
|
||||
require.Equal(t, false, bd.IsBlinded())
|
||||
}
|
||||
@@ -464,6 +464,9 @@ func Test_BeaconBlockBody_Execution(t *testing.T) {
|
||||
gas, err = eDenebHeader.ExcessBlobGas()
|
||||
require.NoError(t, err)
|
||||
require.DeepEqual(t, gas, uint64(223))
|
||||
|
||||
bb = &SignedBeaconBlock{version: version.EPBS, block: &BeaconBlock{version: version.EPBS, body: &BeaconBlockBody{version: version.EPBS}}}
|
||||
require.ErrorContains(t, "Execution is not supported for epbs: unsupported getter", bb.SetExecution(nil))
|
||||
}
|
||||
|
||||
func Test_BeaconBlockBody_HashTreeRoot(t *testing.T) {
|
||||
|
||||
@@ -156,7 +156,12 @@ func topLevelRoots(body interfaces.ReadOnlyBeaconBlockBody) ([][]byte, error) {
|
||||
|
||||
// Attester slashings
|
||||
as := body.AttesterSlashings()
|
||||
root, err = ssz.MerkleizeListSSZ(as, params.BeaconConfig().MaxAttesterSlashings)
|
||||
bodyVersion := body.Version()
|
||||
if bodyVersion < version.Electra {
|
||||
root, err = ssz.MerkleizeListSSZ(as, params.BeaconConfig().MaxAttesterSlashings)
|
||||
} else {
|
||||
root, err = ssz.MerkleizeListSSZ(as, params.BeaconConfig().MaxAttesterSlashingsElectra)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -164,7 +169,11 @@ func topLevelRoots(body interfaces.ReadOnlyBeaconBlockBody) ([][]byte, error) {
|
||||
|
||||
// Attestations
|
||||
att := body.Attestations()
|
||||
root, err = ssz.MerkleizeListSSZ(att, params.BeaconConfig().MaxAttestations)
|
||||
if bodyVersion < version.Electra {
|
||||
root, err = ssz.MerkleizeListSSZ(att, params.BeaconConfig().MaxAttestations)
|
||||
} else {
|
||||
root, err = ssz.MerkleizeListSSZ(att, params.BeaconConfig().MaxAttestationsElectra)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -156,6 +156,16 @@ func (b *SignedBeaconBlock) Proto() (proto.Message, error) { // nolint:gocognit
|
||||
Block: block,
|
||||
Signature: b.signature[:],
|
||||
}, nil
|
||||
case version.EPBS:
|
||||
block, ok := blockMessage.(*eth.BeaconBlockEpbs)
|
||||
if !ok {
|
||||
return nil, errIncorrectBlockVersion
|
||||
}
|
||||
|
||||
return ð.SignedBeaconBlockEpbs{
|
||||
Block: block,
|
||||
Signature: b.signature[:],
|
||||
}, nil
|
||||
default:
|
||||
return nil, errors.New("unsupported signed beacon block version")
|
||||
}
|
||||
@@ -337,6 +347,18 @@ func (b *BeaconBlock) Proto() (proto.Message, error) { // nolint:gocognit
|
||||
StateRoot: b.stateRoot[:],
|
||||
Body: body,
|
||||
}, nil
|
||||
case version.EPBS:
|
||||
body, ok := bodyMessage.(*eth.BeaconBlockBodyEpbs)
|
||||
if !ok {
|
||||
return nil, errIncorrectBodyVersion
|
||||
}
|
||||
return ð.BeaconBlockEpbs{
|
||||
Slot: b.slot,
|
||||
ProposerIndex: b.proposerIndex,
|
||||
ParentRoot: b.parentRoot[:],
|
||||
StateRoot: b.stateRoot[:],
|
||||
Body: body,
|
||||
}, nil
|
||||
|
||||
default:
|
||||
return nil, errors.New("unsupported beacon block version")
|
||||
@@ -556,6 +578,21 @@ func (b *BeaconBlockBody) Proto() (proto.Message, error) {
|
||||
BlobKzgCommitments: b.blobKzgCommitments,
|
||||
}, nil
|
||||
|
||||
case version.EPBS:
|
||||
return ð.BeaconBlockBodyEpbs{
|
||||
RandaoReveal: b.randaoReveal[:],
|
||||
Eth1Data: b.eth1Data,
|
||||
Graffiti: b.graffiti[:],
|
||||
ProposerSlashings: b.proposerSlashings,
|
||||
AttesterSlashings: b.attesterSlashings,
|
||||
Attestations: b.attestations,
|
||||
Deposits: b.deposits,
|
||||
VoluntaryExits: b.voluntaryExits,
|
||||
SyncAggregate: b.syncAggregate,
|
||||
BlsToExecutionChanges: b.blsToExecutionChanges,
|
||||
SignedExecutionPayloadHeader: b.signedExecutionPayloadHeader,
|
||||
PayloadAttestations: b.payloadAttestations,
|
||||
}, nil
|
||||
default:
|
||||
return nil, errors.New("unsupported beacon block body version")
|
||||
}
|
||||
@@ -663,6 +700,22 @@ func initSignedBlockFromProtoElectra(pb *eth.SignedBeaconBlockElectra) (*SignedB
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func initSignedBlockFromProtoEPBS(pb *eth.SignedBeaconBlockEpbs) (*SignedBeaconBlock, error) {
|
||||
if pb == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
block, err := initBlockFromProtoEpbs(pb.Block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := &SignedBeaconBlock{
|
||||
version: version.EPBS,
|
||||
block: block,
|
||||
signature: bytesutil.ToBytes96(pb.Signature),
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func initBlindedSignedBlockFromProtoBellatrix(pb *eth.SignedBlindedBeaconBlockBellatrix) (*SignedBeaconBlock, error) {
|
||||
if pb == nil {
|
||||
return nil, errNilBlock
|
||||
@@ -855,7 +908,6 @@ func initBlockFromProtoElectra(pb *eth.BeaconBlockElectra) (*BeaconBlock, error)
|
||||
if pb == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
|
||||
body, err := initBlockBodyFromProtoElectra(pb.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -871,6 +923,25 @@ func initBlockFromProtoElectra(pb *eth.BeaconBlockElectra) (*BeaconBlock, error)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func initBlockFromProtoEpbs(pb *eth.BeaconBlockEpbs) (*BeaconBlock, error) {
|
||||
if pb == nil {
|
||||
return nil, errNilBlock
|
||||
}
|
||||
body, err := initBlockBodyFromProtoEpbs(pb.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := &BeaconBlock{
|
||||
version: version.EPBS,
|
||||
slot: pb.Slot,
|
||||
proposerIndex: pb.ProposerIndex,
|
||||
parentRoot: bytesutil.ToBytes32(pb.ParentRoot),
|
||||
stateRoot: bytesutil.ToBytes32(pb.StateRoot),
|
||||
body: body,
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func initBlindedBlockFromProtoCapella(pb *eth.BlindedBeaconBlockCapella) (*BeaconBlock, error) {
|
||||
if pb == nil {
|
||||
return nil, errNilBlock
|
||||
@@ -1104,6 +1175,29 @@ func initBlockBodyFromProtoDeneb(pb *eth.BeaconBlockBodyDeneb) (*BeaconBlockBody
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func initBlockBodyFromProtoEpbs(pb *eth.BeaconBlockBodyEpbs) (*BeaconBlockBody, error) {
|
||||
if pb == nil {
|
||||
return nil, errNilBlockBody
|
||||
}
|
||||
|
||||
b := &BeaconBlockBody{
|
||||
version: version.EPBS,
|
||||
randaoReveal: bytesutil.ToBytes96(pb.RandaoReveal),
|
||||
eth1Data: pb.Eth1Data,
|
||||
graffiti: bytesutil.ToBytes32(pb.Graffiti),
|
||||
proposerSlashings: pb.ProposerSlashings,
|
||||
attesterSlashings: pb.AttesterSlashings,
|
||||
attestations: pb.Attestations,
|
||||
deposits: pb.Deposits,
|
||||
voluntaryExits: pb.VoluntaryExits,
|
||||
syncAggregate: pb.SyncAggregate,
|
||||
blsToExecutionChanges: pb.BlsToExecutionChanges,
|
||||
signedExecutionPayloadHeader: pb.SignedExecutionPayloadHeader,
|
||||
payloadAttestations: pb.PayloadAttestations,
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
func initBlindedBlockBodyFromProtoDeneb(pb *eth.BlindedBeaconBlockBodyDeneb) (*BeaconBlockBody, error) {
|
||||
if pb == nil {
|
||||
return nil, errNilBlockBody
|
||||
|
||||
107
consensus-types/blocks/proto_epbs_test.go
Normal file
107
consensus-types/blocks/proto_epbs_test.go
Normal file
@@ -0,0 +1,107 @@
|
||||
package blocks
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
func Test_initSignedBlockFromProtoEpbs(t *testing.T) {
|
||||
f := getFields()
|
||||
expectedBlock := ð.SignedBeaconBlockEpbs{
|
||||
Block: ð.BeaconBlockEpbs{
|
||||
Slot: 128,
|
||||
ProposerIndex: 128,
|
||||
ParentRoot: f.root[:],
|
||||
StateRoot: f.root[:],
|
||||
Body: bodyPbEpbs(),
|
||||
},
|
||||
Signature: f.sig[:],
|
||||
}
|
||||
resultBlock, err := initSignedBlockFromProtoEPBS(expectedBlock)
|
||||
require.NoError(t, err)
|
||||
resultHTR, err := resultBlock.block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
expectedHTR, err := expectedBlock.Block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedHTR, resultHTR)
|
||||
assert.DeepEqual(t, expectedBlock.Signature, resultBlock.signature[:])
|
||||
}
|
||||
|
||||
func Test_initBlockFromProtoEpbs(t *testing.T) {
|
||||
f := getFields()
|
||||
expectedBlock := ð.BeaconBlockEpbs{
|
||||
Slot: 128,
|
||||
ProposerIndex: 128,
|
||||
ParentRoot: f.root[:],
|
||||
StateRoot: f.root[:],
|
||||
Body: bodyPbEpbs(),
|
||||
}
|
||||
resultBlock, err := initBlockFromProtoEpbs(expectedBlock)
|
||||
require.NoError(t, err)
|
||||
resultHTR, err := resultBlock.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
expectedHTR, err := expectedBlock.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedHTR, resultHTR)
|
||||
}
|
||||
|
||||
func Test_initBlockBodyFromProtoEpbs(t *testing.T) {
|
||||
expectedBody := bodyPbEpbs()
|
||||
resultBody, err := initBlockBodyFromProtoEpbs(expectedBody)
|
||||
require.NoError(t, err)
|
||||
resultHTR, err := resultBody.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
expectedHTR, err := expectedBody.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedHTR, resultHTR)
|
||||
}
|
||||
|
||||
func bodyEpbs() *BeaconBlockBody {
|
||||
f := getFields()
|
||||
return &BeaconBlockBody{
|
||||
version: version.EPBS,
|
||||
randaoReveal: f.sig,
|
||||
eth1Data: ð.Eth1Data{
|
||||
DepositRoot: f.root[:],
|
||||
DepositCount: 128,
|
||||
BlockHash: f.root[:],
|
||||
},
|
||||
graffiti: f.root,
|
||||
proposerSlashings: f.proposerSlashings,
|
||||
attesterSlashings: f.attesterSlashings,
|
||||
attestations: f.atts,
|
||||
deposits: f.deposits,
|
||||
voluntaryExits: f.voluntaryExits,
|
||||
syncAggregate: f.syncAggregate,
|
||||
signedExecutionPayloadHeader: f.signedPayloadHeader,
|
||||
blsToExecutionChanges: f.blsToExecutionChanges,
|
||||
blobKzgCommitments: f.kzgCommitments,
|
||||
payloadAttestations: f.payloadAttestation,
|
||||
}
|
||||
}
|
||||
|
||||
func bodyPbEpbs() *eth.BeaconBlockBodyEpbs {
|
||||
f := getFields()
|
||||
return ð.BeaconBlockBodyEpbs{
|
||||
RandaoReveal: f.sig[:],
|
||||
Eth1Data: ð.Eth1Data{
|
||||
DepositRoot: f.root[:],
|
||||
DepositCount: 128,
|
||||
BlockHash: f.root[:],
|
||||
},
|
||||
Graffiti: f.root[:],
|
||||
ProposerSlashings: f.proposerSlashings,
|
||||
AttesterSlashings: f.attesterSlashings,
|
||||
Attestations: f.atts,
|
||||
Deposits: f.deposits,
|
||||
VoluntaryExits: f.voluntaryExits,
|
||||
SyncAggregate: f.syncAggregate,
|
||||
BlsToExecutionChanges: f.blsToExecutionChanges,
|
||||
SignedExecutionPayloadHeader: f.signedPayloadHeader,
|
||||
PayloadAttestations: f.payloadAttestation,
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
@@ -27,8 +29,10 @@ type fields struct {
|
||||
execPayloadHeaderCapella *enginev1.ExecutionPayloadHeaderCapella
|
||||
execPayloadDeneb *enginev1.ExecutionPayloadDeneb
|
||||
execPayloadHeaderDeneb *enginev1.ExecutionPayloadHeaderDeneb
|
||||
signedPayloadHeader *enginev1.SignedExecutionPayloadHeader
|
||||
blsToExecutionChanges []*eth.SignedBLSToExecutionChange
|
||||
kzgCommitments [][]byte
|
||||
payloadAttestation []*eth.PayloadAttestation
|
||||
}
|
||||
|
||||
func Test_SignedBeaconBlock_Proto(t *testing.T) {
|
||||
@@ -306,6 +310,42 @@ func Test_SignedBeaconBlock_Proto(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedHTR, resultHTR)
|
||||
})
|
||||
t.Run("ePBS", func(t *testing.T) {
|
||||
slot := primitives.Slot(12345)
|
||||
proposerIndex := primitives.ValidatorIndex(23434)
|
||||
expectedBlock := ð.SignedBeaconBlockEpbs{
|
||||
Block: ð.BeaconBlockEpbs{
|
||||
Slot: slot,
|
||||
ProposerIndex: proposerIndex,
|
||||
ParentRoot: f.root[:],
|
||||
StateRoot: f.root[:],
|
||||
Body: bodyPbEpbs(),
|
||||
},
|
||||
Signature: f.sig[:],
|
||||
}
|
||||
block := &SignedBeaconBlock{
|
||||
version: version.EPBS,
|
||||
block: &BeaconBlock{
|
||||
version: version.EPBS,
|
||||
slot: slot,
|
||||
proposerIndex: proposerIndex,
|
||||
parentRoot: f.root,
|
||||
stateRoot: f.root,
|
||||
body: bodyEpbs(),
|
||||
},
|
||||
signature: f.sig,
|
||||
}
|
||||
|
||||
result, err := block.Proto()
|
||||
require.NoError(t, err)
|
||||
resultBlock, ok := result.(*eth.SignedBeaconBlockEpbs)
|
||||
require.Equal(t, true, ok)
|
||||
resultHTR, err := resultBlock.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
expectedHTR, err := expectedBlock.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedHTR, resultHTR)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_BeaconBlock_Proto(t *testing.T) {
|
||||
@@ -527,6 +567,34 @@ func Test_BeaconBlock_Proto(t *testing.T) {
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedHTR, resultHTR)
|
||||
})
|
||||
t.Run("ePBS", func(t *testing.T) {
|
||||
expectedBlock := ð.BeaconBlockEpbs{
|
||||
Slot: 128,
|
||||
ProposerIndex: 128,
|
||||
ParentRoot: f.root[:],
|
||||
StateRoot: f.root[:],
|
||||
Body: bodyPbEpbs(),
|
||||
}
|
||||
block := &BeaconBlock{
|
||||
version: version.EPBS,
|
||||
slot: 128,
|
||||
proposerIndex: 128,
|
||||
parentRoot: f.root,
|
||||
stateRoot: f.root,
|
||||
body: bodyEpbs(),
|
||||
}
|
||||
|
||||
result, err := block.Proto()
|
||||
require.NoError(t, err)
|
||||
resultBlock, ok := result.(*eth.BeaconBlockEpbs)
|
||||
require.Equal(t, true, ok)
|
||||
resultHTR, err := resultBlock.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
expectedHTR, err := expectedBlock.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedHTR, resultHTR)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
func Test_BeaconBlockBody_Proto(t *testing.T) {
|
||||
@@ -671,6 +739,19 @@ func Test_BeaconBlockBody_Proto(t *testing.T) {
|
||||
_, err := body.Proto()
|
||||
require.ErrorIs(t, err, errPayloadHeaderWrongType)
|
||||
})
|
||||
t.Run("epbs", func(t *testing.T) {
|
||||
expectedBody := bodyPbEpbs()
|
||||
body := bodyEpbs()
|
||||
result, err := body.Proto()
|
||||
require.NoError(t, err)
|
||||
resultBlock, ok := result.(*eth.BeaconBlockBodyEpbs)
|
||||
require.Equal(t, true, ok)
|
||||
resultHTR, err := resultBlock.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
expectedHTR, err := expectedBody.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
assert.DeepEqual(t, expectedHTR, resultHTR)
|
||||
})
|
||||
}
|
||||
|
||||
func Test_initSignedBlockFromProtoPhase0(t *testing.T) {
|
||||
@@ -1681,6 +1762,19 @@ func getFields() fields {
|
||||
BlobGasUsed: 128,
|
||||
ExcessBlobGas: 128,
|
||||
}
|
||||
signedExecutionPayloadHeader := &enginev1.SignedExecutionPayloadHeader{
|
||||
Message: &enginev1.ExecutionPayloadHeaderEPBS{
|
||||
ParentBlockHash: bytesutil.PadTo([]byte("parentblockhash"), fieldparams.RootLength),
|
||||
ParentBlockRoot: bytesutil.PadTo([]byte("parentblockroot"), fieldparams.RootLength),
|
||||
BlockHash: bytesutil.PadTo([]byte("blockhash"), fieldparams.RootLength),
|
||||
BuilderIndex: 1,
|
||||
Slot: 2,
|
||||
Value: 3,
|
||||
BlobKzgCommitmentsRoot: bytesutil.PadTo([]byte("blobkzgcommitmentsroot"), fieldparams.RootLength),
|
||||
GasLimit: 4,
|
||||
},
|
||||
Signature: bytesutil.PadTo([]byte("signature"), fieldparams.BLSSignatureLength),
|
||||
}
|
||||
|
||||
kzgCommitments := [][]byte{
|
||||
bytesutil.PadTo([]byte{123}, 48),
|
||||
@@ -1689,6 +1783,18 @@ func getFields() fields {
|
||||
bytesutil.PadTo([]byte{143}, 48),
|
||||
}
|
||||
|
||||
payloadAttestation := []*eth.PayloadAttestation{
|
||||
{
|
||||
AggregationBits: bitfield.NewBitvector512(),
|
||||
Data: ð.PayloadAttestationData{
|
||||
BeaconBlockRoot: bytesutil.PadTo([]byte{123}, 32),
|
||||
Slot: 1,
|
||||
PayloadStatus: 2,
|
||||
},
|
||||
Signature: bytesutil.PadTo([]byte("signature"), fieldparams.BLSSignatureLength),
|
||||
},
|
||||
}
|
||||
|
||||
return fields{
|
||||
root: root,
|
||||
sig: sig,
|
||||
@@ -1704,7 +1810,9 @@ func getFields() fields {
|
||||
execPayloadHeaderCapella: execPayloadHeaderCapella,
|
||||
execPayloadDeneb: execPayloadDeneb,
|
||||
execPayloadHeaderDeneb: execPayloadHeaderDeneb,
|
||||
signedPayloadHeader: signedExecutionPayloadHeader,
|
||||
blsToExecutionChanges: blsToExecutionChanges,
|
||||
kzgCommitments: kzgCommitments,
|
||||
payloadAttestation: payloadAttestation,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
@@ -143,7 +144,7 @@ func (b *SignedBeaconBlock) SetSyncAggregate(s *eth.SyncAggregate) error {
|
||||
// SetExecution sets the execution payload of the block body.
|
||||
// This function is not thread safe, it is only used during block creation.
|
||||
func (b *SignedBeaconBlock) SetExecution(e interfaces.ExecutionData) error {
|
||||
if b.version == version.Phase0 || b.version == version.Altair {
|
||||
if b.version >= version.EPBS || b.version < version.Bellatrix {
|
||||
return consensus_types.ErrNotSupported("Execution", b.version)
|
||||
}
|
||||
if e.IsBlinded() {
|
||||
@@ -172,3 +173,21 @@ func (b *SignedBeaconBlock) SetBlobKzgCommitments(c [][]byte) error {
|
||||
b.block.body.blobKzgCommitments = c
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetPayloadAttestations sets the payload attestations in the block.
|
||||
func (b *SignedBeaconBlock) SetPayloadAttestations(p []*eth.PayloadAttestation) error {
|
||||
if b.version < version.EPBS {
|
||||
return consensus_types.ErrNotSupported("PayloadAttestations", b.version)
|
||||
}
|
||||
b.block.body.payloadAttestations = p
|
||||
return nil
|
||||
}
|
||||
|
||||
// SetSignedExecutionPayloadHeader sets the signed execution payload header of the block body.
|
||||
func (b *SignedBeaconBlock) SetSignedExecutionPayloadHeader(h *enginev1.SignedExecutionPayloadHeader) error {
|
||||
if b.version < version.EPBS {
|
||||
return consensus_types.ErrNotSupported("SetSignedExecutionPayloadHeader", b.version)
|
||||
}
|
||||
b.block.body.signedExecutionPayloadHeader = h
|
||||
return nil
|
||||
}
|
||||
|
||||
71
consensus-types/blocks/setters_test.go
Normal file
71
consensus-types/blocks/setters_test.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package blocks
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
consensus_types "github.com/prysmaticlabs/prysm/v5/consensus-types"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
|
||||
func Test_EpbsBlock_SetPayloadAttestations(t *testing.T) {
|
||||
b := &SignedBeaconBlock{version: version.Deneb}
|
||||
require.ErrorIs(t, b.SetPayloadAttestations(nil), consensus_types.ErrUnsupportedField)
|
||||
|
||||
b = &SignedBeaconBlock{version: version.EPBS,
|
||||
block: &BeaconBlock{version: version.EPBS,
|
||||
body: &BeaconBlockBody{version: version.EPBS}}}
|
||||
aggregationBits := bitfield.NewBitvector512()
|
||||
aggregationBits.SetBitAt(0, true)
|
||||
payloadAttestation := []*eth.PayloadAttestation{
|
||||
{
|
||||
AggregationBits: aggregationBits,
|
||||
Data: ð.PayloadAttestationData{
|
||||
BeaconBlockRoot: bytesutil.PadTo([]byte{123}, 32),
|
||||
Slot: 1,
|
||||
PayloadStatus: 2,
|
||||
},
|
||||
Signature: bytesutil.PadTo([]byte("signature"), fieldparams.BLSSignatureLength),
|
||||
},
|
||||
{
|
||||
AggregationBits: aggregationBits,
|
||||
Data: ð.PayloadAttestationData{
|
||||
BeaconBlockRoot: bytesutil.PadTo([]byte{123}, 32),
|
||||
Slot: 1,
|
||||
PayloadStatus: 3,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
require.NoError(t, b.SetPayloadAttestations(payloadAttestation))
|
||||
require.DeepEqual(t, b.block.body.PayloadAttestations(), payloadAttestation)
|
||||
}
|
||||
|
||||
func Test_EpbsBlock_SetSignedExecutionPayloadHeader(t *testing.T) {
|
||||
b := &SignedBeaconBlock{version: version.Deneb}
|
||||
require.ErrorIs(t, b.SetSignedExecutionPayloadHeader(nil), consensus_types.ErrUnsupportedField)
|
||||
|
||||
b = &SignedBeaconBlock{version: version.EPBS,
|
||||
block: &BeaconBlock{version: version.EPBS,
|
||||
body: &BeaconBlockBody{version: version.EPBS}}}
|
||||
signedExecutionPayloadHeader := &enginev1.SignedExecutionPayloadHeader{
|
||||
Message: &enginev1.ExecutionPayloadHeaderEPBS{
|
||||
ParentBlockHash: []byte("parentBlockHash"),
|
||||
ParentBlockRoot: []byte("parentBlockRoot"),
|
||||
BlockHash: []byte("blockHash"),
|
||||
BuilderIndex: 1,
|
||||
Slot: 2,
|
||||
Value: 3,
|
||||
BlobKzgCommitmentsRoot: []byte("blobKzgCommitmentsRoot"),
|
||||
GasLimit: 4,
|
||||
},
|
||||
Signature: []byte("signature"),
|
||||
}
|
||||
require.NoError(t, b.SetSignedExecutionPayloadHeader(signedExecutionPayloadHeader))
|
||||
require.DeepEqual(t, b.block.body.SignedExecutionPayloadHeader(), signedExecutionPayloadHeader)
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
@@ -38,22 +39,24 @@ var (
|
||||
|
||||
// BeaconBlockBody is the main beacon block body structure. It can represent any block type.
|
||||
type BeaconBlockBody struct {
|
||||
version int
|
||||
randaoReveal [field_params.BLSSignatureLength]byte
|
||||
eth1Data *eth.Eth1Data
|
||||
graffiti [field_params.RootLength]byte
|
||||
proposerSlashings []*eth.ProposerSlashing
|
||||
attesterSlashings []*eth.AttesterSlashing
|
||||
attesterSlashingsElectra []*eth.AttesterSlashingElectra
|
||||
attestations []*eth.Attestation
|
||||
attestationsElectra []*eth.AttestationElectra
|
||||
deposits []*eth.Deposit
|
||||
voluntaryExits []*eth.SignedVoluntaryExit
|
||||
syncAggregate *eth.SyncAggregate
|
||||
executionPayload interfaces.ExecutionData
|
||||
executionPayloadHeader interfaces.ExecutionData
|
||||
blsToExecutionChanges []*eth.SignedBLSToExecutionChange
|
||||
blobKzgCommitments [][]byte
|
||||
version int
|
||||
randaoReveal [field_params.BLSSignatureLength]byte
|
||||
eth1Data *eth.Eth1Data
|
||||
graffiti [field_params.RootLength]byte
|
||||
proposerSlashings []*eth.ProposerSlashing
|
||||
attesterSlashings []*eth.AttesterSlashing
|
||||
attesterSlashingsElectra []*eth.AttesterSlashingElectra
|
||||
attestations []*eth.Attestation
|
||||
attestationsElectra []*eth.AttestationElectra
|
||||
deposits []*eth.Deposit
|
||||
voluntaryExits []*eth.SignedVoluntaryExit
|
||||
syncAggregate *eth.SyncAggregate
|
||||
executionPayload interfaces.ExecutionData
|
||||
executionPayloadHeader interfaces.ExecutionData
|
||||
blsToExecutionChanges []*eth.SignedBLSToExecutionChange
|
||||
blobKzgCommitments [][]byte
|
||||
signedExecutionPayloadHeader *enginev1.SignedExecutionPayloadHeader
|
||||
payloadAttestations []*eth.PayloadAttestation
|
||||
}
|
||||
|
||||
var _ interfaces.ReadOnlyBeaconBlockBody = &BeaconBlockBody{}
|
||||
|
||||
@@ -71,6 +71,12 @@ type ReadOnlyBeaconBlockBody interface {
|
||||
BlobKzgCommitments() ([][]byte, error)
|
||||
}
|
||||
|
||||
type ROBlockBodyEpbs interface {
|
||||
ReadOnlyBeaconBlockBody
|
||||
PayloadAttestations() []*ethpb.PayloadAttestation
|
||||
SignedExecutionPayloadHeader() *enginev1.SignedExecutionPayloadHeader
|
||||
}
|
||||
|
||||
type SignedBeaconBlock interface {
|
||||
ReadOnlySignedBeaconBlock
|
||||
SetExecution(ExecutionData) error
|
||||
@@ -91,6 +97,8 @@ type SignedBeaconBlock interface {
|
||||
SetSlot(slot primitives.Slot)
|
||||
SetSignature(sig []byte)
|
||||
Unblind(e ExecutionData) error
|
||||
SetSignedExecutionPayloadHeader(h *enginev1.SignedExecutionPayloadHeader) error
|
||||
SetPayloadAttestations([]*ethpb.PayloadAttestation) error
|
||||
}
|
||||
|
||||
// ExecutionData represents execution layer information that is contained
|
||||
|
||||
@@ -9,6 +9,7 @@ go_library(
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//proto/engine/v1:go_default_library",
|
||||
"//proto/eth/v1:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//proto/prysm/v1alpha1/validator-client:go_default_library",
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
field_params "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
|
||||
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
enginev1 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/eth/v1"
|
||||
eth "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
validatorpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1/validator-client"
|
||||
@@ -280,6 +281,14 @@ func (b *BeaconBlockBody) Version() int {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) PayloadAttestations() ([]*eth.PayloadAttestation, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (b *BeaconBlockBody) SignedExecutionPayloadHeader() (*enginev1.SignedExecutionPayloadHeader, error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
var _ interfaces.ReadOnlySignedBeaconBlock = &SignedBeaconBlock{}
|
||||
var _ interfaces.ReadOnlyBeaconBlock = &BeaconBlock{}
|
||||
var _ interfaces.ReadOnlyBeaconBlockBody = &BeaconBlockBody{}
|
||||
|
||||
@@ -10,6 +10,7 @@ go_library(
|
||||
"epoch.go",
|
||||
"execution_address.go",
|
||||
"payload_id.go",
|
||||
"ptc_status.go",
|
||||
"randao.go",
|
||||
"slot.go",
|
||||
"sszbytes.go",
|
||||
|
||||
71
consensus-types/primitives/ptc_status.go
Normal file
71
consensus-types/primitives/ptc_status.go
Normal file
@@ -0,0 +1,71 @@
|
||||
package primitives
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
|
||||
fssz "github.com/prysmaticlabs/fastssz"
|
||||
)
|
||||
|
||||
var _ fssz.HashRoot = (PTCStatus)(0)
|
||||
var _ fssz.Marshaler = (*PTCStatus)(nil)
|
||||
var _ fssz.Unmarshaler = (*PTCStatus)(nil)
|
||||
|
||||
// PTCStatus represents a single payload status. These are the
|
||||
// possible votes that the Payload Timeliness Committee can cast
|
||||
// in ePBS when attesting for an execution payload.
|
||||
type PTCStatus uint64
|
||||
|
||||
// Defined constants
|
||||
const (
|
||||
PAYLOAD_ABSENT PTCStatus = 0
|
||||
PAYLOAD_PRESENT PTCStatus = 1
|
||||
PAYLOAD_WITHHELD PTCStatus = 2
|
||||
PAYLOAD_INVALID_STATUS PTCStatus = 3
|
||||
)
|
||||
|
||||
// HashTreeRoot --
|
||||
func (s PTCStatus) HashTreeRoot() ([32]byte, error) {
|
||||
return fssz.HashWithDefaultHasher(s)
|
||||
}
|
||||
|
||||
// HashTreeRootWith --
|
||||
func (s PTCStatus) HashTreeRootWith(hh *fssz.Hasher) error {
|
||||
if s > math.MaxUint8 {
|
||||
return fmt.Errorf("expected uint8 value, received %d", uint64(s))
|
||||
}
|
||||
hh.PutUint8(uint8(s))
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalSSZ --
|
||||
func (s *PTCStatus) UnmarshalSSZ(buf []byte) error {
|
||||
if len(buf) != s.SizeSSZ() {
|
||||
return fmt.Errorf("expected buffer of length %d received %d", s.SizeSSZ(), len(buf))
|
||||
}
|
||||
*s = PTCStatus(fssz.UnmarshallUint8(buf))
|
||||
return nil
|
||||
}
|
||||
|
||||
// MarshalSSZTo --
|
||||
func (s *PTCStatus) MarshalSSZTo(dst []byte) ([]byte, error) {
|
||||
marshalled, err := s.MarshalSSZ()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return append(dst, marshalled...), nil
|
||||
}
|
||||
|
||||
// MarshalSSZ --
|
||||
func (s *PTCStatus) MarshalSSZ() ([]byte, error) {
|
||||
if *s > math.MaxUint8 {
|
||||
return nil, fmt.Errorf("expected uint8 value, received %d", uint64(*s))
|
||||
}
|
||||
marshalled := fssz.MarshalUint8([]byte{}, uint8(*s))
|
||||
return marshalled, nil
|
||||
}
|
||||
|
||||
// SizeSSZ --
|
||||
func (s *PTCStatus) SizeSSZ() int {
|
||||
return 1
|
||||
}
|
||||
@@ -116,6 +116,21 @@ func PowerOf2(n uint64) uint64 {
|
||||
return 1 << n
|
||||
}
|
||||
|
||||
// LargestPowerOfTwo returns the largest power of 2 that is lower or equal than
|
||||
// the parameter
|
||||
func LargestPowerOfTwo(n uint64) uint64 {
|
||||
if n == 0 {
|
||||
return 0
|
||||
}
|
||||
n |= n >> 1
|
||||
n |= n >> 2
|
||||
n |= n >> 4
|
||||
n |= n >> 8
|
||||
n |= n >> 16
|
||||
n |= n >> 32
|
||||
return n - (n >> 1)
|
||||
}
|
||||
|
||||
// Max returns the larger integer of the two
|
||||
// given ones.This is used over the Max function
|
||||
// in the standard math library because that max function
|
||||
|
||||
@@ -549,3 +549,27 @@ func TestAddInt(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestLargestPowerOfTwo(t *testing.T) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
input uint64
|
||||
expected uint64
|
||||
}{
|
||||
{"Zero", 0, 0},
|
||||
{"One", 1, 1},
|
||||
{"Just below power of two", 14, 8},
|
||||
{"Power of two", 16, 16},
|
||||
{"Large number", 123456789, 67108864},
|
||||
{"Max uint64", 18446744073709551615, 9223372036854775808},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
result := math.LargestPowerOfTwo(tc.input)
|
||||
if result != tc.expected {
|
||||
t.Errorf("For input %d, expected %d but got %d", tc.input, tc.expected, result)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,13 @@ ssz_gen_marshal(
|
||||
"ExecutionPayloadDeneb",
|
||||
"ExecutionPayloadHeaderElectra",
|
||||
"ExecutionPayloadElectra",
|
||||
"PayloadAttestationData",
|
||||
"PayloadAttestation",
|
||||
"PayloadAttestationMessage",
|
||||
"ExecutionPayloadHeaderEPBS",
|
||||
"ExecutionPayloadEnvelope",
|
||||
"SignedExecutionPayloadHeader",
|
||||
"SignedExecutionPayloadEnvelope",
|
||||
"BlindedBlobsBundle",
|
||||
"BlobsBundle",
|
||||
"Withdrawal",
|
||||
@@ -56,7 +63,7 @@ ssz_gen_marshal(
|
||||
go_proto_library(
|
||||
name = "go_proto",
|
||||
compilers = [
|
||||
"@com_github_prysmaticlabs_protoc_gen_go_cast//:go_cast_grpc",
|
||||
"@com_github_prysmaticlabs_protoc_gen_go_cast//:go_cast_grpc",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v5/proto/engine/v1",
|
||||
proto = ":proto",
|
||||
@@ -66,6 +73,7 @@ go_proto_library(
|
||||
"//proto/eth/ext:go_default_library",
|
||||
"@com_github_golang_protobuf//proto:go_default_library",
|
||||
"@googleapis//google/api:annotations_go_proto",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
|
||||
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
|
||||
"@org_golang_google_protobuf//runtime/protoimpl:go_default_library",
|
||||
@@ -99,6 +107,7 @@ go_library(
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@googleapis//google/api:annotations_go_proto",
|
||||
"@io_bazel_rules_go//proto/wkt:descriptor_go_proto",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library", # keep
|
||||
"@io_bazel_rules_go//proto/wkt:timestamp_go_proto",
|
||||
"@org_golang_google_protobuf//encoding/protojson:go_default_library",
|
||||
"@org_golang_google_protobuf//reflect/protoreflect:go_default_library",
|
||||
@@ -110,6 +119,7 @@ ssz_proto_files(
|
||||
name = "ssz_proto_files",
|
||||
srcs = [
|
||||
"execution_engine.proto",
|
||||
"epbs.proto",
|
||||
],
|
||||
config = select({
|
||||
"//conditions:default": "mainnet",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: d1cee811bee5b5cfcedf5be00dfff21d5e6caf432cd8fc42f551264f7b8e296c
|
||||
// Hash: 267522f5fc96f69efb25124116e9f3ed9853b6ff1f9be9868875ddb26ef0c20b
|
||||
package enginev1
|
||||
|
||||
import (
|
||||
@@ -7,6 +7,563 @@ import (
|
||||
github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
)
|
||||
|
||||
// MarshalSSZ ssz marshals the ExecutionPayloadHeaderEPBS object
|
||||
func (e *ExecutionPayloadHeaderEPBS) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(e)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the ExecutionPayloadHeaderEPBS object to a target array
|
||||
func (e *ExecutionPayloadHeaderEPBS) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
|
||||
// Field (0) 'ParentBlockHash'
|
||||
if size := len(e.ParentBlockHash); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.ParentBlockHash", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, e.ParentBlockHash...)
|
||||
|
||||
// Field (1) 'ParentBlockRoot'
|
||||
if size := len(e.ParentBlockRoot); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.ParentBlockRoot", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, e.ParentBlockRoot...)
|
||||
|
||||
// Field (2) 'BlockHash'
|
||||
if size := len(e.BlockHash); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.BlockHash", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, e.BlockHash...)
|
||||
|
||||
// Field (3) 'GasLimit'
|
||||
dst = ssz.MarshalUint64(dst, e.GasLimit)
|
||||
|
||||
// Field (4) 'BuilderIndex'
|
||||
dst = ssz.MarshalUint64(dst, uint64(e.BuilderIndex))
|
||||
|
||||
// Field (5) 'Slot'
|
||||
dst = ssz.MarshalUint64(dst, uint64(e.Slot))
|
||||
|
||||
// Field (6) 'Value'
|
||||
dst = ssz.MarshalUint64(dst, e.Value)
|
||||
|
||||
// Field (7) 'BlobKzgCommitmentsRoot'
|
||||
if size := len(e.BlobKzgCommitmentsRoot); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.BlobKzgCommitmentsRoot", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, e.BlobKzgCommitmentsRoot...)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the ExecutionPayloadHeaderEPBS object
|
||||
func (e *ExecutionPayloadHeaderEPBS) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 160 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
// Field (0) 'ParentBlockHash'
|
||||
if cap(e.ParentBlockHash) == 0 {
|
||||
e.ParentBlockHash = make([]byte, 0, len(buf[0:32]))
|
||||
}
|
||||
e.ParentBlockHash = append(e.ParentBlockHash, buf[0:32]...)
|
||||
|
||||
// Field (1) 'ParentBlockRoot'
|
||||
if cap(e.ParentBlockRoot) == 0 {
|
||||
e.ParentBlockRoot = make([]byte, 0, len(buf[32:64]))
|
||||
}
|
||||
e.ParentBlockRoot = append(e.ParentBlockRoot, buf[32:64]...)
|
||||
|
||||
// Field (2) 'BlockHash'
|
||||
if cap(e.BlockHash) == 0 {
|
||||
e.BlockHash = make([]byte, 0, len(buf[64:96]))
|
||||
}
|
||||
e.BlockHash = append(e.BlockHash, buf[64:96]...)
|
||||
|
||||
// Field (3) 'GasLimit'
|
||||
e.GasLimit = ssz.UnmarshallUint64(buf[96:104])
|
||||
|
||||
// Field (4) 'BuilderIndex'
|
||||
e.BuilderIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[104:112]))
|
||||
|
||||
// Field (5) 'Slot'
|
||||
e.Slot = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(ssz.UnmarshallUint64(buf[112:120]))
|
||||
|
||||
// Field (6) 'Value'
|
||||
e.Value = ssz.UnmarshallUint64(buf[120:128])
|
||||
|
||||
// Field (7) 'BlobKzgCommitmentsRoot'
|
||||
if cap(e.BlobKzgCommitmentsRoot) == 0 {
|
||||
e.BlobKzgCommitmentsRoot = make([]byte, 0, len(buf[128:160]))
|
||||
}
|
||||
e.BlobKzgCommitmentsRoot = append(e.BlobKzgCommitmentsRoot, buf[128:160]...)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadHeaderEPBS object
|
||||
func (e *ExecutionPayloadHeaderEPBS) SizeSSZ() (size int) {
|
||||
size = 160
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the ExecutionPayloadHeaderEPBS object
|
||||
func (e *ExecutionPayloadHeaderEPBS) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(e)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the ExecutionPayloadHeaderEPBS object with a hasher
|
||||
func (e *ExecutionPayloadHeaderEPBS) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'ParentBlockHash'
|
||||
if size := len(e.ParentBlockHash); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.ParentBlockHash", size, 32)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(e.ParentBlockHash)
|
||||
|
||||
// Field (1) 'ParentBlockRoot'
|
||||
if size := len(e.ParentBlockRoot); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.ParentBlockRoot", size, 32)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(e.ParentBlockRoot)
|
||||
|
||||
// Field (2) 'BlockHash'
|
||||
if size := len(e.BlockHash); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.BlockHash", size, 32)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(e.BlockHash)
|
||||
|
||||
// Field (3) 'GasLimit'
|
||||
hh.PutUint64(e.GasLimit)
|
||||
|
||||
// Field (4) 'BuilderIndex'
|
||||
hh.PutUint64(uint64(e.BuilderIndex))
|
||||
|
||||
// Field (5) 'Slot'
|
||||
hh.PutUint64(uint64(e.Slot))
|
||||
|
||||
// Field (6) 'Value'
|
||||
hh.PutUint64(e.Value)
|
||||
|
||||
// Field (7) 'BlobKzgCommitmentsRoot'
|
||||
if size := len(e.BlobKzgCommitmentsRoot); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.BlobKzgCommitmentsRoot", size, 32)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(e.BlobKzgCommitmentsRoot)
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the SignedExecutionPayloadHeader object
|
||||
func (s *SignedExecutionPayloadHeader) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(s)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the SignedExecutionPayloadHeader object to a target array
|
||||
func (s *SignedExecutionPayloadHeader) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
|
||||
// Field (0) 'Message'
|
||||
if s.Message == nil {
|
||||
s.Message = new(ExecutionPayloadHeaderEPBS)
|
||||
}
|
||||
if dst, err = s.Message.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'Signature'
|
||||
if size := len(s.Signature); size != 96 {
|
||||
err = ssz.ErrBytesLengthFn("--.Signature", size, 96)
|
||||
return
|
||||
}
|
||||
dst = append(dst, s.Signature...)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the SignedExecutionPayloadHeader object
|
||||
func (s *SignedExecutionPayloadHeader) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size != 256 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
// Field (0) 'Message'
|
||||
if s.Message == nil {
|
||||
s.Message = new(ExecutionPayloadHeaderEPBS)
|
||||
}
|
||||
if err = s.Message.UnmarshalSSZ(buf[0:160]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Field (1) 'Signature'
|
||||
if cap(s.Signature) == 0 {
|
||||
s.Signature = make([]byte, 0, len(buf[160:256]))
|
||||
}
|
||||
s.Signature = append(s.Signature, buf[160:256]...)
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the SignedExecutionPayloadHeader object
|
||||
func (s *SignedExecutionPayloadHeader) SizeSSZ() (size int) {
|
||||
size = 256
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the SignedExecutionPayloadHeader object
|
||||
func (s *SignedExecutionPayloadHeader) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(s)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the SignedExecutionPayloadHeader object with a hasher
|
||||
func (s *SignedExecutionPayloadHeader) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'Message'
|
||||
if err = s.Message.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'Signature'
|
||||
if size := len(s.Signature); size != 96 {
|
||||
err = ssz.ErrBytesLengthFn("--.Signature", size, 96)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(s.Signature)
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the ExecutionPayloadEnvelope object
|
||||
func (e *ExecutionPayloadEnvelope) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(e)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the ExecutionPayloadEnvelope object to a target array
|
||||
func (e *ExecutionPayloadEnvelope) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(81)
|
||||
|
||||
// Offset (0) 'Payload'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if e.Payload == nil {
|
||||
e.Payload = new(ExecutionPayloadElectra)
|
||||
}
|
||||
offset += e.Payload.SizeSSZ()
|
||||
|
||||
// Field (1) 'BuilderIndex'
|
||||
dst = ssz.MarshalUint64(dst, uint64(e.BuilderIndex))
|
||||
|
||||
// Field (2) 'BeaconBlockRoot'
|
||||
if size := len(e.BeaconBlockRoot); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.BeaconBlockRoot", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, e.BeaconBlockRoot...)
|
||||
|
||||
// Offset (3) 'BlobKzgCommitments'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
offset += len(e.BlobKzgCommitments) * 48
|
||||
|
||||
// Field (4) 'PayloadWithheld'
|
||||
dst = ssz.MarshalBool(dst, e.PayloadWithheld)
|
||||
|
||||
// Field (5) 'StateRoot'
|
||||
if size := len(e.StateRoot); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32)
|
||||
return
|
||||
}
|
||||
dst = append(dst, e.StateRoot...)
|
||||
|
||||
// Field (0) 'Payload'
|
||||
if dst, err = e.Payload.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (3) 'BlobKzgCommitments'
|
||||
if size := len(e.BlobKzgCommitments); size > 4096 {
|
||||
err = ssz.ErrListTooBigFn("--.BlobKzgCommitments", size, 4096)
|
||||
return
|
||||
}
|
||||
for ii := 0; ii < len(e.BlobKzgCommitments); ii++ {
|
||||
if size := len(e.BlobKzgCommitments[ii]); size != 48 {
|
||||
err = ssz.ErrBytesLengthFn("--.BlobKzgCommitments[ii]", size, 48)
|
||||
return
|
||||
}
|
||||
dst = append(dst, e.BlobKzgCommitments[ii]...)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the ExecutionPayloadEnvelope object
|
||||
func (e *ExecutionPayloadEnvelope) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 81 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o0, o3 uint64
|
||||
|
||||
// Offset (0) 'Payload'
|
||||
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o0 != 81 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Field (1) 'BuilderIndex'
|
||||
e.BuilderIndex = github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(ssz.UnmarshallUint64(buf[4:12]))
|
||||
|
||||
// Field (2) 'BeaconBlockRoot'
|
||||
if cap(e.BeaconBlockRoot) == 0 {
|
||||
e.BeaconBlockRoot = make([]byte, 0, len(buf[12:44]))
|
||||
}
|
||||
e.BeaconBlockRoot = append(e.BeaconBlockRoot, buf[12:44]...)
|
||||
|
||||
// Offset (3) 'BlobKzgCommitments'
|
||||
if o3 = ssz.ReadOffset(buf[44:48]); o3 > size || o0 > o3 {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
// Field (4) 'PayloadWithheld'
|
||||
e.PayloadWithheld = ssz.UnmarshalBool(buf[48:49])
|
||||
|
||||
// Field (5) 'StateRoot'
|
||||
if cap(e.StateRoot) == 0 {
|
||||
e.StateRoot = make([]byte, 0, len(buf[49:81]))
|
||||
}
|
||||
e.StateRoot = append(e.StateRoot, buf[49:81]...)
|
||||
|
||||
// Field (0) 'Payload'
|
||||
{
|
||||
buf = tail[o0:o3]
|
||||
if e.Payload == nil {
|
||||
e.Payload = new(ExecutionPayloadElectra)
|
||||
}
|
||||
if err = e.Payload.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Field (3) 'BlobKzgCommitments'
|
||||
{
|
||||
buf = tail[o3:]
|
||||
num, err := ssz.DivideInt2(len(buf), 48, 4096)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
e.BlobKzgCommitments = make([][]byte, num)
|
||||
for ii := 0; ii < num; ii++ {
|
||||
if cap(e.BlobKzgCommitments[ii]) == 0 {
|
||||
e.BlobKzgCommitments[ii] = make([]byte, 0, len(buf[ii*48:(ii+1)*48]))
|
||||
}
|
||||
e.BlobKzgCommitments[ii] = append(e.BlobKzgCommitments[ii], buf[ii*48:(ii+1)*48]...)
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the ExecutionPayloadEnvelope object
|
||||
func (e *ExecutionPayloadEnvelope) SizeSSZ() (size int) {
|
||||
size = 81
|
||||
|
||||
// Field (0) 'Payload'
|
||||
if e.Payload == nil {
|
||||
e.Payload = new(ExecutionPayloadElectra)
|
||||
}
|
||||
size += e.Payload.SizeSSZ()
|
||||
|
||||
// Field (3) 'BlobKzgCommitments'
|
||||
size += len(e.BlobKzgCommitments) * 48
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the ExecutionPayloadEnvelope object
|
||||
func (e *ExecutionPayloadEnvelope) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(e)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the ExecutionPayloadEnvelope object with a hasher
|
||||
func (e *ExecutionPayloadEnvelope) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'Payload'
|
||||
if err = e.Payload.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'BuilderIndex'
|
||||
hh.PutUint64(uint64(e.BuilderIndex))
|
||||
|
||||
// Field (2) 'BeaconBlockRoot'
|
||||
if size := len(e.BeaconBlockRoot); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.BeaconBlockRoot", size, 32)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(e.BeaconBlockRoot)
|
||||
|
||||
// Field (3) 'BlobKzgCommitments'
|
||||
{
|
||||
if size := len(e.BlobKzgCommitments); size > 4096 {
|
||||
err = ssz.ErrListTooBigFn("--.BlobKzgCommitments", size, 4096)
|
||||
return
|
||||
}
|
||||
subIndx := hh.Index()
|
||||
for _, i := range e.BlobKzgCommitments {
|
||||
if len(i) != 48 {
|
||||
err = ssz.ErrBytesLength
|
||||
return
|
||||
}
|
||||
hh.PutBytes(i)
|
||||
}
|
||||
|
||||
numItems := uint64(len(e.BlobKzgCommitments))
|
||||
hh.MerkleizeWithMixin(subIndx, numItems, 4096)
|
||||
}
|
||||
|
||||
// Field (4) 'PayloadWithheld'
|
||||
hh.PutBool(e.PayloadWithheld)
|
||||
|
||||
// Field (5) 'StateRoot'
|
||||
if size := len(e.StateRoot); size != 32 {
|
||||
err = ssz.ErrBytesLengthFn("--.StateRoot", size, 32)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(e.StateRoot)
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the SignedExecutionPayloadEnvelope object
|
||||
func (s *SignedExecutionPayloadEnvelope) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(s)
|
||||
}
|
||||
|
||||
// MarshalSSZTo ssz marshals the SignedExecutionPayloadEnvelope object to a target array
|
||||
func (s *SignedExecutionPayloadEnvelope) MarshalSSZTo(buf []byte) (dst []byte, err error) {
|
||||
dst = buf
|
||||
offset := int(100)
|
||||
|
||||
// Offset (0) 'Message'
|
||||
dst = ssz.WriteOffset(dst, offset)
|
||||
if s.Message == nil {
|
||||
s.Message = new(ExecutionPayloadEnvelope)
|
||||
}
|
||||
offset += s.Message.SizeSSZ()
|
||||
|
||||
// Field (1) 'Signature'
|
||||
if size := len(s.Signature); size != 96 {
|
||||
err = ssz.ErrBytesLengthFn("--.Signature", size, 96)
|
||||
return
|
||||
}
|
||||
dst = append(dst, s.Signature...)
|
||||
|
||||
// Field (0) 'Message'
|
||||
if dst, err = s.Message.MarshalSSZTo(dst); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalSSZ ssz unmarshals the SignedExecutionPayloadEnvelope object
|
||||
func (s *SignedExecutionPayloadEnvelope) UnmarshalSSZ(buf []byte) error {
|
||||
var err error
|
||||
size := uint64(len(buf))
|
||||
if size < 100 {
|
||||
return ssz.ErrSize
|
||||
}
|
||||
|
||||
tail := buf
|
||||
var o0 uint64
|
||||
|
||||
// Offset (0) 'Message'
|
||||
if o0 = ssz.ReadOffset(buf[0:4]); o0 > size {
|
||||
return ssz.ErrOffset
|
||||
}
|
||||
|
||||
if o0 != 100 {
|
||||
return ssz.ErrInvalidVariableOffset
|
||||
}
|
||||
|
||||
// Field (1) 'Signature'
|
||||
if cap(s.Signature) == 0 {
|
||||
s.Signature = make([]byte, 0, len(buf[4:100]))
|
||||
}
|
||||
s.Signature = append(s.Signature, buf[4:100]...)
|
||||
|
||||
// Field (0) 'Message'
|
||||
{
|
||||
buf = tail[o0:]
|
||||
if s.Message == nil {
|
||||
s.Message = new(ExecutionPayloadEnvelope)
|
||||
}
|
||||
if err = s.Message.UnmarshalSSZ(buf); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// SizeSSZ returns the ssz encoded size in bytes for the SignedExecutionPayloadEnvelope object
|
||||
func (s *SignedExecutionPayloadEnvelope) SizeSSZ() (size int) {
|
||||
size = 100
|
||||
|
||||
// Field (0) 'Message'
|
||||
if s.Message == nil {
|
||||
s.Message = new(ExecutionPayloadEnvelope)
|
||||
}
|
||||
size += s.Message.SizeSSZ()
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// HashTreeRoot ssz hashes the SignedExecutionPayloadEnvelope object
|
||||
func (s *SignedExecutionPayloadEnvelope) HashTreeRoot() ([32]byte, error) {
|
||||
return ssz.HashWithDefaultHasher(s)
|
||||
}
|
||||
|
||||
// HashTreeRootWith ssz hashes the SignedExecutionPayloadEnvelope object with a hasher
|
||||
func (s *SignedExecutionPayloadEnvelope) HashTreeRootWith(hh *ssz.Hasher) (err error) {
|
||||
indx := hh.Index()
|
||||
|
||||
// Field (0) 'Message'
|
||||
if err = s.Message.HashTreeRootWith(hh); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Field (1) 'Signature'
|
||||
if size := len(s.Signature); size != 96 {
|
||||
err = ssz.ErrBytesLengthFn("--.Signature", size, 96)
|
||||
return
|
||||
}
|
||||
hh.PutBytes(s.Signature)
|
||||
|
||||
hh.Merkleize(indx)
|
||||
return
|
||||
}
|
||||
|
||||
// MarshalSSZ ssz marshals the ExecutionPayload object
|
||||
func (e *ExecutionPayload) MarshalSSZ() ([]byte, error) {
|
||||
return ssz.MarshalSSZ(e)
|
||||
|
||||
530
proto/engine/v1/epbs.pb.go
generated
Executable file
530
proto/engine/v1/epbs.pb.go
generated
Executable file
@@ -0,0 +1,530 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.31.0
|
||||
// protoc v4.25.1
|
||||
// source: proto/engine/v1/epbs.proto
|
||||
|
||||
package enginev1
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
|
||||
github_com_prysmaticlabs_prysm_v5_consensus_types_primitives "github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
|
||||
_ "github.com/prysmaticlabs/prysm/v5/proto/eth/ext"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
)
|
||||
|
||||
const (
|
||||
// Verify that this generated code is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
|
||||
// Verify that runtime/protoimpl is sufficiently up-to-date.
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
type ExecutionPayloadHeaderEPBS struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
ParentBlockHash []byte `protobuf:"bytes,1,opt,name=parent_block_hash,json=parentBlockHash,proto3" json:"parent_block_hash,omitempty" ssz-size:"32"`
|
||||
ParentBlockRoot []byte `protobuf:"bytes,2,opt,name=parent_block_root,json=parentBlockRoot,proto3" json:"parent_block_root,omitempty" ssz-size:"32"`
|
||||
BlockHash []byte `protobuf:"bytes,3,opt,name=block_hash,json=blockHash,proto3" json:"block_hash,omitempty" ssz-size:"32"`
|
||||
GasLimit uint64 `protobuf:"varint,4,opt,name=gas_limit,json=gasLimit,proto3" json:"gas_limit,omitempty"`
|
||||
BuilderIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,5,opt,name=builder_index,json=builderIndex,proto3" json:"builder_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"`
|
||||
Slot github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot `protobuf:"varint,6,opt,name=slot,proto3" json:"slot,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.Slot"`
|
||||
Value uint64 `protobuf:"varint,7,opt,name=value,proto3" json:"value,omitempty"`
|
||||
BlobKzgCommitmentsRoot []byte `protobuf:"bytes,8,opt,name=blob_kzg_commitments_root,json=blobKzgCommitmentsRoot,proto3" json:"blob_kzg_commitments_root,omitempty" ssz-size:"32"`
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadHeaderEPBS) Reset() {
|
||||
*x = ExecutionPayloadHeaderEPBS{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_engine_v1_epbs_proto_msgTypes[0]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadHeaderEPBS) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ExecutionPayloadHeaderEPBS) ProtoMessage() {}
|
||||
|
||||
func (x *ExecutionPayloadHeaderEPBS) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_engine_v1_epbs_proto_msgTypes[0]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ExecutionPayloadHeaderEPBS.ProtoReflect.Descriptor instead.
|
||||
func (*ExecutionPayloadHeaderEPBS) Descriptor() ([]byte, []int) {
|
||||
return file_proto_engine_v1_epbs_proto_rawDescGZIP(), []int{0}
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadHeaderEPBS) GetParentBlockHash() []byte {
|
||||
if x != nil {
|
||||
return x.ParentBlockHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadHeaderEPBS) GetParentBlockRoot() []byte {
|
||||
if x != nil {
|
||||
return x.ParentBlockRoot
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadHeaderEPBS) GetBlockHash() []byte {
|
||||
if x != nil {
|
||||
return x.BlockHash
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadHeaderEPBS) GetGasLimit() uint64 {
|
||||
if x != nil {
|
||||
return x.GasLimit
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadHeaderEPBS) GetBuilderIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex {
|
||||
if x != nil {
|
||||
return x.BuilderIndex
|
||||
}
|
||||
return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0)
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadHeaderEPBS) GetSlot() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot {
|
||||
if x != nil {
|
||||
return x.Slot
|
||||
}
|
||||
return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.Slot(0)
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadHeaderEPBS) GetValue() uint64 {
|
||||
if x != nil {
|
||||
return x.Value
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadHeaderEPBS) GetBlobKzgCommitmentsRoot() []byte {
|
||||
if x != nil {
|
||||
return x.BlobKzgCommitmentsRoot
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SignedExecutionPayloadHeader struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Message *ExecutionPayloadHeaderEPBS `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
|
||||
Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"`
|
||||
}
|
||||
|
||||
func (x *SignedExecutionPayloadHeader) Reset() {
|
||||
*x = SignedExecutionPayloadHeader{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_engine_v1_epbs_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SignedExecutionPayloadHeader) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SignedExecutionPayloadHeader) ProtoMessage() {}
|
||||
|
||||
func (x *SignedExecutionPayloadHeader) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_engine_v1_epbs_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SignedExecutionPayloadHeader.ProtoReflect.Descriptor instead.
|
||||
func (*SignedExecutionPayloadHeader) Descriptor() ([]byte, []int) {
|
||||
return file_proto_engine_v1_epbs_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *SignedExecutionPayloadHeader) GetMessage() *ExecutionPayloadHeaderEPBS {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SignedExecutionPayloadHeader) GetSignature() []byte {
|
||||
if x != nil {
|
||||
return x.Signature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ExecutionPayloadEnvelope struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Payload *ExecutionPayloadElectra `protobuf:"bytes,1,opt,name=payload,proto3" json:"payload,omitempty"`
|
||||
BuilderIndex github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex `protobuf:"varint,2,opt,name=builder_index,json=builderIndex,proto3" json:"builder_index,omitempty" cast-type:"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives.ValidatorIndex"`
|
||||
BeaconBlockRoot []byte `protobuf:"bytes,3,opt,name=beacon_block_root,json=beaconBlockRoot,proto3" json:"beacon_block_root,omitempty" ssz-size:"32"`
|
||||
BlobKzgCommitments [][]byte `protobuf:"bytes,4,rep,name=blob_kzg_commitments,json=blobKzgCommitments,proto3" json:"blob_kzg_commitments,omitempty" ssz-max:"4096" ssz-size:"?,48"`
|
||||
PayloadWithheld bool `protobuf:"varint,8,opt,name=payload_withheld,json=payloadWithheld,proto3" json:"payload_withheld,omitempty"`
|
||||
StateRoot []byte `protobuf:"bytes,9,opt,name=state_root,json=stateRoot,proto3" json:"state_root,omitempty" ssz-size:"32"`
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadEnvelope) Reset() {
|
||||
*x = ExecutionPayloadEnvelope{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_engine_v1_epbs_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadEnvelope) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*ExecutionPayloadEnvelope) ProtoMessage() {}
|
||||
|
||||
func (x *ExecutionPayloadEnvelope) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_engine_v1_epbs_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use ExecutionPayloadEnvelope.ProtoReflect.Descriptor instead.
|
||||
func (*ExecutionPayloadEnvelope) Descriptor() ([]byte, []int) {
|
||||
return file_proto_engine_v1_epbs_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadEnvelope) GetPayload() *ExecutionPayloadElectra {
|
||||
if x != nil {
|
||||
return x.Payload
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadEnvelope) GetBuilderIndex() github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex {
|
||||
if x != nil {
|
||||
return x.BuilderIndex
|
||||
}
|
||||
return github_com_prysmaticlabs_prysm_v5_consensus_types_primitives.ValidatorIndex(0)
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadEnvelope) GetBeaconBlockRoot() []byte {
|
||||
if x != nil {
|
||||
return x.BeaconBlockRoot
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadEnvelope) GetBlobKzgCommitments() [][]byte {
|
||||
if x != nil {
|
||||
return x.BlobKzgCommitments
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadEnvelope) GetPayloadWithheld() bool {
|
||||
if x != nil {
|
||||
return x.PayloadWithheld
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *ExecutionPayloadEnvelope) GetStateRoot() []byte {
|
||||
if x != nil {
|
||||
return x.StateRoot
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SignedExecutionPayloadEnvelope struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Message *ExecutionPayloadEnvelope `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"`
|
||||
Signature []byte `protobuf:"bytes,2,opt,name=signature,proto3" json:"signature,omitempty" ssz-size:"96"`
|
||||
}
|
||||
|
||||
func (x *SignedExecutionPayloadEnvelope) Reset() {
|
||||
*x = SignedExecutionPayloadEnvelope{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_proto_engine_v1_epbs_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *SignedExecutionPayloadEnvelope) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*SignedExecutionPayloadEnvelope) ProtoMessage() {}
|
||||
|
||||
func (x *SignedExecutionPayloadEnvelope) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_proto_engine_v1_epbs_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use SignedExecutionPayloadEnvelope.ProtoReflect.Descriptor instead.
|
||||
func (*SignedExecutionPayloadEnvelope) Descriptor() ([]byte, []int) {
|
||||
return file_proto_engine_v1_epbs_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *SignedExecutionPayloadEnvelope) GetMessage() *ExecutionPayloadEnvelope {
|
||||
if x != nil {
|
||||
return x.Message
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *SignedExecutionPayloadEnvelope) GetSignature() []byte {
|
||||
if x != nil {
|
||||
return x.Signature
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
var File_proto_engine_v1_epbs_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_proto_engine_v1_epbs_proto_rawDesc = []byte{
|
||||
0x0a, 0x1a, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2f, 0x76,
|
||||
0x31, 0x2f, 0x65, 0x70, 0x62, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x12, 0x65, 0x74,
|
||||
0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31,
|
||||
0x1a, 0x1b, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x74, 0x68, 0x2f, 0x65, 0x78, 0x74, 0x2f,
|
||||
0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x26, 0x70,
|
||||
0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x2f, 0x65,
|
||||
0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e,
|
||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xf2, 0x03, 0x0a, 0x1a, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72,
|
||||
0x45, 0x50, 0x42, 0x53, 0x12, 0x32, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x62,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x42,
|
||||
0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x42,
|
||||
0x6c, 0x6f, 0x63, 0x6b, 0x48, 0x61, 0x73, 0x68, 0x12, 0x32, 0x0a, 0x11, 0x70, 0x61, 0x72, 0x65,
|
||||
0x6e, 0x74, 0x5f, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x70, 0x61, 0x72,
|
||||
0x65, 0x6e, 0x74, 0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x25, 0x0a, 0x0a,
|
||||
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x68, 0x61, 0x73, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x48,
|
||||
0x61, 0x73, 0x68, 0x12, 0x1b, 0x0a, 0x09, 0x67, 0x61, 0x73, 0x5f, 0x6c, 0x69, 0x6d, 0x69, 0x74,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x04, 0x52, 0x08, 0x67, 0x61, 0x73, 0x4c, 0x69, 0x6d, 0x69, 0x74,
|
||||
0x12, 0x74, 0x0a, 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65,
|
||||
0x78, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74,
|
||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69,
|
||||
0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63,
|
||||
0x6f, 0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70,
|
||||
0x72, 0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61,
|
||||
0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65,
|
||||
0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x59, 0x0a, 0x04, 0x73, 0x6c, 0x6f, 0x74, 0x18, 0x06,
|
||||
0x20, 0x01, 0x28, 0x04, 0x42, 0x45, 0x82, 0xb5, 0x18, 0x41, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
|
||||
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61,
|
||||
0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f, 0x6e, 0x73,
|
||||
0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72, 0x69, 0x6d,
|
||||
0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x53, 0x6c, 0x6f, 0x74, 0x52, 0x04, 0x73, 0x6c, 0x6f,
|
||||
0x74, 0x12, 0x14, 0x0a, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x04,
|
||||
0x52, 0x05, 0x76, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x41, 0x0a, 0x19, 0x62, 0x6c, 0x6f, 0x62, 0x5f,
|
||||
0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x5f,
|
||||
0x72, 0x6f, 0x6f, 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02,
|
||||
0x33, 0x32, 0x52, 0x16, 0x62, 0x6c, 0x6f, 0x62, 0x4b, 0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69,
|
||||
0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x6f, 0x6f, 0x74, 0x22, 0x8e, 0x01, 0x0a, 0x1c, 0x53,
|
||||
0x69, 0x67, 0x6e, 0x65, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61,
|
||||
0x79, 0x6c, 0x6f, 0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x12, 0x48, 0x0a, 0x07, 0x6d,
|
||||
0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2e, 0x2e, 0x65,
|
||||
0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f,
|
||||
0x61, 0x64, 0x48, 0x65, 0x61, 0x64, 0x65, 0x72, 0x45, 0x50, 0x42, 0x53, 0x52, 0x07, 0x6d, 0x65,
|
||||
0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75,
|
||||
0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x39, 0x36,
|
||||
0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xa1, 0x03, 0x0a, 0x18,
|
||||
0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
|
||||
0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70, 0x65, 0x12, 0x45, 0x0a, 0x07, 0x70, 0x61, 0x79, 0x6c,
|
||||
0x6f, 0x61, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2b, 0x2e, 0x65, 0x74, 0x68, 0x65,
|
||||
0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45,
|
||||
0x78, 0x65, 0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x45,
|
||||
0x6c, 0x65, 0x63, 0x74, 0x72, 0x61, 0x52, 0x07, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x12,
|
||||
0x74, 0x0a, 0x0d, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x6e, 0x64, 0x65, 0x78,
|
||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x42, 0x4f, 0x82, 0xb5, 0x18, 0x4b, 0x67, 0x69, 0x74, 0x68,
|
||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63,
|
||||
0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72, 0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x63, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x6e, 0x73, 0x75, 0x73, 0x2d, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x70, 0x72,
|
||||
0x69, 0x6d, 0x69, 0x74, 0x69, 0x76, 0x65, 0x73, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74,
|
||||
0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x52, 0x0c, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x65, 0x72,
|
||||
0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x32, 0x0a, 0x11, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e, 0x5f,
|
||||
0x62, 0x6c, 0x6f, 0x63, 0x6b, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c,
|
||||
0x42, 0x06, 0x8a, 0xb5, 0x18, 0x02, 0x33, 0x32, 0x52, 0x0f, 0x62, 0x65, 0x61, 0x63, 0x6f, 0x6e,
|
||||
0x42, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x42, 0x0a, 0x14, 0x62, 0x6c, 0x6f,
|
||||
0x62, 0x5f, 0x6b, 0x7a, 0x67, 0x5f, 0x63, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74,
|
||||
0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0c, 0x42, 0x10, 0x8a, 0xb5, 0x18, 0x04, 0x3f, 0x2c, 0x34,
|
||||
0x38, 0x92, 0xb5, 0x18, 0x04, 0x34, 0x30, 0x39, 0x36, 0x52, 0x12, 0x62, 0x6c, 0x6f, 0x62, 0x4b,
|
||||
0x7a, 0x67, 0x43, 0x6f, 0x6d, 0x6d, 0x69, 0x74, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x29, 0x0a,
|
||||
0x10, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x77, 0x69, 0x74, 0x68, 0x68, 0x65, 0x6c,
|
||||
0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x70, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64,
|
||||
0x57, 0x69, 0x74, 0x68, 0x68, 0x65, 0x6c, 0x64, 0x12, 0x25, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x74,
|
||||
0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a, 0xb5,
|
||||
0x18, 0x02, 0x33, 0x32, 0x52, 0x09, 0x73, 0x74, 0x61, 0x74, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x22,
|
||||
0x8e, 0x01, 0x0a, 0x1e, 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f,
|
||||
0x70, 0x65, 0x12, 0x46, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20,
|
||||
0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x65,
|
||||
0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x69,
|
||||
0x6f, 0x6e, 0x50, 0x61, 0x79, 0x6c, 0x6f, 0x61, 0x64, 0x45, 0x6e, 0x76, 0x65, 0x6c, 0x6f, 0x70,
|
||||
0x65, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x24, 0x0a, 0x09, 0x73, 0x69,
|
||||
0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x42, 0x06, 0x8a,
|
||||
0xb5, 0x18, 0x02, 0x39, 0x36, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65,
|
||||
0x42, 0x96, 0x01, 0x0a, 0x16, 0x6f, 0x72, 0x67, 0x2e, 0x65, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75,
|
||||
0x6d, 0x2e, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x2e, 0x76, 0x31, 0x42, 0x14, 0x45, 0x78, 0x65,
|
||||
0x63, 0x75, 0x74, 0x69, 0x6f, 0x6e, 0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x50, 0x72, 0x6f, 0x74,
|
||||
0x6f, 0x50, 0x01, 0x5a, 0x3a, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
||||
0x70, 0x72, 0x79, 0x73, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x6c, 0x61, 0x62, 0x73, 0x2f, 0x70, 0x72,
|
||||
0x79, 0x73, 0x6d, 0x2f, 0x76, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x65, 0x6e, 0x67,
|
||||
0x69, 0x6e, 0x65, 0x2f, 0x76, 0x31, 0x3b, 0x65, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x76, 0x31, 0xaa,
|
||||
0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x2e, 0x45, 0x6e, 0x67, 0x69, 0x6e,
|
||||
0x65, 0x2e, 0x56, 0x31, 0xca, 0x02, 0x12, 0x45, 0x74, 0x68, 0x65, 0x72, 0x65, 0x75, 0x6d, 0x5c,
|
||||
0x45, 0x6e, 0x67, 0x69, 0x6e, 0x65, 0x5c, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||
0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
file_proto_engine_v1_epbs_proto_rawDescOnce sync.Once
|
||||
file_proto_engine_v1_epbs_proto_rawDescData = file_proto_engine_v1_epbs_proto_rawDesc
|
||||
)
|
||||
|
||||
func file_proto_engine_v1_epbs_proto_rawDescGZIP() []byte {
|
||||
file_proto_engine_v1_epbs_proto_rawDescOnce.Do(func() {
|
||||
file_proto_engine_v1_epbs_proto_rawDescData = protoimpl.X.CompressGZIP(file_proto_engine_v1_epbs_proto_rawDescData)
|
||||
})
|
||||
return file_proto_engine_v1_epbs_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_proto_engine_v1_epbs_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_proto_engine_v1_epbs_proto_goTypes = []interface{}{
|
||||
(*ExecutionPayloadHeaderEPBS)(nil), // 0: ethereum.engine.v1.ExecutionPayloadHeaderEPBS
|
||||
(*SignedExecutionPayloadHeader)(nil), // 1: ethereum.engine.v1.SignedExecutionPayloadHeader
|
||||
(*ExecutionPayloadEnvelope)(nil), // 2: ethereum.engine.v1.ExecutionPayloadEnvelope
|
||||
(*SignedExecutionPayloadEnvelope)(nil), // 3: ethereum.engine.v1.SignedExecutionPayloadEnvelope
|
||||
(*ExecutionPayloadElectra)(nil), // 4: ethereum.engine.v1.ExecutionPayloadElectra
|
||||
}
|
||||
var file_proto_engine_v1_epbs_proto_depIdxs = []int32{
|
||||
0, // 0: ethereum.engine.v1.SignedExecutionPayloadHeader.message:type_name -> ethereum.engine.v1.ExecutionPayloadHeaderEPBS
|
||||
4, // 1: ethereum.engine.v1.ExecutionPayloadEnvelope.payload:type_name -> ethereum.engine.v1.ExecutionPayloadElectra
|
||||
2, // 2: ethereum.engine.v1.SignedExecutionPayloadEnvelope.message:type_name -> ethereum.engine.v1.ExecutionPayloadEnvelope
|
||||
3, // [3:3] is the sub-list for method output_type
|
||||
3, // [3:3] is the sub-list for method input_type
|
||||
3, // [3:3] is the sub-list for extension type_name
|
||||
3, // [3:3] is the sub-list for extension extendee
|
||||
0, // [0:3] is the sub-list for field type_name
|
||||
}
|
||||
|
||||
func init() { file_proto_engine_v1_epbs_proto_init() }
|
||||
func file_proto_engine_v1_epbs_proto_init() {
|
||||
if File_proto_engine_v1_epbs_proto != nil {
|
||||
return
|
||||
}
|
||||
file_proto_engine_v1_execution_engine_proto_init()
|
||||
if !protoimpl.UnsafeEnabled {
|
||||
file_proto_engine_v1_epbs_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ExecutionPayloadHeaderEPBS); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proto_engine_v1_epbs_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SignedExecutionPayloadHeader); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proto_engine_v1_epbs_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*ExecutionPayloadEnvelope); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_proto_engine_v1_epbs_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*SignedExecutionPayloadEnvelope); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
File: protoimpl.DescBuilder{
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_proto_engine_v1_epbs_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
GoTypes: file_proto_engine_v1_epbs_proto_goTypes,
|
||||
DependencyIndexes: file_proto_engine_v1_epbs_proto_depIdxs,
|
||||
MessageInfos: file_proto_engine_v1_epbs_proto_msgTypes,
|
||||
}.Build()
|
||||
File_proto_engine_v1_epbs_proto = out.File
|
||||
file_proto_engine_v1_epbs_proto_rawDesc = nil
|
||||
file_proto_engine_v1_epbs_proto_goTypes = nil
|
||||
file_proto_engine_v1_epbs_proto_depIdxs = nil
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user