mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2025-01-11 12:10:05 +00:00
de73baa4a7
* rename last_withdrawal_validator_index * Update Capella methods to Specs #3068 * Add missing renames * rename minimal state Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
124 lines
4.6 KiB
Go
124 lines
4.6 KiB
Go
package blocks
|
|
|
|
import (
|
|
"bytes"
|
|
|
|
"github.com/pkg/errors"
|
|
"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/state"
|
|
"github.com/prysmaticlabs/prysm/v3/config/params"
|
|
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
|
|
"github.com/prysmaticlabs/prysm/v3/crypto/hash/htr"
|
|
"github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
|
|
enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1"
|
|
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
|
"github.com/prysmaticlabs/prysm/v3/time/slots"
|
|
)
|
|
|
|
const executionToBLSPadding = 12
|
|
|
|
// ProcessBLSToExecutionChange validates a SignedBLSToExecution message and
|
|
// changes the validator's withdrawal address accordingly.
|
|
//
|
|
// Spec pseudocode definition:
|
|
//
|
|
//def process_bls_to_execution_change(state: BeaconState, signed_address_change: SignedBLSToExecutionChange) -> None:
|
|
// validator = state.validators[address_change.validator_index]
|
|
//
|
|
// assert validator.withdrawal_credentials[:1] == BLS_WITHDRAWAL_PREFIX
|
|
// assert validator.withdrawal_credentials[1:] == hash(address_change.from_bls_pubkey)[1:]
|
|
//
|
|
// domain = get_domain(state, DOMAIN_BLS_TO_EXECUTION_CHANGE)
|
|
// signing_root = compute_signing_root(address_change, domain)
|
|
// assert bls.Verify(address_change.from_bls_pubkey, signing_root, signed_address_change.signature)
|
|
//
|
|
// validator.withdrawal_credentials = (
|
|
// ETH1_ADDRESS_WITHDRAWAL_PREFIX
|
|
// + b'\x00' * 11
|
|
// + address_change.to_execution_address
|
|
// )
|
|
//
|
|
func ProcessBLSToExecutionChange(st state.BeaconState, signed *ethpb.SignedBLSToExecutionChange) (state.BeaconState, error) {
|
|
if signed == nil {
|
|
return st, errNilSignedWithdrawalMessage
|
|
}
|
|
message := signed.Message
|
|
if message == nil {
|
|
return st, errNilWithdrawalMessage
|
|
}
|
|
|
|
val, err := st.ValidatorAtIndex(message.ValidatorIndex)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cred := val.WithdrawalCredentials
|
|
if cred[0] != params.BeaconConfig().BLSWithdrawalPrefixByte {
|
|
return nil, errInvalidBLSPrefix
|
|
}
|
|
|
|
// hash the public key and verify it matches the withdrawal credentials
|
|
fromPubkey := message.FromBlsPubkey
|
|
pubkeyChunks := [][32]byte{bytesutil.ToBytes32(fromPubkey[:32]), bytesutil.ToBytes32(fromPubkey[32:])}
|
|
digest := make([][32]byte, 1)
|
|
htr.VectorizedSha256(pubkeyChunks, digest)
|
|
if !bytes.Equal(digest[0][1:], cred[1:]) {
|
|
return nil, errInvalidWithdrawalCredentials
|
|
}
|
|
|
|
epoch := slots.ToEpoch(st.Slot())
|
|
domain, err := signing.Domain(st.Fork(), epoch, params.BeaconConfig().DomainBLSToExecutionChange, st.GenesisValidatorsRoot())
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if err := signing.VerifySigningRoot(message, fromPubkey, signed.Signature, domain); err != nil {
|
|
return nil, signing.ErrSigFailedToVerify
|
|
}
|
|
newCredentials := make([]byte, executionToBLSPadding)
|
|
newCredentials[0] = params.BeaconConfig().ETH1AddressWithdrawalPrefixByte
|
|
val.WithdrawalCredentials = append(newCredentials, message.ToExecutionAddress...)
|
|
err = st.UpdateValidatorAtIndex(message.ValidatorIndex, val)
|
|
return st, err
|
|
}
|
|
|
|
func ProcessWithdrawals(st state.BeaconState, withdrawals []*enginev1.Withdrawal) (state.BeaconState, error) {
|
|
expected, err := st.ExpectedWithdrawals()
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not get expected withdrawals")
|
|
}
|
|
if len(expected) != len(withdrawals) {
|
|
return nil, errInvalidWithdrawalNumber
|
|
}
|
|
for i, withdrawal := range withdrawals {
|
|
if withdrawal.WithdrawalIndex != expected[i].WithdrawalIndex {
|
|
return nil, errInvalidWithdrawalIndex
|
|
}
|
|
if withdrawal.ValidatorIndex != expected[i].ValidatorIndex {
|
|
return nil, errInvalidValidatorIndex
|
|
}
|
|
if !bytes.Equal(withdrawal.ExecutionAddress, expected[i].ExecutionAddress) {
|
|
return nil, errInvalidExecutionAddress
|
|
}
|
|
if withdrawal.Amount != expected[i].Amount {
|
|
return nil, errInvalidWithdrawalAmount
|
|
}
|
|
err := helpers.DecreaseBalance(st, withdrawal.ValidatorIndex, withdrawal.Amount)
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not decrease balance")
|
|
}
|
|
}
|
|
if len(withdrawals) > 0 {
|
|
if err := st.SetNextWithdrawalIndex(withdrawals[len(withdrawals)-1].WithdrawalIndex + 1); err != nil {
|
|
return nil, errors.Wrap(err, "could not set next withdrawal index")
|
|
}
|
|
nextValidatorIndex := withdrawals[len(withdrawals)-1].ValidatorIndex + 1
|
|
if nextValidatorIndex == types.ValidatorIndex(st.NumValidators()) {
|
|
nextValidatorIndex = 0
|
|
}
|
|
if err := st.SetNextWithdrawalValidatorIndex(nextValidatorIndex); err != nil {
|
|
return nil, errors.Wrap(err, "could not set latest withdrawal validator index")
|
|
}
|
|
}
|
|
return st, nil
|
|
}
|