diff --git a/src/consensus/helpers/justification_finalization.zig b/src/consensus/helpers/justification_finalization.zig new file mode 100644 index 0000000..dca8a72 --- /dev/null +++ b/src/consensus/helpers/justification_finalization.zig @@ -0,0 +1,75 @@ +const std = @import("std"); +const primitives = @import("../../primitives/types.zig"); +const consensus = @import("../../consensus/types.zig"); +const configs = @import("../../configs/config.zig"); +const constants = @import("../../primitives/constants.zig"); +const preset = @import("../../presets/preset.zig"); +const phase0 = @import("../../consensus/phase0/types.zig"); +const altair = @import("../../consensus/altair/types.zig"); +const electra = @import("../../consensus/electra/types.zig"); +const epoch_helper = @import("../../consensus/helpers/epoch.zig"); +const shuffle_helper = @import("../../consensus/helpers/shuffle.zig"); +const balance_helper = @import("../../consensus/helpers/balance.zig"); +const committee_helper = @import("../../consensus/helpers/committee.zig"); + +// pub fn weighJustificationAndFinalization( +// state: *consensus.BeaconState, +// total_active_balance: primitives.Gwei, +// previous_epoch_target_balance: primitives.Gwei, +// current_epoch_target_balance: primitives.Gwei, +// ) void { +// const previous_epoch = epoch_helper.getPreviousEpoch(state); +// const current_epoch = epoch_helper.getCurrentEpoch(state); +// const old_previous_justified_checkpoint = state.p; +// const old_current_justified_checkpoint = state.current_justified_checkpoint; +// +// // Process justifications +// state.previous_justified_checkpoint = state.current_justified_checkpoint; +// +// // Shift justification bits +// var i: usize = constants.JUSTIFICATION_BITS_LENGTH - 1; +// while (i > 0) : (i -= 1) { +// state.justification_bits[i] = state.justification_bits[i - 1]; +// } +// state.justification_bits[0] = 0; +// +// if (previous_epoch_target_balance * 3 >= total_active_balance * 2) { +// state.current_justified_checkpoint = consensus.Checkpoint{ +// .epoch = previous_epoch, +// .root = getBlockRoot(state, previous_epoch), +// }; +// state.justification_bits[1] = 1; +// } +// +// if (current_epoch_target_balance * 3 >= total_active_balance * 2) { +// state.current_justified_checkpoint = Checkpoint{ +// .epoch = current_epoch, +// .root = getBlockRoot(state, current_epoch), +// }; +// state.justification_bits[0] = 1; +// } +// +// // Process finalizations +// const bits = state.justification_bits; +// +// // The 2nd/3rd/4th most recent epochs are justified, the 2nd using the 4th as source +// if (allBitsSet(bits[1..4]) and old_previous_justified_checkpoint.epoch + 3 == current_epoch) { +// state.finalized_checkpoint = old_previous_justified_checkpoint; +// } +// // The 2nd/3rd most recent epochs are justified, the 2nd using the 3rd as source +// if (allBitsSet(bits[1..3]) and old_previous_justified_checkpoint.epoch + 2 == current_epoch) { +// state.finalized_checkpoint = old_previous_justified_checkpoint; +// } +// // The 1st/2nd/3rd most recent epochs are justified, the 1st using the 3rd as source +// if (allBitsSet(bits[0..3]) and old_current_justified_checkpoint.epoch + 2 == current_epoch) { +// state.finalized_checkpoint = old_current_justified_checkpoint; +// } +// // The 1st/2nd most recent epochs are justified, the 1st using the 2nd as source +// if (allBitsSet(bits[0..2]) and old_current_justified_checkpoint.epoch + 1 == current_epoch) { +// state.finalized_checkpoint = old_current_justified_checkpoint; +// } +// } + +fn allBitsSet(bits: []const bool) bool { + return !std.mem.containsAtLeast(bool, bits, 1, false); +} diff --git a/src/consensus/helpers/validator.zig b/src/consensus/helpers/validator.zig index a00dc22..c8171e8 100644 --- a/src/consensus/helpers/validator.zig +++ b/src/consensus/helpers/validator.zig @@ -497,6 +497,48 @@ pub fn getPendingBalanceToWithdraw(state: *const consensus.BeaconState, validato return total; } +pub fn getUnslashedParticipatingIndices( + state: *const consensus.BeaconState, + flagIndex: u3, + epoch: primitives.Epoch, + allocator: std.mem.Allocator, +) ![]primitives.ValidatorIndex { + var result = std.AutoHashMap(primitives.ValidatorIndex, void).init(allocator); + defer result.deinit(); + + const currentEpoch = epoch_helper.getCurrentEpoch(state); + const previousEpoch = epoch_helper.getPreviousEpoch(state); + + if (epoch != previousEpoch and epoch != currentEpoch) { + return error.InvalidEpoch; + } + + const epochParticipation = if (epoch == currentEpoch) + state.currentEpochParticipation() + else + state.previousEpochParticipation(); + + const activeValidatorIndices = try getActiveValidatorIndices(state, epoch, allocator); + defer allocator.free(activeValidatorIndices); + + for (activeValidatorIndices) |index| { + if (primitives.hasFlag(epochParticipation[index], flagIndex) and + !state.validators()[index].slashed) + { + try result.put(index, {}); + } + } + + const result_slice = try allocator.alloc(primitives.ValidatorIndex, result.count()); + var i: usize = 0; + var iterator = result.keyIterator(); + while (iterator.next()) |key| { + result_slice[i] = key.*; + i += 1; + } + return result_slice; +} + test "test getBalanceChurnLimit" { preset.ActivePreset.set(preset.Presets.minimal); defer preset.ActivePreset.reset(); diff --git a/src/primitives/types.zig b/src/primitives/types.zig index 78dcdb1..7434765 100644 --- a/src/primitives/types.zig +++ b/src/primitives/types.zig @@ -125,6 +125,12 @@ pub fn setOrAppendList(comptime T: type, list: []T, index: ValidatorIndex, value } } +pub fn hasFlag(flags: ParticipationFlags, flagIndex: u3) bool { + const flag = @as(ParticipationFlags, @intCast(@as(u8, 1) << flagIndex)); + return (flags & flag) == flag; +} + + test "test ExecutionBranch length" { const ExecutionBranchLength = @typeInfo(ExecutionBranch).array.len; try std.testing.expectEqual(4, ExecutionBranchLength); diff --git a/src/root.zig b/src/root.zig index 317f0e8..3290724 100644 --- a/src/root.zig +++ b/src/root.zig @@ -29,6 +29,7 @@ pub const bls_helper = @import("consensus/helpers/bls.zig"); pub const bls = @import("./bls/bls.zig"); pub const deposit_helper = @import("consensus/helpers/deposit.zig"); pub const voluntary_exit_helper = @import("consensus/helpers/voluntary_exit.zig"); +pub const justification_finalization_helper = @import("consensus/helpers/justification_finalization.zig"); test { @import("std").testing.refAllDeclsRecursive(@This());