github.com/prysmaticlabs/prysm@v1.4.4/beacon-chain/core/epoch/precompute/justification_finalization.go (about)

     1  package precompute
     2  
     3  import (
     4  	"github.com/pkg/errors"
     5  	"github.com/prysmaticlabs/prysm/beacon-chain/core/helpers"
     6  	iface "github.com/prysmaticlabs/prysm/beacon-chain/state/interface"
     7  	ethpb "github.com/prysmaticlabs/prysm/proto/eth/v1alpha1"
     8  )
     9  
    10  // ProcessJustificationAndFinalizationPreCompute processes justification and finalization during
    11  // epoch processing. This is where a beacon node can justify and finalize a new epoch.
    12  // Note: this is an optimized version by passing in precomputed total and attesting balances.
    13  //
    14  // Spec pseudocode definition:
    15  //  def process_justification_and_finalization(state: BeaconState) -> None:
    16  //    # Initial FFG checkpoint values have a `0x00` stub for `root`.
    17  //    # Skip FFG updates in the first two epochs to avoid corner cases that might result in modifying this stub.
    18  //    if get_current_epoch(state) <= GENESIS_EPOCH + 1:
    19  //        return
    20  //    previous_attestations = get_matching_target_attestations(state, get_previous_epoch(state))
    21  //    current_attestations = get_matching_target_attestations(state, get_current_epoch(state))
    22  //    total_active_balance = get_total_active_balance(state)
    23  //    previous_target_balance = get_attesting_balance(state, previous_attestations)
    24  //    current_target_balance = get_attesting_balance(state, current_attestations)
    25  //    weigh_justification_and_finalization(state, total_active_balance, previous_target_balance, current_target_balance)
    26  func ProcessJustificationAndFinalizationPreCompute(state iface.BeaconState, pBal *Balance) (iface.BeaconState, error) {
    27  	canProcessSlot, err := helpers.StartSlot(2 /*epoch*/)
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  	if state.Slot() <= canProcessSlot {
    32  		return state, nil
    33  	}
    34  
    35  	return weighJustificationAndFinalization(state, pBal.ActiveCurrentEpoch, pBal.PrevEpochTargetAttested, pBal.CurrentEpochTargetAttested)
    36  }
    37  
    38  // weighJustificationAndFinalization processes justification and finalization during
    39  // epoch processing. This is where a beacon node can justify and finalize a new epoch.
    40  //
    41  // Spec pseudocode definition:
    42  // def weigh_justification_and_finalization(state: BeaconState,
    43  //                                         total_active_balance: Gwei,
    44  //                                         previous_epoch_target_balance: Gwei,
    45  //                                         current_epoch_target_balance: Gwei) -> None:
    46  //    previous_epoch = get_previous_epoch(state)
    47  //    current_epoch = get_current_epoch(state)
    48  //    old_previous_justified_checkpoint = state.previous_justified_checkpoint
    49  //    old_current_justified_checkpoint = state.current_justified_checkpoint
    50  //
    51  //    # Process justifications
    52  //    state.previous_justified_checkpoint = state.current_justified_checkpoint
    53  //    state.justification_bits[1:] = state.justification_bits[:JUSTIFICATION_BITS_LENGTH - 1]
    54  //    state.justification_bits[0] = 0b0
    55  //    if previous_epoch_target_balance * 3 >= total_active_balance * 2:
    56  //        state.current_justified_checkpoint = Checkpoint(epoch=previous_epoch,
    57  //                                                        root=get_block_root(state, previous_epoch))
    58  //        state.justification_bits[1] = 0b1
    59  //    if current_epoch_target_balance * 3 >= total_active_balance * 2:
    60  //        state.current_justified_checkpoint = Checkpoint(epoch=current_epoch,
    61  //                                                        root=get_block_root(state, current_epoch))
    62  //        state.justification_bits[0] = 0b1
    63  //
    64  //    # Process finalizations
    65  //    bits = state.justification_bits
    66  //    # The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source
    67  //    if all(bits[1:4]) and old_previous_justified_checkpoint.epoch + 3 == current_epoch:
    68  //        state.finalized_checkpoint = old_previous_justified_checkpoint
    69  //    # The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as source
    70  //    if all(bits[1:3]) and old_previous_justified_checkpoint.epoch + 2 == current_epoch:
    71  //        state.finalized_checkpoint = old_previous_justified_checkpoint
    72  //    # The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as source
    73  //    if all(bits[0:3]) and old_current_justified_checkpoint.epoch + 2 == current_epoch:
    74  //        state.finalized_checkpoint = old_current_justified_checkpoint
    75  //    # The 1st/2nd most recent epochs are justified, the 1st using the 2nd as source
    76  //    if all(bits[0:2]) and old_current_justified_checkpoint.epoch + 1 == current_epoch:
    77  //        state.finalized_checkpoint = old_current_justified_checkpoint
    78  func weighJustificationAndFinalization(state iface.BeaconState,
    79  	totalActiveBalance, prevEpochTargetBalance, currEpochTargetBalance uint64) (iface.BeaconState, error) {
    80  	prevEpoch := helpers.PrevEpoch(state)
    81  	currentEpoch := helpers.CurrentEpoch(state)
    82  	oldPrevJustifiedCheckpoint := state.PreviousJustifiedCheckpoint()
    83  	oldCurrJustifiedCheckpoint := state.CurrentJustifiedCheckpoint()
    84  
    85  	// Process justifications
    86  	if err := state.SetPreviousJustifiedCheckpoint(state.CurrentJustifiedCheckpoint()); err != nil {
    87  		return nil, err
    88  	}
    89  	newBits := state.JustificationBits()
    90  	newBits.Shift(1)
    91  	if err := state.SetJustificationBits(newBits); err != nil {
    92  		return nil, err
    93  	}
    94  
    95  	// Note: the spec refers to the bit index position starting at 1 instead of starting at zero.
    96  	// We will use that paradigm here for consistency with the godoc spec definition.
    97  
    98  	// If 2/3 or more of total balance attested in the previous epoch.
    99  	if 3*prevEpochTargetBalance >= 2*totalActiveBalance {
   100  		blockRoot, err := helpers.BlockRoot(state, prevEpoch)
   101  		if err != nil {
   102  			return nil, errors.Wrapf(err, "could not get block root for previous epoch %d", prevEpoch)
   103  		}
   104  		if err := state.SetCurrentJustifiedCheckpoint(&ethpb.Checkpoint{Epoch: prevEpoch, Root: blockRoot}); err != nil {
   105  			return nil, err
   106  		}
   107  		newBits := state.JustificationBits()
   108  		newBits.SetBitAt(1, true)
   109  		if err := state.SetJustificationBits(newBits); err != nil {
   110  			return nil, err
   111  		}
   112  	}
   113  
   114  	// If 2/3 or more of the total balance attested in the current epoch.
   115  	if 3*currEpochTargetBalance >= 2*totalActiveBalance {
   116  		blockRoot, err := helpers.BlockRoot(state, currentEpoch)
   117  		if err != nil {
   118  			return nil, errors.Wrapf(err, "could not get block root for current epoch %d", prevEpoch)
   119  		}
   120  		if err := state.SetCurrentJustifiedCheckpoint(&ethpb.Checkpoint{Epoch: currentEpoch, Root: blockRoot}); err != nil {
   121  			return nil, err
   122  		}
   123  		newBits := state.JustificationBits()
   124  		newBits.SetBitAt(0, true)
   125  		if err := state.SetJustificationBits(newBits); err != nil {
   126  			return nil, err
   127  		}
   128  	}
   129  
   130  	// Process finalization according to Ethereum Beacon Chain specification.
   131  	justification := state.JustificationBits().Bytes()[0]
   132  
   133  	// 2nd/3rd/4th (0b1110) most recent epochs are justified, the 2nd using the 4th as source.
   134  	if justification&0x0E == 0x0E && (oldPrevJustifiedCheckpoint.Epoch+3) == currentEpoch {
   135  		if err := state.SetFinalizedCheckpoint(oldPrevJustifiedCheckpoint); err != nil {
   136  			return nil, err
   137  		}
   138  	}
   139  
   140  	// 2nd/3rd (0b0110) most recent epochs are justified, the 2nd using the 3rd as source.
   141  	if justification&0x06 == 0x06 && (oldPrevJustifiedCheckpoint.Epoch+2) == currentEpoch {
   142  		if err := state.SetFinalizedCheckpoint(oldPrevJustifiedCheckpoint); err != nil {
   143  			return nil, err
   144  		}
   145  	}
   146  
   147  	// 1st/2nd/3rd (0b0111) most recent epochs are justified, the 1st using the 3rd as source.
   148  	if justification&0x07 == 0x07 && (oldCurrJustifiedCheckpoint.Epoch+2) == currentEpoch {
   149  		if err := state.SetFinalizedCheckpoint(oldCurrJustifiedCheckpoint); err != nil {
   150  			return nil, err
   151  		}
   152  	}
   153  
   154  	// The 1st/2nd (0b0011) most recent epochs are justified, the 1st using the 2nd as source
   155  	if justification&0x03 == 0x03 && (oldCurrJustifiedCheckpoint.Epoch+1) == currentEpoch {
   156  		if err := state.SetFinalizedCheckpoint(oldCurrJustifiedCheckpoint); err != nil {
   157  			return nil, err
   158  		}
   159  	}
   160  
   161  	return state, nil
   162  }