import {TIMELY_HEAD_FLAG_INDEX, TIMELY_SOURCE_FLAG_INDEX, TIMELY_TARGET_FLAG_INDEX} from "@lodestar/params"; // We pack both previous and current epoch attester flags // as well as slashed and eligibility flags into a single number // to save space in our epoch transition cache. // Note: the order of the flags is important for efficiently translating // from the BeaconState flags to our flags. // [prevSource, prevTarget, prevHead, currSource, currTarget, currHead, unslashed, eligible] export const FLAG_PREV_SOURCE_ATTESTER = 1 << TIMELY_SOURCE_FLAG_INDEX; export const FLAG_PREV_TARGET_ATTESTER = 1 << TIMELY_TARGET_FLAG_INDEX; export const FLAG_PREV_HEAD_ATTESTER = 1 << TIMELY_HEAD_FLAG_INDEX; export const FLAG_CURR_SOURCE_ATTESTER = 1 << (3 + TIMELY_SOURCE_FLAG_INDEX); export const FLAG_CURR_TARGET_ATTESTER = 1 << (3 + TIMELY_TARGET_FLAG_INDEX); export const FLAG_CURR_HEAD_ATTESTER = 1 << (3 + TIMELY_HEAD_FLAG_INDEX); export const FLAG_UNSLASHED = 1 << 6; export const FLAG_ELIGIBLE_ATTESTER = 1 << 7; // Precompute OR flags used in epoch processing export const FLAG_PREV_SOURCE_ATTESTER_UNSLASHED = FLAG_PREV_SOURCE_ATTESTER | FLAG_UNSLASHED; export const FLAG_PREV_TARGET_ATTESTER_UNSLASHED = FLAG_PREV_TARGET_ATTESTER | FLAG_UNSLASHED; export const FLAG_PREV_HEAD_ATTESTER_UNSLASHED = FLAG_PREV_HEAD_ATTESTER | FLAG_UNSLASHED; export function hasMarkers(flags: number, markers: number): boolean { return (flags & markers) === markers; } export type AttesterFlags = { prevSourceAttester: boolean; prevTargetAttester: boolean; prevHeadAttester: boolean; currSourceAttester: boolean; currTargetAttester: boolean; currHeadAttester: boolean; unslashed: boolean; eligibleAttester: boolean; }; export function parseAttesterFlags(flags: number): AttesterFlags { return { prevSourceAttester: hasMarkers(flags, FLAG_PREV_SOURCE_ATTESTER), prevTargetAttester: hasMarkers(flags, FLAG_PREV_TARGET_ATTESTER), prevHeadAttester: hasMarkers(flags, FLAG_PREV_HEAD_ATTESTER), currSourceAttester: hasMarkers(flags, FLAG_CURR_SOURCE_ATTESTER), currTargetAttester: hasMarkers(flags, FLAG_CURR_TARGET_ATTESTER), currHeadAttester: hasMarkers(flags, FLAG_CURR_HEAD_ATTESTER), unslashed: hasMarkers(flags, FLAG_UNSLASHED), eligibleAttester: hasMarkers(flags, FLAG_ELIGIBLE_ATTESTER), }; } export function toAttesterFlags(flagsObj: AttesterFlags): number { let flag = 0; if (flagsObj.prevSourceAttester) flag |= FLAG_PREV_SOURCE_ATTESTER; if (flagsObj.prevTargetAttester) flag |= FLAG_PREV_TARGET_ATTESTER; if (flagsObj.prevHeadAttester) flag |= FLAG_PREV_HEAD_ATTESTER; if (flagsObj.currSourceAttester) flag |= FLAG_CURR_SOURCE_ATTESTER; if (flagsObj.currTargetAttester) flag |= FLAG_CURR_TARGET_ATTESTER; if (flagsObj.currHeadAttester) flag |= FLAG_CURR_HEAD_ATTESTER; if (flagsObj.unslashed) flag |= FLAG_UNSLASHED; if (flagsObj.eligibleAttester) flag |= FLAG_ELIGIBLE_ATTESTER; return flag; } /** Same to https://github.com/ethereum/eth2.0-specs/blob/v1.1.0-alpha.5/specs/altair/beacon-chain.md#has_flag */ const TIMELY_SOURCE = 1 << TIMELY_SOURCE_FLAG_INDEX; const TIMELY_TARGET = 1 << TIMELY_TARGET_FLAG_INDEX; const TIMELY_HEAD = 1 << TIMELY_HEAD_FLAG_INDEX; export type ParticipationFlags = { timelySource: boolean; timelyTarget: boolean; timelyHead: boolean; }; export function parseParticipationFlags(flags: number): ParticipationFlags { return { timelySource: hasMarkers(flags, TIMELY_SOURCE), timelyTarget: hasMarkers(flags, TIMELY_TARGET), timelyHead: hasMarkers(flags, TIMELY_HEAD), }; }