Define common implementation
This commit is contained in:
parent
c354386dab
commit
4424bed87d
|
@ -4,6 +4,7 @@ import {PrivateKey} from "./privateKey";
|
|||
import {PublicKey} from "./publicKey";
|
||||
import {Signature} from "./signature";
|
||||
import {toBuffer} from "../helpers/utils";
|
||||
import {IBls} from "../interface";
|
||||
export * from "../constants";
|
||||
|
||||
export {Keypair, PrivateKey, PublicKey, Signature};
|
||||
|
@ -15,23 +16,6 @@ export function destroy(): void {
|
|||
// Native bindings require no destroy() call
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates new secret and public key
|
||||
*/
|
||||
export function generateKeyPair(): Keypair {
|
||||
return Keypair.generate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates public key from given secret.
|
||||
* @param {BLSSecretKey} secretKey
|
||||
*/
|
||||
export function generatePublicKey(secretKey: Uint8Array): Buffer {
|
||||
assert(secretKey, "secretKey is null or undefined");
|
||||
const keypair = new Keypair(PrivateKey.fromBytes(toBuffer(secretKey)));
|
||||
return keypair.publicKey.toBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs given message using secret key.
|
||||
* @param secretKey
|
||||
|
@ -127,9 +111,7 @@ export function verifyMultiple(publicKeys: Uint8Array[], messageHashes: Uint8Arr
|
|||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
generateKeyPair,
|
||||
generatePublicKey,
|
||||
const bls: IBls = {
|
||||
sign,
|
||||
aggregateSignatures,
|
||||
aggregatePubkeys,
|
||||
|
@ -137,10 +119,12 @@ export default {
|
|||
verifyAggregate,
|
||||
verifyMultiple,
|
||||
|
||||
Keypair,
|
||||
// Keypair,
|
||||
PrivateKey,
|
||||
PublicKey,
|
||||
Signature,
|
||||
initBLS,
|
||||
destroy,
|
||||
};
|
||||
|
||||
export default bls;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import {PublicKey} from "./publicKey";
|
||||
import {PrivateKey} from "./privateKey";
|
||||
import {IKeypair} from "../interface";
|
||||
|
||||
export class Keypair {
|
||||
export class Keypair implements IKeypair {
|
||||
private readonly _publicKey: PublicKey;
|
||||
|
||||
private readonly _privateKey: PrivateKey;
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
import * as blst from "@chainsafe/blst";
|
||||
import {bytesToHex, getRandomBytes, hexToBytes} from "../helpers/utils";
|
||||
import {IPrivateKey} from "../interface";
|
||||
import {PublicKey} from "./publicKey";
|
||||
import {Signature} from "./signature";
|
||||
|
||||
export class PrivateKey {
|
||||
export class PrivateKey implements IPrivateKey {
|
||||
readonly value: blst.SecretKey;
|
||||
|
||||
constructor(value: blst.SecretKey) {
|
||||
|
@ -25,7 +26,7 @@ export class PrivateKey {
|
|||
}
|
||||
|
||||
signMessage(message: Uint8Array): Signature {
|
||||
return Signature.fromValue(this.value.sign(message));
|
||||
return new Signature(this.value.sign(message));
|
||||
}
|
||||
|
||||
toPublicKey(): PublicKey {
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import * as blst from "@chainsafe/blst";
|
||||
import {bytesToHex, hexToBytes} from "../helpers/utils";
|
||||
import {IPublicKey} from "../interface";
|
||||
import {Signature} from "./signature";
|
||||
|
||||
export class PublicKey {
|
||||
export class PublicKey implements IPublicKey {
|
||||
readonly affine: blst.PublicKey;
|
||||
readonly jacobian: blst.AggregatePublicKey;
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import * as blst from "@chainsafe/blst";
|
||||
import {bytesToHex, hexToBytes} from "../helpers/utils";
|
||||
import {ISignature} from "../interface";
|
||||
import {PublicKey} from "./publicKey";
|
||||
|
||||
export class Signature {
|
||||
export class Signature implements ISignature {
|
||||
readonly affine: blst.Signature;
|
||||
|
||||
constructor(value: blst.Signature) {
|
||||
|
@ -17,10 +18,6 @@ export class Signature {
|
|||
return this.fromBytes(hexToBytes(hex));
|
||||
}
|
||||
|
||||
static fromValue(signature: blst.Signature): Signature {
|
||||
return new Signature(signature);
|
||||
}
|
||||
|
||||
static aggregate(signatures: Signature[]): Signature {
|
||||
const agg = blst.AggregateSignature.fromSignatures(signatures.map((sig) => sig.affine));
|
||||
return new Signature(agg.toSignature());
|
||||
|
|
|
@ -3,18 +3,17 @@ import bls from "@chainsafe/eth2-bls-wasm";
|
|||
|
||||
type Bls = typeof bls;
|
||||
let blsGlobal: Bls | null = null;
|
||||
let blsGlobalPromise: Promise<Bls> | null = null;
|
||||
let blsGlobalPromise: Promise<void> | null = null;
|
||||
|
||||
export async function setupBls(): Promise<Bls> {
|
||||
export async function setupBls(): Promise<void> {
|
||||
if (!blsGlobal) {
|
||||
await bls.init();
|
||||
blsGlobal = bls;
|
||||
}
|
||||
return blsGlobal;
|
||||
}
|
||||
|
||||
// Cache a promise for Bls instead of Bls to make sure it is initialized only once
|
||||
export async function initBLS(): Promise<Bls> {
|
||||
export async function initBLS(): Promise<void> {
|
||||
if (!blsGlobalPromise) {
|
||||
blsGlobalPromise = setupBls();
|
||||
}
|
||||
|
|
|
@ -5,26 +5,10 @@ import {Signature} from "./signature";
|
|||
import {initBLS, destroy} from "./context";
|
||||
import assert from "assert";
|
||||
import {toBuffer} from "../helpers/utils";
|
||||
import {IBls} from "../interface";
|
||||
|
||||
export {Keypair, PrivateKey, PublicKey, Signature, initBLS, destroy};
|
||||
|
||||
/**
|
||||
* Generates new secret and public key
|
||||
*/
|
||||
export function generateKeyPair(): Keypair {
|
||||
return Keypair.generate();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates public key from given secret.
|
||||
* @param {BLSSecretKey} secretKey
|
||||
*/
|
||||
export function generatePublicKey(secretKey: Uint8Array): Buffer {
|
||||
assert(secretKey, "secretKey is null or undefined");
|
||||
const keypair = new Keypair(PrivateKey.fromBytes(toBuffer(secretKey)));
|
||||
return keypair.publicKey.toBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Signs given message using secret key.
|
||||
* @param secretKey
|
||||
|
@ -121,9 +105,7 @@ export function verifyMultiple(publicKeys: Uint8Array[], messageHashes: Uint8Arr
|
|||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
generateKeyPair,
|
||||
generatePublicKey,
|
||||
const bls: IBls = {
|
||||
sign,
|
||||
aggregateSignatures,
|
||||
aggregatePubkeys,
|
||||
|
@ -131,10 +113,12 @@ export default {
|
|||
verifyAggregate,
|
||||
verifyMultiple,
|
||||
|
||||
Keypair,
|
||||
// Keypair,
|
||||
PrivateKey,
|
||||
PublicKey,
|
||||
Signature,
|
||||
initBLS,
|
||||
destroy,
|
||||
};
|
||||
|
||||
export default bls;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
import {PublicKey} from "./publicKey";
|
||||
import {PrivateKey} from "./privateKey";
|
||||
import {IKeypair} from "../interface";
|
||||
|
||||
export class Keypair {
|
||||
export class Keypair implements IKeypair {
|
||||
private readonly _publicKey: PublicKey;
|
||||
|
||||
private readonly _privateKey: PrivateKey;
|
||||
|
|
|
@ -6,8 +6,9 @@ import {getContext} from "./context";
|
|||
import {PublicKey} from "./publicKey";
|
||||
import {Signature} from "./signature";
|
||||
import {bytesToHex, hexToBytes} from "../helpers/utils";
|
||||
import {IPrivateKey} from "../interface";
|
||||
|
||||
export class PrivateKey {
|
||||
export class PrivateKey implements IPrivateKey {
|
||||
readonly value: SecretKeyType;
|
||||
|
||||
constructor(value: SecretKeyType) {
|
||||
|
|
|
@ -3,8 +3,9 @@ import {getContext} from "./context";
|
|||
import {EMPTY_PUBLIC_KEY} from "../constants";
|
||||
import {Signature} from "./signature";
|
||||
import {bytesToHex, hexToBytes, isEqualBytes} from "../helpers/utils";
|
||||
import {IPublicKey} from "../interface";
|
||||
|
||||
export class PublicKey {
|
||||
export class PublicKey implements IPublicKey {
|
||||
readonly value: PublicKeyType;
|
||||
|
||||
constructor(value: PublicKeyType) {
|
||||
|
|
|
@ -4,8 +4,9 @@ import {SignatureType} from "@chainsafe/eth2-bls-wasm";
|
|||
import {getContext} from "./context";
|
||||
import {PublicKey} from "./publicKey";
|
||||
import {bytesToHex, hexToBytes, isEqualBytes} from "../helpers/utils";
|
||||
import {ISignature} from "../interface";
|
||||
|
||||
export class Signature {
|
||||
export class Signature implements ISignature {
|
||||
readonly value: SignatureType;
|
||||
|
||||
constructor(value: SignatureType) {
|
||||
|
|
|
@ -0,0 +1,53 @@
|
|||
export interface IBls {
|
||||
PrivateKey: {
|
||||
fromBytes(bytes: Uint8Array): IPrivateKey;
|
||||
fromHex(hex: string): IPrivateKey;
|
||||
fromKeygen(): IPrivateKey;
|
||||
};
|
||||
PublicKey: {
|
||||
fromBytes(bytes: Uint8Array): IPublicKey;
|
||||
fromHex(hex: string): IPublicKey;
|
||||
aggregate(pubkeys: IPublicKey[]): IPublicKey;
|
||||
};
|
||||
Signature: {
|
||||
fromBytes(bytes: Uint8Array): ISignature;
|
||||
fromHex(hex: string): ISignature;
|
||||
aggregate(signatures: ISignature[]): ISignature;
|
||||
};
|
||||
|
||||
sign(secretKey: Uint8Array, messageHash: Uint8Array): Buffer;
|
||||
aggregatePubkeys(publicKeys: Uint8Array[]): Buffer;
|
||||
aggregateSignatures(signatures: Uint8Array[]): Buffer;
|
||||
verify(publicKey: Uint8Array, messageHash: Uint8Array, signature: Uint8Array): boolean;
|
||||
verifyAggregate(publicKeys: Uint8Array[], messageHash: Uint8Array, signature: Uint8Array): boolean;
|
||||
verifyMultiple(publicKeys: Uint8Array[], messageHashes: Uint8Array[], signature: Uint8Array): boolean;
|
||||
|
||||
initBLS: () => Promise<void>;
|
||||
destroy: () => void;
|
||||
}
|
||||
|
||||
export interface IKeypair {
|
||||
publicKey: IPublicKey;
|
||||
privateKey: IPrivateKey;
|
||||
}
|
||||
|
||||
export interface IPublicKey {
|
||||
toBytes(): Buffer;
|
||||
toHex(): string;
|
||||
}
|
||||
|
||||
export interface ISignature {
|
||||
toBytes(): Buffer;
|
||||
toHex(): string;
|
||||
verify(publicKey: IPublicKey, message: Uint8Array): boolean;
|
||||
verifyAggregate(publicKeys: IPublicKey[], message: Uint8Array): boolean;
|
||||
verifyMultiple(publicKeys: IPublicKey[], messages: Uint8Array[]): boolean;
|
||||
}
|
||||
|
||||
export interface IPrivateKey {
|
||||
value: any;
|
||||
toPublicKey(): IPublicKey;
|
||||
signMessage(message: Uint8Array): ISignature;
|
||||
toBytes(): Buffer;
|
||||
toHex(): string;
|
||||
}
|
|
@ -1,11 +1,11 @@
|
|||
import blst from "../src/blst";
|
||||
import herumi from "../src/herumi";
|
||||
import {IBls} from "../src/interface";
|
||||
|
||||
export type Implementation = "blst" | "herumi";
|
||||
export const implementations: Implementation[] = ["blst", "herumi"];
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
export function getBls(implementation: Implementation) {
|
||||
export function getBls(implementation: Implementation): IBls {
|
||||
switch (implementation) {
|
||||
case "blst":
|
||||
return blst;
|
||||
|
@ -15,17 +15,16 @@ export function getBls(implementation: Implementation) {
|
|||
}
|
||||
|
||||
export function forEachImplementation(
|
||||
implementations: Implementation[],
|
||||
callback: (bls: ReturnType<typeof getBls>, implementation: Implementation) => void
|
||||
): void {
|
||||
for (const implementation of implementations) {
|
||||
describe(implementation, () => {
|
||||
const bls = getBls(implementation);
|
||||
|
||||
if (implementation === "herumi") {
|
||||
before(async () => {
|
||||
await bls.initBLS();
|
||||
});
|
||||
}
|
||||
before(async () => {
|
||||
await bls.initBLS();
|
||||
});
|
||||
|
||||
callback(bls, implementation);
|
||||
});
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {expect} from "chai";
|
||||
import {forEachImplementation} from "../switch";
|
||||
import {IBls} from "../../src/interface";
|
||||
import {getN, randomMessage} from "../util";
|
||||
|
||||
forEachImplementation((bls) => {
|
||||
export function runIndexTests(bls: IBls) {
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
function getRandomData() {
|
||||
const sk = bls.PrivateKey.fromKeygen();
|
||||
|
@ -95,4 +95,4 @@ forEachImplementation((bls) => {
|
|||
expect(isValid).to.be.false;
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,27 +1,27 @@
|
|||
import {expect} from "chai";
|
||||
import {forEachImplementation} from "../switch";
|
||||
// import {expect} from "chai";
|
||||
// import {IBls} from "../../src/interface";
|
||||
|
||||
forEachImplementation((bls) => {
|
||||
describe("Keypair", () => {
|
||||
it("should create from private and public key", () => {
|
||||
const sk = bls.PrivateKey.fromKeygen();
|
||||
const sk2 = bls.PrivateKey.fromKeygen();
|
||||
const pk = sk.toPublicKey();
|
||||
// export function runKeypairTests(bls: IBls) {
|
||||
// describe("Keypair", () => {
|
||||
// it("should create from private and public key", () => {
|
||||
// const sk = bls.PrivateKey.fromKeygen();
|
||||
// const sk2 = bls.PrivateKey.fromKeygen();
|
||||
// const pk = sk.toPublicKey();
|
||||
|
||||
const keypair = new bls.Keypair(sk as any, pk as any);
|
||||
// const keypair = new bls.Keypair(sk, pk);
|
||||
|
||||
expect(keypair.publicKey).to.be.equal(pk);
|
||||
expect(keypair.privateKey).to.be.equal(sk);
|
||||
expect(keypair.privateKey).to.not.be.equal(sk2);
|
||||
});
|
||||
// expect(keypair.publicKey).to.be.equal(pk);
|
||||
// expect(keypair.privateKey).to.be.equal(sk);
|
||||
// expect(keypair.privateKey).to.not.be.equal(sk2);
|
||||
// });
|
||||
|
||||
it("should create from PrivateKey", () => {
|
||||
const sk = bls.PrivateKey.fromKeygen();
|
||||
const pk = sk.toPublicKey();
|
||||
// it("should create from PrivateKey", () => {
|
||||
// const sk = bls.PrivateKey.fromKeygen();
|
||||
// const pk = sk.toPublicKey();
|
||||
|
||||
const keypair = new bls.Keypair(sk as any);
|
||||
// const keypair = new bls.Keypair(sk as any);
|
||||
|
||||
expect(keypair.publicKey.toHex()).to.equal(pk.toHex());
|
||||
});
|
||||
});
|
||||
});
|
||||
// expect(keypair.publicKey.toHex()).to.equal(pk.toHex());
|
||||
// });
|
||||
// });
|
||||
// }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {expect} from "chai";
|
||||
import {forEachImplementation} from "../switch";
|
||||
import {IBls} from "../../src/interface";
|
||||
|
||||
forEachImplementation((bls) => {
|
||||
export function runPrivateKeyTests(bls: IBls) {
|
||||
describe("PrivateKey", () => {
|
||||
it("should generate fromKeygen private key", () => {
|
||||
const privateKey1 = bls.PrivateKey.fromKeygen();
|
||||
|
@ -23,4 +23,4 @@ forEachImplementation((bls) => {
|
|||
expect(() => bls.PrivateKey.fromHex("0x2123")).to.throw();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {expect} from "chai";
|
||||
import {forEachImplementation} from "../switch";
|
||||
import {IBls} from "../../src/interface";
|
||||
|
||||
forEachImplementation((bls) => {
|
||||
export function runPublicKeyTests(bls: IBls) {
|
||||
describe("PublicKey", () => {
|
||||
const publicKey =
|
||||
"0xb6f21199594b56d77670564bf422cb331d5281ca2c1f9a45588a56881d8287ef8619efa6456d6cd2ef61306aa5b21311";
|
||||
|
@ -18,4 +18,4 @@ forEachImplementation((bls) => {
|
|||
bls.PrivateKey.fromKeygen().toPublicKey();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
import {runPrivateKeyTests} from "./privateKey.test";
|
||||
import {runPublicKeyTests} from "./publicKey.test";
|
||||
// import {runKeypairTests} from "./keypair.test";
|
||||
import {runIndexTests} from "./index.test";
|
||||
import {forEachImplementation} from "../switch";
|
||||
|
||||
forEachImplementation(["blst", "herumi"], (bls) => {
|
||||
runPrivateKeyTests(bls);
|
||||
runPublicKeyTests(bls);
|
||||
// runKeypairTests(bls);
|
||||
runIndexTests(bls);
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
import {runPrivateKeyTests} from "./privateKey.test";
|
||||
import {runPublicKeyTests} from "./publicKey.test";
|
||||
// import {runKeypairTests} from "./keypair.test";
|
||||
import {runIndexTests} from "./index.test";
|
||||
import {forEachImplementation} from "../switch";
|
||||
|
||||
forEachImplementation(["herumi"], (bls) => {
|
||||
runPrivateKeyTests(bls);
|
||||
runPublicKeyTests(bls);
|
||||
// runKeypairTests(bls);
|
||||
runIndexTests(bls);
|
||||
});
|
Reference in New Issue