2020-01-22 20:19:52 +00:00
|
|
|
package protoarray
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
|
|
|
|
"github.com/prysmaticlabs/prysm/shared/params"
|
|
|
|
"go.opencensus.io/trace"
|
|
|
|
)
|
|
|
|
|
|
|
|
// This computes validator balance delta from validator votes.
|
|
|
|
// It returns a list of deltas that represents the difference between old balances and new balances.
|
|
|
|
func computeDeltas(
|
|
|
|
ctx context.Context,
|
|
|
|
blockIndices map[[32]byte]uint64,
|
|
|
|
votes []Vote,
|
2020-10-12 15:43:19 +00:00
|
|
|
oldBalances, newBalances []uint64,
|
2020-01-22 20:19:52 +00:00
|
|
|
) ([]int, []Vote, error) {
|
|
|
|
ctx, span := trace.StartSpan(ctx, "protoArrayForkChoice.computeDeltas")
|
|
|
|
defer span.End()
|
|
|
|
|
|
|
|
deltas := make([]int, len(blockIndices))
|
|
|
|
|
|
|
|
for validatorIndex, vote := range votes {
|
|
|
|
oldBalance := uint64(0)
|
|
|
|
newBalance := uint64(0)
|
|
|
|
|
|
|
|
// Skip if validator has never voted for current root and next root (ie. if the
|
|
|
|
// votes are zero hash aka genesis block), there's nothing to compute.
|
|
|
|
if vote.currentRoot == params.BeaconConfig().ZeroHash && vote.nextRoot == params.BeaconConfig().ZeroHash {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
// If the validator index did not exist in `oldBalance` or `newBalance` list above, the balance is just 0.
|
|
|
|
if validatorIndex < len(oldBalances) {
|
|
|
|
oldBalance = oldBalances[validatorIndex]
|
|
|
|
}
|
|
|
|
if validatorIndex < len(newBalances) {
|
|
|
|
newBalance = newBalances[validatorIndex]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Perform delta only if the validator's balance or vote has changed.
|
|
|
|
if vote.currentRoot != vote.nextRoot || oldBalance != newBalance {
|
|
|
|
// Ignore the vote if it's not known in `blockIndices`,
|
|
|
|
// that means we have not seen the block before.
|
|
|
|
nextDeltaIndex, ok := blockIndices[vote.nextRoot]
|
|
|
|
if ok {
|
2020-01-23 16:33:39 +00:00
|
|
|
// Protection against out of bound, the `nextDeltaIndex` which defines
|
2020-01-22 20:19:52 +00:00
|
|
|
// the block location in the dag can not exceed the total `delta` length.
|
|
|
|
if int(nextDeltaIndex) >= len(deltas) {
|
|
|
|
return nil, nil, errInvalidNodeDelta
|
|
|
|
}
|
|
|
|
deltas[nextDeltaIndex] += int(newBalance)
|
|
|
|
}
|
|
|
|
|
|
|
|
currentDeltaIndex, ok := blockIndices[vote.currentRoot]
|
|
|
|
if ok {
|
2020-01-23 16:33:39 +00:00
|
|
|
// Protection against out of bound (same as above)
|
2020-01-22 20:19:52 +00:00
|
|
|
if int(currentDeltaIndex) >= len(deltas) {
|
|
|
|
return nil, nil, errInvalidNodeDelta
|
|
|
|
}
|
|
|
|
deltas[currentDeltaIndex] -= int(oldBalance)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Rotate the validator vote.
|
|
|
|
vote.currentRoot = vote.nextRoot
|
|
|
|
votes[validatorIndex] = vote
|
|
|
|
}
|
|
|
|
|
|
|
|
return deltas, votes, nil
|
|
|
|
}
|
2020-02-10 19:09:12 +00:00
|
|
|
|
|
|
|
// This return a copy of the proto array node object.
|
|
|
|
func copyNode(node *Node) *Node {
|
|
|
|
if node == nil {
|
|
|
|
return &Node{}
|
|
|
|
}
|
|
|
|
|
|
|
|
copiedRoot := [32]byte{}
|
2020-08-08 01:37:08 +00:00
|
|
|
copy(copiedRoot[:], node.root[:])
|
2020-02-10 19:09:12 +00:00
|
|
|
|
|
|
|
return &Node{
|
2020-08-08 01:37:08 +00:00
|
|
|
slot: node.slot,
|
|
|
|
root: copiedRoot,
|
|
|
|
parent: node.parent,
|
|
|
|
justifiedEpoch: node.justifiedEpoch,
|
|
|
|
finalizedEpoch: node.finalizedEpoch,
|
|
|
|
weight: node.weight,
|
|
|
|
bestChild: node.bestChild,
|
|
|
|
bestDescendant: node.bestDescendant,
|
2020-02-10 19:09:12 +00:00
|
|
|
}
|
|
|
|
}
|