Skip to content

Commit 8c6547c

Browse files
committed
feat: add async functions for blst-native
1 parent 739e436 commit 8c6547c

File tree

4 files changed

+113
-10
lines changed

4 files changed

+113
-10
lines changed

src/blst-native/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,14 @@ export * from "../constants.js";
77

88
export {SecretKey, PublicKey, Signature};
99

10+
const implementation = "blst-native";
1011
export const bls: IBls = {
11-
implementation: "blst-native",
12+
implementation,
1213
SecretKey,
1314
PublicKey,
1415
Signature,
1516

16-
...functionalInterfaceFactory({SecretKey, PublicKey, Signature}),
17+
...functionalInterfaceFactory({implementation, SecretKey, PublicKey, Signature}),
1718
};
1819

1920
export default bls;

src/functional.ts

Lines changed: 99 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1-
import {IBls} from "./types.js";
1+
/* eslint-disable @typescript-eslint/no-explicit-any */
2+
import * as blst from "@chainsafe/blst-ts";
3+
import {IBls, PublicKey, PublicKeyArg, Signature, SignatureArg} from "./types.js";
24
import {validateBytes} from "./helpers/index.js";
3-
import {NotInitializedError} from "./errors.js";
5+
import {NotInitializedError, ZeroSignatureError} from "./errors.js";
46

57
// Returned type is enforced at each implementation's index
68
// eslint-disable-next-line max-len
79
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type,@typescript-eslint/explicit-module-boundary-types
810
export function functionalInterfaceFactory({
11+
implementation,
912
SecretKey,
1013
PublicKey,
1114
Signature,
12-
}: Pick<IBls, "SecretKey" | "PublicKey" | "Signature">) {
15+
}: Pick<IBls, "implementation" | "SecretKey" | "PublicKey" | "Signature">) {
1316
/**
1417
* Signs given message using secret key.
1518
* @param secretKey
@@ -47,9 +50,11 @@ export function functionalInterfaceFactory({
4750
* @param signature
4851
*/
4952
function verify(publicKey: Uint8Array, message: Uint8Array, signature: Uint8Array): boolean {
50-
validateBytes(publicKey, "publicKey");
51-
validateBytes(message, "message");
52-
validateBytes(signature, "signature");
53+
if (implementation === "herumi") {
54+
validateBytes(publicKey, "publicKey");
55+
validateBytes(message, "message");
56+
validateBytes(signature, "signature");
57+
}
5358

5459
try {
5560
return Signature.fromBytes(signature).verify(PublicKey.fromBytes(publicKey), message);
@@ -58,6 +63,27 @@ export function functionalInterfaceFactory({
5863
return false;
5964
}
6065
}
66+
async function asyncVerify(message: Uint8Array, publicKey: PublicKeyArg, signature: SignatureArg): Promise<boolean> {
67+
if (implementation === "herumi") {
68+
throw new Error("WASM implementation does not support asyncVerify, use verify instead");
69+
}
70+
71+
const pk = publicKey instanceof PublicKey ? ((publicKey as any).key as blst.PublicKey) : publicKey;
72+
const sig =
73+
signature instanceof Signature
74+
? ((signature as any).sig as blst.Signature)
75+
: blst.Signature.deserialize(signature);
76+
77+
if (sig.isInfinity()) {
78+
false;
79+
}
80+
81+
try {
82+
return blst.asyncVerify(message, pk, sig);
83+
} catch {
84+
return false;
85+
}
86+
}
6187

6288
/**
6389
* Verifies if aggregated signature is same message signed with given public keys.
@@ -80,6 +106,26 @@ export function functionalInterfaceFactory({
80106
return false;
81107
}
82108
}
109+
async function asyncVerifyAggregate(
110+
message: Uint8Array,
111+
publicKeys: PublicKeyArg[],
112+
signature: SignatureArg
113+
): Promise<boolean> {
114+
if (implementation === "herumi") {
115+
throw new Error("WASM implementation does not support asyncVerifyAggregate, use verifyAggregate instead");
116+
}
117+
118+
const pks = publicKeys.map((pk) => (pk instanceof PublicKey ? ((pk as any).key as blst.PublicKey) : pk));
119+
const sig = signature instanceof Signature ? ((signature as any).sig as blst.Signature) : signature;
120+
121+
// TODO: (matthewkeil) check spec to make sure this sig does not need inf check
122+
123+
try {
124+
return blst.fastAggregateVerify(message, pks, sig);
125+
} catch {
126+
return false;
127+
}
128+
}
83129

84130
/**
85131
* Verifies if signature is list of message signed with corresponding public key.
@@ -106,6 +152,30 @@ export function functionalInterfaceFactory({
106152
return false;
107153
}
108154
}
155+
async function asyncVerifyMultiple(
156+
messages: Uint8Array[],
157+
publicKeys: PublicKeyArg[],
158+
signature: SignatureArg
159+
): Promise<boolean> {
160+
if (implementation === "herumi") {
161+
throw new Error("WASM implementation does not support asyncVerifyMultiple, use verifyMultiple instead");
162+
}
163+
164+
if (publicKeys.length === 0 || publicKeys.length != messages.length) {
165+
return false;
166+
}
167+
168+
const pks = publicKeys.map((pk) => (pk instanceof PublicKey ? ((pk as any).key as blst.PublicKey) : pk));
169+
const sig = signature instanceof Signature ? ((signature as any).sig as blst.Signature) : signature;
170+
171+
// TODO: (matthewkeil) check spec to make sure this sig does not need inf check
172+
173+
try {
174+
return blst.aggregateVerify(messages, pks, sig);
175+
} catch {
176+
return false;
177+
}
178+
}
109179

110180
/**
111181
* Verifies multiple signatures at once returning true if all valid or false
@@ -135,6 +205,25 @@ export function functionalInterfaceFactory({
135205
return false;
136206
}
137207
}
208+
async function asyncVerifyMultipleSignatures(
209+
sets: {message: Uint8Array; publicKey: PublicKeyArg; signature: SignatureArg}[]
210+
): Promise<boolean> {
211+
if (!sets) throw Error("sets is null or undefined");
212+
213+
try {
214+
return blst.asyncVerifyMultipleAggregateSignatures(
215+
sets.map((set) => ({
216+
message: set.message,
217+
publicKey:
218+
set.publicKey instanceof PublicKey ? ((set.publicKey as any).key as blst.PublicKey) : set.publicKey,
219+
signature:
220+
set.signature instanceof Signature ? ((set.signature as any).sig as blst.Signature) : set.signature,
221+
}))
222+
);
223+
} catch {
224+
return false;
225+
}
226+
}
138227

139228
/**
140229
* Computes a public key from a secret key
@@ -152,6 +241,10 @@ export function functionalInterfaceFactory({
152241
verifyAggregate,
153242
verifyMultiple,
154243
verifyMultipleSignatures,
244+
asyncVerify,
245+
asyncVerifyAggregate,
246+
asyncVerifyMultiple,
247+
asyncVerifyMultipleSignatures,
155248
secretKeyToPublicKey,
156249
};
157250
}

src/herumi/index.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ export * from "../constants.js";
1111

1212
export {SecretKey, PublicKey, Signature, init, destroy};
1313

14+
const implementation = "herumi";
1415
export const bls: IBls = {
15-
implementation: "herumi",
16+
implementation,
1617
SecretKey,
1718
PublicKey,
1819
Signature,
1920

20-
...functionalInterfaceFactory({SecretKey, PublicKey, Signature}),
21+
...functionalInterfaceFactory({implementation, SecretKey, PublicKey, Signature}),
2122
};
2223

2324
export default bls;

src/types.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import {CoordType} from "@chainsafe/blst-ts";
22

3+
export type PublicKeyArg = PublicKey | Uint8Array;
4+
export type SignatureArg = Signature | Uint8Array;
35
export interface IBls {
46
implementation: Implementation;
57
SecretKey: typeof SecretKey;
@@ -13,6 +15,12 @@ export interface IBls {
1315
verifyAggregate(publicKeys: Uint8Array[], message: Uint8Array, signature: Uint8Array): boolean;
1416
verifyMultiple(publicKeys: Uint8Array[], messages: Uint8Array[], signature: Uint8Array): boolean;
1517
verifyMultipleSignatures(sets: {publicKey: Uint8Array; message: Uint8Array; signature: Uint8Array}[]): boolean;
18+
asyncVerify(message: Uint8Array, publicKey: PublicKeyArg, signature: SignatureArg): Promise<boolean>;
19+
asyncVerifyAggregate(message: Uint8Array, publicKeys: PublicKeyArg[], signature: SignatureArg): Promise<boolean>;
20+
asyncVerifyMultiple(messages: Uint8Array[], publicKeys: PublicKeyArg[], signature: SignatureArg): Promise<boolean>;
21+
asyncVerifyMultipleSignatures(
22+
sets: {message: Uint8Array; publicKey: PublicKeyArg; signature: SignatureArg}[]
23+
): Promise<boolean>;
1624
secretKeyToPublicKey(secretKey: Uint8Array): Uint8Array;
1725
}
1826

0 commit comments

Comments
 (0)