Merge pull request #28 from ChainSafe/prettier

Add Prettier eslint plugin
This commit is contained in:
Lion - dapplion 2020-11-05 21:52:10 +00:00 committed by GitHub
commit 7ace4c55cc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 159 additions and 204 deletions

View File

@ -18,7 +18,8 @@ module.exports = {
}, },
plugins: [ plugins: [
"@typescript-eslint", "@typescript-eslint",
"eslint-plugin-import" "eslint-plugin-import",
"prettier"
], ],
extends: [ extends: [
"eslint:recommended", "eslint:recommended",
@ -29,6 +30,7 @@ module.exports = {
], ],
settings: {}, settings: {},
rules: { rules: {
"prettier/prettier": "error",
//doesnt work, it reports false errors //doesnt work, it reports false errors
"constructor-super": "off", "constructor-super": "off",
"@typescript-eslint/class-name-casing": "error", "@typescript-eslint/class-name-casing": "error",

9
.prettierrc.yml Normal file
View File

@ -0,0 +1,9 @@
printWidth: 120
tabWidth: 2
useTabs: false
semi: true
singleQuote: false
quoteProps: "as-needed"
trailingComma: "es5"
bracketSpacing: false
arrowParens: "always"

View File

@ -10,22 +10,23 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [4.0.0] - 2020-08-31 ## [4.0.0] - 2020-08-31
### BREAKING CHANGES ### BREAKING CHANGES
* Signature.verifyAggregate now takes decompressed pubkeys instead of raw bytes of compressed key
- Signature.verifyAggregate now takes decompressed pubkeys instead of raw bytes of compressed key
## [3.0.0] - 2020-07-31 ## [3.0.0] - 2020-07-31
### BREAKING CHANGES ### BREAKING CHANGES
* Update bls-keygen to latest EIP-2333 standard ([55dd5d](https://github.com/chainsafe/bls/commit/55dd5d)) - Update bls-keygen to latest EIP-2333 standard ([55dd5d](https://github.com/chainsafe/bls/commit/55dd5d))
## [2.0.0] - 2020-05-21 ## [2.0.0] - 2020-05-21
Compatible with [Eth2 spec 0.12.0](https://github.com/ethereum/eth2.0-specs/blob/v0.12.0/specs/phase0/beacon-chain.md#bls-signatures) Compatible with [Eth2 spec 0.12.0](https://github.com/ethereum/eth2.0-specs/blob/v0.12.0/specs/phase0/beacon-chain.md#bls-signatures)
and [IETF draft bls specification](https://github.com/ethereum/eth2.0-specs/blob/v0.12.0/specs/phase0/beacon-chain.md#bls-signatures) and [IETF draft bls specification](https://github.com/ethereum/eth2.0-specs/blob/v0.12.0/specs/phase0/beacon-chain.md#bls-signatures)
## [1.0.0] - 2020-02-25 ## [1.0.0] - 2020-02-25
Compatible with [Eth2 spec 0.10.1](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#bls-signatures) Compatible with [Eth2 spec 0.10.1](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#bls-signatures)
and [IETF draft bls specification](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#bls-signatures) and [IETF draft bls specification](https://github.com/ethereum/eth2.0-specs/blob/v0.10.1/specs/phase0/beacon-chain.md#bls-signatures)
### BREAKING CHANGES ### BREAKING CHANGES
@ -42,4 +43,5 @@ and [IETF draft bls specification](https://github.com/ethereum/eth2.0-specs/blob
## [0.2.2] - 2020-02-12 ## [0.2.2] - 2020-02-12
###Bugfixes: ###Bugfixes:
- updated bls wasm binding version - it isn't catching unhandled rejections and modify stacktraces - updated bls wasm binding version - it isn't catching unhandled rejections and modify stacktraces

View File

@ -8,17 +8,18 @@
This is a Javascript library that implements BLS (Boneh-Lynn-Shacham) signatures and supports signature aggregation. This is a Javascript library that implements BLS (Boneh-Lynn-Shacham) signatures and supports signature aggregation.
| Version | Bls spec version | | Version | Bls spec version |
|----------|:-------------:| | ------- | :--------------: |
| 0.3.x | initial version | | 0.3.x | initial version |
| 1.x.x | draft #6 | | 1.x.x | draft #6 |
| 2.x.x | draft #7 | | 2.x.x | draft #7 |
>[spec](https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/beacon-chain.md#bls-signatures) > [spec](https://github.com/ethereum/eth2.0-specs/blob/v0.11.1/specs/phase0/beacon-chain.md#bls-signatures)
>[test vectors](https://github.com/ethereum/eth2.0-spec-tests/tree/master/tests/bls) > [test vectors](https://github.com/ethereum/eth2.0-spec-tests/tree/master/tests/bls)
## Usage ## Usage
- `yarn add @chainsafe/bls` - `yarn add @chainsafe/bls`
## License ## License

View File

@ -23,10 +23,10 @@
"build": "yarn build-lib && yarn build-types", "build": "yarn build-lib && yarn build-types",
"build:release": "yarn clean && yarn build && yarn build-web", "build:release": "yarn clean && yarn build && yarn build-web",
"build-lib": "babel src -x .ts -d lib", "build-lib": "babel src -x .ts -d lib",
"build-types": "tsc --declaration --incremental --outDir lib --emitDeclarationOnly", "build-types": "tsc --declaration --incremental --outDir lib --project tsconfig.build.json --emitDeclarationOnly",
"build-web": "webpack --mode production --entry ./lib/web.js --output ./dist/bls.min.js", "build-web": "webpack --mode production --entry ./lib/web.js --output ./dist/bls.min.js",
"check-types": "tsc --noEmit", "check-types": "tsc --noEmit",
"lint": "eslint --color --ext .ts src/", "lint": "eslint --color --ext .ts src/ test/",
"lint:fix": "yarn run lint --fix", "lint:fix": "yarn run lint --fix",
"pretest": "yarn check-types", "pretest": "yarn check-types",
"prepublishOnly": "yarn build", "prepublishOnly": "yarn build",
@ -53,6 +53,7 @@
"@babel/preset-typescript": "^7.8.3", "@babel/preset-typescript": "^7.8.3",
"@babel/register": "^7.8.3", "@babel/register": "^7.8.3",
"@chainsafe/as-sha256": "0.2.0", "@chainsafe/as-sha256": "0.2.0",
"@chainsafe/eth2-spec-tests": "0.12.0",
"@chainsafe/lodestar-spec-test-util": "^0.5.0", "@chainsafe/lodestar-spec-test-util": "^0.5.0",
"@types/chai": "^4.2.9", "@types/chai": "^4.2.9",
"@types/mocha": "^7.0.1", "@types/mocha": "^7.0.1",
@ -61,6 +62,7 @@
"chai": "^4.2.0", "chai": "^4.2.0",
"eslint": "^6.8.0", "eslint": "^6.8.0",
"eslint-plugin-import": "^2.20.1", "eslint-plugin-import": "^2.20.1",
"eslint-plugin-prettier": "^3.1.4",
"karma": "^4.4.1", "karma": "^4.4.1",
"karma-chai": "^0.1.0", "karma-chai": "^0.1.0",
"karma-chrome-launcher": "^3.1.0", "karma-chrome-launcher": "^3.1.0",
@ -70,11 +72,11 @@
"karma-webpack": "^4.0.2", "karma-webpack": "^4.0.2",
"mocha": "^6.2.0", "mocha": "^6.2.0",
"nyc": "^15.0.0", "nyc": "^15.0.0",
"prettier": "^2.1.2",
"ts-loader": "^6.2.1", "ts-loader": "^6.2.1",
"ts-node": "^8.6.2", "ts-node": "^8.6.2",
"typescript": "^3.7.5", "typescript": "^3.7.5",
"webpack": "^4.30.0", "webpack": "^4.30.0",
"webpack-cli": "^3.3.2", "webpack-cli": "^3.3.2"
"@chainsafe/eth2-spec-tests": "0.12.0"
} }
} }

View File

@ -31,4 +31,4 @@ export function getContext(): Bls {
throw new Error("BLS not initialized"); throw new Error("BLS not initialized");
} }
return blsGlobal; return blsGlobal;
} }

View File

@ -49,9 +49,11 @@ export function sign(secretKey: Uint8Array, messageHash: Uint8Array): Buffer {
export function aggregateSignatures(signatures: Uint8Array[]): Buffer { export function aggregateSignatures(signatures: Uint8Array[]): Buffer {
assert(signatures && signatures.length > 0, "signatures is null or undefined or empty array"); assert(signatures && signatures.length > 0, "signatures is null or undefined or empty array");
return Signature.aggregate( return Signature.aggregate(
signatures.map((signature): Signature => { signatures.map(
return Signature.fromCompressedBytes(signature); (signature): Signature => {
}) return Signature.fromCompressedBytes(signature);
}
)
).toBytesCompressed(); ).toBytesCompressed();
} }
@ -61,7 +63,7 @@ export function aggregateSignatures(signatures: Uint8Array[]): Buffer {
*/ */
export function aggregatePubkeys(publicKeys: Uint8Array[]): Buffer { export function aggregatePubkeys(publicKeys: Uint8Array[]): Buffer {
assert(publicKeys, "publicKeys is null or undefined"); assert(publicKeys, "publicKeys is null or undefined");
if(publicKeys.length === 0) { if (publicKeys.length === 0) {
return Buffer.alloc(PUBLIC_KEY_LENGTH); return Buffer.alloc(PUBLIC_KEY_LENGTH);
} }
return publicKeys return publicKeys
@ -81,9 +83,10 @@ export function verify(publicKey: Uint8Array, messageHash: Uint8Array, signature
assert(messageHash, "messageHash is null or undefined"); assert(messageHash, "messageHash is null or undefined");
assert(signature, "signature is null or undefined"); assert(signature, "signature is null or undefined");
try { try {
return PublicKey return PublicKey.fromBytes(publicKey).verifyMessage(
.fromBytes(publicKey) Signature.fromCompressedBytes(toBuffer(signature)),
.verifyMessage(Signature.fromCompressedBytes(toBuffer(signature)), toBuffer(messageHash)); toBuffer(messageHash)
);
} catch (e) { } catch (e) {
return false; return false;
} }
@ -100,9 +103,10 @@ export function verifyAggregate(publicKeys: Uint8Array[], messageHash: Uint8Arra
assert(messageHash, "messageHash is null or undefined"); assert(messageHash, "messageHash is null or undefined");
assert(signature, "signature is null or undefined"); assert(signature, "signature is null or undefined");
try { try {
return Signature return Signature.fromCompressedBytes(signature).verifyAggregate(
.fromCompressedBytes(signature) publicKeys.map((pubkey) => PublicKey.fromBytes(pubkey)),
.verifyAggregate(publicKeys.map(pubkey => PublicKey.fromBytes(pubkey)), messageHash); messageHash
);
} catch (e) { } catch (e) {
return false; return false;
} }
@ -125,17 +129,15 @@ export function verifyMultiple(
assert(messageHashes, "messageHash is null or undefined"); assert(messageHashes, "messageHash is null or undefined");
assert(signature, "signature is null or undefined"); assert(signature, "signature is null or undefined");
if(publicKeys.length === 0 || publicKeys.length != messageHashes.length) { if (publicKeys.length === 0 || publicKeys.length != messageHashes.length) {
return false; return false;
} }
try { try {
return Signature return Signature.fromCompressedBytes(toBuffer(signature)).verifyMultiple(
.fromCompressedBytes(toBuffer(signature)) publicKeys.map((key) => PublicKey.fromBytes(toBuffer(key))),
.verifyMultiple( messageHashes.map((m) => toBuffer(m)),
publicKeys.map((key) => PublicKey.fromBytes(toBuffer(key))), fast
messageHashes.map((m) => toBuffer(m)), );
fast
);
} catch (e) { } catch (e) {
return false; return false;
} }
@ -149,5 +151,5 @@ export default {
aggregatePubkeys, aggregatePubkeys,
verify, verify,
verifyAggregate, verifyAggregate,
verifyMultiple verifyMultiple,
}; };

View File

@ -1,16 +1,14 @@
import {PublicKey} from "./publicKey"; import {PublicKey} from "./publicKey";
import {PrivateKey} from "./privateKey"; import {PrivateKey} from "./privateKey";
export class Keypair { export class Keypair {
private readonly _publicKey: PublicKey; private readonly _publicKey: PublicKey;
private readonly _privateKey: PrivateKey; private readonly _privateKey: PrivateKey;
public constructor(privateKey: PrivateKey, publicKey?: PublicKey) { public constructor(privateKey: PrivateKey, publicKey?: PublicKey) {
this._privateKey = privateKey; this._privateKey = privateKey;
if(!publicKey) { if (!publicKey) {
this._publicKey = PublicKey.fromPrivateKey(this._privateKey); this._publicKey = PublicKey.fromPrivateKey(this._privateKey);
} else { } else {
this._publicKey = publicKey; this._publicKey = publicKey;

View File

@ -7,7 +7,6 @@ import {PublicKey} from "./publicKey";
import {Signature} from "./signature"; import {Signature} from "./signature";
export class PrivateKey { export class PrivateKey {
private value: SecretKeyType; private value: SecretKeyType;
protected constructor(value: SecretKeyType) { protected constructor(value: SecretKeyType) {

View File

@ -7,7 +7,6 @@ import {Signature} from "./signature";
import {EMPTY_PUBLIC_KEY} from "./helpers/utils"; import {EMPTY_PUBLIC_KEY} from "./helpers/utils";
export class PublicKey { export class PublicKey {
private value: PublicKeyType; private value: PublicKeyType;
protected constructor(value: PublicKeyType) { protected constructor(value: PublicKeyType) {
@ -21,21 +20,17 @@ export class PublicKey {
public static fromBytes(bytes: Uint8Array): PublicKey { public static fromBytes(bytes: Uint8Array): PublicKey {
const context = getContext(); const context = getContext();
const publicKey = new context.PublicKey(); const publicKey = new context.PublicKey();
if(!EMPTY_PUBLIC_KEY.equals(bytes)) { if (!EMPTY_PUBLIC_KEY.equals(bytes)) {
publicKey.deserialize(bytes); publicKey.deserialize(bytes);
} }
return new PublicKey( return new PublicKey(publicKey);
publicKey
);
} }
public static fromHex(value: string): PublicKey { public static fromHex(value: string): PublicKey {
value = value.replace("0x", ""); value = value.replace("0x", "");
assert(value.length === PUBLIC_KEY_LENGTH * 2); assert(value.length === PUBLIC_KEY_LENGTH * 2);
const context = getContext(); const context = getContext();
return new PublicKey( return new PublicKey(context.deserializeHexStrToPublicKey(value));
context.deserializeHexStrToPublicKey(value)
);
} }
public static fromPublicKeyType(value: PublicKeyType): PublicKey { public static fromPublicKeyType(value: PublicKeyType): PublicKey {

View File

@ -6,7 +6,6 @@ import {PublicKey} from "./publicKey";
import {EMPTY_SIGNATURE} from "./helpers/utils"; import {EMPTY_SIGNATURE} from "./helpers/utils";
export class Signature { export class Signature {
private value: SignatureType; private value: SignatureType;
protected constructor(value: SignatureType) { protected constructor(value: SignatureType) {
@ -15,13 +14,10 @@ export class Signature {
} }
public static fromCompressedBytes(value: Uint8Array): Signature { public static fromCompressedBytes(value: Uint8Array): Signature {
assert( assert(value.length === 2 * FP_POINT_LENGTH, `Signature must have ${2 * FP_POINT_LENGTH} bytes`);
value.length === 2 * FP_POINT_LENGTH,
`Signature must have ${2 * FP_POINT_LENGTH} bytes`
);
const context = getContext(); const context = getContext();
const signature = new context.Signature(); const signature = new context.Signature();
if(!EMPTY_SIGNATURE.equals(value)) { if (!EMPTY_SIGNATURE.equals(value)) {
signature.deserialize(value); signature.deserialize(value);
} }
return new Signature(signature); return new Signature(signature);
@ -35,17 +31,13 @@ export class Signature {
const context = getContext(); const context = getContext();
const signature = new context.Signature(); const signature = new context.Signature();
signature.aggregate(signatures.map((sig) => sig.getValue())); signature.aggregate(signatures.map((sig) => sig.getValue()));
return new Signature( return new Signature(signature);
signature
);
} }
public add(other: Signature): Signature { public add(other: Signature): Signature {
const agg = this.value.clone(); const agg = this.value.clone();
agg.add(other.value); agg.add(other.value);
return new Signature( return new Signature(agg);
agg
);
} }
public getValue(): SignatureType { public getValue(): SignatureType {
@ -61,7 +53,7 @@ export class Signature {
public verifyMultiple(publicKeys: PublicKey[], messages: Uint8Array[], fast = false): boolean { public verifyMultiple(publicKeys: PublicKey[], messages: Uint8Array[], fast = false): boolean {
const msgs = Buffer.concat(messages); const msgs = Buffer.concat(messages);
if(!fast && !getContext().areAllMsgDifferent(msgs)) { if (!fast && !getContext().areAllMsgDifferent(msgs)) {
return false; return false;
} }
return this.value.aggregateVerifyNoCheck( return this.value.aggregateVerifyNoCheck(

View File

@ -15,27 +15,26 @@ before(async function f() {
describeDirectorySpecTest<IAggregateSigsTestCase, string>( describeDirectorySpecTest<IAggregateSigsTestCase, string>(
"BLS - aggregate sigs", "BLS - aggregate sigs",
path.join( path.join(__dirname, "../../node_modules/@chainsafe/eth2-spec-tests/tests/general/phase0/bls/aggregate/small"),
__dirname, (testCase) => {
"../../node_modules/@chainsafe/eth2-spec-tests/tests/general/phase0/bls/aggregate/small"
),
(testCase => {
try { try {
const result = bls.aggregateSignatures(testCase.data.input.map(pubKey => { const result = bls.aggregateSignatures(
return Buffer.from(pubKey.replace("0x", ""), "hex"); testCase.data.input.map((pubKey) => {
})); return Buffer.from(pubKey.replace("0x", ""), "hex");
})
);
return `0x${result.toString("hex")}`; return `0x${result.toString("hex")}`;
} catch (e) { } catch (e) {
if(e.message === "signatures is null or undefined or empty array") { if (e.message === "signatures is null or undefined or empty array") {
return null; return null;
} }
throw e; throw e;
} }
}), },
{ {
inputTypes: { inputTypes: {
data: InputType.YAML, data: InputType.YAML,
}, },
getExpected: (testCase => testCase.data.output) getExpected: (testCase) => testCase.data.output,
} }
); );

View File

@ -2,7 +2,7 @@ import path from "path";
import bls, {initBLS} from "../../src"; import bls, {initBLS} from "../../src";
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util"; import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
interface AggregateSigsVerifyTestCase { interface IAggregateSigsVerifyTestCase {
data: { data: {
input: { input: {
pubkeys: string[]; pubkeys: string[];
@ -21,29 +21,22 @@ before(async function f() {
} }
}); });
describeDirectorySpecTest<AggregateSigsVerifyTestCase, boolean>( describeDirectorySpecTest<IAggregateSigsVerifyTestCase, boolean>(
"BLS - aggregate sigs verify", "BLS - aggregate sigs verify",
path.join( path.join(__dirname, "../../node_modules/@chainsafe/eth2-spec-tests/tests/general/phase0/bls/aggregate_verify/small"),
__dirname, (testCase) => {
"../../node_modules/@chainsafe/eth2-spec-tests/tests/general/phase0/bls/aggregate_verify/small" const pubkeys = testCase.data.input.pubkeys.map((pubkey) => {
),
(testCase => {
const pubkeys = testCase.data.input.pubkeys.map(pubkey => {
return Buffer.from(pubkey.replace("0x", ""), "hex"); return Buffer.from(pubkey.replace("0x", ""), "hex");
}); });
const messages = testCase.data.input.messages.map(msg => { const messages = testCase.data.input.messages.map((msg) => {
return Buffer.from(msg.replace("0x", ""), "hex"); return Buffer.from(msg.replace("0x", ""), "hex");
}); });
return bls.verifyMultiple( return bls.verifyMultiple(pubkeys, messages, Buffer.from(testCase.data.input.signature.replace("0x", ""), "hex"));
pubkeys, },
messages,
Buffer.from(testCase.data.input.signature.replace("0x", ""), "hex"),
);
}),
{ {
inputTypes: { inputTypes: {
data: InputType.YAML, data: InputType.YAML,
}, },
getExpected: (testCase => testCase.data.output) getExpected: (testCase) => testCase.data.output,
} }
); );

View File

@ -2,7 +2,7 @@ import path from "path";
import bls, {initBLS} from "../../src"; import bls, {initBLS} from "../../src";
import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util"; import {describeDirectorySpecTest, InputType} from "@chainsafe/lodestar-spec-test-util";
interface AggregateSigsVerifyTestCase { interface IAggregateSigsVerifyTestCase {
data: { data: {
input: { input: {
pubkeys: string[]; pubkeys: string[];
@ -21,23 +21,23 @@ before(async function f() {
} }
}); });
describeDirectorySpecTest<AggregateSigsVerifyTestCase, boolean>( describeDirectorySpecTest<IAggregateSigsVerifyTestCase, boolean>(
"BLS - aggregate sigs verify", "BLS - aggregate sigs verify",
path.join( path.join(
__dirname, __dirname,
"../../node_modules/@chainsafe/eth2-spec-tests/tests/general/phase0/bls/fast_aggregate_verify/small" "../../node_modules/@chainsafe/eth2-spec-tests/tests/general/phase0/bls/fast_aggregate_verify/small"
), ),
(testCase => { (testCase) => {
return bls.verifyAggregate( return bls.verifyAggregate(
testCase.data.input.pubkeys.map((key) => Buffer.from(key.replace("0x", ""), "hex")), testCase.data.input.pubkeys.map((key) => Buffer.from(key.replace("0x", ""), "hex")),
Buffer.from(testCase.data.input.message.replace("0x", ""), "hex"), Buffer.from(testCase.data.input.message.replace("0x", ""), "hex"),
Buffer.from(testCase.data.input.signature.replace("0x", ""), "hex"), Buffer.from(testCase.data.input.signature.replace("0x", ""), "hex")
); );
}), },
{ {
inputTypes: { inputTypes: {
data: InputType.YAML, data: InputType.YAML,
}, },
getExpected: (testCase => testCase.data.output) getExpected: (testCase) => testCase.data.output,
} }
); );

View File

@ -18,21 +18,18 @@ before(async function f() {
describeDirectorySpecTest<ISignMessageTestCase, string>( describeDirectorySpecTest<ISignMessageTestCase, string>(
"BLS - sign", "BLS - sign",
path.join( path.join(__dirname, "../../node_modules/@chainsafe/eth2-spec-tests/tests/general/phase0/bls/sign/small"),
__dirname, (testCase) => {
"../../node_modules/@chainsafe/eth2-spec-tests/tests/general/phase0/bls/sign/small" const signature = bls.sign(
),
(testCase => {
const signature = bls.sign(
Buffer.from(testCase.data.input.privkey.replace("0x", ""), "hex"), Buffer.from(testCase.data.input.privkey.replace("0x", ""), "hex"),
Buffer.from(testCase.data.input.message.replace("0x", ""), "hex") Buffer.from(testCase.data.input.message.replace("0x", ""), "hex")
); );
return `0x${signature.toString("hex")}`; return `0x${signature.toString("hex")}`;
}), },
{ {
inputTypes: { inputTypes: {
data: InputType.YAML, data: InputType.YAML,
}, },
getExpected: (testCase => testCase.data.output) getExpected: (testCase) => testCase.data.output,
} }
); );

View File

@ -19,21 +19,18 @@ before(async function f() {
describeDirectorySpecTest<IVerifyTestCase, boolean>( describeDirectorySpecTest<IVerifyTestCase, boolean>(
"BLS - verify", "BLS - verify",
path.join( path.join(__dirname, "../../node_modules/@chainsafe/eth2-spec-tests/tests/general/phase0/bls/verify/small"),
__dirname, (testCase) => {
"../../node_modules/@chainsafe/eth2-spec-tests/tests/general/phase0/bls/verify/small"
),
(testCase => {
return bls.verify( return bls.verify(
Buffer.from(testCase.data.input.pubkey.replace("0x", ""), "hex"), Buffer.from(testCase.data.input.pubkey.replace("0x", ""), "hex"),
Buffer.from(testCase.data.input.message.replace("0x", ""), "hex"), Buffer.from(testCase.data.input.message.replace("0x", ""), "hex"),
Buffer.from(testCase.data.input.signature.replace("0x", ""), "hex") Buffer.from(testCase.data.input.signature.replace("0x", ""), "hex")
); );
}), },
{ {
inputTypes: { inputTypes: {
data: InputType.YAML, data: InputType.YAML,
}, },
getExpected: (testCase => testCase.data.output) getExpected: (testCase) => testCase.data.output,
} }
); );

View File

@ -2,19 +2,18 @@ import {init, getContext, destroy} from "../../src/context";
import {expect} from "chai"; import {expect} from "chai";
describe("bls wasm constext", function () { describe("bls wasm constext", function () {
afterEach(() => { afterEach(() => {
destroy(); destroy();
}); });
it("initializes and works", async function () { it("initializes and works", async function () {
await init(); await init();
expect(getContext().getCurveOrder()) expect(getContext().getCurveOrder()).to.be.equal(
.to.be.equal("52435875175126190479447740508185965837690552500527637822603658699938581184513"); "52435875175126190479447740508185965837690552500527637822603658699938581184513"
);
}); });
it("throws if context not initialized", async function () { it("throws if context not initialized", async function () {
expect(() => getContext().getCurveOrder()).to.throw(); expect(() => getContext().getCurveOrder()).to.throw();
}); });
});
});

View File

@ -2,11 +2,9 @@ import bls, {aggregatePubkeys, aggregateSignatures, initBLS, Keypair, verify, ve
import SHA256 from "@chainsafe/as-sha256"; import SHA256 from "@chainsafe/as-sha256";
import {expect} from "chai"; import {expect} from "chai";
import {destroy} from "../../src/context"; import {destroy} from "../../src/context";
import {padLeft} from "../../src/helpers/utils";
describe("test bls", function () { describe("test bls", function () {
before(async function () {
before(async function() {
await initBLS(); await initBLS();
}); });
@ -20,47 +18,29 @@ describe("test bls", function () {
}); });
}); });
describe("verify", function() { describe("verify", function () {
it("should verify signature", () => { it("should verify signature", () => {
const keypair = Keypair.generate(); const keypair = Keypair.generate();
const messageHash = Buffer.from(SHA256.digest(Buffer.from("Test"))); const messageHash = Buffer.from(SHA256.digest(Buffer.from("Test")));
const signature = keypair.privateKey.signMessage( const signature = keypair.privateKey.signMessage(messageHash);
messageHash, const result = verify(keypair.publicKey.toBytesCompressed(), messageHash, signature.toBytesCompressed());
);
const result = verify(
keypair.publicKey.toBytesCompressed(),
messageHash,
signature.toBytesCompressed(),
);
expect(result).to.be.true; expect(result).to.be.true;
}); });
it("should not modify original pubkey when verifying", () => { it("should not modify original pubkey when verifying", () => {
const keypair = Keypair.generate(); const keypair = Keypair.generate();
const messageHash = Buffer.from(SHA256.digest(Buffer.from("Test"))); const messageHash = Buffer.from(SHA256.digest(Buffer.from("Test")));
const signature = keypair.privateKey.signMessage( const signature = keypair.privateKey.signMessage(messageHash);
messageHash,
);
const pubKey = keypair.publicKey.toBytesCompressed(); const pubKey = keypair.publicKey.toBytesCompressed();
verify( verify(pubKey, messageHash, signature.toBytesCompressed());
pubKey,
messageHash,
signature.toBytesCompressed(),
);
expect("0x" + pubKey.toString("hex")).to.be.equal(keypair.publicKey.toHexString()); expect("0x" + pubKey.toString("hex")).to.be.equal(keypair.publicKey.toHexString());
}); });
it("should fail verify empty signature", () => { it("should fail verify empty signature", () => {
const keypair = Keypair.generate(); const keypair = Keypair.generate();
const messageHash2 = Buffer.from(SHA256.digest(Buffer.from("Test message2"))); const messageHash2 = Buffer.from(SHA256.digest(Buffer.from("Test message2")));
const signature = Buffer.alloc(96); const signature = Buffer.alloc(96);
const result = verify( const result = verify(keypair.publicKey.toBytesCompressed(), messageHash2, signature);
keypair.publicKey.toBytesCompressed(),
messageHash2,
signature,
);
expect(result).to.be.false; expect(result).to.be.false;
}); });
@ -68,14 +48,8 @@ describe("test bls", function () {
const keypair = Keypair.generate(); const keypair = Keypair.generate();
const messageHash = Buffer.from(SHA256.digest(Buffer.from("Test message"))); const messageHash = Buffer.from(SHA256.digest(Buffer.from("Test message")));
const messageHash2 = Buffer.from(SHA256.digest(Buffer.from("Test message2"))); const messageHash2 = Buffer.from(SHA256.digest(Buffer.from("Test message2")));
const signature = keypair.privateKey.signMessage( const signature = keypair.privateKey.signMessage(messageHash);
messageHash, const result = verify(keypair.publicKey.toBytesCompressed(), messageHash2, signature.toBytesCompressed());
);
const result = verify(
keypair.publicKey.toBytesCompressed(),
messageHash2,
signature.toBytesCompressed(),
);
expect(result).to.be.false; expect(result).to.be.false;
}); });
@ -83,25 +57,16 @@ describe("test bls", function () {
const keypair = Keypair.generate(); const keypair = Keypair.generate();
const keypair2 = Keypair.generate(); const keypair2 = Keypair.generate();
const messageHash = Buffer.from(SHA256.digest(Buffer.from("Test message"))); const messageHash = Buffer.from(SHA256.digest(Buffer.from("Test message")));
const signature = keypair.privateKey.signMessage( const signature = keypair.privateKey.signMessage(messageHash);
messageHash, const result = verify(keypair2.publicKey.toBytesCompressed(), messageHash, signature.toBytesCompressed());
);
const result = verify(
keypair2.publicKey.toBytesCompressed(),
messageHash,
signature.toBytesCompressed(),
);
expect(result).to.be.false; expect(result).to.be.false;
}); });
}); });
describe("verify multiple", function() { describe("verify multiple", function () {
it("should verify aggregated signatures", function () { it("should verify aggregated signatures", function () {
this.timeout(5000); this.timeout(5000);
const keypair1 = Keypair.generate(); const keypair1 = Keypair.generate();
const keypair2 = Keypair.generate(); const keypair2 = Keypair.generate();
const keypair3 = Keypair.generate(); const keypair3 = Keypair.generate();
@ -132,11 +97,7 @@ describe("test bls", function () {
signature4.toBytesCompressed(), signature4.toBytesCompressed(),
]); ]);
const result = verifyMultiple( const result = verifyMultiple([aggregatePubKey12, aggregatePubKey34], [message1, message2], aggregateSignature);
[aggregatePubKey12, aggregatePubKey34],
[message1, message2],
aggregateSignature,
);
expect(result).to.be.true; expect(result).to.be.true;
}); });
@ -144,8 +105,6 @@ describe("test bls", function () {
it("should verify aggregated signatures - same message", function () { it("should verify aggregated signatures - same message", function () {
this.timeout(5000); this.timeout(5000);
const keypair1 = Keypair.generate(); const keypair1 = Keypair.generate();
const keypair2 = Keypair.generate(); const keypair2 = Keypair.generate();
const keypair3 = Keypair.generate(); const keypair3 = Keypair.generate();
@ -170,11 +129,11 @@ describe("test bls", function () {
keypair1.publicKey.toBytesCompressed(), keypair1.publicKey.toBytesCompressed(),
keypair2.publicKey.toBytesCompressed(), keypair2.publicKey.toBytesCompressed(),
keypair3.publicKey.toBytesCompressed(), keypair3.publicKey.toBytesCompressed(),
keypair4.publicKey.toBytesCompressed() keypair4.publicKey.toBytesCompressed(),
], ],
[message, message, message, message], [message, message, message, message],
aggregateSignature, aggregateSignature,
true, true
); );
expect(result).to.be.true; expect(result).to.be.true;
@ -183,7 +142,6 @@ describe("test bls", function () {
it("should fail to verify aggregated signatures - swapped messages", function () { it("should fail to verify aggregated signatures - swapped messages", function () {
this.timeout(5000); this.timeout(5000);
const keypair1 = Keypair.generate(); const keypair1 = Keypair.generate();
const keypair2 = Keypair.generate(); const keypair2 = Keypair.generate();
const keypair3 = Keypair.generate(); const keypair3 = Keypair.generate();
@ -217,15 +175,13 @@ describe("test bls", function () {
const result = bls.verifyMultiple( const result = bls.verifyMultiple(
[aggregatePubKey12, aggregatePubKey34], [aggregatePubKey12, aggregatePubKey34],
[message2, message1], [message2, message1],
aggregateSignature, aggregateSignature
); );
expect(result).to.be.false; expect(result).to.be.false;
}); });
it("should fail to verify aggregated signatures - different pubkeys and messsages", () => { it("should fail to verify aggregated signatures - different pubkeys and messsages", () => {
const keypair1 = Keypair.generate(); const keypair1 = Keypair.generate();
const keypair2 = Keypair.generate(); const keypair2 = Keypair.generate();
const keypair3 = Keypair.generate(); const keypair3 = Keypair.generate();
@ -244,7 +200,6 @@ describe("test bls", function () {
keypair2.publicKey.toBytesCompressed(), keypair2.publicKey.toBytesCompressed(),
]); ]);
const aggregateSignature = bls.aggregateSignatures([ const aggregateSignature = bls.aggregateSignatures([
signature1.toBytesCompressed(), signature1.toBytesCompressed(),
signature2.toBytesCompressed(), signature2.toBytesCompressed(),
@ -252,32 +207,20 @@ describe("test bls", function () {
signature4.toBytesCompressed(), signature4.toBytesCompressed(),
]); ]);
const result = bls.verifyMultiple( const result = bls.verifyMultiple([aggregatePubKey12], [message2, message1], aggregateSignature);
[aggregatePubKey12],
[message2, message1],
aggregateSignature,
);
expect(result).to.be.false; expect(result).to.be.false;
}); });
it("should fail to verify aggregated signatures - no public keys", () => { it("should fail to verify aggregated signatures - no public keys", () => {
const signature = Buffer.alloc(96); const signature = Buffer.alloc(96);
const message1 = Buffer.from(SHA256.digest(Buffer.from("Test1"))); const message1 = Buffer.from(SHA256.digest(Buffer.from("Test1")));
const message2 = Buffer.from(SHA256.digest(Buffer.from("Test2"))); const message2 = Buffer.from(SHA256.digest(Buffer.from("Test2")));
const result = bls.verifyMultiple( const result = bls.verifyMultiple([], [message2, message1], signature);
[],
[message2, message1],
signature,
);
expect(result).to.be.false; expect(result).to.be.false;
}); });
}); });
}); });

View File

@ -1,9 +1,8 @@
import {PrivateKey,PublicKey,Keypair} from "../../src"; import {PrivateKey, PublicKey, Keypair} from "../../src";
import {expect} from "chai"; import {expect} from "chai";
import {destroy, init} from "../../src/context"; import {destroy, init} from "../../src/context";
describe("keypair", function() { describe("keypair", function () {
before(async function () { before(async function () {
await init(); await init();
}); });
@ -26,7 +25,8 @@ describe("keypair", function() {
const secret = PrivateKey.random(); const secret = PrivateKey.random();
const publicKey = PublicKey.fromPrivateKey(secret); const publicKey = PublicKey.fromPrivateKey(secret);
const keypair = new Keypair(secret); const keypair = new Keypair(secret);
expect(keypair.publicKey.toBytesCompressed().toString("hex")) expect(keypair.publicKey.toBytesCompressed().toString("hex")).to.be.equal(
.to.be.equal(publicKey.toBytesCompressed().toString("hex")); publicKey.toBytesCompressed().toString("hex")
);
}); });
}); });

View File

@ -3,8 +3,7 @@ import {expect} from "chai";
import {SECRET_KEY_LENGTH} from "../../src/constants"; import {SECRET_KEY_LENGTH} from "../../src/constants";
import {destroy, init} from "../../src/context"; import {destroy, init} from "../../src/context";
describe("privateKey", function() { describe("privateKey", function () {
before(async function () { before(async function () {
await init(); await init();
}); });
@ -32,9 +31,8 @@ describe("privateKey", function() {
it("should export private key to bytes", function () { it("should export private key to bytes", function () {
expect(PrivateKey.random().toBytes().length).to.be.equal(SECRET_KEY_LENGTH); expect(PrivateKey.random().toBytes().length).to.be.equal(SECRET_KEY_LENGTH);
}); });
it("should not accept too short private key", function () { it("should not accept too short private key", function () {
expect(() => PrivateKey.fromHexString("0x2123")).to.throw(); expect(() => PrivateKey.fromHexString("0x2123")).to.throw();
}); });
}); });

View File

@ -3,7 +3,6 @@ import {PublicKey, PrivateKey} from "../../src";
import {expect} from "chai"; import {expect} from "chai";
describe("public key", function () { describe("public key", function () {
before(async function f() { before(async function f() {
await init(); await init();
}); });
@ -14,18 +13,17 @@ describe("public key", function () {
it("from hex", function () { it("from hex", function () {
const publicKey = const publicKey =
"0xb6f21199594b56d77670564bf422cb331d5281ca2c1f9a45588a56881d8287ef8619efa6456d6cd2ef61306aa5b21311"; "0xb6f21199594b56d77670564bf422cb331d5281ca2c1f9a45588a56881d8287ef8619efa6456d6cd2ef61306aa5b21311";
expect(PublicKey.fromHex(publicKey).toHexString()).to.be.equal(publicKey); expect(PublicKey.fromHex(publicKey).toHexString()).to.be.equal(publicKey);
}); });
it("from bytes", function () { it("from bytes", function () {
const publicKey = const publicKey =
"b6f21199594b56d77670564bf422cb331d5281ca2c1f9a45588a56881d8287ef8619efa6456d6cd2ef61306aa5b21311"; "b6f21199594b56d77670564bf422cb331d5281ca2c1f9a45588a56881d8287ef8619efa6456d6cd2ef61306aa5b21311";
expect(PublicKey.fromBytes(Buffer.from(publicKey, "hex")).toHexString()).to.be.equal(`0x${publicKey}`); expect(PublicKey.fromBytes(Buffer.from(publicKey, "hex")).toHexString()).to.be.equal(`0x${publicKey}`);
}); });
it("from private key", function () { it("from private key", function () {
PublicKey.fromPrivateKey(PrivateKey.random()); PublicKey.fromPrivateKey(PrivateKey.random());
}); });
});
});

5
tsconfig.build.json Normal file
View File

@ -0,0 +1,5 @@
{
"extends": "./tsconfig",
"include": ["src"],
"exclude": ["test"],
}

View File

@ -1,5 +1,5 @@
{ {
"include": ["src"], "include": ["src", "test"],
"compilerOptions": { "compilerOptions": {
"target": "esnext", "target": "esnext",
"module": "commonjs", "module": "commonjs",

View File

@ -2600,6 +2600,13 @@ eslint-plugin-import@^2.20.1:
read-pkg-up "^2.0.0" read-pkg-up "^2.0.0"
resolve "^1.12.0" resolve "^1.12.0"
eslint-plugin-prettier@^3.1.4:
version "3.1.4"
resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-3.1.4.tgz#168ab43154e2ea57db992a2cd097c828171f75c2"
integrity sha512-jZDa8z76klRqo+TdGDTFJSavwbnWK2ZpqGKNZ+VvweMW516pDUMmQ2koXvxEE4JhzNvTv+radye/bWGBmA6jmg==
dependencies:
prettier-linter-helpers "^1.0.0"
eslint-scope@^4.0.3: eslint-scope@^4.0.3:
version "4.0.3" version "4.0.3"
resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848" resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-4.0.3.tgz#ca03833310f6889a3264781aa82e63eb9cfe7848"
@ -2808,6 +2815,11 @@ fast-deep-equal@^3.1.1:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4"
integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA==
fast-diff@^1.1.2:
version "1.2.0"
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
fast-json-stable-stringify@^2.0.0: fast-json-stable-stringify@^2.0.0:
version "2.1.0" version "2.1.0"
resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633"
@ -4924,6 +4936,18 @@ prelude-ls@~1.1.2:
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54" resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.1.2.tgz#21932a549f5e52ffd9a827f570e04be62a97da54"
integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= integrity sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=
prettier-linter-helpers@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
dependencies:
fast-diff "^1.1.2"
prettier@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.1.2.tgz#3050700dae2e4c8b67c4c3f666cdb8af405e1ce5"
integrity sha512-16c7K+x4qVlJg9rEbXl7HEGmQyZlG4R9AgP+oHKRMsMsuk8s+ATStlf1NpDqyBI1HpVyfjLOeMhH2LvuNvV5Vg==
private@^0.1.6: private@^0.1.6:
version "0.1.8" version "0.1.8"
resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff" resolved "https://registry.yarnpkg.com/private/-/private-0.1.8.tgz#2381edb3689f7a53d653190060fcf822d2f368ff"