Skip to content

Commit

Permalink
Friday progress
Browse files Browse the repository at this point in the history
  • Loading branch information
prestonvanloon committed Apr 22, 2024
1 parent 661cc58 commit 519e5fe
Show file tree
Hide file tree
Showing 13 changed files with 132 additions and 32 deletions.
11 changes: 9 additions & 2 deletions beacon-chain/core/blocks/exit.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ var ValidatorCannotExitYetMsg = "validator has not been active long enough to ex
// 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 EIP7251]
// # Verify signature
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
// signing_root = compute_signing_root(voluntary_exit, domain)
Expand Down Expand Up @@ -98,6 +100,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 EIP7251]
// # Verify signature
// domain = get_domain(state, DOMAIN_VOLUNTARY_EXIT, voluntary_exit.epoch)
// signing_root = compute_signing_root(voluntary_exit, domain)
Expand Down Expand Up @@ -128,7 +132,7 @@ func VerifyExitAndSignature(
}

exit := signed.Exit
if err := verifyExitConditions(validator, currentSlot, exit); err != nil {
if err := verifyExitConditions(state, validator, currentSlot, exit); err != nil {
return err
}
domain, err := signing.Domain(fork, exit.Epoch, params.BeaconConfig().DomainVoluntaryExit, genesisRoot)
Expand Down Expand Up @@ -163,7 +167,7 @@ func VerifyExitAndSignature(
// 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 {
func verifyExitConditions(st state.ReadOnlyBeaconState, validator state.ReadOnlyValidator, currentSlot primitives.Slot, exit *ethpb.VoluntaryExit) error {
currentEpoch := slots.ToEpoch(currentSlot)
// Verify the validator is active.
if !helpers.IsActiveValidatorUsingTrie(validator, currentEpoch) {
Expand All @@ -187,5 +191,8 @@ func verifyExitConditions(validator state.ReadOnlyValidator, currentSlot primiti
validator.ActivationEpoch()+params.BeaconConfig().ShardCommitteePeriod,
)
}
if st.Version() >= version.EIP7251 {
panic("implement me")
}
return nil
}
2 changes: 2 additions & 0 deletions beacon-chain/core/eip7251/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,13 @@ go_library(
"//beacon-chain/core/epoch:go_default_library",
"//beacon-chain/core/epoch/precompute:go_default_library",
"//beacon-chain/core/helpers:go_default_library",
"//beacon-chain/core/signing:go_default_library",
"//beacon-chain/core/time:go_default_library",
"//beacon-chain/core/validators:go_default_library",
"//beacon-chain/state:go_default_library",
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
"//crypto/bls:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//time/slots:go_default_library",
"@com_github_pkg_errors//:go_default_library",
Expand Down
57 changes: 56 additions & 1 deletion beacon-chain/core/eip7251/transition.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import (
e "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/epoch/precompute"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/signing"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/crypto/bls"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/time/slots"
"go.opencensus.io/trace"
Expand Down Expand Up @@ -316,6 +318,11 @@ func ProcessConsolidations(ctx context.Context, st state.BeaconState, cs []*ethp
return nil, errors.New("nil consolidations")
}

domain, err := signing.ComputeDomain(params.BeaconConfig().DomainConsolidation, st.Fork().CurrentVersion, st.GenesisValidatorsRoot())
if err != nil {
return nil, err
}

for _, c := range cs {
if c == nil || c.Message == nil {
return nil, errors.New("nil consolidation")
Expand Down Expand Up @@ -362,7 +369,55 @@ func ProcessConsolidations(ctx context.Context, st state.BeaconState, cs []*ethp
if currentEpoch < c.Message.Epoch {
return nil, errors.New("consolidation is not valid yet")
}

if !helpers.HasExecutionWithdrawalCredentials(source) {
return nil, errors.New("source does not have execution withdrawal credentials")
}
if !helpers.HasExecutionWithdrawalCredentials(target) {
return nil, errors.New("target does not have execution withdrawal credentials")
}
if !helpers.IsSameWithdrawalCredentials(source, target) {
return nil, errors.New("source and target have different withdrawal credentials")
}

sr, err := signing.ComputeSigningRoot(c.Message, domain)
if err != nil {
return nil, err
}
sourcePk, err := bls.PublicKeyFromBytes(source.PublicKey)
if err != nil {
return nil, errors.Wrap(err, "could not convert bytes to public key")
}
targetPk, err := bls.PublicKeyFromBytes(target.PublicKey)
if err != nil {
return nil, errors.Wrap(err, "could not convert bytes to public key")
}
sig, err := bls.SignatureFromBytes(c.Signature)
if err != nil {
return nil, errors.Wrap(err, "could not convert bytes to signature")
}
if !sig.FastAggregateVerify([]bls.PublicKey{sourcePk, targetPk}, sr) {
return nil, errors.New("consolidation signature verification failed")
}

sEE, err := ComputeConsolidationEpochAndUpdateChurn(ctx, st, source.EffectiveBalance)
if err != nil {
return nil, err
}
source.ExitEpoch = sEE
source.WithdrawableEpoch = sEE + params.BeaconConfig().MinValidatorWithdrawabilityDelay
if err := st.UpdateValidatorAtIndex(c.Message.SourceIndex, source); err != nil {
return nil, err
}
if err := st.AppendPendingConsolidation(c.Message.ToPendingConsolidation()); err != nil {
return nil, err
}
}

return nil, errors.New("not implemented")
return st, nil
}

func ProcessExecutionLayerWithdrawRequests(ctx context.Context, st state.BeaconState, wds []*ethpb.ExecutionLayerWithdrawalRequest) (state.BeaconState, error) {
// TODO: Need to align with James He. This is a placeholder implementation.
panic("implement me")
}
27 changes: 27 additions & 0 deletions beacon-chain/core/helpers/validators.go
Original file line number Diff line number Diff line change
Expand Up @@ -534,3 +534,30 @@ func HasCompoundingWithdrawalCredential(v *ethpb.Validator) bool {
func isCompoundingWithdrawalCredential(creds []byte) bool {
return bytes.HasPrefix(creds, []byte{params.BeaconConfig().CompoundingWithdrawalPrefix})
}

// HasExecutionWithdrawalCredentials checks if the validator has an execution withdrawal credential or compounding credential.
// New in EIP-7251: https://eips.ethereum.org/EIPS/eip-7251
//
// Spec definition:
//
// def has_execution_withdrawal_credential(validator: Validator) -> bool:
// """
// Check if ``validator`` has a 0x01 or 0x02 prefixed withdrawal credential.
// """
// return has_compounding_withdrawal_credential(validator) or has_eth1_withdrawal_credential(validator)
func HasExecutionWithdrawalCredentials(v *ethpb.Validator) bool {
if v == nil {
return false
}
return HasCompoundingWithdrawalCredential(v) || HasETH1WithdrawalCredential(v)
}

// IsSameWithdrawalCredentials returns true if both validators have the same withdrawal credentials.
//
// return a.withdrawal_credentials[12:] == b.withdrawal_credentials[12:]
func IsSameWithdrawalCredentials(a, b *ethpb.Validator) bool {
if len(a.WithdrawalCredentials) <= 12 || len(b.WithdrawalCredentials) <= 12 {
return false
}
return bytes.Equal(a.WithdrawalCredentials[12:], b.WithdrawalCredentials[12:])
}
8 changes: 6 additions & 2 deletions beacon-chain/core/transition/transition_no_verify_sig.go
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ func VerifyBlobCommitmentCount(blk interfaces.ReadOnlyBeaconBlock) error {
// for_ops(body.deposits, process_deposit) # [Modified in EIP7251]
// for_ops(body.voluntary_exits, process_voluntary_exit) # [Modified in EIP7251]
// for_ops(body.bls_to_execution_changes, process_bls_to_execution_change)
// for_ops(body.execution_payload.withdraw_requests, process_execution_layer_withdraw_request) # [New in EIP7251]
// for_ops(body.execution_payload.withdraw_requests, process_execution_layer_withdraw_request) # [New in EIP7002/EIP7251]
// for_ops(body.consolidations, process_consolidation) # [New in EIP7251]
func eip7251Operations(
ctx context.Context,
Expand All @@ -418,6 +418,11 @@ func eip7251Operations(
return nil, err
}

st, err = eip7251.ProcessExecutionLayerWithdrawRequests(ctx, st, nil)
if err != nil {
return nil, errors.Wrap(err, "could not process execution layer withdrawal requests")
}

cs, err := block.Body().Consolidations()
if err != nil {
return nil, errors.Wrap(err, "could not get consolidations")
Expand All @@ -427,7 +432,6 @@ func eip7251Operations(
return nil, errors.Wrap(err, "could not process consolidations")
}

// TODO
return st, nil
}

Expand Down
1 change: 1 addition & 0 deletions beacon-chain/state/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,4 +306,5 @@ type WriteOnlyEIP7241 interface {
SetDepositBalanceToConsume(gwei uint64) error
SetPendingConsolidations(val []*ethpb.PendingConsolidation) error
DequeuePartialWithdrawals(idx uint64) error
AppendPendingConsolidation(val *ethpb.PendingConsolidation) error
}
13 changes: 13 additions & 0 deletions beacon-chain/state/state-native/getters_eip7251.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"github.com/prysmaticlabs/prysm/v5/runtime/version"
)

// TODO: This file has getters and setters related to EIP-7251. Split it up!

func (b *BeaconState) EarliestConsolidationEpoch() (primitives.Epoch, error) {
if b.version < version.EIP7251 {
return 0, errNotSupported("EarliestConsolidationEpoch", b.version)
Expand Down Expand Up @@ -111,3 +113,14 @@ func (b *BeaconState) SetPendingConsolidations(val []*ethpb.PendingConsolidation
b.pendingConsolidations = val
return nil
}

func (b *BeaconState) AppendPendingConsolidation(val *ethpb.PendingConsolidation) error {
if b.version < version.EIP7251 {
return errNotSupported("AppendPendingConsolidation", b.version)
}
b.lock.Lock() // TODO: Is this necessary?
defer b.lock.Unlock()

b.pendingConsolidations = append(b.pendingConsolidations, val)
return nil
}
4 changes: 2 additions & 2 deletions beacon-chain/state/state-native/getters_withdrawal.go
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ func isFullyWithdrawableValidator(val *ethpb.Validator, balance uint64, epoch pr

// EIP-7251 logic
if epoch >= params.BeaconConfig().EIP7251ForkEpoch {
return HasExecutionWithdrawalCredentials(val) && val.WithdrawableEpoch <= epoch
return helpers.HasExecutionWithdrawalCredentials(val) && val.WithdrawableEpoch <= epoch
}

return helpers.HasETH1WithdrawalCredential(val) && val.WithdrawableEpoch <= epoch
Expand Down Expand Up @@ -238,7 +238,7 @@ func isPartiallyWithdrawableValidator(val *ethpb.Validator, balance uint64, epoc
hasMaxBalance := val.EffectiveBalance == maxEB
hasExcessBalance := balance > maxEB

return HasExecutionWithdrawalCredentials(val) &&
return helpers.HasExecutionWithdrawalCredentials(val) &&
hasMaxBalance &&
hasExcessBalance
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ package state_native
import (
"bytes"

"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
"github.com/prysmaticlabs/prysm/v5/config/params"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
)

// TODO: Move all of this to core/helpers.
Expand Down Expand Up @@ -37,20 +35,3 @@ func HasCompoundingWithdrawalCredentialUsingTrie(v state.ReadOnlyValidator) bool
func isCompoundingWithdrawalCredential(creds []byte) bool {
return bytes.HasPrefix(creds, []byte{params.BeaconConfig().CompoundingWithdrawalPrefix})
}

// HasExecutionWithdrawalCredentials checks if the validator has an execution withdrawal credential or compounding credential.
// New in EIP-7251: https://eips.ethereum.org/EIPS/eip-7251
//
// Spec definition:
//
// def has_execution_withdrawal_credential(validator: Validator) -> bool:
// """
// Check if ``validator`` has a 0x01 or 0x02 prefixed withdrawal credential.
// """
// return has_compounding_withdrawal_credential(validator) or has_eth1_withdrawal_credential(validator)
func HasExecutionWithdrawalCredentials(v *ethpb.Validator) bool {
if v == nil {
return false
}
return helpers.HasCompoundingWithdrawalCredential(v) || helpers.HasETH1WithdrawalCredential(v)
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,15 @@ package state_native_test
import (
"testing"

state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/core/helpers"
"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/testing/assert"
)

// TODO: Test WithTrie version.
// TODO: Move this to helpers.
func TestHasExecutionWithdrawalCredentials(t *testing.T) {
tests := []struct {
name string
Expand All @@ -30,7 +31,7 @@ func TestHasExecutionWithdrawalCredentials(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equal(t, tt.want, state_native.HasExecutionWithdrawalCredentials(tt.validator))
assert.Equal(t, tt.want, helpers.HasExecutionWithdrawalCredentials(tt.validator))
})
}
}
1 change: 1 addition & 0 deletions proto/prysm/v1alpha1/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ go_library(
name = "go_default_library",
srcs = [
"cloners.go",
"eip_7251.go",
"sync_committee_mainnet.go",
"sync_committee_minimal.go", # keep
":ssz_generated_files", # keep
Expand Down
12 changes: 12 additions & 0 deletions proto/prysm/v1alpha1/eip_7251.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package eth

func (c *Consolidation) ToPendingConsolidation() *PendingConsolidation {
if c == nil {
return nil
}
p := &PendingConsolidation{
SourceIndex: c.SourceIndex,
TargetIndex: c.TargetIndex,
}
return p
}
4 changes: 0 additions & 4 deletions testing/spectest/shared/deneb/operations/withdrawals.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,6 @@ func RunWithdrawalsTest(t *testing.T, config string) {
testFolders, testsFolderPath := utils.TestFolders(t, config, "deneb", "operations/withdrawals/pyspec_tests")
for _, folder := range testFolders {
t.Run(folder.Name(), func(t *testing.T) {
if folder.Name() == "success_excess_balance_but_no_max_effective_balance" {
t.Skip("Skipping broken spec test for EIP-7251") // TODO: Unskip
// This spectest is broken by changes in is_partially_withdrawable_validator.
}
folderPath := path.Join(testsFolderPath, folder.Name())
payloadFile, err := util.BazelFileBytes(folderPath, "execution_payload.ssz_snappy")
require.NoError(t, err)
Expand Down

0 comments on commit 519e5fe

Please sign in to comment.