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 }