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(ðpb.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(ðpb.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 }