import {DOMAIN_BEACON_PROPOSER} from "@lodestar/params"; import {allForks, phase0, ssz} from "@lodestar/types"; import {computeSigningRoot, ISignatureSet, SignatureSetType} from "../util/index.js"; import {CachedBeaconStateAllForks} from "../types.js"; /** * Extract signatures to allow validating all block signatures at once */ export function getProposerSlashingSignatureSets( state: CachedBeaconStateAllForks, proposerSlashing: phase0.ProposerSlashing ): ISignatureSet[] { const {epochCtx} = state; const pubkey = epochCtx.index2pubkey[proposerSlashing.signedHeader1.message.proposerIndex]; // In state transition, ProposerSlashing headers are only partially validated. Their slot could be higher than the // clock and the slashing would still be valid. Must use bigint variants to hash correctly to all possible values return [proposerSlashing.signedHeader1, proposerSlashing.signedHeader2].map( (signedHeader): ISignatureSet => { const domain = state.config.getDomain( state.slot, DOMAIN_BEACON_PROPOSER, Number(signedHeader.message.slot as bigint) ); return { type: SignatureSetType.single, pubkey, signingRoot: computeSigningRoot(ssz.phase0.BeaconBlockHeaderBigint, signedHeader.message, domain), signature: signedHeader.signature, }; } ); } export function getProposerSlashingsSignatureSets( state: CachedBeaconStateAllForks, signedBlock: allForks.SignedBeaconBlock ): ISignatureSet[] { return signedBlock.message.body.proposerSlashings .map((proposerSlashing) => getProposerSlashingSignatureSets(state, proposerSlashing)) .flat(1); }