mirror of
https://gitlab.com/pulsechaincom/prysm-pulse.git
synced 2024-12-25 21:07:18 +00:00
14dbc2b74d
* Add blst third party dep * initial build * add init * blst passing tests * add feature flag * blst and herumi for spec tests * maybe this works for mac * Actually set feature flag * Add stub for VerifyMultipleSignatures for blst * verifyCompressed * use correct cores sizes * aggregate public keys * add multi-sig verification * encode not hash * revert back * go mod tidy * update blst to latest commit * add batch decompress * fix * add test * gofmt * update blst * go mod tidy * remove kubesec, fix * mod tidy * disable some remote cache * disable some remote cache * disable some remote cache * disable some remote cache * Switch to -D__ADX__ * update * tidy * fix build * Make blst for only linux,amd64 * gofmt * lint * lint * gazelle * fix build tag * more stub methods * shift adx instructions to x86 * fix arm64 * Revert "fix arm64" This reverts commit 4d34ac21b7509a1b385374e3039efecfcab614c1. * add one more in * Revert "Revert "fix arm64"" This reverts commit 1c8ae24ad16ff9811590f1058b9d98c90b63251a. * try darwin now * Revert "try darwin now" This reverts commit 6f884714b8e14a7a803b72157672b6e942047f37. * Add sha256 * remove TODO * checkpoint * finally builds * fix up * add tag * try again * explicit disabling * remove * select properly * fix * better * make CI happy too * Update .bazelrc * Update .bazelrc * fix tests * revert back * Update shared/bls/blst/public_key.go Co-authored-by: Victor Farazdagi <simple.square@gmail.com> * Update shared/bls/blst/public_key.go Co-authored-by: Victor Farazdagi <simple.square@gmail.com> * clean up tests * more clean up * clean up * add * Update shared/bls/blst/signature.go * Update shared/bls/blst/signature.go * Update .buildkite-bazelrc Co-authored-by: Preston Van Loon <preston@prysmaticlabs.com> * try again * remove go tag * revert change * gaz * gazelle ignore Co-authored-by: nisdas <nishdas93@gmail.com> Co-authored-by: Victor Farazdagi <simple.square@gmail.com> Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com>
273 lines
9.3 KiB
Go
273 lines
9.3 KiB
Go
package blocks
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/pkg/errors"
|
|
ethpb "github.com/prysmaticlabs/ethereumapis/eth/v1alpha1"
|
|
"github.com/prysmaticlabs/go-ssz"
|
|
"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
|
|
stateTrie "github.com/prysmaticlabs/prysm/beacon-chain/state"
|
|
pb "github.com/prysmaticlabs/prysm/proto/beacon/p2p/v1"
|
|
"github.com/prysmaticlabs/prysm/shared/bls"
|
|
"github.com/prysmaticlabs/prysm/shared/bytesutil"
|
|
"github.com/prysmaticlabs/prysm/shared/depositutil"
|
|
"github.com/prysmaticlabs/prysm/shared/mathutil"
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
"github.com/prysmaticlabs/prysm/shared/trieutil"
|
|
)
|
|
|
|
// ProcessPreGenesisDeposits processes a deposit for the beacon state before chainstart.
|
|
func ProcessPreGenesisDeposits(
|
|
ctx context.Context,
|
|
beaconState *stateTrie.BeaconState,
|
|
deposits []*ethpb.Deposit,
|
|
) (*stateTrie.BeaconState, error) {
|
|
var err error
|
|
beaconState, err = ProcessDeposits(ctx, beaconState, ðpb.SignedBeaconBlock{
|
|
Block: ðpb.BeaconBlock{Body: ðpb.BeaconBlockBody{Deposits: deposits}}})
|
|
if err != nil {
|
|
return nil, errors.Wrap(err, "could not process deposit")
|
|
}
|
|
for _, deposit := range deposits {
|
|
pubkey := deposit.Data.PublicKey
|
|
index, ok := beaconState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubkey))
|
|
if !ok {
|
|
return beaconState, nil
|
|
}
|
|
balance, err := beaconState.BalanceAtIndex(index)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
validator, err := beaconState.ValidatorAtIndex(index)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
validator.EffectiveBalance = mathutil.Min(balance-balance%params.BeaconConfig().EffectiveBalanceIncrement, params.BeaconConfig().MaxEffectiveBalance)
|
|
if validator.EffectiveBalance ==
|
|
params.BeaconConfig().MaxEffectiveBalance {
|
|
validator.ActivationEligibilityEpoch = 0
|
|
validator.ActivationEpoch = 0
|
|
}
|
|
if err := beaconState.UpdateValidatorAtIndex(index, validator); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
return beaconState, nil
|
|
}
|
|
|
|
// ProcessDeposits is one of the operations performed on each processed
|
|
// beacon block to verify queued validators from the Ethereum 1.0 Deposit Contract
|
|
// into the beacon chain.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// For each deposit in block.body.deposits:
|
|
// process_deposit(state, deposit)
|
|
func ProcessDeposits(
|
|
ctx context.Context,
|
|
beaconState *stateTrie.BeaconState,
|
|
b *ethpb.SignedBeaconBlock,
|
|
) (*stateTrie.BeaconState, error) {
|
|
if b.Block == nil || b.Block.Body == nil {
|
|
return nil, errors.New("block and block body can't be nil")
|
|
}
|
|
|
|
deposits := b.Block.Body.Deposits
|
|
var err error
|
|
domain, err := helpers.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Attempt to verify all deposit signatures at once, if this fails then fall back to processing
|
|
// individual deposits with signature verification enabled.
|
|
var verifySignature bool
|
|
if err := verifyDepositDataWithDomain(ctx, deposits, domain); err != nil {
|
|
log.WithError(err).Debug("Failed to verify deposit data, verifying signatures individually")
|
|
verifySignature = true
|
|
}
|
|
|
|
for _, deposit := range deposits {
|
|
if deposit == nil || deposit.Data == nil {
|
|
return nil, errors.New("got a nil deposit in block")
|
|
}
|
|
beaconState, err = ProcessDeposit(beaconState, deposit, verifySignature)
|
|
if err != nil {
|
|
return nil, errors.Wrapf(err, "could not process deposit from %#x", bytesutil.Trunc(deposit.Data.PublicKey))
|
|
}
|
|
}
|
|
return beaconState, nil
|
|
}
|
|
|
|
// ProcessDeposit takes in a deposit object and inserts it
|
|
// into the registry as a new validator or balance change.
|
|
//
|
|
// Spec pseudocode definition:
|
|
// def process_deposit(state: BeaconState, deposit: Deposit) -> None:
|
|
// # Verify the Merkle branch
|
|
// assert is_valid_merkle_branch(
|
|
// leaf=hash_tree_root(deposit.data),
|
|
// branch=deposit.proof,
|
|
// depth=DEPOSIT_CONTRACT_TREE_DEPTH + 1, # Add 1 for the List length mix-in
|
|
// index=state.eth1_deposit_index,
|
|
// root=state.eth1_data.deposit_root,
|
|
// )
|
|
//
|
|
// # Deposits must be processed in order
|
|
// state.eth1_deposit_index += 1
|
|
//
|
|
// pubkey = deposit.data.pubkey
|
|
// amount = deposit.data.amount
|
|
// validator_pubkeys = [v.pubkey for v in state.validators]
|
|
// if pubkey not in validator_pubkeys:
|
|
// # Verify the deposit signature (proof of possession) which is not checked by the deposit contract
|
|
// deposit_message = DepositMessage(
|
|
// pubkey=deposit.data.pubkey,
|
|
// withdrawal_credentials=deposit.data.withdrawal_credentials,
|
|
// amount=deposit.data.amount,
|
|
// )
|
|
// domain = compute_domain(DOMAIN_DEPOSIT) # Fork-agnostic domain since deposits are valid across forks
|
|
// signing_root = compute_signing_root(deposit_message, domain)
|
|
// if not bls.Verify(pubkey, signing_root, deposit.data.signature):
|
|
// return
|
|
//
|
|
// # Add validator and balance entries
|
|
// state.validators.append(get_validator_from_deposit(state, deposit))
|
|
// state.balances.append(amount)
|
|
// else:
|
|
// # Increase balance by deposit amount
|
|
// index = ValidatorIndex(validator_pubkeys.index(pubkey))
|
|
// increase_balance(state, index, amount)
|
|
func ProcessDeposit(beaconState *stateTrie.BeaconState, deposit *ethpb.Deposit, verifySignature bool) (*stateTrie.BeaconState, error) {
|
|
if err := verifyDeposit(beaconState, deposit); err != nil {
|
|
if deposit == nil || deposit.Data == nil {
|
|
return nil, err
|
|
}
|
|
return nil, errors.Wrapf(err, "could not verify deposit from %#x", bytesutil.Trunc(deposit.Data.PublicKey))
|
|
}
|
|
if err := beaconState.SetEth1DepositIndex(beaconState.Eth1DepositIndex() + 1); err != nil {
|
|
return nil, err
|
|
}
|
|
pubKey := deposit.Data.PublicKey
|
|
amount := deposit.Data.Amount
|
|
index, ok := beaconState.ValidatorIndexByPubkey(bytesutil.ToBytes48(pubKey))
|
|
if !ok {
|
|
if verifySignature {
|
|
domain, err := helpers.ComputeDomain(params.BeaconConfig().DomainDeposit, nil, nil)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
depositSig := deposit.Data.Signature
|
|
if err := verifyDepositDataSigningRoot(deposit.Data, pubKey, depositSig, domain); err != nil {
|
|
// Ignore this error as in the spec pseudo code.
|
|
log.Debugf("Skipping deposit: could not verify deposit data signature: %v", err)
|
|
return beaconState, nil
|
|
}
|
|
}
|
|
|
|
effectiveBalance := amount - (amount % params.BeaconConfig().EffectiveBalanceIncrement)
|
|
if params.BeaconConfig().MaxEffectiveBalance < effectiveBalance {
|
|
effectiveBalance = params.BeaconConfig().MaxEffectiveBalance
|
|
}
|
|
if err := beaconState.AppendValidator(ðpb.Validator{
|
|
PublicKey: pubKey,
|
|
WithdrawalCredentials: deposit.Data.WithdrawalCredentials,
|
|
ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
ActivationEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
ExitEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
WithdrawableEpoch: params.BeaconConfig().FarFutureEpoch,
|
|
EffectiveBalance: effectiveBalance,
|
|
}); err != nil {
|
|
return nil, err
|
|
}
|
|
if err := beaconState.AppendBalance(amount); err != nil {
|
|
return nil, err
|
|
}
|
|
} else if err := helpers.IncreaseBalance(beaconState, index, amount); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return beaconState, nil
|
|
}
|
|
|
|
func verifyDeposit(beaconState *stateTrie.BeaconState, deposit *ethpb.Deposit) error {
|
|
// Verify Merkle proof of deposit and deposit trie root.
|
|
if deposit == nil || deposit.Data == nil {
|
|
return errors.New("received nil deposit or nil deposit data")
|
|
}
|
|
eth1Data := beaconState.Eth1Data()
|
|
if eth1Data == nil {
|
|
return errors.New("received nil eth1data in the beacon state")
|
|
}
|
|
|
|
receiptRoot := eth1Data.DepositRoot
|
|
leaf, err := deposit.Data.HashTreeRoot()
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not tree hash deposit data")
|
|
}
|
|
if ok := trieutil.VerifyMerkleBranch(
|
|
receiptRoot,
|
|
leaf[:],
|
|
int(beaconState.Eth1DepositIndex()),
|
|
deposit.Proof,
|
|
params.BeaconConfig().DepositContractTreeDepth,
|
|
); !ok {
|
|
return fmt.Errorf(
|
|
"deposit merkle branch of deposit root did not verify for root: %#x",
|
|
receiptRoot,
|
|
)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Deprecated: This method uses deprecated ssz.SigningRoot.
|
|
func verifyDepositDataSigningRoot(obj *ethpb.Deposit_Data, pub []byte, signature []byte, domain []byte) error {
|
|
return depositutil.VerifyDepositSignature(obj, domain)
|
|
}
|
|
|
|
func verifyDepositDataWithDomain(ctx context.Context, deps []*ethpb.Deposit, domain []byte) error {
|
|
if len(deps) == 0 {
|
|
return nil
|
|
}
|
|
pks := make([]bls.PublicKey, len(deps))
|
|
sigs := make([][]byte, len(deps))
|
|
msgs := make([][32]byte, len(deps))
|
|
for i, dep := range deps {
|
|
if ctx.Err() != nil {
|
|
return ctx.Err()
|
|
}
|
|
if dep == nil || dep.Data == nil {
|
|
return errors.New("nil deposit")
|
|
}
|
|
dpk, err := bls.PublicKeyFromBytes(dep.Data.PublicKey)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
pks[i] = dpk
|
|
sigs[i] = dep.Data.Signature
|
|
root, err := ssz.SigningRoot(dep.Data)
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not get signing root")
|
|
}
|
|
signingData := &pb.SigningData{
|
|
ObjectRoot: root[:],
|
|
Domain: domain,
|
|
}
|
|
ctrRoot, err := signingData.HashTreeRoot()
|
|
if err != nil {
|
|
return errors.Wrap(err, "could not get container root")
|
|
}
|
|
msgs[i] = ctrRoot
|
|
}
|
|
verify, err := bls.VerifyMultipleSignatures(sigs, msgs, pks)
|
|
if err != nil {
|
|
return errors.Errorf("could not verify multiple signatures: %v", err)
|
|
}
|
|
if !verify {
|
|
return errors.New("one or more deposit signatures did not verify")
|
|
}
|
|
return nil
|
|
}
|