This repository has been archived on 2023-04-09. You can view files and clone it, but cannot push or open issues or pull requests.
chainsafe-bls/src/blst-native/signature.ts

78 lines
2.6 KiB
TypeScript
Raw Normal View History

2020-11-19 13:22:41 +00:00
import * as blst from "@chainsafe/blst";
import {bytesToHex, hexToBytes} from "../helpers/index.js";
2022-04-14 17:16:06 +00:00
import {PointFormat, Signature as ISignature} from "../types.js";
import {PublicKey} from "./publicKey.js";
import {EmptyAggregateError, ZeroSignatureError} from "../errors.js";
2020-11-19 13:22:41 +00:00
export class Signature extends blst.Signature implements ISignature {
constructor(value: ConstructorParameters<typeof blst.Signature>[0]) {
super(value);
2020-11-19 13:22:41 +00:00
}
/** @param type Defaults to `CoordType.affine` */
static fromBytes(bytes: Uint8Array, type?: blst.CoordType, validate = true): Signature {
const sig = blst.Signature.fromBytes(bytes, type);
if (validate) sig.sigValidate();
return new Signature(sig.value);
2020-11-19 13:22:41 +00:00
}
static fromHex(hex: string): Signature {
return this.fromBytes(hexToBytes(hex));
}
static aggregate(signatures: Signature[]): Signature {
2020-11-30 00:20:52 +00:00
if (signatures.length === 0) {
throw new EmptyAggregateError();
}
const agg = blst.aggregateSignatures(signatures);
return new Signature(agg.value);
2020-11-19 13:22:41 +00:00
}
static verifyMultipleSignatures(sets: {publicKey: PublicKey; message: Uint8Array; signature: Signature}[]): boolean {
2020-12-02 21:44:25 +00:00
return blst.verifyMultipleAggregateSignatures(
sets.map((s) => ({msg: s.message, pk: s.publicKey, sig: s.signature}))
2020-12-02 21:44:25 +00:00
);
}
2020-11-19 13:22:41 +00:00
verify(publicKey: PublicKey, message: Uint8Array): boolean {
2020-11-30 00:20:52 +00:00
// Individual infinity signatures are NOT okay. Aggregated signatures MAY be infinity
if (this.value.is_inf()) {
2020-11-30 00:20:52 +00:00
throw new ZeroSignatureError();
}
return blst.verify(message, publicKey, this);
2020-11-19 13:22:41 +00:00
}
verifyAggregate(publicKeys: PublicKey[], message: Uint8Array): boolean {
return blst.fastAggregateVerify(message, publicKeys, this);
2020-11-19 13:22:41 +00:00
}
verifyMultiple(publicKeys: PublicKey[], messages: Uint8Array[]): boolean {
return blst.aggregateVerify(messages, publicKeys, this);
2020-11-19 13:22:41 +00:00
}
toBytes(format?: PointFormat): Uint8Array {
if (format === PointFormat.uncompressed) {
return this.value.serialize();
} else {
return this.value.compress();
}
2020-11-20 12:27:30 +00:00
}
toHex(format?: PointFormat): string {
return bytesToHex(this.toBytes(format));
2020-11-20 12:27:30 +00:00
}
2020-11-19 13:22:41 +00:00
private aggregateVerify(msgs: Uint8Array[], pks: blst.PublicKey[]): boolean {
2020-11-30 18:01:13 +00:00
// 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.
2020-11-19 13:22:41 +00:00
// for Eth2.0 specs tests
if (this.value.is_inf() && pks.length === 1 && pks[0].value.is_inf()) {
2020-11-19 13:22:41 +00:00
return true;
}
return blst.aggregateVerify(msgs, pks, this);
2020-11-19 13:22:41 +00:00
}
}