github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/forkchoice/protoarray/helpers.go (about)

     1  package protoarray
     2  
     3  import (
     4  	"context"
     5  
     6  	"github.com/prysmaticlabs/prysm/shared/params"
     7  	"go.opencensus.io/trace"
     8  )
     9  
    10  // This computes validator balance delta from validator votes.
    11  // It returns a list of deltas that represents the difference between old balances and new balances.
    12  func computeDeltas(
    13  	ctx context.Context,
    14  	blockIndices map[[32]byte]uint64,
    15  	votes []Vote,
    16  	oldBalances, newBalances []uint64,
    17  ) ([]int, []Vote, error) {
    18  	ctx, span := trace.StartSpan(ctx, "protoArrayForkChoice.computeDeltas")
    19  	defer span.End()
    20  
    21  	deltas := make([]int, len(blockIndices))
    22  
    23  	for validatorIndex, vote := range votes {
    24  		oldBalance := uint64(0)
    25  		newBalance := uint64(0)
    26  
    27  		// Skip if validator has never voted for current root and next root (ie. if the
    28  		// votes are zero hash aka genesis block), there's nothing to compute.
    29  		if vote.currentRoot == params.BeaconConfig().ZeroHash && vote.nextRoot == params.BeaconConfig().ZeroHash {
    30  			continue
    31  		}
    32  
    33  		// If the validator index did not exist in `oldBalance` or `newBalance` list above, the balance is just 0.
    34  		if validatorIndex < len(oldBalances) {
    35  			oldBalance = oldBalances[validatorIndex]
    36  		}
    37  		if validatorIndex < len(newBalances) {
    38  			newBalance = newBalances[validatorIndex]
    39  		}
    40  
    41  		// Perform delta only if the validator's balance or vote has changed.
    42  		if vote.currentRoot != vote.nextRoot || oldBalance != newBalance {
    43  			// Ignore the vote if it's not known in `blockIndices`,
    44  			// that means we have not seen the block before.
    45  			nextDeltaIndex, ok := blockIndices[vote.nextRoot]
    46  			if ok {
    47  				// Protection against out of bound, the `nextDeltaIndex` which defines
    48  				// the block location in the dag can not exceed the total `delta` length.
    49  				if int(nextDeltaIndex) >= len(deltas) {
    50  					return nil, nil, errInvalidNodeDelta
    51  				}
    52  				deltas[nextDeltaIndex] += int(newBalance)
    53  			}
    54  
    55  			currentDeltaIndex, ok := blockIndices[vote.currentRoot]
    56  			if ok {
    57  				// Protection against out of bound (same as above)
    58  				if int(currentDeltaIndex) >= len(deltas) {
    59  					return nil, nil, errInvalidNodeDelta
    60  				}
    61  				deltas[currentDeltaIndex] -= int(oldBalance)
    62  			}
    63  		}
    64  
    65  		// Rotate the validator vote.
    66  		vote.currentRoot = vote.nextRoot
    67  		votes[validatorIndex] = vote
    68  	}
    69  
    70  	return deltas, votes, nil
    71  }
    72  
    73  // This return a copy of the proto array node object.
    74  func copyNode(node *Node) *Node {
    75  	if node == nil {
    76  		return &Node{}
    77  	}
    78  
    79  	copiedRoot := [32]byte{}
    80  	copy(copiedRoot[:], node.root[:])
    81  
    82  	return &Node{
    83  		slot:           node.slot,
    84  		root:           copiedRoot,
    85  		parent:         node.parent,
    86  		justifiedEpoch: node.justifiedEpoch,
    87  		finalizedEpoch: node.finalizedEpoch,
    88  		weight:         node.weight,
    89  		bestChild:      node.bestChild,
    90  		bestDescendant: node.bestDescendant,
    91  	}
    92  }