commit
a112b21347
|
@ -13,13 +13,15 @@ module.exports = {
|
|||
},
|
||||
parser: "@typescript-eslint/parser",
|
||||
parserOptions: {
|
||||
ecmaVersion: 10,
|
||||
project: "./tsconfig.json"
|
||||
ecmaVersion: "latest",
|
||||
project: "./tsconfig.json",
|
||||
sourceType: "module",
|
||||
},
|
||||
plugins: [
|
||||
"@typescript-eslint",
|
||||
"eslint-plugin-import",
|
||||
"prettier"
|
||||
"prettier",
|
||||
"@chainsafe/eslint-plugin-node"
|
||||
],
|
||||
extends: [
|
||||
"eslint:recommended",
|
||||
|
@ -33,13 +35,13 @@ module.exports = {
|
|||
"prettier/prettier": "error",
|
||||
//doesnt work, it reports false errors
|
||||
"constructor-super": "off",
|
||||
"@typescript-eslint/class-name-casing": "error",
|
||||
//"@typescript-eslint/class-name-casing": "error",
|
||||
"@typescript-eslint/explicit-function-return-type": ["error", {
|
||||
"allowExpressions": true
|
||||
}],
|
||||
"@typescript-eslint/func-call-spacing": "error",
|
||||
"@typescript-eslint/indent": ["error", 2],
|
||||
"@typescript-eslint/interface-name-prefix": ["error", "always"],
|
||||
//"@typescript-eslint/interface-name-prefix": ["error", "always"],
|
||||
"@typescript-eslint/member-ordering": "error",
|
||||
"@typescript-eslint/no-explicit-any": "error",
|
||||
"@typescript-eslint/no-require-imports": "error",
|
||||
|
@ -47,7 +49,7 @@ module.exports = {
|
|||
"varsIgnorePattern": "^_",
|
||||
"argsIgnorePattern": "^_",
|
||||
}],
|
||||
"@typescript-eslint/ban-ts-ignore": "warn",
|
||||
"@typescript-eslint/ban-ts-comment": "warn",
|
||||
"@typescript-eslint/no-use-before-define": "off",
|
||||
"@typescript-eslint/semi": "error",
|
||||
"@typescript-eslint/type-annotation-spacing": "error",
|
||||
|
@ -76,7 +78,15 @@ module.exports = {
|
|||
"no-prototype-builtins": 0,
|
||||
"prefer-const": "error",
|
||||
"quotes": ["error", "double"],
|
||||
"semi": "off"
|
||||
"semi": "off",
|
||||
"@chainsafe/node/file-extension-in-import": [
|
||||
"error",
|
||||
"always",
|
||||
{
|
||||
"esm": true
|
||||
}
|
||||
],
|
||||
"import/no-unresolved": "off",
|
||||
},
|
||||
"overrides": [
|
||||
{
|
|
@ -9,7 +9,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
node: [12, 14]
|
||||
node: [14, 16]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
|
|
|
@ -1,2 +1,6 @@
|
|||
extension: ["ts"]
|
||||
colors: true
|
||||
require: ts-node/register
|
||||
node-option:
|
||||
- "experimental-specifier-resolution=node"
|
||||
- "loader=ts-node/esm"
|
||||
|
||||
|
|
46
README.md
46
README.md
|
@ -2,8 +2,8 @@
|
|||
|
||||
[![codecov](https://codecov.io/gh/ChainSafe/lodestar/branch/master/graph/badge.svg)](https://codecov.io/gh/ChainSafe/lodestar)
|
||||
![ETH2.0_Spec_Version 1.0.0](https://img.shields.io/badge/ETH2.0_Spec_Version-1.0.0-2e86c1.svg)
|
||||
![ES Version](https://img.shields.io/badge/ES-2017-yellow)
|
||||
![Node Version](https://img.shields.io/badge/node-12.x-green)
|
||||
![ES Version](https://img.shields.io/badge/ES-2022-yellow)
|
||||
![Node Version](https://img.shields.io/badge/node-14.8-green)
|
||||
|
||||
Javascript library for BLS (Boneh-Lynn-Shacham) signatures and signature aggregation, tailored for use in Eth2.
|
||||
|
||||
|
@ -19,10 +19,10 @@ To use native bindings you must install peer dependency `@chainsafe/blst`
|
|||
yarn add @chainsafe/bls @chainsafe/blst
|
||||
```
|
||||
|
||||
You must initialize the library once in your application before using it. The result is cached and use across all your imports
|
||||
By default, native bindings will be used if in NodeJS and they are installed. A WASM implementation ("herumi") is used as a fallback in case any error occurs.
|
||||
|
||||
```ts
|
||||
import {init, SecretKey, secretKeyToPublicKey, sign, verify} from "@chainsafe/bls";
|
||||
import {SecretKey, secretKeyToPublicKey, sign, verify} from "@chainsafe/bls";
|
||||
|
||||
(async () => {
|
||||
await init("herumi");
|
||||
|
@ -45,48 +45,52 @@ import {init, SecretKey, secretKeyToPublicKey, sign, verify} from "@chainsafe/bl
|
|||
|
||||
### Browser
|
||||
|
||||
If you are in the browser, import from `/browser` to import directly the WASM version
|
||||
If you are in the browser, import from `/herumi` to explicitly import the WASM version
|
||||
|
||||
```ts
|
||||
import bls from "@chainsafe/bls/browser";
|
||||
import bls from "@chainsafe/bls/herumi";
|
||||
```
|
||||
|
||||
### Native bindings only
|
||||
|
||||
If you are in NodeJS, import from `/node` to skip browser specific code. Also install peer dependency `@chainsafe/blst` which has the native bindings
|
||||
If you are in NodeJS, import from `/blst-native` to explicitly import the native bindings. Also install peer dependency `@chainsafe/blst` which has the native bindings
|
||||
|
||||
```bash
|
||||
yarn add @chainsafe/bls @chainsafe/blst
|
||||
```
|
||||
|
||||
```ts
|
||||
import bls from "@chainsafe/bls/node";
|
||||
import bls from "@chainsafe/bls/blst-native";
|
||||
```
|
||||
|
||||
### Native bindings + WASM fallback
|
||||
### Get implementation at runtime
|
||||
|
||||
If you want to offer a fallback in NodeJS, first try to load native bindings and then fallback to WASM. Also install peer dependency `@chainsafe/blst` which has the native bindings
|
||||
|
||||
```bash
|
||||
yarn add @chainsafe/bls @chainsafe/blst
|
||||
```
|
||||
If you need to get a bls implementation at runtime, import from `/getImplementation`.
|
||||
|
||||
```ts
|
||||
import {init} from "@chainsafe/bls";
|
||||
import {getImplementation} from "@chainsafe/bls/getImplementation";
|
||||
|
||||
try {
|
||||
await init("blst-native");
|
||||
} catch (e) {
|
||||
const bls = await getImplementation("herumi");
|
||||
```
|
||||
|
||||
### Switchable singleton
|
||||
|
||||
If you need a singleton that is switchable at runtime (the default behavior in <=v6), import from `/switchable`.
|
||||
|
||||
```ts
|
||||
import bls, {init} from "@chainsafe/bls/switchable";
|
||||
|
||||
// here `bls` is uninitialized
|
||||
await init("herumi");
|
||||
console.warn("Using WASM");
|
||||
}
|
||||
// here `bls` is initialized
|
||||
// now other modules can `import bls from "@chainsafe/bls/switchable"` and it will be initialized
|
||||
```
|
||||
|
||||
The API is identical for all implementations.
|
||||
|
||||
## Benchmarks
|
||||
|
||||
- `blst`: [src/blst](src/blst) (node.js-only, bindings to C via node-gyp)
|
||||
- `blst`: [src/blst-native](src/blst-native) (node.js-only, bindings to C via node-gyp)
|
||||
- `herumi`: [src/herumi](src/herumi) (node.js & browser, wasm)
|
||||
- `noble`: [noble-bls12-381](https://github.com/paulmillr/noble-bls12-381) (node.js & browser, pure JS)
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {runBenchmark} from "./runner";
|
||||
import {runForAllImplementations} from "../test/switch";
|
||||
import {PublicKey, Signature} from "../src/interface";
|
||||
import {aggCount} from "./params";
|
||||
import {runBenchmark} from "./runner.js";
|
||||
import {runForAllImplementations} from "../test/switch.js";
|
||||
import {PublicKey, Signature} from "../src/types.js";
|
||||
import {aggCount} from "./params.js";
|
||||
|
||||
(async function () {
|
||||
await runForAllImplementations(async (bls, implementation) => {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import {runBenchmark} from "./runner";
|
||||
import {range, randomMessage} from "../test/util";
|
||||
import {runBenchmark} from "./runner.js";
|
||||
import {range, randomMessage} from "../test/util.js";
|
||||
import {generateRandomSecretKey} from "@chainsafe/bls-keygen";
|
||||
import * as noble from "noble-bls12-381";
|
||||
import {aggCount, runsNoble} from "./params";
|
||||
import {aggCount, runsNoble} from "./params.js";
|
||||
|
||||
(async function () {
|
||||
{
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"name": "bls-libs-benchmark",
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
"exports": "./index.js",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"benchmark": "ts-node index",
|
||||
"benchmark:all": "ts-node index && ts-node noble && ts-node verifyMultipleSignaturesSavings"
|
||||
"benchmark": "ts-node-esm index",
|
||||
"benchmark:all": "ts-node-esm index && ts-node-esm noble && ts-node-esm verifyMultipleSignaturesSavings"
|
||||
},
|
||||
"dependencies": {
|
||||
"noble-bls12-381": "^0.7.2"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {runForAllImplementations} from "../test/switch";
|
||||
import {range, randomMessage} from "../test/util";
|
||||
import {runForAllImplementations} from "../test/switch.js";
|
||||
import {range, randomMessage} from "../test/util.js";
|
||||
|
||||
(async function () {
|
||||
console.log("verifyMultipleSignatures savings");
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
export * from "./lib/blst";
|
|
@ -1 +0,0 @@
|
|||
module.exports = require("./lib/blst");
|
|
@ -1 +0,0 @@
|
|||
export * from "./lib/herumi";
|
|
@ -1 +0,0 @@
|
|||
export * from "./lib/herumi";
|
|
@ -1 +0,0 @@
|
|||
export * from "./lib/herumi";
|
|
@ -1,20 +1,29 @@
|
|||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
const webpackConfig = require("./webpack.config");
|
||||
const webpackConfig = require("./webpack.config.cjs");
|
||||
|
||||
module.exports = function (config) {
|
||||
config.set({
|
||||
basePath: "",
|
||||
frameworks: ["mocha", "chai"],
|
||||
files: ["test/unit-web/run-web-implementation.test.ts", "test/unit/index-named-exports.test.ts"],
|
||||
frameworks: [
|
||||
"webpack",
|
||||
"mocha",
|
||||
"chai",
|
||||
],
|
||||
files: [
|
||||
"test/unit-web/run-web-implementation.test.ts",
|
||||
"test/unit/index-named-exports.test.ts",
|
||||
],
|
||||
exclude: [],
|
||||
preprocessors: {
|
||||
"test/**/*.ts": ["webpack"],
|
||||
},
|
||||
webpack: {
|
||||
mode: "production",
|
||||
node: webpackConfig.node,
|
||||
module: webpackConfig.module,
|
||||
resolve: webpackConfig.resolve,
|
||||
experiments: webpackConfig.experiments,
|
||||
optimization: webpackConfig.optimization,
|
||||
stats: {warnings:false},
|
||||
},
|
||||
reporters: ["spec"],
|
||||
|
78
package.json
78
package.json
|
@ -2,10 +2,42 @@
|
|||
"name": "@chainsafe/bls",
|
||||
"version": "6.0.3",
|
||||
"description": "Implementation of bls signature verification for ethereum 2.0",
|
||||
"main": "lib/index.js",
|
||||
"engines": {
|
||||
"node": ">=14.8.0"
|
||||
},
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"import": "./lib/index.js"
|
||||
},
|
||||
"./types": {
|
||||
"import": "./lib/types.js"
|
||||
},
|
||||
"./getImplementation": {
|
||||
"import": "./lib/getImplementation.js"
|
||||
},
|
||||
"./switchable": {
|
||||
"import": "./lib/switchable.js"
|
||||
},
|
||||
"./blst-native": {
|
||||
"import": "./lib/blst-native/index.js"
|
||||
},
|
||||
"./herumi": {
|
||||
"import": "./lib/herumi/index.js"
|
||||
}
|
||||
},
|
||||
"types": "lib/index.d.ts",
|
||||
"module": "./browser",
|
||||
"browser": "./browser",
|
||||
"typesVersions": {
|
||||
"*": {
|
||||
"*": [
|
||||
"*",
|
||||
"lib/*",
|
||||
"lib/*/index"
|
||||
]
|
||||
}
|
||||
},
|
||||
"module": "./lib/index.js",
|
||||
"browser": "./lib/herumi.js",
|
||||
"homepage": "https://github.com/chainsafe/bls",
|
||||
"author": "ChainSafe Systems",
|
||||
"license": "Apache-2.0",
|
||||
|
@ -24,18 +56,19 @@
|
|||
],
|
||||
"scripts": {
|
||||
"clean": "rm -rf lib && rm -rf dist && rm -f tsconfig.tsbuildinfo",
|
||||
"check-build": "node -e \"(async function() { await import('./lib/index.js') })()\"",
|
||||
"build": "tsc --incremental --project tsconfig.build.json",
|
||||
"lint": "eslint --color --ext .ts src/ test/",
|
||||
"lint:fix": "yarn run lint --fix",
|
||||
"prepublishOnly": "yarn build",
|
||||
"test:web": "karma start",
|
||||
"test:web": "karma start karma.conf.cjs",
|
||||
"test:unit": "mocha 'test/unit/**/*.test.ts'",
|
||||
"test:coverage": "nyc --cache-dir .nyc_output/.cache -r lcov -e .ts mocha 'test/unit/**/*.test.ts' && nyc report",
|
||||
"test:spec": "mocha 'test/spec/**/*.test.ts'",
|
||||
"test": "yarn run test:unit && yarn run test:spec",
|
||||
"download-test-cases": "ts-node test/downloadSpecTests.ts",
|
||||
"download-test-cases": "ts-node-esm test/downloadSpecTests.ts",
|
||||
"coverage": "codecov -F bls",
|
||||
"benchmark": "ts-node benchmark",
|
||||
"benchmark": "ts-node-esm benchmark",
|
||||
"benchmark:all": "cd benchmark && yarn install && yarn benchmark:all"
|
||||
},
|
||||
"dependencies": {
|
||||
|
@ -45,35 +78,38 @@
|
|||
},
|
||||
"devDependencies": {
|
||||
"@chainsafe/blst": "^0.2.0",
|
||||
"@chainsafe/eslint-plugin-node": "^11.2.3",
|
||||
"@chainsafe/lodestar-spec-test-util": "^0.18.0",
|
||||
"@chainsafe/threads": "^1.9.0",
|
||||
"@types/chai": "^4.2.9",
|
||||
"@types/mocha": "^8.0.4",
|
||||
"@types/randombytes": "^2.0.0",
|
||||
"@typescript-eslint/eslint-plugin": "^2.20.0",
|
||||
"@typescript-eslint/parser": "^2.20.0",
|
||||
"chai": "^4.2.0",
|
||||
"eslint": "^6.8.0",
|
||||
"@typescript-eslint/eslint-plugin": "^4.31.1",
|
||||
"@typescript-eslint/parser": "^4.31.1",
|
||||
"buffer": "^6.0.3",
|
||||
"chai": "^4.3.6",
|
||||
"eslint": "^7.14.0",
|
||||
"eslint-plugin-import": "^2.20.1",
|
||||
"eslint-plugin-prettier": "^3.1.4",
|
||||
"karma": "^6.3.16",
|
||||
"karma": "^6.3.18",
|
||||
"karma-chai": "^0.1.0",
|
||||
"karma-chrome-launcher": "^3.1.0",
|
||||
"karma-cli": "^2.0.0",
|
||||
"karma-mocha": "^1.3.0",
|
||||
"karma-mocha": "^2.0.1",
|
||||
"karma-spec-reporter": "^0.0.32",
|
||||
"karma-webpack": "^4.0.2",
|
||||
"mocha": "^8.2.1",
|
||||
"karma-webpack": "^5.0.0",
|
||||
"mocha": "^9.2.2",
|
||||
"nyc": "^15.0.0",
|
||||
"prettier": "^2.1.2",
|
||||
"threads": "^1.6.3",
|
||||
"ts-loader": "^6.2.1",
|
||||
"ts-node": "^8.6.2",
|
||||
"typescript": "^3.7.5",
|
||||
"webpack": "^4.30.0",
|
||||
"webpack-cli": "^3.3.2"
|
||||
"resolve-typescript-plugin": "^1.2.0",
|
||||
"ts-loader": "^9.2.8",
|
||||
"ts-node": "^10.7.0",
|
||||
"typescript": "^4.6.3",
|
||||
"webpack": "^5.72.0",
|
||||
"webpack-cli": "^4.9.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"mocha": "^8.2.1",
|
||||
"mocha": "^9.2.2",
|
||||
"v8-profiler-next": "1.3.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
|
|
14
register.js
14
register.js
|
@ -1,14 +0,0 @@
|
|||
const {init} = require("./lib");
|
||||
|
||||
// -----------------------------------------
|
||||
// To be used in NodeJS testing environments
|
||||
// node -r @chainsafe/bls/register
|
||||
// -----------------------------------------
|
||||
|
||||
// blst-native initialization is syncronous
|
||||
// Initialize bls here instead of in before() so it's available inside describe() blocks
|
||||
init("blst-native").catch((e) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
});
|
|
@ -0,0 +1,19 @@
|
|||
import {SecretKey} from "./secretKey.js";
|
||||
import {PublicKey} from "./publicKey.js";
|
||||
import {Signature} from "./signature.js";
|
||||
import {IBls} from "../types.js";
|
||||
import {functionalInterfaceFactory} from "../functional.js";
|
||||
export * from "../constants.js";
|
||||
|
||||
export {SecretKey, PublicKey, Signature};
|
||||
|
||||
export const bls: IBls = {
|
||||
implementation: "blst-native",
|
||||
SecretKey,
|
||||
PublicKey,
|
||||
Signature,
|
||||
|
||||
...functionalInterfaceFactory({SecretKey, PublicKey, Signature}),
|
||||
};
|
||||
|
||||
export default bls;
|
|
@ -1,7 +1,7 @@
|
|||
import * as blst from "@chainsafe/blst";
|
||||
import {EmptyAggregateError} from "../errors";
|
||||
import {bytesToHex, hexToBytes} from "../helpers";
|
||||
import {PointFormat, PublicKey as IPublicKey} from "../interface";
|
||||
import {EmptyAggregateError} from "../errors.js";
|
||||
import {bytesToHex, hexToBytes} from "../helpers/index.js";
|
||||
import {PointFormat, PublicKey as IPublicKey} from "../types.js";
|
||||
|
||||
export class PublicKey extends blst.PublicKey implements IPublicKey {
|
||||
constructor(value: ConstructorParameters<typeof blst.PublicKey>[0]) {
|
|
@ -1,10 +1,10 @@
|
|||
import * as blst from "@chainsafe/blst";
|
||||
import {bytesToHex, hexToBytes, isZeroUint8Array, randomBytes} from "../helpers";
|
||||
import {SECRET_KEY_LENGTH} from "../constants";
|
||||
import {SecretKey as ISecretKey} from "../interface";
|
||||
import {PublicKey} from "./publicKey";
|
||||
import {Signature} from "./signature";
|
||||
import {ZeroSecretKeyError} from "../errors";
|
||||
import {bytesToHex, hexToBytes, isZeroUint8Array, randomBytes} from "../helpers/index.js";
|
||||
import {SECRET_KEY_LENGTH} from "../constants.js";
|
||||
import {SecretKey as ISecretKey} from "../types.js";
|
||||
import {PublicKey} from "./publicKey.js";
|
||||
import {Signature} from "./signature.js";
|
||||
import {ZeroSecretKeyError} from "../errors.js";
|
||||
|
||||
export class SecretKey implements ISecretKey {
|
||||
readonly value: blst.SecretKey;
|
|
@ -1,8 +1,8 @@
|
|||
import * as blst from "@chainsafe/blst";
|
||||
import {bytesToHex, hexToBytes} from "../helpers";
|
||||
import {PointFormat, Signature as ISignature} from "../interface";
|
||||
import {PublicKey} from "./publicKey";
|
||||
import {EmptyAggregateError, ZeroSignatureError} from "../errors";
|
||||
import {bytesToHex, hexToBytes} from "../helpers/index.js";
|
||||
import {PointFormat, Signature as ISignature} from "../types.js";
|
||||
import {PublicKey} from "./publicKey.js";
|
||||
import {EmptyAggregateError, ZeroSignatureError} from "../errors.js";
|
||||
|
||||
export class Signature extends blst.Signature implements ISignature {
|
||||
constructor(value: ConstructorParameters<typeof blst.Signature>[0]) {
|
|
@ -1,28 +0,0 @@
|
|||
import {SecretKey} from "./secretKey";
|
||||
import {PublicKey} from "./publicKey";
|
||||
import {Signature} from "./signature";
|
||||
import {IBls} from "../interface";
|
||||
import {functionalInterfaceFactory} from "../functional";
|
||||
export * from "../constants";
|
||||
|
||||
export {SecretKey, PublicKey, Signature};
|
||||
|
||||
export async function init(): Promise<void> {
|
||||
// Native bindings require no init() call
|
||||
}
|
||||
export function destroy(): void {
|
||||
// Native bindings require no destroy() call
|
||||
}
|
||||
|
||||
export const bls: IBls = {
|
||||
implementation: "blst-native",
|
||||
SecretKey,
|
||||
PublicKey,
|
||||
Signature,
|
||||
|
||||
...functionalInterfaceFactory({SecretKey, PublicKey, Signature}),
|
||||
init,
|
||||
destroy,
|
||||
};
|
||||
|
||||
export default bls;
|
|
@ -1,9 +1,10 @@
|
|||
import {IBls} from "./interface";
|
||||
import {validateBytes} from "./helpers";
|
||||
import {NotInitializedError} from "./errors";
|
||||
import {IBls} from "./types.js";
|
||||
import {validateBytes} from "./helpers/index.js";
|
||||
import {NotInitializedError} from "./errors.js";
|
||||
|
||||
// Returned type is enforced at each implementation's index
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
// eslint-disable-next-line max-len
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type,@typescript-eslint/explicit-module-boundary-types
|
||||
export function functionalInterfaceFactory({
|
||||
SecretKey,
|
||||
PublicKey,
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import type {IBls, Implementation} from "./types.js";
|
||||
|
||||
// Thanks https://github.com/iliakan/detect-node/blob/master/index.esm.js
|
||||
const isNode = Object.prototype.toString.call(typeof process !== "undefined" ? process : 0) === "[object process]";
|
||||
|
||||
export async function getImplementation(impl: Implementation = "herumi"): Promise<IBls> {
|
||||
switch (impl) {
|
||||
case "herumi": {
|
||||
return (await import("./herumi/index.js")).bls;
|
||||
}
|
||||
|
||||
case "blst-native":
|
||||
// Lazy import native bindings to prevent automatically importing binding.node files
|
||||
if (!isNode) {
|
||||
throw Error("blst-native is only supported in NodeJS");
|
||||
}
|
||||
return (await import("./blst-native/index.js")).bls;
|
||||
|
||||
default:
|
||||
throw new Error(`Unsupported implementation - ${impl}`);
|
||||
}
|
||||
}
|
|
@ -1,2 +1,2 @@
|
|||
export * from "./hex";
|
||||
export * from "./utils";
|
||||
export * from "./hex.js";
|
||||
export * from "./utils.js";
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
/* eslint-disable require-atomic-updates */
|
||||
import bls from "bls-eth-wasm";
|
||||
import {NotInitializedError} from "../errors";
|
||||
import {NotInitializedError} from "../errors.js";
|
||||
|
||||
type Bls = typeof bls;
|
||||
let blsGlobal: Bls | null = null;
|
||||
|
@ -8,7 +8,6 @@ let blsGlobalPromise: Promise<void> | null = null;
|
|||
|
||||
// Patch to fix multiVerify() calls on a browser with polyfilled NodeJS crypto
|
||||
declare global {
|
||||
// eslint-disable-next-line @typescript-eslint/interface-name-prefix
|
||||
interface Window {
|
||||
msCrypto: typeof window["crypto"];
|
||||
}
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
import {SecretKey} from "./secretKey";
|
||||
import {PublicKey} from "./publicKey";
|
||||
import {Signature} from "./signature";
|
||||
import {init, destroy} from "./context";
|
||||
import {IBls} from "../interface";
|
||||
import {functionalInterfaceFactory} from "../functional";
|
||||
export * from "../constants";
|
||||
import {SecretKey} from "./secretKey.js";
|
||||
import {PublicKey} from "./publicKey.js";
|
||||
import {Signature} from "./signature.js";
|
||||
import {init, destroy} from "./context.js";
|
||||
import {IBls} from "../types.js";
|
||||
import {functionalInterfaceFactory} from "../functional.js";
|
||||
|
||||
await init();
|
||||
|
||||
export * from "../constants.js";
|
||||
|
||||
export {SecretKey, PublicKey, Signature, init, destroy};
|
||||
|
||||
|
@ -15,8 +18,6 @@ export const bls: IBls = {
|
|||
Signature,
|
||||
|
||||
...functionalInterfaceFactory({SecretKey, PublicKey, Signature}),
|
||||
init,
|
||||
destroy,
|
||||
};
|
||||
|
||||
export default bls;
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import {PublicKeyType} from "bls-eth-wasm";
|
||||
import {getContext} from "./context";
|
||||
import {bytesToHex, hexToBytes, isZeroUint8Array} from "../helpers";
|
||||
import {PointFormat, PublicKey as IPublicKey} from "../interface";
|
||||
import {EmptyAggregateError, InvalidLengthError, ZeroPublicKeyError} from "../errors";
|
||||
import {PUBLIC_KEY_LENGTH_COMPRESSED, PUBLIC_KEY_LENGTH_UNCOMPRESSED} from "../constants";
|
||||
import type {PublicKeyType} from "bls-eth-wasm";
|
||||
import {getContext} from "./context.js";
|
||||
import {bytesToHex, hexToBytes, isZeroUint8Array} from "../helpers/index.js";
|
||||
import {PointFormat, PublicKey as IPublicKey} from "../types.js";
|
||||
import {EmptyAggregateError, InvalidLengthError, ZeroPublicKeyError} from "../errors.js";
|
||||
import {PUBLIC_KEY_LENGTH_COMPRESSED, PUBLIC_KEY_LENGTH_UNCOMPRESSED} from "../constants.js";
|
||||
|
||||
export class PublicKey implements IPublicKey {
|
||||
readonly value: PublicKeyType;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
import {SecretKeyType} from "bls-eth-wasm";
|
||||
import type {SecretKeyType} from "bls-eth-wasm";
|
||||
import {generateRandomSecretKey} from "@chainsafe/bls-keygen";
|
||||
import {SECRET_KEY_LENGTH} from "../constants";
|
||||
import {getContext} from "./context";
|
||||
import {PublicKey} from "./publicKey";
|
||||
import {Signature} from "./signature";
|
||||
import {bytesToHex, hexToBytes} from "../helpers";
|
||||
import {SecretKey as ISecretKey} from "../interface";
|
||||
import {InvalidLengthError, ZeroSecretKeyError} from "../errors";
|
||||
import {SECRET_KEY_LENGTH} from "../constants.js";
|
||||
import {getContext} from "./context.js";
|
||||
import {PublicKey} from "./publicKey.js";
|
||||
import {Signature} from "./signature.js";
|
||||
import {bytesToHex, hexToBytes} from "../helpers/index.js";
|
||||
import {SecretKey as ISecretKey} from "../types.js";
|
||||
import {InvalidLengthError, ZeroSecretKeyError} from "../errors.js";
|
||||
|
||||
export class SecretKey implements ISecretKey {
|
||||
readonly value: SecretKeyType;
|
||||
|
@ -35,7 +35,7 @@ export class SecretKey implements ISecretKey {
|
|||
}
|
||||
|
||||
static fromKeygen(entropy?: Uint8Array): SecretKey {
|
||||
const sk = generateRandomSecretKey(entropy && Buffer.from(entropy));
|
||||
const sk = generateRandomSecretKey(entropy);
|
||||
return this.fromBytes(sk);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
import {SignatureType, multiVerify} from "bls-eth-wasm";
|
||||
import {getContext} from "./context";
|
||||
import {PublicKey} from "./publicKey";
|
||||
import {bytesToHex, concatUint8Arrays, hexToBytes, isZeroUint8Array} from "../helpers";
|
||||
import {PointFormat, Signature as ISignature, CoordType} from "../interface";
|
||||
import {EmptyAggregateError, InvalidLengthError, InvalidOrderError} from "../errors";
|
||||
import {SIGNATURE_LENGTH_COMPRESSED, SIGNATURE_LENGTH_UNCOMPRESSED} from "../constants";
|
||||
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 {EmptyAggregateError, InvalidLengthError, InvalidOrderError} from "../errors.js";
|
||||
import {SIGNATURE_LENGTH_COMPRESSED, SIGNATURE_LENGTH_UNCOMPRESSED} from "../constants.js";
|
||||
|
||||
export class Signature implements ISignature {
|
||||
readonly value: SignatureType;
|
||||
|
@ -53,7 +53,8 @@ export class Signature implements ISignature {
|
|||
}
|
||||
|
||||
static verifyMultipleSignatures(sets: {publicKey: PublicKey; message: Uint8Array; signature: Signature}[]): boolean {
|
||||
return multiVerify(
|
||||
const context = getContext();
|
||||
return context.multiVerify(
|
||||
sets.map((s) => s.publicKey.value),
|
||||
sets.map((s) => s.signature.value),
|
||||
sets.map((s) => s.message)
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {bls} from "./index";
|
||||
import {bls} from "./index.js";
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(function (window: any) {
|
||||
|
|
53
src/index.ts
53
src/index.ts
|
@ -1,47 +1,14 @@
|
|||
import {IBls} from "./interface";
|
||||
import {bls as blsHerumi} from "./herumi";
|
||||
import type {IBls} from "./types.js";
|
||||
import {getImplementation} from "./getImplementation.js";
|
||||
|
||||
export type Implementation = "herumi" | "blst-native";
|
||||
// Thanks https://github.com/iliakan/detect-node/blob/master/index.esm.js
|
||||
const isNode = Object.prototype.toString.call(typeof process !== "undefined" ? process : 0) === "[object process]";
|
||||
|
||||
export * from "./interface";
|
||||
let bls: IBls;
|
||||
try {
|
||||
bls = await getImplementation(isNode ? "blst-native" : "herumi");
|
||||
} catch (e) {
|
||||
bls = await getImplementation("herumi");
|
||||
}
|
||||
|
||||
// TODO: Use a Proxy for example to throw an error if it's not initialized yet
|
||||
export const bls: IBls = {} as IBls;
|
||||
export default bls;
|
||||
|
||||
async function getImplementation(impl: Implementation = "herumi"): Promise<IBls> {
|
||||
switch (impl) {
|
||||
case "herumi":
|
||||
await blsHerumi.init();
|
||||
return blsHerumi;
|
||||
|
||||
case "blst-native":
|
||||
// Lazy import native bindings to prevent automatically importing binding.node files
|
||||
if (typeof require !== "function") {
|
||||
throw Error("blst-native is only supported in NodeJS");
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
||||
return require("./blst").bls;
|
||||
|
||||
default:
|
||||
throw new Error(`Unsupported implementation - ${impl}`);
|
||||
}
|
||||
}
|
||||
|
||||
export async function init(impl: Implementation): Promise<void> {
|
||||
// Using Object.assign instead of just bls = getImplementation()
|
||||
// because otherwise the default import breaks. The reference is lost
|
||||
// and the imported object is still undefined after calling init()
|
||||
const blsImpl = await getImplementation(impl);
|
||||
Object.assign(bls, blsImpl);
|
||||
Object.assign(exports, blsImpl);
|
||||
}
|
||||
|
||||
// Proxy named exports, will get set by `Object.assign(exports, blsImpl)`
|
||||
export declare let sign: IBls["sign"];
|
||||
export declare let aggregateSignatures: IBls["aggregateSignatures"];
|
||||
export declare let aggregatePublicKeys: IBls["aggregatePublicKeys"];
|
||||
export declare let verify: IBls["verify"];
|
||||
export declare let verifyAggregate: IBls["verifyAggregate"];
|
||||
export declare let verifyMultiple: IBls["verifyMultiple"];
|
||||
export declare let secretKeyToPublicKey: IBls["secretKeyToPublicKey"];
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
import type {IBls, Implementation} from "./types.js";
|
||||
import {getImplementation} from "./getImplementation.js";
|
||||
|
||||
// TODO: Use a Proxy for example to throw an error if it's not initialized yet
|
||||
const bls: IBls = {} as IBls;
|
||||
export default bls;
|
||||
|
||||
export async function init(impl: Implementation): Promise<void> {
|
||||
// Using Object.assign instead of just bls = getImplementation()
|
||||
// because otherwise the default import breaks. The reference is lost
|
||||
// and the imported object is still undefined after calling init()
|
||||
const blsImpl = await getImplementation(impl);
|
||||
Object.assign(bls, blsImpl);
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
export interface IBls {
|
||||
implementation: Implementation;
|
||||
SecretKey: Omit<typeof SecretKey, "prototype">;
|
||||
PublicKey: Omit<typeof PublicKey, "prototype">;
|
||||
Signature: Omit<typeof Signature, "prototype">;
|
||||
SecretKey: typeof SecretKey;
|
||||
PublicKey: typeof PublicKey;
|
||||
Signature: typeof Signature;
|
||||
|
||||
sign(secretKey: Uint8Array, message: Uint8Array): Uint8Array;
|
||||
aggregatePublicKeys(publicKeys: Uint8Array[]): Uint8Array;
|
||||
|
@ -12,12 +12,11 @@ export interface IBls {
|
|||
verifyMultiple(publicKeys: Uint8Array[], messages: Uint8Array[], signature: Uint8Array): boolean;
|
||||
verifyMultipleSignatures(sets: {publicKey: Uint8Array; message: Uint8Array; signature: Uint8Array}[]): boolean;
|
||||
secretKeyToPublicKey(secretKey: Uint8Array): Uint8Array;
|
||||
|
||||
init(): Promise<void>;
|
||||
destroy(): void;
|
||||
}
|
||||
|
||||
export declare class SecretKey {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private constructor(...value: any);
|
||||
static fromBytes(bytes: Uint8Array): SecretKey;
|
||||
static fromHex(hex: string): SecretKey;
|
||||
static fromKeygen(entropy?: Uint8Array): SecretKey;
|
||||
|
@ -28,6 +27,8 @@ export declare class SecretKey {
|
|||
}
|
||||
|
||||
export declare class PublicKey {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private constructor(...value: any);
|
||||
/** @param type Only for impl `blst-native`. Defaults to `CoordType.jacobian` */
|
||||
static fromBytes(bytes: Uint8Array, type?: CoordType, validate?: boolean): PublicKey;
|
||||
static fromHex(hex: string): PublicKey;
|
||||
|
@ -38,6 +39,8 @@ export declare class PublicKey {
|
|||
}
|
||||
|
||||
export declare class Signature {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
private constructor(...value: any);
|
||||
/** @param type Only for impl `blst-native`. Defaults to `CoordType.affine`
|
||||
* @param validate When using `herumi` implementation, signature validation is always on regardless of this flag. */
|
||||
static fromBytes(bytes: Uint8Array, type?: CoordType, validate?: boolean): Signature;
|
|
@ -1,5 +1,5 @@
|
|||
import {downloadTests} from "@chainsafe/lodestar-spec-test-util";
|
||||
import {SPEC_TEST_VERSION, SPEC_TESTS_DIR, SPEC_TEST_TO_DOWNLOAD} from "./params";
|
||||
import {SPEC_TEST_VERSION, SPEC_TESTS_DIR, SPEC_TEST_TO_DOWNLOAD} from "./params.js";
|
||||
|
||||
/* eslint-disable no-console */
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
import path from "path";
|
||||
import {fileURLToPath} from "url";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export const SPEC_TEST_VERSION = "v1.0.0";
|
||||
export const SPEC_TEST_TO_DOWNLOAD = ["general" as "general"];
|
||||
export const SPEC_TEST_TO_DOWNLOAD = ["general" as const];
|
||||
export const SPEC_TESTS_DIR = path.join(__dirname, "spec-tests");
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import path from "path";
|
||||
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
|
||||
import {bytesToHex, hexToBytes} from "../../src/helpers";
|
||||
import {SPEC_TESTS_DIR} from "../params";
|
||||
import {describeForAllImplementations} from "../switch";
|
||||
import {EmptyAggregateError} from "../../src/errors";
|
||||
import {bytesToHex, hexToBytes} from "../../src/helpers/index.js";
|
||||
import {SPEC_TESTS_DIR} from "../params.js";
|
||||
import {describeForAllImplementations} from "../switch.js";
|
||||
import {EmptyAggregateError} from "../../src/errors.js";
|
||||
|
||||
interface IAggregateSigsTestCase {
|
||||
data: {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import path from "path";
|
||||
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
|
||||
import {hexToBytes} from "../../src/helpers";
|
||||
import {SPEC_TESTS_DIR} from "../params";
|
||||
import {describeForAllImplementations} from "../switch";
|
||||
import {hexToBytes} from "../../src/helpers/index.js";
|
||||
import {SPEC_TESTS_DIR} from "../params.js";
|
||||
import {describeForAllImplementations} from "../switch.js";
|
||||
|
||||
interface IAggregateSigsVerifyTestCase {
|
||||
data: {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import path from "path";
|
||||
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
|
||||
import {hexToBytes} from "../../src/helpers";
|
||||
import {SPEC_TESTS_DIR} from "../params";
|
||||
import {describeForAllImplementations} from "../switch";
|
||||
import {hexToBytes} from "../../src/helpers/index.js";
|
||||
import {SPEC_TESTS_DIR} from "../params.js";
|
||||
import {describeForAllImplementations} from "../switch.js";
|
||||
import {CoordType} from "@chainsafe/blst";
|
||||
|
||||
interface IAggregateSigsVerifyTestCase {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import path from "path";
|
||||
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
|
||||
import {bytesToHex, hexToBytes} from "../../src/helpers";
|
||||
import {SPEC_TESTS_DIR} from "../params";
|
||||
import {describeForAllImplementations} from "../switch";
|
||||
import {ZeroSecretKeyError} from "../../src/errors";
|
||||
import {bytesToHex, hexToBytes} from "../../src/helpers/index.js";
|
||||
import {SPEC_TESTS_DIR} from "../params.js";
|
||||
import {describeForAllImplementations} from "../switch.js";
|
||||
import {ZeroSecretKeyError} from "../../src/errors.js";
|
||||
|
||||
interface ISignMessageTestCase {
|
||||
data: {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import path from "path";
|
||||
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
|
||||
import {hexToBytes} from "../../src/helpers";
|
||||
import {SPEC_TESTS_DIR} from "../params";
|
||||
import {describeForAllImplementations} from "../switch";
|
||||
import {hexToBytes} from "../../src/helpers/index.js";
|
||||
import {SPEC_TESTS_DIR} from "../params.js";
|
||||
import {describeForAllImplementations} from "../switch.js";
|
||||
|
||||
interface IVerifyTestCase {
|
||||
data: {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import blst from "../src/blst";
|
||||
import herumi from "../src/herumi";
|
||||
import {IBls} from "../src/interface";
|
||||
import blst from "../src/blst-native/index.js";
|
||||
import herumi from "../src/herumi/index.js";
|
||||
import {IBls} from "../src/types.js";
|
||||
|
||||
export type Implementation = "blst" | "herumi";
|
||||
|
||||
|
@ -19,7 +19,6 @@ export async function runForAllImplementations(
|
|||
): Promise<void> {
|
||||
for (const implementation of ["blst", "herumi"] as Implementation[]) {
|
||||
const bls = getBls(implementation);
|
||||
await bls.init();
|
||||
callback(bls, implementation);
|
||||
}
|
||||
}
|
||||
|
@ -27,10 +26,6 @@ export async function runForAllImplementations(
|
|||
export function describeForAllImplementations(callback: (bls: IBls) => void): void {
|
||||
runForAllImplementations((bls, implementation) => {
|
||||
describe(implementation, function () {
|
||||
before(async () => {
|
||||
await bls.init();
|
||||
});
|
||||
|
||||
try {
|
||||
callback(bls);
|
||||
} catch (e) {
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
import herumi from "../../src/herumi";
|
||||
import {runSecretKeyTests} from "../unit/secretKey.test";
|
||||
import {runPublicKeyTests} from "../unit/publicKey.test";
|
||||
import {runIndexTests} from "../unit/index.test";
|
||||
import {runSecretKeyTests} from "../unit/secretKey.test.js";
|
||||
import {runPublicKeyTests} from "../unit/publicKey.test.js";
|
||||
import {runIndexTests} from "../unit/index.test.js";
|
||||
|
||||
// This file is intended to be compiled and run by Karma
|
||||
// Do not import the node.bindings or it will break with:
|
||||
// Error: BLST bindings loader should only run in a NodeJS context: process.platform
|
||||
describe("herumi", () => {
|
||||
before(async () => {
|
||||
// For consistency with describeForAllImplementations
|
||||
// eslint-disable-next-line import/no-named-as-default-member
|
||||
await herumi.init();
|
||||
});
|
||||
|
||||
describe("herumi", async () => {
|
||||
const herumi = (await import("../../src/herumi/index.js")).default;
|
||||
runSecretKeyTests(herumi);
|
||||
runPublicKeyTests(herumi);
|
||||
runIndexTests(herumi);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {expect} from "chai";
|
||||
import {concatUint8Arrays, isZeroUint8Array} from "../../../src/helpers/utils";
|
||||
import {hexToBytesNode} from "../../util";
|
||||
import {concatUint8Arrays, isZeroUint8Array} from "../../../src/helpers/utils.js";
|
||||
import {hexToBytesNode} from "../../util.js";
|
||||
|
||||
describe("helpers / bytes", () => {
|
||||
describe("isZeroUint8Array", () => {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {expect} from "chai";
|
||||
import {hexToBytes, bytesToHex} from "../../../src/helpers/hex";
|
||||
import {hexToBytesNode} from "../../util";
|
||||
import {hexToBytes, bytesToHex} from "../../../src/helpers/hex.js";
|
||||
import {hexToBytesNode} from "../../util.js";
|
||||
|
||||
describe("helpers / hex", () => {
|
||||
const testCases: {id: string; hex: string}[] = [
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
import {expect} from "chai";
|
||||
import {SecretKey, PublicKey, Signature, init, bls} from "../../src";
|
||||
import type {SecretKey, PublicKey, Signature, IBls} from "../../src/types.js";
|
||||
|
||||
describe("types named exports", async () => {
|
||||
let bls: IBls;
|
||||
|
||||
before(async () => {
|
||||
bls = (await import("../../src/index.js")).default;
|
||||
});
|
||||
|
||||
describe("index named exports", () => {
|
||||
it("Classes and methods should be defined", async () => {
|
||||
await init("herumi");
|
||||
|
||||
/**
|
||||
* Sample helper to test argument typing
|
||||
*/
|
||||
|
@ -12,7 +16,7 @@ describe("index named exports", () => {
|
|||
return sig.verify(pk, msg);
|
||||
}
|
||||
|
||||
const sk = SecretKey.fromKeygen();
|
||||
const sk = bls.SecretKey.fromKeygen();
|
||||
const msg = new Uint8Array(32);
|
||||
const sig = sk.sign(msg);
|
||||
const pk = sk.toPublicKey();
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import {expect} from "chai";
|
||||
import {IBls, PointFormat} from "../../src/interface";
|
||||
import {getN, randomMessage, hexToBytesNode} from "../util";
|
||||
import {hexToBytes} from "../../src/helpers";
|
||||
import {maliciousVerifyMultipleSignaturesData} from "../data/malicious-signature-test-data";
|
||||
import {Buffer} from "buffer";
|
||||
import {IBls, PointFormat} from "../../src/types.js";
|
||||
import {getN, randomMessage} from "../util.js";
|
||||
import {hexToBytes} from "../../src/helpers/index.js";
|
||||
import {maliciousVerifyMultipleSignaturesData} from "../data/malicious-signature-test-data.js";
|
||||
|
||||
export function runIndexTests(bls: IBls): void {
|
||||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
|
||||
|
@ -178,13 +179,13 @@ export function runIndexTests(bls: IBls): void {
|
|||
"0x0a1a1c26055a329817a5759d877a2795f9499b97d6056edde0eea39512f24e8bc874b4471f0501127abb1ea0d9f68ac111392125a1c3750363c2c97d9650fb78696e6428db8ff9efaf0471cbfd20324916ab545746db83756d335e92f9e8c8b8";
|
||||
|
||||
it("Should serialize comp pubkey", () => {
|
||||
const sk = bls.SecretKey.fromBytes(hexToBytesNode(skHex));
|
||||
const sk = bls.SecretKey.fromBytes(hexToBytes(skHex));
|
||||
const pkHexComp = sk.toPublicKey().toHex(PointFormat.compressed);
|
||||
expect(pkHexComp).to.equal(pkHexCompExpected, "Wrong pkHexComp");
|
||||
});
|
||||
|
||||
it("Should serialize uncomp pubkey", () => {
|
||||
const sk = bls.SecretKey.fromBytes(hexToBytesNode(skHex));
|
||||
const sk = bls.SecretKey.fromBytes(hexToBytes(skHex));
|
||||
const pkHexUncomp = sk.toPublicKey().toHex(PointFormat.uncompressed);
|
||||
expect(pkHexUncomp).to.equal(pkHexUncompExpected, "Wrong pkHexUncomp");
|
||||
});
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {expect} from "chai";
|
||||
import {chunkify} from "./utils";
|
||||
import {chunkify} from "./utils.js";
|
||||
|
||||
describe("chunkify", () => {
|
||||
const arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14, 15];
|
||||
|
|
|
@ -1,11 +1,16 @@
|
|||
import {spawn, Pool, Worker, Thread} from "threads";
|
||||
import {Implementation, PointFormat, PublicKey, Signature} from "../../../../src";
|
||||
import {WorkerApi} from "./worker";
|
||||
import {spawn, Pool, Worker, Thread} from "@chainsafe/threads";
|
||||
import {Implementation, PointFormat, PublicKey, Signature} from "../../../../src/types.js";
|
||||
import {WorkerApi} from "./worker.js";
|
||||
|
||||
type ThreadType = {
|
||||
[K in keyof WorkerApi]: (...args: Parameters<WorkerApi[K]>) => Promise<ReturnType<WorkerApi[K]>>;
|
||||
};
|
||||
|
||||
import path from "path";
|
||||
import {fileURLToPath} from "url";
|
||||
|
||||
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
export class BlsMultiThreadNaive {
|
||||
impl: Implementation;
|
||||
pool: Pool<Thread & ThreadType>;
|
||||
|
@ -17,7 +22,18 @@ export class BlsMultiThreadNaive {
|
|||
// THe worker is not able to deserialize from uncompressed
|
||||
// `Error: err _wrapDeserialize`
|
||||
this.format = impl === "blst-native" ? PointFormat.uncompressed : PointFormat.compressed;
|
||||
this.pool = Pool(() => (spawn(new Worker("./worker")) as any) as Promise<Thread & ThreadType>, workerCount);
|
||||
this.pool = Pool(
|
||||
() =>
|
||||
(spawn(
|
||||
// There is still an annoyance dealing with ESM imports here:
|
||||
// threads.js attempts to require.resolve any files passed to Worker, and
|
||||
// the esm module resolver requires the .js extension, even though the .js file does not actually exist.
|
||||
// The solution for now:
|
||||
// Pass in the script path as an absolute path and suppress threads.js default behavior when importing
|
||||
new Worker(path.join(__dirname, "./worker.js"), {suppressResolveScript: true, suppressTranspileTS: true})
|
||||
) as any) as Promise<Thread & ThreadType>,
|
||||
workerCount
|
||||
);
|
||||
}
|
||||
|
||||
async destroy(): Promise<void> {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import {expect} from "chai";
|
||||
import {IBls, PublicKey, Signature} from "../../../../src";
|
||||
import {BlsMultiThreadNaive} from "./index";
|
||||
import {IBls} from "../../../../src/types.js";
|
||||
import type {PublicKey, Signature} from "../../../../src/types.js";
|
||||
import {BlsMultiThreadNaive} from "./index.js";
|
||||
|
||||
export function runMultithreadTests(bls: IBls): void {
|
||||
describe("bls pool naive", function () {
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {expose} from "threads/worker";
|
||||
import {bls, init, CoordType, Implementation} from "../../../../src";
|
||||
import {expose} from "@chainsafe/threads/worker";
|
||||
import {CoordType, Implementation} from "../../../../src/types.js";
|
||||
import bls, {init} from "../../../../src/switchable.js";
|
||||
|
||||
export type WorkerApi = typeof workerApi;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {expect} from "chai";
|
||||
import {IBls} from "../../src/interface";
|
||||
import {IBls} from "../../src/types.js";
|
||||
|
||||
export function runPublicKeyTests(bls: IBls): void {
|
||||
describe("PublicKey", () => {
|
||||
|
|
|
@ -2,7 +2,7 @@ import {runSecretKeyTests} from "./secretKey.test";
|
|||
import {runPublicKeyTests} from "./publicKey.test";
|
||||
import {runIndexTests} from "./index.test";
|
||||
import {runMultithreadTests} from "./multithread/naive/naive.test";
|
||||
import {describeForAllImplementations} from "../switch";
|
||||
import {describeForAllImplementations} from "../switch.js";
|
||||
|
||||
// Import test's bls lib lazily to prevent breaking test with Karma
|
||||
describeForAllImplementations((bls) => {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import {expect} from "chai";
|
||||
import {IBls} from "../../src/interface";
|
||||
import {IBls} from "../../src/types.js";
|
||||
|
||||
export function runSecretKeyTests(bls: IBls): void {
|
||||
describe("SecretKey", () => {
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import {randomBytes} from "../src/helpers";
|
||||
import {randomBytes} from "../src/helpers/index.js";
|
||||
|
||||
export function randomMessage(): Uint8Array {
|
||||
return randomBytes(32);
|
||||
|
|
|
@ -3,7 +3,8 @@
|
|||
"compilerOptions": {
|
||||
"outDir": "lib",
|
||||
"target": "es2019",
|
||||
"module": "commonjs",
|
||||
"module": "esnext",
|
||||
"moduleResolution": "Node",
|
||||
"pretty": true,
|
||||
"lib": ["esnext.bigint", "DOM"],
|
||||
"typeRoots": ["./node_modules/@types"],
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
const ResolveTypeScriptPlugin = require("resolve-typescript-plugin");
|
||||
|
||||
module.exports = {
|
||||
entry: "./src/index.ts",
|
||||
mode: "production",
|
||||
output: {
|
||||
filename: "dist/bundle.js",
|
||||
},
|
||||
module: {
|
||||
rules: [{test: /\.(ts)$/, use: {loader: "ts-loader", options: {transpileOnly: true}}}],
|
||||
},
|
||||
optimization: {
|
||||
// Disable minification for better debugging on Karma tests
|
||||
minimize: false,
|
||||
//splitChunks: false, runtimeChunk: false,
|
||||
},
|
||||
devtool: "source-map",
|
||||
resolve: {
|
||||
plugins: [new ResolveTypeScriptPlugin()],
|
||||
fallback: {
|
||||
crypto: false,
|
||||
fs: false,
|
||||
path: false,
|
||||
},
|
||||
},
|
||||
experiments: {
|
||||
topLevelAwait: true,
|
||||
},
|
||||
};
|
|
@ -1,21 +0,0 @@
|
|||
module.exports = {
|
||||
entry: "./src/index.ts",
|
||||
mode: "production",
|
||||
node: {
|
||||
fs: "empty",
|
||||
},
|
||||
output: {
|
||||
filename: "dist/bundle.js",
|
||||
},
|
||||
resolve: {
|
||||
extensions: [".ts", ".js"],
|
||||
},
|
||||
module: {
|
||||
rules: [{test: /\.ts$/, use: {loader: "ts-loader", options: {transpileOnly: true}}}],
|
||||
},
|
||||
optimization: {
|
||||
// Disable minification for better debugging on Karma tests
|
||||
minimize: false,
|
||||
},
|
||||
devtool: "source-map",
|
||||
};
|
Reference in New Issue