Skip to content

Commit

Permalink
feat: move all async to respective Signature class
Browse files Browse the repository at this point in the history
  • Loading branch information
matthewkeil committed Apr 19, 2024
1 parent a5aa94c commit 7a3cffc
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 37 deletions.
55 changes: 54 additions & 1 deletion src/blst-native/signature.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import blst from "@chainsafe/blst";
import {bytesToHex, hexToBytes} from "../helpers/index.js";
import {CoordType, PointFormat, Signature as ISignature} from "../types.js";
import {SignatureSet, CoordType, PointFormat, Signature as ISignature, PublicKeyArg, SignatureArg} from "../types.js";
import {PublicKey} from "./publicKey.js";
import {EmptyAggregateError, ZeroSignatureError} from "../errors.js";

Expand Down Expand Up @@ -35,13 +35,37 @@ export class Signature implements ISignature {
);
}

static async asyncVerifyMultipleSignatures(sets: SignatureSet[]): Promise<boolean> {
try {
return blst.asyncVerifyMultipleAggregateSignatures(
sets.map((set) => ({
message: set.message,
publicKey: Signature.convertToBlstPublicKeyArg(set.publicKey),
signature: Signature.convertToBlstSignatureArg(set.signature),
}))
);
} catch {
return false;
}
}

/**
* Implemented for SecretKey to be able to call .sign()
*/
private static friendBuild(sig: blst.Signature): Signature {
return new Signature(sig);
}

private static convertToBlstPublicKeyArg(publicKey: PublicKeyArg): blst.PublicKeyArg {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return publicKey instanceof Uint8Array ? publicKey : publicKey.value;
}

private static convertToBlstSignatureArg(signature: SignatureArg): blst.SignatureArg {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return signature instanceof Uint8Array ? signature : signature.value;
}

verify(publicKey: PublicKey, message: Uint8Array): boolean {
// Individual infinity signatures are NOT okay. Aggregated signatures MAY be infinity
if (this.value.isInfinity()) {
Expand Down Expand Up @@ -69,6 +93,35 @@ export class Signature implements ISignature {
);
}

async asyncVerify(publicKey: PublicKeyArg, message: Uint8Array): Promise<boolean> {
// Individual infinity signatures are NOT okay. Aggregated signatures MAY be infinity
if (this.value.isInfinity()) {
throw new ZeroSignatureError();
}
// @ts-expect-error Need to hack type to get access to the private `value`
return blst.asyncVerify(message, publicKey.value, this.value);
}

async asyncVerifyAggregate(publicKeys: PublicKeyArg[], message: Uint8Array): Promise<boolean> {
return blst.asyncFastAggregateVerify(
message,
// @ts-expect-error Need to hack type to get access to the private `value`
publicKeys.map((pk) => pk.value),
this.value
);
}

async asyncVerifyMultiple(publicKeys: PublicKeyArg[], messages: Uint8Array[]): Promise<boolean> {
// If this set is simply an infinity signature and infinity publicKey then skip verification.
// This has the effect of always declaring that this sig/publicKey combination is valid.
// for Eth2.0 specs tests
const pks = publicKeys.map(Signature.convertToBlstPublicKeyArg);
if (this.value.isInfinity() && publicKeys.length === 1 && publicKeys[0].isInfinity()) {
return true;
}
return blst.asyncAggregateVerify(messages, , this.value);
}

toBytes(format?: PointFormat): Uint8Array {
if (format === PointFormat.uncompressed) {
return this.value.serialize(false);
Expand Down
40 changes: 7 additions & 33 deletions src/functional.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import blst from "@chainsafe/blst";
import {IBls, PublicKey, PublicKeyArg, Signature, SignatureArg, SignatureSet} from "./types.js";
import {validateBytes} from "./helpers/index.js";
import {NotInitializedError} from "./errors.js";
Expand Down Expand Up @@ -171,7 +170,8 @@ export function functionalInterfaceFactory({
async function asyncVerify(publicKey: PublicKeyArg, message: Uint8Array, signature: SignatureArg): Promise<boolean> {
if (implementation === "herumi") return verify(publicKey, message, signature);
try {
return blst.asyncVerify(message, convertToBlstPublicKeyArg(publicKey), convertToBlstSignatureArg(signature));
const sig = signature instanceof Signature ? signature : Signature.fromBytes(signature);
return sig.asyncVerify(publicKey, message);
} catch {
return false;
}
Expand All @@ -187,11 +187,8 @@ export function functionalInterfaceFactory({
): Promise<boolean> {
if (implementation === "herumi") return verifyAggregate(publicKeys, message, signature);
try {
return blst.asyncFastAggregateVerify(
message,
publicKeys.map((key) => convertToBlstPublicKeyArg(key)),
convertToBlstSignatureArg(signature)
);
const sig = signature instanceof Signature ? signature : Signature.fromBytes(signature);
return sig.asyncVerifyAggregate(publicKeys, message);
} catch {
return false;
}
Expand All @@ -207,11 +204,8 @@ export function functionalInterfaceFactory({
): Promise<boolean> {
if (implementation === "herumi") return verifyMultiple(publicKeys, messages, signature);
try {
return blst.asyncAggregateVerify(
messages,
publicKeys.map((key) => convertToBlstPublicKeyArg(key)),
convertToBlstSignatureArg(signature)
);
const sig = signature instanceof Signature ? signature : Signature.fromBytes(signature);
return sig.asyncVerifyMultiple(publicKeys, messages);
} catch {
return false;
}
Expand All @@ -229,17 +223,7 @@ export function functionalInterfaceFactory({
*/
async function asyncVerifyMultipleSignatures(sets: SignatureSet[]): Promise<boolean> {
if (implementation === "herumi") return verifyMultipleSignatures(sets);
try {
return blst.asyncVerifyMultipleAggregateSignatures(
sets.map((set) => ({
message: set.message,
publicKey: convertToBlstPublicKeyArg(set.publicKey),
signature: convertToBlstSignatureArg(set.signature),
}))
);
} catch {
return false;
}
return Signature.asyncVerifyMultipleSignatures(sets);
}

/**
Expand All @@ -250,16 +234,6 @@ export function functionalInterfaceFactory({
return SecretKey.fromBytes(secretKey).toPublicKey().toBytes();
}

function convertToBlstPublicKeyArg(publicKey: PublicKeyArg): blst.PublicKeyArg {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return publicKey instanceof PublicKey ? ((publicKey as any).value as blst.PublicKey) : publicKey;
}

function convertToBlstSignatureArg(signature: SignatureArg): blst.SignatureArg {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
return signature instanceof Signature ? ((signature as any).value as blst.Signature) : signature;
}

return {
sign,
aggregateSignatures,
Expand Down
37 changes: 35 additions & 2 deletions src/herumi/signature.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type {SignatureType} from "bls-eth-wasm";
import {getContext} from "./context.js";
import {PublicKey} from "./publicKey.js";
import {bytesToHex, concatUint8Arrays, hexToBytes, isZeroUint8Array} from "../helpers/index.js";
import {PointFormat, Signature as ISignature, CoordType} from "../types.js";
import {SignatureSet, PointFormat, Signature as ISignature, CoordType} from "../types.js";
import {EmptyAggregateError, InvalidLengthError, InvalidOrderError} from "../errors.js";
import {SIGNATURE_LENGTH_COMPRESSED, SIGNATURE_LENGTH_UNCOMPRESSED} from "../constants.js";

Expand Down Expand Up @@ -52,7 +52,7 @@ export class Signature implements ISignature {
return new Signature(signature);
}

static verifyMultipleSignatures(sets: {publicKey: PublicKey; message: Uint8Array; signature: Signature}[]): boolean {
static verifyMultipleSignatures(sets: SignatureSet[]): boolean {
const context = getContext();
return context.multiVerify(
sets.map((s) => s.publicKey.value),
Expand All @@ -61,6 +61,15 @@ export class Signature implements ISignature {
);
}

static async asyncVerifyMultipleSignatures(sets: SignatureSet[]): Promise<boolean> {
// eslint-disable-next-line no-console
console.log(
"asyncVerifyMultipleSignatures is not implemented by bls-eth-wasm.\n" +
"Please use the synchronous Signature.verifyMultipleSignatures instead"
);
return Signature.verifyMultipleSignatures(sets);
}

verify(publicKey: PublicKey, message: Uint8Array): boolean {
return publicKey.value.verify(this.value, message);
}
Expand All @@ -79,6 +88,30 @@ export class Signature implements ISignature {
);
}

async asyncVerify(publicKey: PublicKey, message: Uint8Array): Promise<boolean> {
// eslint-disable-next-line no-console
console.log("asyncVerify is not implemented by bls-eth-wasm.\nPlease use the synchronous Signature.verify instead");
return this.verify(publicKey, message);
}

async asyncVerifyAggregate(publicKeys: PublicKey[], message: Uint8Array): Promise<boolean> {
// eslint-disable-next-line no-console
console.log(
"asyncVerifyAggregate is not implemented by bls-eth-wasm.\n" +
"Please use the synchronous Signature.verifyAggregate instead"
);
return this.verifyAggregate(publicKeys, message);
}

async asyncVerifyMultiple(publicKeys: PublicKey[], messages: Uint8Array[]): Promise<boolean> {
// eslint-disable-next-line no-console
console.log(
"asyncVerifyMultiple is not implemented by bls-eth-wasm.\n" +
"Please use the synchronous Signature.verifyMultiple instead"
);
return this.verifyMultiple(publicKeys, messages);
}

toBytes(format?: PointFormat): Uint8Array {
if (format === PointFormat.uncompressed) {
return this.value.serializeUncompressed();
Expand Down
6 changes: 5 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,10 +82,14 @@ export declare class Signature {
static fromBytes(bytes: Uint8Array, type?: CoordType, validate?: boolean): Signature;
static fromHex(hex: string): Signature;
static aggregate(signatures: Signature[]): Signature;
static verifyMultipleSignatures(sets: {publicKey: PublicKey; message: Uint8Array; signature: Signature}[]): boolean;
static verifyMultipleSignatures(sets: SignatureSet[]): boolean;
static asyncVerifyMultipleSignatures(sets: SignatureSet[]): Promise<boolean>;
verify(publicKey: PublicKey, message: Uint8Array): boolean;
verifyAggregate(publicKeys: PublicKey[], message: Uint8Array): boolean;
verifyMultiple(publicKeys: PublicKey[], messages: Uint8Array[]): boolean;
asyncVerify(publicKey: PublicKeyArg, message: Uint8Array): Promise<boolean>;
asyncVerifyAggregate(publicKeys: PublicKeyArg[], message: Uint8Array): Promise<boolean>;
asyncVerifyMultiple(publicKeys: PublicKeyArg[], messages: Uint8Array[]): Promise<boolean>;
/** @param format Defaults to `PointFormat.compressed` */
toBytes(format?: PointFormat): Uint8Array;
toHex(format?: PointFormat): string;
Expand Down

0 comments on commit 7a3cffc

Please sign in to comment.