speed up LC signature verification (#5268)
We know the aggregate publickey of a fully participating sync committee. Because participation is typically very high (>95%), it is faster to start from that aggregate publickey and subtract the individual keys of non-participants, than summing up all the participating pubkeys.
This commit is contained in:
parent
8e398001fe
commit
973e9e9a98
|
@ -25,7 +25,7 @@
|
|||
|
||||
import
|
||||
# Status
|
||||
stew/[endians2, objects, results, byteutils],
|
||||
stew/[bitseqs, endians2, objects, results, byteutils],
|
||||
blscurve,
|
||||
chronicles,
|
||||
bearssl/rand,
|
||||
|
@ -314,6 +314,68 @@ proc blsFastAggregateVerify*(
|
|||
let parsedSig = signature.load()
|
||||
parsedSig.isSome and blsFastAggregateVerify(publicKeys, message, parsedSig.get())
|
||||
|
||||
proc blsFastAggregateVerify*(
|
||||
fullParticipationAggregatePublicKey: ValidatorPubKey,
|
||||
nonParticipatingPublicKeys: openArray[ValidatorPubKey],
|
||||
message: openArray[byte],
|
||||
signature: CookedSig
|
||||
): bool =
|
||||
let unwrappedFull = fullParticipationAggregatePublicKey.loadWithCache.valueOr:
|
||||
return false
|
||||
|
||||
var unwrapped = newSeqOfCap[PublicKey](nonParticipatingPublicKeys.len)
|
||||
for pubkey in nonParticipatingPublicKeys:
|
||||
let realkey = pubkey.loadWithCache.valueOr:
|
||||
return false
|
||||
unwrapped.add PublicKey(realkey)
|
||||
|
||||
fastAggregateVerify(
|
||||
PublicKey(unwrappedFull), unwrapped,
|
||||
message, blscurve.Signature(signature))
|
||||
|
||||
proc blsFastAggregateVerify*(
|
||||
fullParticipationAggregatePublicKey: ValidatorPubKey,
|
||||
nonParticipatingPublicKeys: openArray[ValidatorPubKey],
|
||||
message: openArray[byte],
|
||||
signature: ValidatorSig
|
||||
): bool =
|
||||
let parsedSig = signature.load()
|
||||
parsedSig.isSome and blsFastAggregateVerify(
|
||||
fullParticipationAggregatePublicKey, nonParticipatingPublicKeys,
|
||||
message, parsedSig.get())
|
||||
|
||||
proc blsFastAggregateVerify*(
|
||||
allPublicKeys: openArray[ValidatorPubKey],
|
||||
fullParticipationAggregatePublicKey: ValidatorPubKey,
|
||||
participantBits: BitArray,
|
||||
message: openArray[byte],
|
||||
signature: ValidatorSig
|
||||
): bool =
|
||||
const maxParticipants = participantBits.bits
|
||||
var numParticipants = 0
|
||||
for idx in 0 ..< maxParticipants:
|
||||
if participantBits[idx]:
|
||||
inc numParticipants
|
||||
|
||||
return
|
||||
if numParticipants < 1:
|
||||
false
|
||||
elif numParticipants > maxParticipants div 2:
|
||||
var nonParticipatingPublicKeys = newSeqOfCap[ValidatorPubKey](
|
||||
maxParticipants - numParticipants)
|
||||
for idx, pubkey in allPublicKeys:
|
||||
if not participantBits[idx]:
|
||||
nonParticipatingPublicKeys.add pubkey
|
||||
blsFastAggregateVerify(
|
||||
fullParticipationAggregatePublicKey, nonParticipatingPublicKeys,
|
||||
message, signature)
|
||||
else:
|
||||
var publicKeys = newSeqOfCap[ValidatorPubKey](numParticipants)
|
||||
for idx, pubkey in allPublicKeys:
|
||||
if participantBits[idx]:
|
||||
publicKeys.add pubkey
|
||||
blsFastAggregateVerify(publicKeys, message, signature)
|
||||
|
||||
# Codecs
|
||||
# ----------------------------------------------------------------------
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
{.push raises: [].}
|
||||
|
||||
import
|
||||
stew/[bitops2, objects],
|
||||
stew/[bitops2, bitseqs, objects],
|
||||
datatypes/altair,
|
||||
helpers
|
||||
|
||||
|
@ -141,20 +141,19 @@ proc validate_light_client_update*(
|
|||
unsafeAddr store.current_sync_committee
|
||||
else:
|
||||
unsafeAddr store.next_sync_committee
|
||||
var participant_pubkeys =
|
||||
newSeqOfCap[ValidatorPubKey](num_active_participants)
|
||||
for idx, bit in sync_aggregate.sync_committee_bits:
|
||||
if bit:
|
||||
participant_pubkeys.add(sync_committee.pubkeys.data[idx])
|
||||
let
|
||||
fork_version_slot = max(update.signature_slot, 1.Slot) - 1
|
||||
fork_version = cfg.forkVersionAtEpoch(fork_version_slot.epoch)
|
||||
domain = compute_domain(
|
||||
DOMAIN_SYNC_COMMITTEE, fork_version, genesis_validators_root)
|
||||
signing_root = compute_signing_root(update.attested_header.beacon, domain)
|
||||
const maxParticipants = typeof(sync_aggregate.sync_committee_bits).bits
|
||||
if not blsFastAggregateVerify(
|
||||
participant_pubkeys, signing_root.data,
|
||||
sync_aggregate.sync_committee_signature):
|
||||
allPublicKeys = sync_committee.pubkeys.data,
|
||||
fullParticipationAggregatePublicKey = sync_committee.aggregate_pubkey,
|
||||
bitseqs.BitArray[maxParticipants](
|
||||
bytes: sync_aggregate.sync_committee_bits.bytes),
|
||||
signing_root.data, sync_aggregate.sync_committee_signature):
|
||||
return err(VerifierError.UnviableFork)
|
||||
|
||||
ok()
|
||||
|
|
Loading…
Reference in New Issue