Skip to content

Commit

Permalink
Verify SyncCommittee signatures in batch
Browse files Browse the repository at this point in the history
  • Loading branch information
twoeths committed Jun 3, 2021
1 parent 5554cd1 commit e4c6c45
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export function getAllBlockSignatureSetsExceptProposer(
if (computeEpochAtSlot(state.config, signedBlock.message.slot) >= state.config.params.ALTAIR_FORK_EPOCH) {
const syncCommitteeSignatureSet = getSyncCommitteeSignatureSet(
state as CachedBeaconState<altair.BeaconState>,
(signedBlock as altair.SignedBeaconBlock).message.body.syncAggregate
(signedBlock as altair.SignedBeaconBlock).message
);
// There may be no participants in this syncCommitteeSignature, so it must not be validated
if (syncCommitteeSignatureSet) {
Expand Down
2 changes: 1 addition & 1 deletion packages/beacon-state-transition/src/altair/block/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,5 +29,5 @@ export function processBlock(
processRandao(state as CachedBeaconState<allForks.BeaconState>, block, verifySignatures);
processEth1Data(state as CachedBeaconState<allForks.BeaconState>, block.body);
processOperations(state, block.body, verifySignatures);
processSyncCommittee(state, block.body.syncAggregate, verifySignatures);
processSyncCommittee(state, block.body.syncAggregate);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,29 +7,18 @@ import {
increaseBalance,
ISignatureSet,
SignatureSetType,
verifySignatureSet,
zipIndexesInBitList,
} from "../../util";
import {CachedBeaconState} from "../../allForks/util";
import {BitList, isTreeBacked, TreeBacked} from "@chainsafe/ssz";

export function processSyncCommittee(
state: CachedBeaconState<altair.BeaconState>,
syncAggregate: altair.SyncAggregate,
verifySignatures = true
syncAggregate: altair.SyncAggregate
): void {
const {syncParticipantReward, syncProposerReward} = state.epochCtx;
const participantIndices = getParticipantIndices(state, syncAggregate);

// different from the spec but not sure how to get through signature verification for default/empty SyncAggregate in the spec test
if (verifySignatures) {
const signatureSet = getSyncCommitteeSignatureSet(state, syncAggregate, participantIndices);
// When there's no participation we consider the signature valid and just ignore i
if (signatureSet !== null && !verifySignatureSet(signatureSet)) {
throw Error("Sync committee signature invalid");
}
}

const proposerIndex = state.epochCtx.getBeaconProposer(state.slot);
for (const participantIndex of participantIndices) {
increaseBalance(state, participantIndex, syncParticipantReward);
Expand All @@ -39,13 +28,14 @@ export function processSyncCommittee(

export function getSyncCommitteeSignatureSet(
state: CachedBeaconState<altair.BeaconState>,
syncAggregate: altair.SyncAggregate,
block: altair.BeaconBlock,
/** Optional parameter to prevent computing it twice */
participantIndices?: number[]
): ISignatureSet | null {
const {config, epochCtx} = state;
const {syncAggregate} = block.body;

const previousSlot = Math.max(state.slot, 1) - 1;
const previousSlot = Math.max(block.slot, 1) - 1;
const rootSigned = getBlockRootAtSlot(config, state, previousSlot);

if (!participantIndices) {
Expand Down
31 changes: 14 additions & 17 deletions packages/lodestar/src/chain/blocks/process.ts
Original file line number Diff line number Diff line change
Expand Up @@ -119,10 +119,20 @@ export async function processChainSegment(
}

try {
// It's important to process up to block slot to get through signature verification at fork transition
let preState = await regen.getBlockSlotState(firstBlock.message.parentRoot, firstBlock.message.slot);

// Verify the signature of the blocks, returning early if the signature is invalid.
let preState = await regen.getPreState(firstBlock.message);
for (const block of blocksInEpoch) {
preState = await runStateTransition({emitter, forkChoice, metrics}, checkpointStateCache, preState, {
reprocess: job.reprocess,
prefinalized: job.prefinalized,
signedBlock: block,
validProposerSignature: true,
validSignatures: true,
});
importedBlocks++;
// this avoids keeping our node busy processing blocks
await sleep(0);
}
// Verify the signature afterall bc all SyncCommittee signed roots are only known at this point
if (!job.validSignatures && !opts?.disableBlsBatchVerify) {
const signatureSets: ISignatureSet[] = [];
for (const block of blocksInEpoch) {
Expand All @@ -141,19 +151,6 @@ export async function processChainSegment(
});
}
}

for (const block of blocksInEpoch) {
preState = await runStateTransition({emitter, forkChoice, metrics}, checkpointStateCache, preState, {
reprocess: job.reprocess,
prefinalized: job.prefinalized,
signedBlock: block,
validProposerSignature: true,
validSignatures: true,
});
importedBlocks++;
// this avoids keeping our node busy processing blocks
await sleep(0);
}
} catch (e) {
if (e instanceof RegenError) {
throw new ChainSegmentError({
Expand Down

0 comments on commit e4c6c45

Please sign in to comment.