mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 15:37:56 -05:00
Process blind withdrawals (#11995)
* Update head before block proposal * fix e2e runs * Can process blind withdrwals * Rm bad change * Should be in process payload header * Version check * Compare roots * Typo * Remove redundant checks * Add tests * Rm errors --------- Co-authored-by: nisdas <nishdas93@gmail.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
This commit is contained in:
@@ -6,8 +6,3 @@ var errNilSignedWithdrawalMessage = errors.New("nil SignedBLSToExecutionChange m
|
|||||||
var errNilWithdrawalMessage = errors.New("nil BLSToExecutionChange message")
|
var errNilWithdrawalMessage = errors.New("nil BLSToExecutionChange message")
|
||||||
var errInvalidBLSPrefix = errors.New("withdrawal credential prefix is not a BLS prefix")
|
var errInvalidBLSPrefix = errors.New("withdrawal credential prefix is not a BLS prefix")
|
||||||
var errInvalidWithdrawalCredentials = errors.New("withdrawal credentials do not match")
|
var errInvalidWithdrawalCredentials = errors.New("withdrawal credentials do not match")
|
||||||
var errInvalidWithdrawalIndex = errors.New("invalid withdrawal index")
|
|
||||||
var errInvalidValidatorIndex = errors.New("invalid validator index")
|
|
||||||
var errInvalidWithdrawalAmount = errors.New("invalid withdrawal amount")
|
|
||||||
var errInvalidExecutionAddress = errors.New("invalid execution address")
|
|
||||||
var errInvalidWithdrawalNumber = errors.New("invalid number of withdrawals")
|
|
||||||
|
|||||||
@@ -200,12 +200,9 @@ func ValidatePayload(st state.BeaconState, payload interfaces.ExecutionData) err
|
|||||||
// transactions_root=hash_tree_root(payload.transactions),
|
// transactions_root=hash_tree_root(payload.transactions),
|
||||||
// )
|
// )
|
||||||
func ProcessPayload(st state.BeaconState, payload interfaces.ExecutionData) (state.BeaconState, error) {
|
func ProcessPayload(st state.BeaconState, payload interfaces.ExecutionData) (state.BeaconState, error) {
|
||||||
|
var err error
|
||||||
if st.Version() >= version.Capella {
|
if st.Version() >= version.Capella {
|
||||||
withdrawals, err := payload.Withdrawals()
|
st, err = ProcessWithdrawals(st, payload)
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrap(err, "could not get payload withdrawals")
|
|
||||||
}
|
|
||||||
st, err = ProcessWithdrawals(st, withdrawals)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not process withdrawals")
|
return nil, errors.Wrap(err, "could not process withdrawals")
|
||||||
}
|
}
|
||||||
@@ -267,6 +264,13 @@ func ValidatePayloadHeader(st state.BeaconState, header interfaces.ExecutionData
|
|||||||
|
|
||||||
// ProcessPayloadHeader processes the payload header.
|
// ProcessPayloadHeader processes the payload header.
|
||||||
func ProcessPayloadHeader(st state.BeaconState, header interfaces.ExecutionData) (state.BeaconState, error) {
|
func ProcessPayloadHeader(st state.BeaconState, header interfaces.ExecutionData) (state.BeaconState, error) {
|
||||||
|
var err error
|
||||||
|
if st.Version() >= version.Capella {
|
||||||
|
st, err = ProcessWithdrawals(st, header)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not process withdrawals")
|
||||||
|
}
|
||||||
|
}
|
||||||
if err := ValidatePayloadHeaderWhenMergeCompletes(st, header); err != nil {
|
if err := ValidatePayloadHeaderWhenMergeCompletes(st, header); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,20 @@ package blocks
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
|
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
|
||||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing"
|
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing"
|
||||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
||||||
|
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
||||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
"github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||||
"github.com/prysmaticlabs/prysm/v3/crypto/bls"
|
"github.com/prysmaticlabs/prysm/v3/crypto/bls"
|
||||||
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
|
"github.com/prysmaticlabs/prysm/v3/crypto/hash"
|
||||||
|
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
||||||
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
|
"github.com/prysmaticlabs/prysm/v3/encoding/ssz"
|
||||||
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
|
||||||
ethpbv2 "github.com/prysmaticlabs/prysm/v3/proto/eth/v2"
|
ethpbv2 "github.com/prysmaticlabs/prysm/v3/proto/eth/v2"
|
||||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||||
"github.com/prysmaticlabs/prysm/v3/runtime/version"
|
"github.com/prysmaticlabs/prysm/v3/runtime/version"
|
||||||
@@ -110,39 +112,51 @@ func ValidateBLSToExecutionChange(st state.ReadOnlyBeaconState, signed *ethpb.Si
|
|||||||
return val, nil
|
return val, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ProcessWithdrawals(st state.BeaconState, withdrawals []*enginev1.Withdrawal) (state.BeaconState, error) {
|
func ProcessWithdrawals(st state.BeaconState, executionData interfaces.ExecutionData) (state.BeaconState, error) {
|
||||||
expected, err := st.ExpectedWithdrawals()
|
expectedWithdrawals, err := st.ExpectedWithdrawals()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not get expected withdrawals")
|
return nil, errors.Wrap(err, "could not get expected withdrawals")
|
||||||
}
|
}
|
||||||
if len(expected) != len(withdrawals) {
|
|
||||||
return nil, errInvalidWithdrawalNumber
|
var wdRoot [32]byte
|
||||||
|
if executionData.IsBlinded() {
|
||||||
|
r, err := executionData.WithdrawalsRoot()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not get withdrawals root")
|
||||||
|
}
|
||||||
|
wdRoot = bytesutil.ToBytes32(r)
|
||||||
|
} else {
|
||||||
|
wds, err := executionData.Withdrawals()
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not get withdrawals")
|
||||||
|
}
|
||||||
|
wdRoot, err = ssz.WithdrawalSliceRoot(hash.CustomSHA256Hasher(), wds, fieldparams.MaxWithdrawalsPerPayload)
|
||||||
|
if err != nil {
|
||||||
|
return nil, errors.Wrap(err, "could not get withdrawals root")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for i, withdrawal := range withdrawals {
|
|
||||||
if withdrawal.Index != expected[i].Index {
|
expectedRoot, err := ssz.WithdrawalSliceRoot(hash.CustomSHA256Hasher(), expectedWithdrawals, fieldparams.MaxWithdrawalsPerPayload)
|
||||||
return nil, errInvalidWithdrawalIndex
|
if err != nil {
|
||||||
}
|
return nil, errors.Wrap(err, "could not get expected withdrawals root")
|
||||||
if withdrawal.ValidatorIndex != expected[i].ValidatorIndex {
|
}
|
||||||
return nil, errInvalidValidatorIndex
|
if expectedRoot != wdRoot {
|
||||||
}
|
return nil, fmt.Errorf("expected withdrawals root %#x, got %#x", expectedRoot, wdRoot)
|
||||||
if !bytes.Equal(withdrawal.Address, expected[i].Address) {
|
}
|
||||||
return nil, errInvalidExecutionAddress
|
|
||||||
}
|
for _, withdrawal := range expectedWithdrawals {
|
||||||
if withdrawal.Amount != expected[i].Amount {
|
|
||||||
return nil, errInvalidWithdrawalAmount
|
|
||||||
}
|
|
||||||
err := helpers.DecreaseBalance(st, withdrawal.ValidatorIndex, withdrawal.Amount)
|
err := helpers.DecreaseBalance(st, withdrawal.ValidatorIndex, withdrawal.Amount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not decrease balance")
|
return nil, errors.Wrap(err, "could not decrease balance")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(withdrawals) > 0 {
|
if len(expectedWithdrawals) > 0 {
|
||||||
if err := st.SetNextWithdrawalIndex(withdrawals[len(withdrawals)-1].Index + 1); err != nil {
|
if err := st.SetNextWithdrawalIndex(expectedWithdrawals[len(expectedWithdrawals)-1].Index + 1); err != nil {
|
||||||
return nil, errors.Wrap(err, "could not set next withdrawal index")
|
return nil, errors.Wrap(err, "could not set next withdrawal index")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var nextValidatorIndex primitives.ValidatorIndex
|
var nextValidatorIndex primitives.ValidatorIndex
|
||||||
if uint64(len(withdrawals)) < params.BeaconConfig().MaxWithdrawalsPerPayload {
|
if uint64(len(expectedWithdrawals)) < params.BeaconConfig().MaxWithdrawalsPerPayload {
|
||||||
nextValidatorIndex, err = st.NextWithdrawalValidatorIndex()
|
nextValidatorIndex, err = st.NextWithdrawalValidatorIndex()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "could not get next withdrawal validator index")
|
return nil, errors.Wrap(err, "could not get next withdrawal validator index")
|
||||||
@@ -150,7 +164,7 @@ func ProcessWithdrawals(st state.BeaconState, withdrawals []*enginev1.Withdrawal
|
|||||||
nextValidatorIndex += primitives.ValidatorIndex(params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
|
nextValidatorIndex += primitives.ValidatorIndex(params.BeaconConfig().MaxValidatorsPerWithdrawalsSweep)
|
||||||
nextValidatorIndex = nextValidatorIndex % primitives.ValidatorIndex(st.NumValidators())
|
nextValidatorIndex = nextValidatorIndex % primitives.ValidatorIndex(st.NumValidators())
|
||||||
} else {
|
} else {
|
||||||
nextValidatorIndex = withdrawals[len(withdrawals)-1].ValidatorIndex + 1
|
nextValidatorIndex = expectedWithdrawals[len(expectedWithdrawals)-1].ValidatorIndex + 1
|
||||||
if nextValidatorIndex == primitives.ValidatorIndex(st.NumValidators()) {
|
if nextValidatorIndex == primitives.ValidatorIndex(st.NumValidators()) {
|
||||||
nextValidatorIndex = 0
|
nextValidatorIndex = 0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package blocks_test
|
package blocks_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/big"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
@@ -9,6 +10,7 @@ import (
|
|||||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time"
|
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/time"
|
||||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
||||||
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
|
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
|
||||||
|
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||||
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
"github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||||
@@ -236,6 +238,425 @@ func TestProcessBLSToExecutionChange(t *testing.T) {
|
|||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
func TestProcessBlindWithdrawals(t *testing.T) {
|
||||||
|
const (
|
||||||
|
currentEpoch = primitives.Epoch(10)
|
||||||
|
epochInFuture = primitives.Epoch(12)
|
||||||
|
epochInPast = primitives.Epoch(8)
|
||||||
|
numValidators = 128
|
||||||
|
notWithdrawableIndex = 127
|
||||||
|
notPartiallyWithdrawable = 126
|
||||||
|
maxSweep = uint64(80)
|
||||||
|
)
|
||||||
|
maxEffectiveBalance := params.BeaconConfig().MaxEffectiveBalance
|
||||||
|
|
||||||
|
type args struct {
|
||||||
|
Name string
|
||||||
|
NextWithdrawalValidatorIndex primitives.ValidatorIndex
|
||||||
|
NextWithdrawalIndex uint64
|
||||||
|
FullWithdrawalIndices []primitives.ValidatorIndex
|
||||||
|
PartialWithdrawalIndices []primitives.ValidatorIndex
|
||||||
|
Withdrawals []*enginev1.Withdrawal
|
||||||
|
}
|
||||||
|
type control struct {
|
||||||
|
NextWithdrawalValidatorIndex primitives.ValidatorIndex
|
||||||
|
NextWithdrawalIndex uint64
|
||||||
|
ExpectedError bool
|
||||||
|
Balances map[uint64]uint64
|
||||||
|
}
|
||||||
|
type Test struct {
|
||||||
|
Args args
|
||||||
|
Control control
|
||||||
|
}
|
||||||
|
executionAddress := func(i primitives.ValidatorIndex) []byte {
|
||||||
|
wc := make([]byte, 20)
|
||||||
|
wc[19] = byte(i)
|
||||||
|
return wc
|
||||||
|
}
|
||||||
|
withdrawalAmount := func(i primitives.ValidatorIndex) uint64 {
|
||||||
|
return maxEffectiveBalance + uint64(i)*100000
|
||||||
|
}
|
||||||
|
fullWithdrawal := func(i primitives.ValidatorIndex, idx uint64) *enginev1.Withdrawal {
|
||||||
|
return &enginev1.Withdrawal{
|
||||||
|
Index: idx,
|
||||||
|
ValidatorIndex: i,
|
||||||
|
Address: executionAddress(i),
|
||||||
|
Amount: withdrawalAmount(i),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
partialWithdrawal := func(i primitives.ValidatorIndex, idx uint64) *enginev1.Withdrawal {
|
||||||
|
return &enginev1.Withdrawal{
|
||||||
|
Index: idx,
|
||||||
|
ValidatorIndex: i,
|
||||||
|
Address: executionAddress(i),
|
||||||
|
Amount: withdrawalAmount(i) - maxEffectiveBalance,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tests := []Test{
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "success no withdrawals",
|
||||||
|
NextWithdrawalValidatorIndex: 10,
|
||||||
|
NextWithdrawalIndex: 3,
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
NextWithdrawalValidatorIndex: 90,
|
||||||
|
NextWithdrawalIndex: 3,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "success one full withdrawal",
|
||||||
|
NextWithdrawalIndex: 3,
|
||||||
|
NextWithdrawalValidatorIndex: 5,
|
||||||
|
FullWithdrawalIndices: []primitives.ValidatorIndex{70},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
fullWithdrawal(70, 3),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
NextWithdrawalValidatorIndex: 85,
|
||||||
|
NextWithdrawalIndex: 4,
|
||||||
|
Balances: map[uint64]uint64{70: 0},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "success one partial withdrawal",
|
||||||
|
NextWithdrawalIndex: 21,
|
||||||
|
NextWithdrawalValidatorIndex: 120,
|
||||||
|
PartialWithdrawalIndices: []primitives.ValidatorIndex{7},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
partialWithdrawal(7, 21),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
NextWithdrawalValidatorIndex: 72,
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
Balances: map[uint64]uint64{7: maxEffectiveBalance},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "success many full withdrawals",
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
NextWithdrawalValidatorIndex: 4,
|
||||||
|
FullWithdrawalIndices: []primitives.ValidatorIndex{7, 19, 28, 1},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
fullWithdrawal(7, 22), fullWithdrawal(19, 23), fullWithdrawal(28, 24),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
NextWithdrawalValidatorIndex: 84,
|
||||||
|
NextWithdrawalIndex: 25,
|
||||||
|
Balances: map[uint64]uint64{7: 0, 19: 0, 28: 0},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "Less than max sweep at end",
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
NextWithdrawalValidatorIndex: 4,
|
||||||
|
FullWithdrawalIndices: []primitives.ValidatorIndex{80, 81, 82, 83},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
fullWithdrawal(80, 22), fullWithdrawal(81, 23), fullWithdrawal(82, 24),
|
||||||
|
fullWithdrawal(83, 25),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
NextWithdrawalValidatorIndex: 84,
|
||||||
|
NextWithdrawalIndex: 26,
|
||||||
|
Balances: map[uint64]uint64{80: 0, 81: 0, 82: 0, 83: 0},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "Less than max sweep and beginning",
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
NextWithdrawalValidatorIndex: 4,
|
||||||
|
FullWithdrawalIndices: []primitives.ValidatorIndex{4, 5, 6},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
fullWithdrawal(4, 22), fullWithdrawal(5, 23), fullWithdrawal(6, 24),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
NextWithdrawalValidatorIndex: 84,
|
||||||
|
NextWithdrawalIndex: 25,
|
||||||
|
Balances: map[uint64]uint64{4: 0, 5: 0, 6: 0},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "success many partial withdrawals",
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
NextWithdrawalValidatorIndex: 4,
|
||||||
|
PartialWithdrawalIndices: []primitives.ValidatorIndex{7, 19, 28},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
partialWithdrawal(7, 22), partialWithdrawal(19, 23), partialWithdrawal(28, 24),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
NextWithdrawalValidatorIndex: 84,
|
||||||
|
NextWithdrawalIndex: 25,
|
||||||
|
Balances: map[uint64]uint64{
|
||||||
|
7: maxEffectiveBalance,
|
||||||
|
19: maxEffectiveBalance,
|
||||||
|
28: maxEffectiveBalance,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "success many withdrawals",
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
NextWithdrawalValidatorIndex: 88,
|
||||||
|
FullWithdrawalIndices: []primitives.ValidatorIndex{7, 19, 28},
|
||||||
|
PartialWithdrawalIndices: []primitives.ValidatorIndex{2, 1, 89, 15},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
partialWithdrawal(89, 22), partialWithdrawal(1, 23), partialWithdrawal(2, 24),
|
||||||
|
fullWithdrawal(7, 25), partialWithdrawal(15, 26), fullWithdrawal(19, 27),
|
||||||
|
fullWithdrawal(28, 28),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
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",
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
NextWithdrawalValidatorIndex: 0,
|
||||||
|
FullWithdrawalIndices: []primitives.ValidatorIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 21, 22, 23, 24, 25, 26, 27, 29, 35, 89},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
fullWithdrawal(1, 22), fullWithdrawal(2, 23), fullWithdrawal(3, 24),
|
||||||
|
fullWithdrawal(4, 25), fullWithdrawal(5, 26), fullWithdrawal(6, 27),
|
||||||
|
fullWithdrawal(7, 28), fullWithdrawal(8, 29), fullWithdrawal(9, 30),
|
||||||
|
fullWithdrawal(21, 31), fullWithdrawal(22, 32), fullWithdrawal(23, 33),
|
||||||
|
fullWithdrawal(24, 34), fullWithdrawal(25, 35), fullWithdrawal(26, 36),
|
||||||
|
fullWithdrawal(27, 37),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
NextWithdrawalValidatorIndex: 28,
|
||||||
|
NextWithdrawalIndex: 38,
|
||||||
|
Balances: map[uint64]uint64{
|
||||||
|
1: 0, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0, 7: 0, 8: 0, 9: 0,
|
||||||
|
21: 0, 22: 0, 23: 0, 24: 0, 25: 0, 26: 0, 27: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "success more than max partially withdrawals",
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
NextWithdrawalValidatorIndex: 0,
|
||||||
|
PartialWithdrawalIndices: []primitives.ValidatorIndex{1, 2, 3, 4, 5, 6, 7, 8, 9, 21, 22, 23, 24, 25, 26, 27, 29, 35, 89},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
partialWithdrawal(1, 22), partialWithdrawal(2, 23), partialWithdrawal(3, 24),
|
||||||
|
partialWithdrawal(4, 25), partialWithdrawal(5, 26), partialWithdrawal(6, 27),
|
||||||
|
partialWithdrawal(7, 28), partialWithdrawal(8, 29), partialWithdrawal(9, 30),
|
||||||
|
partialWithdrawal(21, 31), partialWithdrawal(22, 32), partialWithdrawal(23, 33),
|
||||||
|
partialWithdrawal(24, 34), partialWithdrawal(25, 35), partialWithdrawal(26, 36),
|
||||||
|
partialWithdrawal(27, 37),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
NextWithdrawalValidatorIndex: 28,
|
||||||
|
NextWithdrawalIndex: 38,
|
||||||
|
Balances: map[uint64]uint64{
|
||||||
|
1: maxEffectiveBalance,
|
||||||
|
2: maxEffectiveBalance,
|
||||||
|
3: maxEffectiveBalance,
|
||||||
|
4: maxEffectiveBalance,
|
||||||
|
5: maxEffectiveBalance,
|
||||||
|
6: maxEffectiveBalance,
|
||||||
|
7: maxEffectiveBalance,
|
||||||
|
8: maxEffectiveBalance,
|
||||||
|
9: maxEffectiveBalance,
|
||||||
|
21: maxEffectiveBalance,
|
||||||
|
22: maxEffectiveBalance,
|
||||||
|
23: maxEffectiveBalance,
|
||||||
|
24: maxEffectiveBalance,
|
||||||
|
25: maxEffectiveBalance,
|
||||||
|
26: maxEffectiveBalance,
|
||||||
|
27: maxEffectiveBalance,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "failure wrong number of partial withdrawal",
|
||||||
|
NextWithdrawalIndex: 21,
|
||||||
|
NextWithdrawalValidatorIndex: 37,
|
||||||
|
PartialWithdrawalIndices: []primitives.ValidatorIndex{7},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
partialWithdrawal(7, 21), partialWithdrawal(9, 22),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
ExpectedError: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "failure invalid withdrawal index",
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
NextWithdrawalValidatorIndex: 4,
|
||||||
|
FullWithdrawalIndices: []primitives.ValidatorIndex{7, 19, 28, 1},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
fullWithdrawal(7, 22), fullWithdrawal(19, 23), fullWithdrawal(28, 25),
|
||||||
|
fullWithdrawal(1, 25),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
ExpectedError: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "failure invalid validator index",
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
NextWithdrawalValidatorIndex: 4,
|
||||||
|
FullWithdrawalIndices: []primitives.ValidatorIndex{7, 19, 28, 1},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
fullWithdrawal(7, 22), fullWithdrawal(19, 23), fullWithdrawal(27, 24),
|
||||||
|
fullWithdrawal(1, 25),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
ExpectedError: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "failure invalid withdrawal amount",
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
NextWithdrawalValidatorIndex: 4,
|
||||||
|
FullWithdrawalIndices: []primitives.ValidatorIndex{7, 19, 28, 1},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
fullWithdrawal(7, 22), fullWithdrawal(19, 23), partialWithdrawal(28, 24),
|
||||||
|
fullWithdrawal(1, 25),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
ExpectedError: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "failure validator not fully withdrawable",
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
NextWithdrawalValidatorIndex: 4,
|
||||||
|
FullWithdrawalIndices: []primitives.ValidatorIndex{notWithdrawableIndex},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
fullWithdrawal(notWithdrawableIndex, 22),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
ExpectedError: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Args: args{
|
||||||
|
Name: "failure validator not partially withdrawable",
|
||||||
|
NextWithdrawalIndex: 22,
|
||||||
|
NextWithdrawalValidatorIndex: 4,
|
||||||
|
PartialWithdrawalIndices: []primitives.ValidatorIndex{notPartiallyWithdrawable},
|
||||||
|
Withdrawals: []*enginev1.Withdrawal{
|
||||||
|
fullWithdrawal(notPartiallyWithdrawable, 22),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Control: control{
|
||||||
|
ExpectedError: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
checkPostState := func(t *testing.T, expected control, st state.BeaconState) {
|
||||||
|
l, err := st.NextWithdrawalValidatorIndex()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, expected.NextWithdrawalValidatorIndex, l)
|
||||||
|
|
||||||
|
n, err := st.NextWithdrawalIndex()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, expected.NextWithdrawalIndex, n)
|
||||||
|
balances := st.Balances()
|
||||||
|
for idx, bal := range expected.Balances {
|
||||||
|
require.Equal(t, bal, balances[idx])
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
prepareValidators := func(st *ethpb.BeaconStateCapella, arguments args) (state.BeaconState, error) {
|
||||||
|
validators := make([]*ethpb.Validator, numValidators)
|
||||||
|
st.Balances = make([]uint64, numValidators)
|
||||||
|
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))
|
||||||
|
validators[i] = v
|
||||||
|
}
|
||||||
|
for _, idx := range arguments.FullWithdrawalIndices {
|
||||||
|
if idx != notWithdrawableIndex {
|
||||||
|
validators[idx].WithdrawableEpoch = epochInPast
|
||||||
|
}
|
||||||
|
st.Balances[idx] = withdrawalAmount(idx)
|
||||||
|
validators[idx].WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||||
|
}
|
||||||
|
for _, idx := range arguments.PartialWithdrawalIndices {
|
||||||
|
validators[idx].WithdrawalCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||||
|
st.Balances[idx] = withdrawalAmount(idx)
|
||||||
|
}
|
||||||
|
st.Validators = validators
|
||||||
|
return state_native.InitializeFromProtoCapella(st)
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
if test.Args.FullWithdrawalIndices == nil {
|
||||||
|
test.Args.FullWithdrawalIndices = make([]primitives.ValidatorIndex, 0)
|
||||||
|
}
|
||||||
|
if test.Args.PartialWithdrawalIndices == nil {
|
||||||
|
test.Args.PartialWithdrawalIndices = 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)
|
||||||
|
wdRoot, err := ssz.WithdrawalSliceRoot(hash.CustomSHA256Hasher(), test.Args.Withdrawals, fieldparams.MaxWithdrawalsPerPayload)
|
||||||
|
require.NoError(t, err)
|
||||||
|
p, err := consensusblocks.WrappedExecutionPayloadHeaderCapella(&enginev1.ExecutionPayloadHeaderCapella{WithdrawalsRoot: wdRoot[:]}, big.NewInt(0))
|
||||||
|
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
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestProcessWithdrawals(t *testing.T) {
|
func TestProcessWithdrawals(t *testing.T) {
|
||||||
const (
|
const (
|
||||||
@@ -641,7 +1062,9 @@ func TestProcessWithdrawals(t *testing.T) {
|
|||||||
}
|
}
|
||||||
st, err := prepareValidators(spb, test.Args)
|
st, err := prepareValidators(spb, test.Args)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
post, err := blocks.ProcessWithdrawals(st, test.Args.Withdrawals)
|
p, err := consensusblocks.WrappedExecutionPayloadCapella(&enginev1.ExecutionPayloadCapella{Withdrawals: test.Args.Withdrawals}, big.NewInt(0))
|
||||||
|
require.NoError(t, err)
|
||||||
|
post, err := blocks.ProcessWithdrawals(st, p)
|
||||||
if test.Control.ExpectedError {
|
if test.Control.ExpectedError {
|
||||||
require.NotNil(t, err)
|
require.NotNil(t, err)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -2694,6 +2694,10 @@ func TestProduceBlindedBlock(t *testing.T) {
|
|||||||
require.NoError(t, beaconState.SetGenesisTime(uint64(ti.Unix())))
|
require.NoError(t, beaconState.SetGenesisTime(uint64(ti.Unix())))
|
||||||
random, err := helpers.RandaoMix(beaconState, coreTime.CurrentEpoch(beaconState))
|
random, err := helpers.RandaoMix(beaconState, coreTime.CurrentEpoch(beaconState))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
wds, err := beaconState.ExpectedWithdrawals()
|
||||||
|
require.NoError(t, err)
|
||||||
|
wr, err := ssz.WithdrawalSliceRoot(hash.CustomSHA256Hasher(), wds, fieldparams.MaxWithdrawalsPerPayload)
|
||||||
|
require.NoError(t, err)
|
||||||
bid := ðpbalpha.BuilderBidCapella{
|
bid := ðpbalpha.BuilderBidCapella{
|
||||||
Header: &enginev1.ExecutionPayloadHeaderCapella{
|
Header: &enginev1.ExecutionPayloadHeaderCapella{
|
||||||
ParentHash: make([]byte, fieldparams.RootLength),
|
ParentHash: make([]byte, fieldparams.RootLength),
|
||||||
@@ -2707,7 +2711,7 @@ func TestProduceBlindedBlock(t *testing.T) {
|
|||||||
TransactionsRoot: make([]byte, fieldparams.RootLength),
|
TransactionsRoot: make([]byte, fieldparams.RootLength),
|
||||||
BlockNumber: 1,
|
BlockNumber: 1,
|
||||||
Timestamp: uint64(ts.Unix()),
|
Timestamp: uint64(ts.Unix()),
|
||||||
WithdrawalsRoot: make([]byte, fieldparams.RootLength),
|
WithdrawalsRoot: wr[:],
|
||||||
},
|
},
|
||||||
Pubkey: sk.PublicKey().Marshal(),
|
Pubkey: sk.PublicKey().Marshal(),
|
||||||
Value: bytesutil.PadTo([]byte{1, 2, 3}, 32),
|
Value: bytesutil.PadTo([]byte{1, 2, 3}, 32),
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ func E2EMainnetTestConfig() *BeaconChainConfig {
|
|||||||
e2eConfig.MinGenesisActiveValidatorCount = 256
|
e2eConfig.MinGenesisActiveValidatorCount = 256
|
||||||
e2eConfig.GenesisDelay = 25 // 25 seconds so E2E has enough time to process deposits and get started.
|
e2eConfig.GenesisDelay = 25 // 25 seconds so E2E has enough time to process deposits and get started.
|
||||||
e2eConfig.ChurnLimitQuotient = 65536
|
e2eConfig.ChurnLimitQuotient = 65536
|
||||||
e2eConfig.MaxValidatorsPerWithdrawalsSweep = 128
|
|
||||||
|
|
||||||
// Time parameters.
|
// Time parameters.
|
||||||
e2eConfig.SecondsPerSlot = 6
|
e2eConfig.SecondsPerSlot = 6
|
||||||
|
|||||||
@@ -36,6 +36,11 @@ func (e executionPayload) IsNil() bool {
|
|||||||
return e.p == nil
|
return e.p == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsBlinded returns true if the underlying data is blinded.
|
||||||
|
func (e executionPayload) IsBlinded() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalSSZ --
|
// MarshalSSZ --
|
||||||
func (e executionPayload) MarshalSSZ() ([]byte, error) {
|
func (e executionPayload) MarshalSSZ() ([]byte, error) {
|
||||||
return e.p.MarshalSSZ()
|
return e.p.MarshalSSZ()
|
||||||
@@ -192,6 +197,11 @@ func (e executionPayloadHeader) IsNil() bool {
|
|||||||
return e.p == nil
|
return e.p == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsBlinded returns true if the underlying data is a header.
|
||||||
|
func (e executionPayloadHeader) IsBlinded() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalSSZ --
|
// MarshalSSZ --
|
||||||
func (e executionPayloadHeader) MarshalSSZ() ([]byte, error) {
|
func (e executionPayloadHeader) MarshalSSZ() ([]byte, error) {
|
||||||
return e.p.MarshalSSZ()
|
return e.p.MarshalSSZ()
|
||||||
@@ -377,6 +387,11 @@ func (e executionPayloadCapella) IsNil() bool {
|
|||||||
return e.p == nil
|
return e.p == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsBlinded returns true if the underlying data is blinded.
|
||||||
|
func (e executionPayloadCapella) IsBlinded() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalSSZ --
|
// MarshalSSZ --
|
||||||
func (e executionPayloadCapella) MarshalSSZ() ([]byte, error) {
|
func (e executionPayloadCapella) MarshalSSZ() ([]byte, error) {
|
||||||
return e.p.MarshalSSZ()
|
return e.p.MarshalSSZ()
|
||||||
@@ -534,6 +549,11 @@ func (e executionPayloadHeaderCapella) IsNil() bool {
|
|||||||
return e.p == nil
|
return e.p == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsBlinded returns true if the underlying data is blinded.
|
||||||
|
func (e executionPayloadHeaderCapella) IsBlinded() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// MarshalSSZ --
|
// MarshalSSZ --
|
||||||
func (e executionPayloadHeaderCapella) MarshalSSZ() ([]byte, error) {
|
func (e executionPayloadHeaderCapella) MarshalSSZ() ([]byte, error) {
|
||||||
return e.p.MarshalSSZ()
|
return e.p.MarshalSSZ()
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ type ExecutionData interface {
|
|||||||
ssz.Unmarshaler
|
ssz.Unmarshaler
|
||||||
ssz.HashRoot
|
ssz.HashRoot
|
||||||
IsNil() bool
|
IsNil() bool
|
||||||
|
IsBlinded() bool
|
||||||
Proto() proto.Message
|
Proto() proto.Message
|
||||||
ParentHash() []byte
|
ParentHash() []byte
|
||||||
FeeRecipient() []byte
|
FeeRecipient() []byte
|
||||||
|
|||||||
@@ -611,6 +611,11 @@ func submitWithdrawal(ec *e2etypes.EvaluationContext, conns ...*grpc.ClientConn)
|
|||||||
}
|
}
|
||||||
|
|
||||||
func validatorsAreWithdrawn(ec *e2etypes.EvaluationContext, conns ...*grpc.ClientConn) error {
|
func validatorsAreWithdrawn(ec *e2etypes.EvaluationContext, conns ...*grpc.ClientConn) error {
|
||||||
|
// We skip this for multiclient runs as lighthouse does not have the ability
|
||||||
|
// to configure the withdrawal sweep for the end to end test.
|
||||||
|
if e2e.TestParams.LighthouseBeaconNodeCount > 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
conn := conns[0]
|
conn := conns[0]
|
||||||
beaconClient := ethpb.NewBeaconChainClient(conn)
|
beaconClient := ethpb.NewBeaconChainClient(conn)
|
||||||
debugClient := ethpb.NewDebugClient(conn)
|
debugClient := ethpb.NewDebugClient(conn)
|
||||||
@@ -642,7 +647,9 @@ func validatorsAreWithdrawn(ec *e2etypes.EvaluationContext, conns ...*grpc.Clien
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if bal != 0 {
|
// Only return an error if the validator has more than 1 eth
|
||||||
|
// in its balance.
|
||||||
|
if bal > 1*params.BeaconConfig().GweiPerEth {
|
||||||
return errors.Errorf("Validator index %d with key %#x hasn't withdrawn. Their balance is %d.", valIdx, key, bal)
|
return errors.Errorf("Validator index %d with key %#x hasn't withdrawn. Their balance is %d.", valIdx, key, bal)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,12 +2,14 @@ package operations
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"math/big"
|
||||||
"path"
|
"path"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/golang/snappy"
|
"github.com/golang/snappy"
|
||||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
|
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks"
|
||||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
||||||
|
consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks"
|
||||||
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
"github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces"
|
||||||
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
||||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||||
@@ -42,7 +44,9 @@ func RunWithdrawalsTest(t *testing.T, config string) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return blocks.ProcessWithdrawals(s, withdrawals)
|
p, err := consensusblocks.WrappedExecutionPayloadCapella(&enginev1.ExecutionPayloadCapella{Withdrawals: withdrawals}, big.NewInt(0))
|
||||||
|
require.NoError(t, err)
|
||||||
|
return blocks.ProcessWithdrawals(s, p)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user