Skip to content

Commit 7d7bd3b

Browse files
authored
signatures: reduce fork code bloat (#7711)
`withState` causes unnecessary template compared to `forky` - also, `items` is ok to use post 1.4.2
1 parent 1c56d95 commit 7d7bd3b

File tree

1 file changed

+114
-122
lines changed

1 file changed

+114
-122
lines changed

beacon_chain/spec/signatures_batch.nim

Lines changed: 114 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ func aggregateAttesters(
120120
if inited:
121121
attestersAgg.aggregate(key)
122122
else:
123-
attestersAgg = AggregatePublicKey.init(key)
123+
attestersAgg.init(key)
124124
inited = true
125125

126126
if not inited:
@@ -287,135 +287,132 @@ proc collectSignatureSets*(
287287
# ----------------------------------------------------
288288
mixin load
289289

290+
const consensusFork = ForkySignedBeaconBlock.kind
291+
template forkyState(): untyped =
292+
state.forky(consensusFork)
293+
290294
let
291-
fork = getStateField(state, fork)
292-
genesis_validators_root = getStateField(state, genesis_validators_root)
295+
fork = forkyState.data.fork
296+
genesis_validators_root = forkyState.data.genesis_validators_root
293297
proposer_index = signed_block.message.proposer_index
294298
proposer_key = validatorKeys.load(proposer_index).valueOr:
295299
return err("collectSignatureSets: invalid proposer index")
296-
epoch = signed_block.message.slot.epoch()
297300

298301

299302
# 1. Block proposer
300303
# ----------------------------------------------------
301-
sigs.add block_signature_set(
302-
fork, genesis_validators_root,
303-
signed_block.message.slot, signed_block.root,
304-
proposer_key, signed_block.signature.load.valueOr do:
305-
return err("collectSignatureSets: cannot load signature"))
304+
block:
305+
let sig = signed_block.signature.load.valueOr:
306+
return err("collectSignatureSets: cannot load signature")
307+
308+
sigs.add block_signature_set(
309+
fork, genesis_validators_root, signed_block.message.slot, signed_block.root,
310+
proposer_key, sig,
311+
)
306312

307313
# 2. Randao Reveal
308314
# ----------------------------------------------------
309-
sigs.add epoch_signature_set(
310-
fork, genesis_validators_root, epoch, proposer_key,
311-
signed_block.message.body.randao_reveal.load().valueOr do:
312-
return err("collectSignatureSets: cannot load randao"))
315+
block:
316+
let
317+
epoch = signed_block.message.slot.epoch()
318+
sig = signed_block.message.body.randao_reveal.load().valueOr:
319+
return err("collectSignatureSets: cannot load randao")
320+
sigs.add epoch_signature_set(
321+
fork, genesis_validators_root, epoch, proposer_key, sig
322+
)
313323

314324
# 3. Proposer slashings
315325
# ----------------------------------------------------
316326
# Denial-of-service:
317327
# SSZ deserialization guarantees that blocks received from random sources
318328
# including peer or RPC
319329
# have at most MAX_PROPOSER_SLASHINGS proposer slashings.
320-
for i in 0 ..< signed_block.message.body.proposer_slashings.len:
321-
# don't use "items" for iterating over large type
322-
# due to https://github.com/nim-lang/Nim/issues/14421
323-
# fixed in 1.4.2
324-
325-
# Alias
326-
template slashing: untyped = signed_block.message.body.proposer_slashings[i]
327-
330+
for slashing in signed_block.message.body.proposer_slashings:
328331
# Proposed block 1
329332
block:
330333
let
331334
header = slashing.signed_header_1
332335
key = validatorKeys.load(header.message.proposer_index).valueOr:
333336
return err("collectSignatureSets: invalid slashing proposer index 1")
337+
sig = header.signature.load().valueOr:
338+
return err("collectSignatureSets: cannot load proposer slashing 1 signature")
334339

335340
sigs.add block_signature_set(
336-
fork, genesis_validators_root, header.message.slot, header.message,
337-
key, header.signature.load().valueOr do:
338-
return err(
339-
"collectSignatureSets: cannot load proposer slashing 1 signature"))
341+
fork, genesis_validators_root, header.message.slot, header.message, key, sig
342+
)
340343

341344
# Conflicting block 2
342345
block:
343346
let
344347
header = slashing.signed_header_2
345348
key = validatorKeys.load(header.message.proposer_index).valueOr:
346349
return err("collectSignatureSets: invalid slashing proposer index 2")
350+
sig = header.signature.load().valueOr:
351+
return err("collectSignatureSets: cannot load proposer slashing 2 signature")
347352

348353
sigs.add block_signature_set(
349-
fork, genesis_validators_root, header.message.slot, header.message,
350-
key, header.signature.load().valueOr do:
351-
return err(
352-
"collectSignatureSets: cannot load proposer slashing 2 signature"))
354+
fork, genesis_validators_root, header.message.slot, header.message, key, sig
355+
)
353356

354357
# 4. Attester slashings
355358
# ----------------------------------------------------
356359
# Denial-of-service:
357360
# SSZ deserialization guarantees that blocks received from random sources
358361
# including peer or RPC
359362
# have at most MAX_ATTESTER_SLASHINGS attester slashings.
360-
for i in 0 ..< signed_block.message.body.attester_slashings.len:
361-
# don't use "items" for iterating over large type
362-
# due to https://github.com/nim-lang/Nim/issues/14421
363-
# fixed in 1.4.2
364-
365-
# Alias
366-
template slashing: untyped = signed_block.message.body.attester_slashings[i]
367-
363+
for slashing in signed_block.message.body.attester_slashings:
368364
# Attestation 1
369365
block:
370366
let
371-
key = ? aggregateAttesters(
372-
slashing.attestation_1.attesting_indices.asSeq(), validatorKeys)
367+
key =
368+
?aggregateAttesters(
369+
slashing.attestation_1.attesting_indices.asSeq(), validatorKeys
370+
)
373371
sig = slashing.attestation_1.signature.load().valueOr:
374372
return err("Invalid attestation slashing signature 1")
375373
sigs.add attestation_signature_set(
376-
fork, genesis_validators_root, slashing.attestation_1.data, key, sig)
374+
fork, genesis_validators_root, slashing.attestation_1.data, key, sig
375+
)
377376

378377
# Conflicting attestation 2
379378
block:
380379
let
381-
key = ? aggregateAttesters(
382-
slashing.attestation_2.attesting_indices.asSeq(), validatorKeys)
380+
key =
381+
?aggregateAttesters(
382+
slashing.attestation_2.attesting_indices.asSeq(), validatorKeys
383+
)
383384
sig = slashing.attestation_2.signature.load().valueOr:
384385
return err("Invalid attestation slashing signature 2")
385386
sigs.add attestation_signature_set(
386-
fork, genesis_validators_root, slashing.attestation_2.data, key, sig)
387+
fork, genesis_validators_root, slashing.attestation_2.data, key, sig
388+
)
387389

388390
# 5. Attestations
389391
# ----------------------------------------------------
390392
# Denial-of-service:
391393
# SSZ deserialization guarantees that blocks received from random sources
392394
# including peer or RPC
393395
# have at most MAX_ATTESTATIONS attestations.
394-
for i in 0 ..< signed_block.message.body.attestations.len:
395-
# don't use "items" for iterating over large type
396-
# due to https://github.com/nim-lang/Nim/issues/14421
397-
# fixed in 1.4.2
398-
template attestation: untyped = signed_block.message.body.attestations[i]
399-
400-
when typeof(signed_block).kind < ConsensusFork.Electra:
401-
let
402-
key = ? aggregateAttesters(
396+
for attestation in signed_block.message.body.attestations:
397+
let
398+
attesting_indices =
399+
when consensusFork < ConsensusFork.Electra:
403400
get_attesting_indices(
404-
state, attestation.data, attestation.aggregation_bits, cache),
405-
validatorKeys)
406-
else:
407-
let
408-
key = ? aggregateAttesters(
401+
forkyState.data, attestation.data, attestation.aggregation_bits, cache
402+
)
403+
else:
409404
get_attesting_indices(
410-
state, attestation.data, attestation.aggregation_bits,
411-
attestation.committee_bits, cache),
412-
validatorKeys)
413-
let
405+
forkyState.data, attestation.data, attestation.aggregation_bits,
406+
attestation.committee_bits, cache,
407+
)
408+
409+
key = ?aggregateAttesters(attesting_indices, validatorKeys)
414410
sig = attestation.signature.load().valueOr:
415411
return err("Invalid attestation signature")
416412

417413
sigs.add attestation_signature_set(
418-
fork, genesis_validators_root, attestation.data, key, sig)
414+
fork, genesis_validators_root, attestation.data, key, sig
415+
)
419416

420417
# 6. VoluntaryExits
421418
# ----------------------------------------------------
@@ -424,72 +421,67 @@ proc collectSignatureSets*(
424421
# including peer or RPC
425422
# have at most MAX_VOLUNTARY_EXITS voluntary exits.
426423
if signed_block.message.body.voluntary_exits.len > 0:
427-
let voluntary_exit_fork = withConsensusFork(state.kind):
424+
# https://eips.ethereum.org/EIPS/eip-7044
425+
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#modified-process_voluntary_exit
426+
let voluntary_exit_fork =
428427
consensusFork.voluntary_exit_signature_fork(fork, capella_fork_version)
429-
for i in 0 ..< signed_block.message.body.voluntary_exits.len:
430-
# don't use "items" for iterating over large type
431-
# due to https://github.com/nim-lang/Nim/issues/14421
432-
# fixed in 1.4.2
433-
template volex: untyped = signed_block.message.body.voluntary_exits[i]
434-
let key = validatorKeys.load(volex.message.validator_index).valueOr:
435-
return err("collectSignatureSets: invalid voluntary exit")
428+
for volex in signed_block.message.body.voluntary_exits:
429+
let
430+
key = validatorKeys.load(volex.message.validator_index).valueOr:
431+
return err("collectSignatureSets: invalid voluntary exit")
432+
sig = volex.signature.load.valueOr:
433+
return err("collectSignatureSets: cannot load voluntary exit signature")
436434

437435
sigs.add voluntary_exit_signature_set(
438-
# https://eips.ethereum.org/EIPS/eip-7044
439-
# https://github.com/ethereum/consensus-specs/blob/v1.4.0/specs/deneb/beacon-chain.md#modified-process_voluntary_exit
440-
voluntary_exit_fork, genesis_validators_root, volex.message, key,
441-
volex.signature.load.valueOr do:
442-
return err(
443-
"collectSignatureSets: cannot load voluntary exit signature"))
436+
voluntary_exit_fork, genesis_validators_root, volex.message, key, sig
437+
)
444438

445-
block:
446-
when signed_block is phase0.SignedBeaconBlock:
447-
discard
439+
# 7. SyncAggregate
440+
# ----------------------------------------------------
441+
when consensusFork >= ConsensusFork.Altair:
442+
if signed_block.message.body.sync_aggregate.sync_committee_bits.isZeros:
443+
if signed_block.message.body.sync_aggregate.sync_committee_signature !=
444+
ValidatorSig.infinity():
445+
return err(
446+
"collectSignatureSets: empty sync aggregates need signature of point at infinity"
447+
)
448448
else:
449-
# 7. SyncAggregate
450-
# ----------------------------------------------------
451-
withState(state):
452-
when consensusFork >= ConsensusFork.Altair:
453-
if signed_block.message.body.sync_aggregate.sync_committee_bits.isZeros:
454-
if signed_block.message.body.sync_aggregate.sync_committee_signature != ValidatorSig.infinity():
455-
return err("collectSignatureSets: empty sync aggregates need signature of point at infinity")
456-
else:
457-
let
458-
current_sync_committee =
459-
forkyState.data.get_sync_committee_cache(cache).current_sync_committee
460-
previous_slot = max(forkyState.data.slot, Slot(1)) - 1
461-
beacon_block_root = get_block_root_at_slot(forkyState.data, previous_slot)
462-
pubkey = ? aggregateAttesters(
463-
current_sync_committee,
464-
signed_block.message.body.sync_aggregate.sync_committee_bits,
465-
validatorKeys)
466-
467-
sigs.add sync_committee_message_signature_set(
468-
fork, genesis_validators_root, previous_slot, beacon_block_root,
469-
pubkey,
470-
signed_block.message.body.sync_aggregate.sync_committee_signature.load().valueOr do:
471-
return err("collectSignatureSets: cannot load signature"))
449+
let
450+
current_sync_committee =
451+
forkyState.data.get_sync_committee_cache(cache).current_sync_committee
452+
previous_slot = max(forkyState.data.slot, Slot(1)) - 1
453+
beacon_block_root = get_block_root_at_slot(forkyState.data, previous_slot)
454+
pubkey =
455+
?aggregateAttesters(
456+
current_sync_committee,
457+
signed_block.message.body.sync_aggregate.sync_committee_bits, validatorKeys,
458+
)
459+
sig = signed_block.message.body.sync_aggregate.sync_committee_signature.load().valueOr:
460+
return err("collectSignatureSets: cannot load signature")
461+
462+
sigs.add sync_committee_message_signature_set(
463+
fork, genesis_validators_root, previous_slot, beacon_block_root, pubkey, sig
464+
)
465+
466+
# 8. BLS to execution changes
467+
when consensusFork >= ConsensusFork.Capella:
468+
for bls_change in signed_block.message.body.bls_to_execution_changes:
469+
# Otherwise, expensive loadWithCache can be spammed with irrelevant pubkeys
470+
?check_bls_to_execution_change(
471+
genesis_fork_version, forkyState.data, bls_change, {skipBlsValidation}
472+
)
472473

473-
block:
474-
# 8. BLS to execution changes
475-
when typeof(signed_block).kind >= ConsensusFork.Capella:
476-
withState(state):
477-
when consensusFork >= ConsensusFork.Capella:
478-
for bls_change in signed_block.message.body.bls_to_execution_changes:
479-
let sig = bls_change.signature.load.valueOr:
480-
return err("collectSignatureSets: cannot load BLS to execution change signature")
481-
482-
# Otherwise, expensive loadWithCache can be spammed with irrelevant pubkeys
483-
? check_bls_to_execution_change(
484-
genesis_fork_version, forkyState.data, bls_change, {skipBlsValidation})
485-
486-
let validator_pubkey =
487-
bls_change.message.from_bls_pubkey.loadWithCache.valueOr:
488-
return err("collectSignatureSets: cannot load BLS to execution change pubkey")
489-
490-
sigs.add bls_to_execution_change_signature_set(
491-
genesis_fork_version, genesis_validators_root, bls_change.message,
492-
validator_pubkey, sig)
474+
let
475+
sig = bls_change.signature.load.valueOr:
476+
return
477+
err("collectSignatureSets: cannot load BLS to execution change signature")
478+
validator_pubkey = bls_change.message.from_bls_pubkey.loadWithCache.valueOr:
479+
return err("collectSignatureSets: cannot load BLS to execution change pubkey")
480+
481+
sigs.add bls_to_execution_change_signature_set(
482+
genesis_fork_version, genesis_validators_root, bls_change.message,
483+
validator_pubkey, sig,
484+
)
493485

494486
ok()
495487

0 commit comments

Comments
 (0)