mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 13:28:01 -05:00
Compare commits
7 Commits
ba2333069a
...
debugging-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bb53d3cbb6 | ||
|
|
5c918dd710 | ||
|
|
8cf9c22e4c | ||
|
|
e0c7c5e630 | ||
|
|
31f7604c88 | ||
|
|
5757e0b159 | ||
|
|
50ffb535be |
@@ -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")
|
||||
@@ -173,6 +181,9 @@ func ProcessWithdrawals(st state.BeaconState, executionData interfaces.Execution
|
||||
return nil, errors.Wrap(err, "could not get expected withdrawals root")
|
||||
}
|
||||
if expectedRoot != wdRoot {
|
||||
if true {
|
||||
panic("moo")
|
||||
}
|
||||
return nil, fmt.Errorf("expected withdrawals root %#x, got %#x", expectedRoot, wdRoot)
|
||||
}
|
||||
|
||||
@@ -182,6 +193,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"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
@@ -84,7 +85,7 @@ func ProcessRegistryUpdates(ctx context.Context, st state.BeaconState) error {
|
||||
var err error
|
||||
// exitQueueEpoch and churn arguments are not used in electra.
|
||||
st, _, err = validators.InitiateValidatorExit(ctx, st, idx, 0 /*exitQueueEpoch*/, 0 /*churn*/)
|
||||
if err != nil {
|
||||
if err != nil && !errors.Is(err, validators.ErrValidatorAlreadyExited) {
|
||||
return fmt.Errorf("failed to initiate validator exit at index %d: %w", idx, err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -93,6 +93,8 @@ func ProcessOperations(
|
||||
return nil, errors.Wrap(err, "could not process deposit receipts")
|
||||
}
|
||||
|
||||
// TODO: Process consolidations from execution header.
|
||||
if err := ProcessConsolidationRequests(ctx, st, exe.ConsolidationRequests()); err != nil {
|
||||
return nil, errors.Wrap(err, "could not process consolidations")
|
||||
}
|
||||
return st, nil
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -79,6 +79,7 @@ go_test(
|
||||
"//crypto/hash:go_default_library",
|
||||
"//encoding/bytesutil: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",
|
||||
|
||||
@@ -584,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
|
||||
}
|
||||
|
||||
@@ -600,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))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ go_test(
|
||||
],
|
||||
data = [
|
||||
"//testing/benchmark/benchmark_files:benchmark_data",
|
||||
],
|
||||
] + glob(["testdata/**"]),
|
||||
embed = [":go_default_library"],
|
||||
shard_count = 3,
|
||||
deps = [
|
||||
@@ -84,6 +84,7 @@ go_test(
|
||||
"//config/fieldparams:go_default_library",
|
||||
"//config/params:go_default_library",
|
||||
"//consensus-types/blocks:go_default_library",
|
||||
"//consensus-types/interfaces:go_default_library",
|
||||
"//consensus-types/primitives:go_default_library",
|
||||
"//crypto/bls:go_default_library",
|
||||
"//crypto/hash:go_default_library",
|
||||
@@ -97,8 +98,11 @@ go_test(
|
||||
"//testing/require:go_default_library",
|
||||
"//testing/util:go_default_library",
|
||||
"//time/slots:go_default_library",
|
||||
"@com_github_golang_snappy//:go_default_library",
|
||||
"@com_github_google_go_cmp//cmp:go_default_library",
|
||||
"@com_github_google_gofuzz//:go_default_library",
|
||||
"@com_github_prysmaticlabs_go_bitfield//:go_default_library",
|
||||
"@org_golang_google_protobuf//proto:go_default_library",
|
||||
"@org_golang_google_protobuf//testing/protocmp:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
BIN
beacon-chain/core/transition/testdata/blocks_0.ssz_snappy
vendored
Normal file
BIN
beacon-chain/core/transition/testdata/blocks_0.ssz_snappy
vendored
Normal file
Binary file not shown.
BIN
beacon-chain/core/transition/testdata/blocks_1.ssz_snappy
vendored
Normal file
BIN
beacon-chain/core/transition/testdata/blocks_1.ssz_snappy
vendored
Normal file
Binary file not shown.
1
beacon-chain/core/transition/testdata/meta.yaml
vendored
Normal file
1
beacon-chain/core/transition/testdata/meta.yaml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{blocks_count: 2, bls_setting: 1}
|
||||
BIN
beacon-chain/core/transition/testdata/post.ssz_snappy
vendored
Normal file
BIN
beacon-chain/core/transition/testdata/post.ssz_snappy
vendored
Normal file
Binary file not shown.
BIN
beacon-chain/core/transition/testdata/pre.ssz_snappy
vendored
Normal file
BIN
beacon-chain/core/transition/testdata/pre.ssz_snappy
vendored
Normal file
Binary file not shown.
@@ -356,11 +356,15 @@ func VerifyOperationLengths(_ context.Context, state state.BeaconState, b interf
|
||||
)
|
||||
}
|
||||
|
||||
if uint64(len(body.Attestations())) > params.BeaconConfig().MaxAttestations {
|
||||
maxAtts := params.BeaconConfig().MaxAttestationsElectra
|
||||
if state.Version() < version.Electra {
|
||||
maxAtts = params.BeaconConfig().MaxAttestations
|
||||
}
|
||||
if uint64(len(body.Attestations())) > maxAtts {
|
||||
return nil, fmt.Errorf(
|
||||
"number of attestations (%d) in block body exceeds allowed threshold of %d",
|
||||
len(body.Attestations()),
|
||||
params.BeaconConfig().MaxAttestations,
|
||||
maxAtts,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -3,8 +3,11 @@ package transition_test
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/golang/snappy"
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/prysmaticlabs/go-bitfield"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/blocks"
|
||||
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
|
||||
@@ -16,6 +19,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/encoding/bytesutil"
|
||||
@@ -25,6 +29,8 @@ import (
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/util"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/testing/protocmp"
|
||||
)
|
||||
|
||||
func init() {
|
||||
@@ -112,6 +118,55 @@ func TestExecuteStateTransition_FullProcess(t *testing.T) {
|
||||
assert.DeepNotEqual(t, oldMix, mix, "Did not expect new and old randao mix to equal")
|
||||
}
|
||||
|
||||
func TestExecuteStateTransition_SpecTestRandom0TestCauseDebugging(t *testing.T) {
|
||||
var blks []interfaces.ReadOnlySignedBeaconBlock
|
||||
for _, fp := range []string{
|
||||
"testdata/blocks_0.ssz_snappy",
|
||||
"testdata/blocks_1.ssz_snappy",
|
||||
} {
|
||||
b, err := os.ReadFile(fp)
|
||||
require.NoError(t, err)
|
||||
decoded, err := snappy.Decode(nil, b)
|
||||
require.NoError(t, err)
|
||||
block := ðpb.SignedBeaconBlockElectra{}
|
||||
require.NoError(t, block.UnmarshalSSZ(decoded))
|
||||
wsb, err := consensusblocks.NewSignedBeaconBlock(block)
|
||||
require.NoError(t, err)
|
||||
blks = append(blks, wsb)
|
||||
}
|
||||
|
||||
var states []state.BeaconState
|
||||
|
||||
for _, fp := range []string{
|
||||
"testdata/pre.ssz_snappy",
|
||||
"testdata/post.ssz_snappy",
|
||||
} {
|
||||
base := ðpb.BeaconStateElectra{}
|
||||
b, err := os.ReadFile(fp)
|
||||
require.NoError(t, err)
|
||||
decoded, err := snappy.Decode(nil, b)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, base.UnmarshalSSZ(decoded))
|
||||
state, err := state_native.InitializeFromProtoElectra(base)
|
||||
require.NoError(t, err)
|
||||
states = append(states, state)
|
||||
}
|
||||
|
||||
s := states[0]
|
||||
for _, wsb := range blks {
|
||||
st, err := transition.ExecuteStateTransition(context.Background(), s, wsb)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
s = st
|
||||
}
|
||||
|
||||
pre, post := s.ToProtoUnsafe().(proto.Message), states[1].ToProtoUnsafe().(proto.Message)
|
||||
if !proto.Equal(pre, post) {
|
||||
t.Log(cmp.Diff(pre, post, protocmp.Transform()))
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessBlock_IncorrectProcessExits(t *testing.T) {
|
||||
beaconState, _ := util.DeterministicGenesisState(t, 100)
|
||||
|
||||
|
||||
@@ -359,7 +359,7 @@ func (bs *Server) AttestationPoolElectra(_ context.Context, req *ethpb.Attestati
|
||||
}
|
||||
|
||||
func blockAttestations[T ethpb.Att](blocks []interfaces.ReadOnlySignedBeaconBlock) ([]T, error) {
|
||||
blockAtts := make([]ethpb.Att, 0, params.BeaconConfig().MaxAttestations*uint64(len(blocks)))
|
||||
blockAtts := make([]ethpb.Att, 0, params.BeaconConfig().MaxAttestations*uint64(len(blocks))) // TODO: Electra
|
||||
for _, blk := range blocks {
|
||||
blockAtts = append(blockAtts, blk.Block().Body().Attestations()...)
|
||||
}
|
||||
@@ -388,7 +388,7 @@ func blockIndexedAttestations[T ethpb.IndexedAtt](
|
||||
blocks []interfaces.ReadOnlySignedBeaconBlock,
|
||||
stateGen stategen.StateManager,
|
||||
) ([]T, error) {
|
||||
attsArray := make([]ethpb.Att, 0, params.BeaconConfig().MaxAttestations*uint64(len(blocks)))
|
||||
attsArray := make([]ethpb.Att, 0, params.BeaconConfig().MaxAttestations*uint64(len(blocks))) // TODO: Electra
|
||||
for _, b := range blocks {
|
||||
attsArray = append(attsArray, b.Block().Body().Attestations()...)
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -54,7 +54,7 @@ func (b *BeaconState) AppendCurrentEpochAttestations(val *ethpb.PendingAttestati
|
||||
}
|
||||
|
||||
atts := b.currentEpochAttestations
|
||||
max := params.BeaconConfig().CurrentEpochAttestationsLength()
|
||||
max := params.BeaconConfig().CurrentEpochAttestationsLength(b.version)
|
||||
if uint64(len(atts)) >= max {
|
||||
return fmt.Errorf("current pending attestation exceeds max length %d", max)
|
||||
}
|
||||
@@ -84,7 +84,7 @@ func (b *BeaconState) AppendPreviousEpochAttestations(val *ethpb.PendingAttestat
|
||||
}
|
||||
|
||||
atts := b.previousEpochAttestations
|
||||
max := params.BeaconConfig().PreviousEpochAttestationsLength()
|
||||
max := params.BeaconConfig().PreviousEpochAttestationsLength(b.version)
|
||||
if uint64(len(atts)) >= max {
|
||||
return fmt.Errorf("previous pending attestation exceeds max length %d", max)
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ 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/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/assert"
|
||||
"github.com/prysmaticlabs/prysm/v5/testing/require"
|
||||
)
|
||||
@@ -79,7 +80,7 @@ func BenchmarkAppendPreviousEpochAttestations(b *testing.B) {
|
||||
st, err := InitializeFromProtoPhase0(ðpb.BeaconState{})
|
||||
require.NoError(b, err)
|
||||
|
||||
max := params.BeaconConfig().PreviousEpochAttestationsLength()
|
||||
max := params.BeaconConfig().PreviousEpochAttestationsLength(version.Phase0)
|
||||
if max < 2 {
|
||||
b.Fatalf("previous epoch attestations length is less than 2: %d", max)
|
||||
}
|
||||
|
||||
@@ -1227,7 +1227,7 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
|
||||
err := b.resetFieldTrie(
|
||||
field,
|
||||
b.previousEpochAttestations,
|
||||
params.BeaconConfig().PreviousEpochAttestationsLength(),
|
||||
params.BeaconConfig().PreviousEpochAttestationsLength(b.version),
|
||||
)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
@@ -1241,7 +1241,7 @@ func (b *BeaconState) rootSelector(ctx context.Context, field types.FieldIndex)
|
||||
err := b.resetFieldTrie(
|
||||
field,
|
||||
b.currentEpochAttestations,
|
||||
params.BeaconConfig().CurrentEpochAttestationsLength(),
|
||||
params.BeaconConfig().CurrentEpochAttestationsLength(b.version),
|
||||
)
|
||||
if err != nil {
|
||||
return [32]byte{}, err
|
||||
|
||||
@@ -38,6 +38,7 @@ go_library(
|
||||
"//encoding/ssz:go_default_library",
|
||||
"//math:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/version:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
params "github.com/prysmaticlabs/prysm/v5/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v5/runtime/version"
|
||||
)
|
||||
|
||||
// RootsArrayHashTreeRoot computes the Merkle root of arrays of 32-byte hashes, such as [64][32]byte
|
||||
@@ -18,7 +19,7 @@ func RootsArrayHashTreeRoot(vals [][]byte, length uint64) ([32]byte, error) {
|
||||
}
|
||||
|
||||
func EpochAttestationsRoot(atts []*ethpb.PendingAttestation) ([32]byte, error) {
|
||||
max := params.BeaconConfig().CurrentEpochAttestationsLength()
|
||||
max := params.BeaconConfig().CurrentEpochAttestationsLength(version.Phase0)
|
||||
if uint64(len(atts)) > max {
|
||||
return [32]byte{}, fmt.Errorf("epoch attestation exceeds max length %d", max)
|
||||
}
|
||||
@@ -32,7 +33,7 @@ func EpochAttestationsRoot(atts []*ethpb.PendingAttestation) ([32]byte, error) {
|
||||
roots[i] = pendingRoot
|
||||
}
|
||||
|
||||
attsRootsRoot, err := ssz.BitwiseMerkleize(roots, uint64(len(roots)), params.BeaconConfig().CurrentEpochAttestationsLength())
|
||||
attsRootsRoot, err := ssz.BitwiseMerkleize(roots, uint64(len(roots)), params.BeaconConfig().CurrentEpochAttestationsLength(version.Phase0))
|
||||
if err != nil {
|
||||
return [32]byte{}, errors.Wrap(err, "could not compute epoch attestations merkleization")
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -325,15 +325,21 @@ func (b *BeaconChainConfig) Eth1DataVotesLength() uint64 {
|
||||
// PreviousEpochAttestationsLength returns the maximum length of the pending
|
||||
// attestation list for the previous epoch, computed from the parameters in
|
||||
// BeaconChainConfig.
|
||||
func (b *BeaconChainConfig) PreviousEpochAttestationsLength() uint64 {
|
||||
return uint64(b.SlotsPerEpoch.Mul(b.MaxAttestations))
|
||||
func (b *BeaconChainConfig) PreviousEpochAttestationsLength(fork int) uint64 {
|
||||
if fork < version.Electra {
|
||||
return uint64(b.SlotsPerEpoch.Mul(b.MaxAttestations))
|
||||
}
|
||||
return uint64(b.SlotsPerEpoch.Mul(b.MaxAttestationsElectra))
|
||||
}
|
||||
|
||||
// CurrentEpochAttestationsLength returns the maximum length of the pending
|
||||
// attestation list for the current epoch, computed from the parameters in
|
||||
// BeaconChainConfig.
|
||||
func (b *BeaconChainConfig) CurrentEpochAttestationsLength() uint64 {
|
||||
return uint64(b.SlotsPerEpoch.Mul(b.MaxAttestations))
|
||||
func (b *BeaconChainConfig) CurrentEpochAttestationsLength(fork int) uint64 {
|
||||
if fork < version.Electra {
|
||||
return uint64(b.SlotsPerEpoch.Mul(b.MaxAttestations))
|
||||
}
|
||||
return uint64(b.SlotsPerEpoch.Mul(b.MaxAttestationsElectra))
|
||||
}
|
||||
|
||||
// TtfbTimeoutDuration returns the time duration of the timeout.
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -7,6 +7,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMainnet_Electra_Transition(t *testing.T) {
|
||||
t.Skip("TODO: Electra")
|
||||
fork.RunForkTransitionTest(t, "mainnet")
|
||||
}
|
||||
|
||||
@@ -8,6 +8,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMainnet_Electra_Forkchoice(t *testing.T) {
|
||||
t.Skip("TODO: Electra")
|
||||
forkchoice.Run(t, "mainnet", version.Electra)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMainnet_Electra_Random(t *testing.T) {
|
||||
t.Skip("TODO: Electra")
|
||||
sanity.RunBlockProcessingTest(t, "mainnet", "random/random/pyspec_tests")
|
||||
}
|
||||
|
||||
@@ -7,6 +7,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMinimal_Electra_Transition(t *testing.T) {
|
||||
t.Skip("TODO: Electra")
|
||||
fork.RunForkTransitionTest(t, "minimal")
|
||||
}
|
||||
|
||||
@@ -8,6 +8,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMinimal_Electra_Forkchoice(t *testing.T) {
|
||||
t.Skip("TODO: Electra")
|
||||
forkchoice.Run(t, "minimal", version.Electra)
|
||||
}
|
||||
|
||||
@@ -7,6 +7,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMinimal_Electra_Random(t *testing.T) {
|
||||
t.Skip("TODO: Electra")
|
||||
sanity.RunBlockProcessingTest(t, "minimal", "random/random/pyspec_tests")
|
||||
}
|
||||
|
||||
@@ -7,6 +7,5 @@ import (
|
||||
)
|
||||
|
||||
func TestMinimal_Electra_Sanity_Blocks(t *testing.T) {
|
||||
t.Skip("TODO: Electra")
|
||||
sanity.RunBlockProcessingTest(t, "minimal", "sanity/blocks/pyspec_tests")
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ func (bb *Builder) PoWBlock(pb *ethpb.PowBlock) {
|
||||
}
|
||||
|
||||
// Attestation receives the attestation and updates forkchoice.
|
||||
func (bb *Builder) Attestation(t testing.TB, a *ethpb.Attestation) {
|
||||
func (bb *Builder) Attestation(t testing.TB, a ethpb.Att) {
|
||||
require.NoError(t, bb.service.OnAttestation(context.TODO(), a, params.BeaconConfig().MaximumGossipClockDisparityDuration()))
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ func Run(t *testing.T, config string, fork int) {
|
||||
}
|
||||
}
|
||||
|
||||
func runTest(t *testing.T, config string, fork int, basePath string) {
|
||||
func runTest(t *testing.T, config string, fork int, basePath string) { // nolint:gocognit
|
||||
require.NoError(t, utils.SetConfig(t, config))
|
||||
testFolders, _ := utils.TestFolders(t, config, version.String(fork), basePath)
|
||||
if len(testFolders) == 0 {
|
||||
@@ -144,7 +144,12 @@ func runTest(t *testing.T, config string, fork int, basePath string) {
|
||||
require.NoError(t, err)
|
||||
attSSZ, err := snappy.Decode(nil /* dst */, attFile)
|
||||
require.NoError(t, err)
|
||||
att := ðpb.Attestation{}
|
||||
var att ethpb.Att
|
||||
if fork < version.Electra {
|
||||
att = ðpb.Attestation{}
|
||||
} else {
|
||||
att = ðpb.AttestationElectra{}
|
||||
}
|
||||
require.NoError(t, att.UnmarshalSSZ(attSSZ), "Failed to unmarshal")
|
||||
builder.Attestation(t, att)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user