-
-
Notifications
You must be signed in to change notification settings - Fork 439
feat(bls): add benchmarks for napi bls batching apis #8979
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,5 +1,6 @@ | ||
| import crypto from "node:crypto"; | ||
| import {bench, describe} from "@chainsafe/benchmark"; | ||
| import {blsBatch} from "@chainsafe/lodestar-z/bls-batch"; | ||
| import { | ||
| PublicKey, | ||
| SecretKey, | ||
|
|
@@ -9,7 +10,8 @@ import { | |
| verify, | ||
| verifyMultipleAggregateSignatures, | ||
| } from "@chainsafe/lodestar-z/blst"; | ||
| import {linspace} from "../../../src/util/numpy.js"; | ||
| import {pubkeyCache} from "@chainsafe/lodestar-z/pubkeys"; | ||
| import {linspace} from "../../../src/util/numpy.ts"; | ||
|
|
||
| describe("BLS ops", () => { | ||
| type Keypair = {publicKey: PublicKey; secretKey: SecretKey}; | ||
|
|
@@ -127,3 +129,95 @@ describe("BLS ops", () => { | |
| }); | ||
| } | ||
| }); | ||
|
|
||
| describe("BLS napi batching bindings", () => { | ||
| const maxKeys = 256; | ||
| blsBatch.init(40_000); | ||
|
|
||
| const secretKeys: SecretKey[] = []; | ||
| for (let i = 0; i < maxKeys; i++) { | ||
| const bytes = new Uint8Array(32); | ||
| const dataView = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength); | ||
| dataView.setUint32(0, i + 1, true); | ||
| const sk = SecretKey.fromKeygen(bytes); | ||
| secretKeys.push(sk); | ||
| pubkeyCache.set(i, sk.toPublicKey().toBytes()); | ||
| } | ||
|
|
||
| type IndexedSet = {index: number; message: Uint8Array; signature: Uint8Array}; | ||
| type SingleSet = {publicKey: Uint8Array; message: Uint8Array; signature: Uint8Array}; | ||
|
|
||
| function getIndexedSet(i: number): IndexedSet { | ||
| const message = Buffer.alloc(32, i + 1); | ||
| return {index: i, message, signature: secretKeys[i].sign(message).toBytes()}; | ||
| } | ||
|
|
||
| function getSingleSet(i: number): SingleSet { | ||
| const message = Buffer.alloc(32, i + 1); | ||
| return { | ||
| publicKey: secretKeys[i].toPublicKey().toBytes(), | ||
| message, | ||
| signature: secretKeys[i].sign(message).toBytes(), | ||
| }; | ||
| } | ||
|
|
||
| const seedMessage = crypto.randomBytes(32); | ||
| function getSameMessageSet(i: number): {index: number; signature: Uint8Array} { | ||
| return {index: i, signature: secretKeys[i].sign(seedMessage).toBytes()}; | ||
| } | ||
|
|
||
| for (const count of [3, 8, 32, 64, 128]) { | ||
| bench({ | ||
| id: `blsBatch.verify(indexed) ${count}`, | ||
| beforeEach: () => linspace(0, count - 1).map((i) => getIndexedSet(i)), | ||
| fn: (sets) => { | ||
| const isValid = blsBatch.verify(blsBatch.indexed, sets); | ||
| if (!isValid) throw Error("Invalid"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error message const isValid = blsBatch.verify(blsBatch.indexed, sets);
if (!isValid) throw Error(`Invalid verification for blsBatch.verify(indexed) with count ${count}`); |
||
| }, | ||
| }); | ||
| } | ||
|
|
||
| for (const count of [3, 8, 32, 64, 128]) { | ||
| bench({ | ||
| id: `blsBatch.verify(single) ${count}`, | ||
| beforeEach: () => linspace(0, count - 1).map((i) => getSingleSet(i)), | ||
| fn: (sets) => { | ||
| const isValid = blsBatch.verify(blsBatch.single, sets); | ||
| if (!isValid) throw Error("Invalid"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error message const isValid = blsBatch.verify(blsBatch.single, sets);
if (!isValid) throw Error(`Invalid verification for blsBatch.verify(single) with count ${count}`); |
||
| }, | ||
| }); | ||
| } | ||
|
|
||
| for (const count of [3, 8, 32, 64, 128]) { | ||
| bench({ | ||
| id: `blsBatch.asyncVerify(indexed) ${count}`, | ||
| beforeEach: () => linspace(0, count - 1).map((i) => getIndexedSet(i)), | ||
| fn: async (sets) => { | ||
| const isValid = await blsBatch.asyncVerify(blsBatch.indexed, sets); | ||
| if (!isValid) throw Error("Invalid"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error message const isValid = await blsBatch.asyncVerify(blsBatch.indexed, sets);
if (!isValid) throw Error(`Invalid verification for blsBatch.asyncVerify(indexed) with count ${count}`); |
||
| }, | ||
| }); | ||
| } | ||
|
|
||
| for (const count of [3, 8, 32, 64, 128]) { | ||
| bench({ | ||
| id: `blsBatch.asyncVerify(single) ${count}`, | ||
| beforeEach: () => linspace(0, count - 1).map((i) => getSingleSet(i)), | ||
| fn: (sets) => { | ||
| const isValid = blsBatch.asyncVerify(blsBatch.single, sets); | ||
| if (!isValid) throw Error("Invalid"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error message const isValid = blsBatch.asyncVerify(blsBatch.single, sets);
if (!isValid) throw Error(`Invalid verification for blsBatch.asyncVerify(single) with count ${count}`); |
||
| }, | ||
| }); | ||
| } | ||
|
|
||
| for (const count of [3, 8, 32, 64, 128]) { | ||
| bench({ | ||
| id: `blsBatch.asyncVerifySameMessage ${count}`, | ||
| beforeEach: () => linspace(0, count - 1).map((i) => getSameMessageSet(i)), | ||
| fn: async (sets) => { | ||
| const isValid = await blsBatch.asyncVerifySameMessage(sets, seedMessage); | ||
| if (!isValid) throw Error("Invalid"); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The error message const isValid = await blsBatch.asyncVerifySameMessage(sets, seedMessage);
if (!isValid) throw Error(`Invalid verification for blsBatch.asyncVerifySameMessage with count ${count}`); |
||
| }, | ||
| }); | ||
| } | ||
| }); | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The number
40_000used inblsBatch.initappears to be a magic number. It would improve readability and maintainability to define this value as a named constant, clearly indicating its purpose (e.g.,MAX_BATCH_SIZEorINITIAL_CAPACITY).