mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 13:28:01 -05:00
Add Withdrawal helpers (#11552)
* Add Withdrawal helpers * Review Co-authored-by: terencechain <terence@prysmaticlabs.com>
This commit is contained in:
@@ -96,6 +96,9 @@ type ReadOnlyValidator interface {
|
||||
ExitEpoch() types.Epoch
|
||||
PublicKey() [fieldparams.BLSPubkeyLength]byte
|
||||
WithdrawalCredentials() []byte
|
||||
HasETH1WithdrawalCredential() bool
|
||||
IsFullyWithdrawable(types.Epoch) bool
|
||||
IsPartiallyWithdrawable(uint64) bool
|
||||
Slashed() bool
|
||||
IsNil() bool
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state"
|
||||
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
)
|
||||
@@ -78,6 +79,28 @@ func (v readOnlyValidator) WithdrawalCredentials() []byte {
|
||||
return creds
|
||||
}
|
||||
|
||||
// HasETH1WithdrawalCredential returns whether the validator has an ETH1
|
||||
// Withdrawal prefix.
|
||||
func (v readOnlyValidator) HasETH1WithdrawalCredential() bool {
|
||||
cred := v.WithdrawalCredentials()
|
||||
return len(cred) > 0 && cred[0] == params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
||||
}
|
||||
|
||||
// IsFullyWithdrawable returns whether the validator is able to perform a full
|
||||
// withdrawal. This differ from the spec helper in that the balance > 0 is not
|
||||
// checked.
|
||||
func (v readOnlyValidator) IsFullyWithdrawable(epoch types.Epoch) bool {
|
||||
return v.HasETH1WithdrawalCredential() && v.WithdrawableEpoch() <= epoch
|
||||
}
|
||||
|
||||
// IsPartiallyWithdrawable returns whether the validator is able to perform a
|
||||
// partial withdrawal.
|
||||
func (v readOnlyValidator) IsPartiallyWithdrawable(balance uint64) bool {
|
||||
hasMaxBalance := v.EffectiveBalance() == params.BeaconConfig().MaxEffectiveBalance
|
||||
hasExcessBalance := balance > params.BeaconConfig().MaxEffectiveBalance
|
||||
return v.HasETH1WithdrawalCredential() && hasExcessBalance && hasMaxBalance
|
||||
}
|
||||
|
||||
// Slashed returns the read only validator is slashed.
|
||||
func (v readOnlyValidator) Slashed() bool {
|
||||
return v.validator.Slashed
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
statenative "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"
|
||||
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/testing/assert"
|
||||
@@ -66,6 +67,82 @@ func TestReadOnlyValidator_WithdrawalCredentials(t *testing.T) {
|
||||
assert.DeepEqual(t, creds, v.WithdrawalCredentials())
|
||||
}
|
||||
|
||||
func TestReadOnlyValidator_HasETH1WithdrawalCredentials(t *testing.T) {
|
||||
creds := []byte{0xFA, 0xCC}
|
||||
v, err := statenative.NewValidator(ðpb.Validator{WithdrawalCredentials: creds})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, v.HasETH1WithdrawalCredential())
|
||||
creds = []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte, 0xCC}
|
||||
v, err = statenative.NewValidator(ðpb.Validator{WithdrawalCredentials: creds})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, v.HasETH1WithdrawalCredential())
|
||||
// No Withdrawal cred
|
||||
v, err = statenative.NewValidator(ðpb.Validator{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, v.HasETH1WithdrawalCredential())
|
||||
}
|
||||
|
||||
func TestReadOnlyValidator_IsFullyWithdrawable(t *testing.T) {
|
||||
// No ETH1 prefix
|
||||
creds := []byte{0xFA, 0xCC}
|
||||
v, err := statenative.NewValidator(ðpb.Validator{
|
||||
WithdrawalCredentials: creds,
|
||||
WithdrawableEpoch: 2,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, v.IsFullyWithdrawable(3))
|
||||
// Wrong withdrawable epoch
|
||||
creds = []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte, 0xCC}
|
||||
v, err = statenative.NewValidator(ðpb.Validator{
|
||||
WithdrawalCredentials: creds,
|
||||
WithdrawableEpoch: 2,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, v.IsFullyWithdrawable(1))
|
||||
// Fully withdrawable
|
||||
creds = []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte, 0xCC}
|
||||
v, err = statenative.NewValidator(ðpb.Validator{
|
||||
WithdrawalCredentials: creds,
|
||||
WithdrawableEpoch: 2,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, v.IsFullyWithdrawable(3))
|
||||
}
|
||||
|
||||
func TestReadOnlyValidator_IsPartiallyWithdrawable(t *testing.T) {
|
||||
// No ETH1 prefix
|
||||
creds := []byte{0xFA, 0xCC}
|
||||
v, err := statenative.NewValidator(ðpb.Validator{
|
||||
WithdrawalCredentials: creds,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, v.IsPartiallyWithdrawable(params.BeaconConfig().MaxEffectiveBalance+1))
|
||||
// Not the right effective balance
|
||||
creds = []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte, 0xCC}
|
||||
v, err = statenative.NewValidator(ðpb.Validator{
|
||||
WithdrawalCredentials: creds,
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance - 1,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, v.IsPartiallyWithdrawable(params.BeaconConfig().MaxEffectiveBalance+1))
|
||||
// Not enough balance
|
||||
creds = []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte, 0xCC}
|
||||
v, err = statenative.NewValidator(ðpb.Validator{
|
||||
WithdrawalCredentials: creds,
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, false, v.IsPartiallyWithdrawable(params.BeaconConfig().MaxEffectiveBalance))
|
||||
// Partially Withdrawable
|
||||
creds = []byte{params.BeaconConfig().ETH1AddressWithdrawalPrefixByte, 0xCC}
|
||||
v, err = statenative.NewValidator(ðpb.Validator{
|
||||
WithdrawalCredentials: creds,
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, true, v.IsPartiallyWithdrawable(params.BeaconConfig().MaxEffectiveBalance+1))
|
||||
}
|
||||
|
||||
func TestReadOnlyValidator_Slashed(t *testing.T) {
|
||||
v, err := statenative.NewValidator(ðpb.Validator{Slashed: true})
|
||||
require.NoError(t, err)
|
||||
|
||||
Reference in New Issue
Block a user