Squashed 'src/dashbls/' changes from 22b066020c..9329803969

9329803969 wip: fix FromBytesUnchecked (#68)
767713de3d feat: js bindings in camel case (#66)
06df92693a chore(release): bump version (#64)
73593feefd fix: the JS bundle script and bindings (#47)
38a8f768c6 Merge pull request #61 from kittywhiskers/compat_support
d9b375145e ci: ensure that CMakeFiles are compatible with LTS-bundled cmake
5ba1b520cc build: restore CMake 3.14.0 compatibility
d1c1b66e5f backport: merge bls-signatures#332 (Python 3.11)

git-subtree-dir: src/dashbls
git-subtree-split: 9329803969fd325dc0d5c9029ab15669d658ed5d
This commit is contained in:
Kittywhiskers Van Gogh 2023-03-16 16:34:17 +00:00
parent 8bf0c812f5
commit c1992c149e
21 changed files with 4653 additions and 447 deletions

View File

@ -24,14 +24,13 @@ jobs:
matrix:
os: [macos-latest, ubuntu-latest]
golang: [ '1.17' ]
python: ['3.7', '3.8', '3.9', '3.10']
python: ['3.7', '3.8', '3.9', '3.10', '3.11']
steps:
- name: Checkout code
uses: actions/checkout@v3
- uses: actions/setup-python@v2
name: Install Python
- uses: chia-network/actions/setup-python@main
with:
python-version: ${{ matrix.python }}
@ -60,9 +59,7 @@ jobs:
if: startsWith(matrix.os, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install -qq --yes snap libgmp-dev
sudo apt-get remove --purge cmake -y
sudo snap install cmake --classic
sudo apt-get install -qq --yes valgrind libgmp-dev cmake
hash -r
cmake --version

View File

@ -38,9 +38,7 @@ jobs:
if: startsWith(matrix.os, 'ubuntu')
run: |
sudo apt-get update
sudo apt-get install -qq --yes valgrind snap libgmp-dev libsodium-dev
sudo apt-get remove --purge cmake -y
sudo snap install cmake --classic
sudo apt-get install -qq --yes valgrind libgmp-dev cmake
hash -r
cmake --version
@ -49,7 +47,7 @@ jobs:
run: |
ls -l
export MACOSX_DEPLOYMENT_TARGET=10.14
brew install autoconf automake gmp
brew install autoconf automake gmp pkg-config
- name: Build library using CMake
if: startsWith(matrix.builder, 'cmake')

View File

@ -43,16 +43,34 @@ jobs:
python:
- major-dot-minor: '3.7'
cibw-build: 'cp37-*'
manylinux:
arch: manylinux2014
intel: manylinux2010
matrix: '3.7'
- major-dot-minor: '3.8'
cibw-build: 'cp38-*'
manylinux:
arch: manylinux2014
intel: manylinux2010
matrix: '3.8'
- major-dot-minor: '3.9'
cibw-build: 'cp39-*'
manylinux:
arch: manylinux2014
intel: manylinux2010
matrix: '3.9'
- major-dot-minor: '3.10'
cibw-build: 'cp310-*'
manylinux:
arch: manylinux2014
intel: manylinux2010
matrix: '3.10'
- major-dot-minor: '3.11'
cibw-build: 'cp311-*'
manylinux:
arch: manylinux2014
intel: manylinux2014
matrix: '3.11'
arch:
- name: ARM
matrix: arm
@ -114,25 +132,24 @@ jobs:
- name: Install pipx
run: |
pip install pipx
- name: Build and test
uses: pypa/cibuildwheel@v2.7.0
with:
output-dir: dist
env:
CIBW_PRERELEASE_PYTHONS: True
CIBW_BUILD_VERBOSITY_MACOS: 0
CIBW_BUILD_VERBOSITY_LINUX: 0
CIBW_BUILD_VERBOSITY_WINDOWS: 0
CIBW_BUILD: ${{ matrix.python.cibw-build }}
CIBW_SKIP: '*-manylinux_i686 *-win32 *-musllinux_*'
CIBW_MANYLINUX_AARCH64_IMAGE: manylinux2014
CIBW_MANYLINUX_X86_64_IMAGE: manylinux2010
CIBW_ENVIRONMENT_LINUX: "PATH=/project/cmake-3.17.3-Linux-`uname -m`/bin:$PATH"
CIBW_MANYLINUX_AARCH64_IMAGE: ${{ matrix.python.manylinux['arm'] }}
CIBW_MANYLINUX_X86_64_IMAGE: ${{ matrix.python.manylinux['intel'] }}
CIBW_ENVIRONMENT_LINUX: "PATH=/project/cmake-3.14.3-Linux-`uname -m`/bin:$PATH"
CIBW_BEFORE_ALL_LINUX: >
yum -y install epel-release
&& echo "epel-release installed"
&& yum -y install lzip
&& echo "lzip installed"
&& curl -L https://github.com/Kitware/CMake/releases/download/v3.17.3/cmake-3.17.3-Linux-`uname -m`.sh > cmake.sh
&& curl -L https://github.com/Kitware/CMake/releases/download/v3.14.3/cmake-3.14.3-Linux-`uname -m`.sh > cmake.sh
&& yes | sh cmake.sh | cat
&& rm -f /usr/bin/cmake
&& curl -L https://gmplib.org/download/gmp/gmp-6.2.1.tar.lz | tar x --lzip
@ -176,6 +193,8 @@ jobs:
&& cp {wheel} {dest_dir}
CIBW_TEST_REQUIRES: pytest
CIBW_TEST_COMMAND: py.test -v {project}/python-bindings/test.py
run:
pipx run --spec='cibuildwheel==2.9.0' cibuildwheel --output-dir dist 2>&1
- name: Upload artifacts
uses: actions/upload-artifact@v3

View File

@ -8,7 +8,6 @@ project(
LANGUAGES CXX
)
set(
${PROJECT_NAME}_HEADERS
catch2/catch.hpp
@ -22,6 +21,11 @@ list(
add_library(
${PROJECT_NAME}
INTERFACE
)
target_sources(
${PROJECT_NAME}
INTERFACE
"${${PROJECT_NAME}_HEADERS}"
)

View File

@ -41,7 +41,7 @@ class BLS {
static void SetSecureAllocator(Util::SecureAllocCallback allocCb, Util::SecureFreeCallback freeCb);
static void CheckRelicErrors();
static void CheckRelicErrors(bool should_throw = true);
};
} // end namespace bls

View File

@ -13,24 +13,26 @@ include_directories(
file(GLOB_RECURSE WRAP_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/*.h)
file(GLOB_RECURSE WRAP_SRC ${CMAKE_CURRENT_SOURCE_DIR}/wrappers/*.cpp)
add_executable(blsjs ${CMAKE_CURRENT_SOURCE_DIR}/jsbindings.cpp
add_executable(blsjstmp ${CMAKE_CURRENT_SOURCE_DIR}/jsbindings.cpp
${WRAP_HEADERS} ${WRAP_SRC} ${CMAKE_CURRENT_SOURCE_DIR}/helpers.h ${CMAKE_CURRENT_SOURCE_DIR}/helpers.cpp
)
add_custom_target(install_npm_dependencies npm ci)
add_dependencies(blsjs install_npm_dependencies)
target_link_libraries(blsjs PRIVATE dashbls)
add_dependencies(blsjstmp install_npm_dependencies)
target_link_libraries(blsjstmp PRIVATE dashbls)
# Copy necessary files for the npm package
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/package.json package.json COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/package-lock.json package-lock.json COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/blsjs.d.ts blsjs.d.ts COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/README.md README.md COPYONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/bundle_wasm_for_web.js bundle_wasm_for_web.js COPYONLY)
# Copy test files
file(GLOB JS_BINDINGS_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/tests/ ${CMAKE_CURRENT_SOURCE_DIR}/tests/*.js ${CMAKE_CURRENT_SOURCE_DIR}/tests/*.ts)
file(GLOB JS_BINDINGS_TESTS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/tests/ ${CMAKE_CURRENT_SOURCE_DIR}/tests/*)
foreach(file ${JS_BINDINGS_TESTS})
message(FILE ${file})
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/tests/${file} tests/${file} COPYONLY)
endforeach()
set_target_properties(blsjs PROPERTIES LINK_FLAGS "--bind -Oz --closure 1 -s MODULARIZE=1")
set_target_properties(blsjstmp PROPERTIES LINK_FLAGS "--bind -Oz --closure 1 -s MODULARIZE=1 -s NODEJS_CATCH_EXIT=1 -s NODEJS_CATCH_REJECTION=1")
add_custom_command(TARGET blsjstmp POST_BUILD COMMAND npm run build:web)

View File

@ -1,95 +1,95 @@
export declare class AugSchemeMPL {
static sk_to_g1(sk: PrivateKey): G1Element;
static key_gen(msg: Uint8Array): PrivateKey;
static skToG1(sk: PrivateKey): G1Element;
static keyGen(msg: Uint8Array): PrivateKey;
static sign(sk: PrivateKey, msg: Uint8Array): G2Element;
static sign_prepend(sk: PrivateKey, msg: Uint8Array, prependPk: G1Element): G2Element;
static signPrepend(sk: PrivateKey, msg: Uint8Array, prependPk: G1Element): G2Element;
static verify(pk: G1Element, msg: Uint8Array, sig: G2Element): boolean;
static aggregate(g2Elements: G2Element[]): G2Element;
static aggregate_verify(pks: G1Element[], msgs: Uint8Array[], sig: G2Element): boolean;
static derive_child_sk(sk: PrivateKey, index: number): PrivateKey;
static derive_child_sk_unhardened(sk: PrivateKey, index: number): PrivateKey;
static derive_child_pk_unhardened(pk: G1Element, index: number): G1Element;
static aggregateVerify(pks: G1Element[], msgs: Uint8Array[], sig: G2Element): boolean;
static deriveChildSk(sk: PrivateKey, index: number): PrivateKey;
static deriveChildSkUnhardened(sk: PrivateKey, index: number): PrivateKey;
static deriveChildPkUnhardened(pk: G1Element, index: number): G1Element;
}
export declare class BasicSchemeMPL {
static sk_to_g1(sk: PrivateKey): G1Element;
static key_gen(msg: Uint8Array): PrivateKey;
static skToG1(sk: PrivateKey): G1Element;
static keyGen(msg: Uint8Array): PrivateKey;
static sign(sk: PrivateKey, msg: Uint8Array): G2Element;
static verify(pk: G1Element, msg: Uint8Array, sig: G2Element): boolean;
static aggregate(g2Elements: G2Element[]): G2Element;
static aggregate_verify(pks: G1Element[], msgs: Uint8Array[], sig: G2Element): boolean;
static derive_child_sk(sk: PrivateKey, index: number): PrivateKey;
static derive_child_sk_unhardened(sk: PrivateKey, index: number): PrivateKey;
static derive_child_pk_unhardened(pk: G1Element, index: number): G1Element;
static aggregateVerify(pks: G1Element[], msgs: Uint8Array[], sig: G2Element): boolean;
static deriveChildSk(sk: PrivateKey, index: number): PrivateKey;
static deriveChildSkUnhardened(sk: PrivateKey, index: number): PrivateKey;
static deriveChildPkUnhardened(pk: G1Element, index: number): G1Element;
}
export declare class PopSchemeMPL {
static sk_to_g1(sk: PrivateKey): G1Element;
static key_gen(msg: Uint8Array): PrivateKey;
static skToG1(sk: PrivateKey): G1Element;
static keyGen(msg: Uint8Array): PrivateKey;
static sign(sk: PrivateKey, msg: Uint8Array): G2Element;
static verify(pk: G1Element, msg: Uint8Array, sig: G2Element): boolean;
static aggregate(g2Elements: G2Element[]): G2Element;
static aggregate_verify(pks: G1Element[], msgs: Uint8Array[], sig: G2Element): boolean;
static derive_child_sk(sk: PrivateKey, index: number): PrivateKey;
static derive_child_sk_unhardened(sk: PrivateKey, index: number): PrivateKey;
static derive_child_pk_unhardened(pk: G1Element, index: number): G1Element;
static pop_prove(sk: PrivateKey): G2Element;
static pop_verify(pk: G1Element, signatureProof: G2Element): boolean;
static fast_aggregate_verify(pks: G1Element[], msg: Uint8Array, sig: G2Element): boolean;
static aggregateVerify(pks: G1Element[], msgs: Uint8Array[], sig: G2Element): boolean;
static deriveChildSk(sk: PrivateKey, index: number): PrivateKey;
static deriveChildSkUnhardened(sk: PrivateKey, index: number): PrivateKey;
static deriveChildPkUnhardened(pk: G1Element, index: number): G1Element;
static popProve(sk: PrivateKey): G2Element;
static popVerify(pk: G1Element, signatureProof: G2Element): boolean;
static fastAggregateVerify(pks: G1Element[], msg: Uint8Array, sig: G2Element): boolean;
}
export declare class G1Element {
static SIZE: number;
static from_bytes(bytes: Uint8Array): G1Element;
static fromBytes(bytes: Uint8Array): G1Element;
static generator(): G2Element;
serialize(): Uint8Array;
negate(): G1Element;
deepcopy(): G1Element;
get_fingerprint(): number;
getFingerprint(): number;
add(el: G1Element): G1Element;
mul(bn: Bignum): G1Element;
equal_to(el: G1Element): boolean;
equalTo(el: G1Element): boolean;
delete(): void;
}
export declare class G2Element {
static SIZE: number;
static from_bytes(bytes: Uint8Array): G2Element;
static from_g2(sk: G2Element): G2Element;
static aggregate_sigs(sigs: G2Element[]): G2Element;
static fromBytes(bytes: Uint8Array): G2Element;
static fromG2(sk: G2Element): G2Element;
static aggregateSigs(sigs: G2Element[]): G2Element;
static generator(): G2Element;
serialize(): Uint8Array;
negate(): G2Element;
deepcopy(): G2Element;
add(el: G2Element): G2Element;
mul(bn: Bignum): G2Element;
equal_to(el: G2Element): boolean;
equalTo(el: G2Element): boolean;
delete(): void;
}
export declare class PrivateKey {
static PRIVATE_KEY_SIZE: number;
static from_bytes(bytes: Uint8Array, modOrder: boolean): PrivateKey;
static fromBytes(bytes: Uint8Array, modOrder: boolean): PrivateKey;
static aggregate(pks: PrivateKey[]): PrivateKey;
deepcopy(): PrivateKey;
serialize(): Uint8Array;
get_g1(): G1Element;
get_g2(): G2Element;
mul_g1(el: G1Element): G1Element;
mul_g2(el: G2Element): G2Element;
equal_to(key: PrivateKey): boolean;
getG1(): G1Element;
getG2(): G2Element;
mulG1(el: G1Element): G1Element;
mulG2(el: G2Element): G2Element;
equalTo(key: PrivateKey): boolean;
delete(): void;
}
export declare class Bignum {
static from_string(s: string, radix: number): Bignum;
static fromString(s: string, radix: number): Bignum;
toString(radix: number): string;
delete(): void;
}
export declare class Util {
static hash256(msg: Uint8Array): Uint8Array;
static hex_str(msg: Uint8Array): string;
static hexStr(msg: Uint8Array): string;
}
export interface ModuleInstance {

View File

@ -0,0 +1,37 @@
// The code manipulation from this file needs to be done for Chrome, as
// it requires wasm to be loaded asynchronously, and it doesn't
// work when bundling complex projects. With this solution, wasm is
// included right into the bundle itself in a form of base64 string
// and compiled asynchronously, just as Chrome requires
const fs = require('fs');
const outputPath = './blsjs.js';
const wasm = fs.readFileSync('./blsjstmp.wasm');
const wasmBase = wasm.toString('base64');
const codeToPrepend = `
if (typeof window === "object") {
var buf = Buffer.from("${wasmBase}", "base64");
var blob = new Blob([buf], { type: "application/wasm" });
var wasmUrl = URL.createObjectURL(blob);
}
`;
const originalSourceCode = fs.readFileSync('./blsjstmp.js', 'utf-8');
const modifiedSourceCode = originalSourceCode
.replace(/fetch\(.,/g, "fetch(wasmUrl,");
const modifiedSourceBuffer = Buffer.from(modifiedSourceCode, 'utf-8');
const bundleFileDescriptor = fs.openSync(outputPath, 'w+');
const bufferToPrepend = Buffer.from(codeToPrepend);
fs.writeSync(bundleFileDescriptor, bufferToPrepend, 0, bufferToPrepend.length, 0);
fs.writeSync(bundleFileDescriptor, modifiedSourceBuffer, 0, modifiedSourceBuffer.length, bufferToPrepend.length);
fs.close(bundleFileDescriptor, (err) => {
if (err) throw err;
});

View File

@ -22,92 +22,88 @@ using namespace emscripten;
namespace js_wrappers {
EMSCRIPTEN_BINDINGS(blsjs) {
class_<AugSchemeMPLWrapper>("AugSchemeMPL")
.class_function("sk_to_g1", &AugSchemeMPLWrapper::SkToG1)
.class_function("key_gen", &AugSchemeMPLWrapper::KeyGen)
.class_function("skToG1", &AugSchemeMPLWrapper::SkToG1)
.class_function("keyGen", &AugSchemeMPLWrapper::KeyGen)
.class_function("sign", &AugSchemeMPLWrapper::Sign)
.class_function("sign_prepend", &AugSchemeMPLWrapper::SignPrepend)
.class_function("signPrepend", &AugSchemeMPLWrapper::SignPrepend)
.class_function("verify", &AugSchemeMPLWrapper::Verify)
.class_function("aggregate", &AugSchemeMPLWrapper::Aggregate)
.class_function("aggregate_verify", &AugSchemeMPLWrapper::AggregateVerify)
.class_function("derive_child_sk", &AugSchemeMPLWrapper::DeriveChildSk)
.class_function("derive_child_sk_unhardened", &AugSchemeMPLWrapper::DeriveChildSkUnhardened)
.class_function("derive_child_pk_unhardened", &AugSchemeMPLWrapper::DeriveChildPkUnhardened);
.class_function("aggregateVerify", &AugSchemeMPLWrapper::AggregateVerify)
.class_function("deriveChildSk", &AugSchemeMPLWrapper::DeriveChildSk)
.class_function("deriveChildSkUnhardened", &AugSchemeMPLWrapper::DeriveChildSkUnhardened)
.class_function("deriveChildPkUnhardened", &AugSchemeMPLWrapper::DeriveChildPkUnhardened);
class_<SchemeMPLWrapper<BasicSchemeMPL>>("BasicSchemeMPL")
.class_function("sk_to_g1", &SchemeMPLWrapper<BasicSchemeMPL>::SkToG1)
.class_function("key_gen", &SchemeMPLWrapper<BasicSchemeMPL>::KeyGen)
.class_function("skToG1", &SchemeMPLWrapper<BasicSchemeMPL>::SkToG1)
.class_function("keyGen", &SchemeMPLWrapper<BasicSchemeMPL>::KeyGen)
.class_function("sign", &SchemeMPLWrapper<BasicSchemeMPL>::Sign)
.class_function("verify", &SchemeMPLWrapper<BasicSchemeMPL>::Verify)
.class_function("aggregate", &SchemeMPLWrapper<BasicSchemeMPL>::Aggregate)
.class_function("aggregate_verify", &SchemeMPLWrapper<BasicSchemeMPL>::AggregateVerify)
.class_function("derive_child_sk", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildSk)
.class_function("derive_child_sk_unhardened", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildSkUnhardened)
.class_function("derive_child_pk_unhardened", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildPkUnhardened);
.class_function("aggregateVerify", &SchemeMPLWrapper<BasicSchemeMPL>::AggregateVerify)
.class_function("deriveChildSk", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildSk)
.class_function("deriveChildSkUnhardened", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildSkUnhardened)
.class_function("deriveChildPkUnhardened", &SchemeMPLWrapper<BasicSchemeMPL>::DeriveChildPkUnhardened);
class_<PopSchemeMPLWrapper>("PopSchemeMPL")
.class_function("sk_to_g1", &PopSchemeMPLWrapper::SkToG1)
.class_function("key_gen", &PopSchemeMPLWrapper::KeyGen)
.class_function("skToG1", &PopSchemeMPLWrapper::SkToG1)
.class_function("keyGen", &PopSchemeMPLWrapper::KeyGen)
.class_function("sign", &PopSchemeMPLWrapper::Sign)
.class_function("verify", &PopSchemeMPLWrapper::Verify)
.class_function("aggregate", &PopSchemeMPLWrapper::Aggregate)
.class_function("aggregate_verify", &PopSchemeMPLWrapper::AggregateVerify)
.class_function("derive_child_sk", &PopSchemeMPLWrapper::DeriveChildSk)
.class_function("derive_child_sk_unhardened", &PopSchemeMPLWrapper::DeriveChildSkUnhardened)
.class_function("derive_child_pk_unhardened", &PopSchemeMPLWrapper::DeriveChildPkUnhardened)
.class_function("pop_prove", &PopSchemeMPLWrapper::PopProve)
.class_function("pop_verify", &PopSchemeMPLWrapper::PopVerify)
.class_function("fast_aggregate_verify", &PopSchemeMPLWrapper::FastAggregateVerify);
.class_function("aggregateVerify", &PopSchemeMPLWrapper::AggregateVerify)
.class_function("deriveChildSk", &PopSchemeMPLWrapper::DeriveChildSk)
.class_function("deriveChildSkUnhardened", &PopSchemeMPLWrapper::DeriveChildSkUnhardened)
.class_function("deriveChildPkUnhardened", &PopSchemeMPLWrapper::DeriveChildPkUnhardened)
.class_function("popProve", &PopSchemeMPLWrapper::PopProve)
.class_function("popVerify", &PopSchemeMPLWrapper::PopVerify)
.class_function("fastAggregateVerify", &PopSchemeMPLWrapper::FastAggregateVerify);
class_<G1ElementWrapper>("G1Element")
.class_property("SIZE", &G1ElementWrapper::SIZE)
.constructor<>()
.class_function("fromBytes", &G1ElementWrapper::FromBytes) // Not removing this for compatibility
.class_function("from_bytes", &G1ElementWrapper::FromBytes)
.class_function("fromBytes", &G1ElementWrapper::FromBytes)
.class_function("generator", &G2ElementWrapper::Generator)
.function("serialize", &G1ElementWrapper::Serialize)
.function("negate", &G1ElementWrapper::Negate)
.function("deepcopy", &G1ElementWrapper::Deepcopy)
.function("get_fingerprint", &G1ElementWrapper::GetFingerprint)
.function("getFingerprint", &G1ElementWrapper::GetFingerprint)
.function("add", &G1ElementWrapper::Add)
.function("mul", &G1ElementWrapper::Mul)
.function("equal_to", &G1ElementWrapper::EqualTo);
.function("equalTo", &G1ElementWrapper::EqualTo);
class_<G2ElementWrapper>("G2Element")
.class_property("SIZE", &G2ElementWrapper::SIZE)
.constructor<>()
.class_function("fromBytes", &G2ElementWrapper::FromBytes) // Not removing this for compatibility
.class_function("from_bytes", &G2ElementWrapper::FromBytes)
.class_function("from_g2", &G2ElementWrapper::FromG2Element)
.class_function("aggregate_sigs", &G2ElementWrapper::AggregateSigs)
.class_function("fromBytes", &G2ElementWrapper::FromBytes)
.class_function("fromG2", &G2ElementWrapper::FromG2Element)
.class_function("aggregateSigs", &G2ElementWrapper::AggregateSigs)
.class_function("generator", &G2ElementWrapper::Generator)
.function("serialize", &G2ElementWrapper::Serialize)
.function("negate", &G2ElementWrapper::Negate)
.function("deepcopy", &G2ElementWrapper::Deepcopy)
.function("add", &G2ElementWrapper::Add)
.function("mul", &G2ElementWrapper::Mul)
.function("equal_to", &G2ElementWrapper::EqualTo);
.function("equalTo", &G2ElementWrapper::EqualTo);
class_<PrivateKeyWrapper>("PrivateKey")
.class_property("PRIVATE_KEY_SIZE", &PrivateKeyWrapper::PRIVATE_KEY_SIZE)
.class_function("fromBytes", &PrivateKeyWrapper::FromBytes) // Not removing this for compatibility
.class_function("from_bytes", &PrivateKeyWrapper::FromBytes)
.class_function("fromBytes", &PrivateKeyWrapper::FromBytes)
.class_function("aggregate", &PrivateKeyWrapper::Aggregate)
.function("deepcopy", &PrivateKeyWrapper::Deepcopy)
.function("serialize", &PrivateKeyWrapper::Serialize)
.function("get_g1", &PrivateKeyWrapper::GetG1)
.function("get_g2", &PrivateKeyWrapper::GetG2)
.function("mul_g1", &PrivateKeyWrapper::MulG1)
.function("mul_g2", &PrivateKeyWrapper::MulG2)
.function("equal_to", &PrivateKeyWrapper::EqualTo);
.function("getG1", &PrivateKeyWrapper::GetG1)
.function("getG2", &PrivateKeyWrapper::GetG2)
.function("mulG1", &PrivateKeyWrapper::MulG1)
.function("mulG2", &PrivateKeyWrapper::MulG2)
.function("equalTo", &PrivateKeyWrapper::EqualTo);
class_<BignumWrapper>("Bignum")
.class_function("fromString", &BignumWrapper::FromString) // Not removing this for compatibility
.class_function("from_string", &BignumWrapper::FromString)
.class_function("fromString", &BignumWrapper::FromString)
.function("toString", &BignumWrapper::ToString);
class_<UtilWrapper>("Util")
.class_function("hash256", &UtilWrapper::Hash256)
.class_function("hex_str", &UtilWrapper::HexStr);
.class_function("hexStr", &UtilWrapper::HexStr);
};
} // namespace js_wrappers

File diff suppressed because it is too large Load Diff

View File

@ -1,28 +1,31 @@
{
"name": "bls-signatures",
"version": "0.2.1-beta.0",
"name": "@dashevo/bls",
"version": "1.0.0-beta.3",
"description": "The most advanced BLS library for JavaScript",
"main": "blsjs.js",
"types": "blsjs.d.ts",
"files": [
"blsjs.js",
"blsjs.wasm",
"blsjstmp.wasm",
"blsjs.d.ts"
],
"directories": {
"test": "tests"
},
"scripts": {
"build:web": "node bundle_wasm_for_web.js",
"test": "npm run test:node && npm run test:browser",
"test:typings": "tsc --esModuleInterop ./tests/typings.spec.ts",
"test:node": "npm run test:typings && mocha ./tests/*.spec.js",
"test:browser": "npm run test:typings && ./node_modules/.bin/karma start ./tests/karma.conf.js --single-run"
"test:typings": "tsc ./tests/typings.spec.ts",
"test:node": "mocha ./tests/*.spec.js",
"test:browser": "npm run test:typings && karma start ./tests/karma.conf.js --single-run",
"webpack": "webpack --config=./webpack.config.js",
"rollup": "rollup -c"
},
"repository": {
"type": "git",
"url": "git@github.com:Chia-Network/bls-signatures.git"
"url": "git@github.com:dashpay/bls-signatures.git"
},
"homepage": "https://github.com/Chia-Network/bls-signatures/tree/master/js-bindings",
"homepage": "https://github.com/dashpay/bls-signatures/tree/main/js-bindings",
"author": {
"name": "Anton Suprunchuk",
"email": "antouhou@gmail.com",

View File

@ -56,8 +56,8 @@ describe('PrivateKey', () => {
const message1 = Uint8Array.from([1, 65, 254, 88, 90, 45, 22]);
const seed = Uint8Array.from([28, 20, 102, 229, 1, 157]);
const sk1 = AugSchemeMPL.key_gen(getPkSeed());
const pk1 = AugSchemeMPL.sk_to_g1(sk1);
const sk1 = AugSchemeMPL.keyGen(getPkSeed());
const pk1 = AugSchemeMPL.skToG1(sk1);
const sig1 = AugSchemeMPL.sign(sk1, message1);
assert(AugSchemeMPL.verify(pk1, message1, sig1));
@ -67,7 +67,7 @@ describe('PrivateKey', () => {
it('Should create a private key from a seed', () => {
const {AugSchemeMPL, PrivateKey} = blsSignatures;
const pk = AugSchemeMPL.key_gen(getPkSeed());
const pk = AugSchemeMPL.keyGen(getPkSeed());
assert(pk instanceof PrivateKey);
assert.deepStrictEqual(pk.serialize(), getPkBuffer());
});
@ -77,14 +77,14 @@ describe('PrivateKey', () => {
it('Should create a private key from a Buffer', () => {
const {PrivateKey, Util} = blsSignatures;
const pk = PrivateKey.from_bytes(getPkBuffer(), false);
const pk = PrivateKey.fromBytes(getPkBuffer(), false);
assert(pk instanceof PrivateKey);
assert.deepStrictEqual(pk.serialize(), getPkBuffer());
});
it('Should create a private key from a Uint8Array', () => {
const {PrivateKey, Util} = blsSignatures;
const pk = PrivateKey.from_bytes(getPkUint8Array(), false);
const pk = PrivateKey.fromBytes(getPkUint8Array(), false);
assert(pk instanceof PrivateKey);
assert.deepStrictEqual(pk.serialize(), getPkBuffer());
});
@ -94,7 +94,7 @@ describe('PrivateKey', () => {
it('Should serialize key to a Buffer', () => {
const {AugSchemeMPL, PrivateKey} = blsSignatures;
const pk = AugSchemeMPL.key_gen(getPkSeed());
const pk = AugSchemeMPL.keyGen(getPkSeed());
const serialized = pk.serialize();
assert(serialized instanceof Uint8Array);
assert.deepStrictEqual(serialized, getPkBuffer());
@ -106,7 +106,7 @@ describe('PrivateKey', () => {
const {AugSchemeMPL, PrivateKey, G2Element} = blsSignatures;
const pk = PrivateKey.fromBytes(getPkBuffer(), false);
const pubkey = AugSchemeMPL.sk_to_g1(pk);
const pubkey = AugSchemeMPL.skToG1(pk);
const message = 'Hello world';
const messageBuffer = Uint8Array.from(Buffer.from(message, 'utf8'));
const signature = AugSchemeMPL.sign(pk, messageBuffer);
@ -119,10 +119,10 @@ describe('PrivateKey', () => {
it('Should return a public key with a verifiable fingerprint', () => {
const {AugSchemeMPL, PrivateKey, G1Element} = blsSignatures;
const pk = AugSchemeMPL.key_gen(getPkSeed());
const publicKey = AugSchemeMPL.sk_to_g1(pk);
const pk = AugSchemeMPL.keyGen(getPkSeed());
const publicKey = AugSchemeMPL.skToG1(pk);
assert(publicKey instanceof G1Element);
assert.strictEqual(publicKey.get_fingerprint(), getSeedAndFinferprint().fingerprint);
assert.strictEqual(publicKey.getFingerprint(), getSeedAndFinferprint().fingerprint);
});
});
});

View File

@ -41,11 +41,11 @@ before((done) => {
});
describe('G1Element', () => {
describe('.from_bytes', () => {
describe('.fromBytes', () => {
it('Should create a public key from bytes', () => {
const {G1Element, Util} = blsSignatures;
const pk = G1Element.from_bytes(getPublicKeyFixture().buffer);
const pk = G1Element.fromBytes(getPublicKeyFixture().buffer);
assert(pk instanceof G1Element);
});
});
@ -54,12 +54,12 @@ describe('G1Element', () => {
it('Should aggregate keys if keys array contains more than one key', () => {
const {G1Element} = blsSignatures;
const pks = getPublicKeysArray().map(buf => G1Element.from_bytes(buf));
let first_pk = pks[0];
const pks = getPublicKeysArray().map(buf => G1Element.fromBytes(buf));
let firstPk = pks[0];
for (var i = 1; i < pks.length; i++) {
first_pk = first_pk.add(pks[i]);
firstPk = firstPk.add(pks[i]);
}
assert(first_pk instanceof G1Element);
assert(firstPk instanceof G1Element);
});
});
@ -67,7 +67,7 @@ describe('G1Element', () => {
it('Should serialize key to the same buffer', () => {
const {G1Element} = blsSignatures;
const pk = G1Element.from_bytes(getPublicKeyFixture().buffer);
const pk = G1Element.fromBytes(getPublicKeyFixture().buffer);
const serialized = pk.serialize();
assert.deepStrictEqual(Buffer.from(serialized).toString('hex'), getPublicKeyFixtureHex());
});
@ -77,8 +77,8 @@ describe('G1Element', () => {
it('Should get correct fingerprint', () => {
const {G1Element} = blsSignatures;
const pk = G1Element.from_bytes(getPublicKeyFixture().buffer);
const fingerprint = pk.get_fingerprint();
const pk = G1Element.fromBytes(getPublicKeyFixture().buffer);
const fingerprint = pk.getFingerprint();
assert.strictEqual(fingerprint, getPublicKeyFixture().fingerprint);
});
});

View File

@ -38,13 +38,13 @@ describe('Signature', () => {
const seed2 = makehash(Uint8Array.from([3, 4, 5, 6, 7]));
const seed3 = makehash(Uint8Array.from([4, 5, 6, 7, 8]));
const privateKey1 = BasicSchemeMPL.key_gen(seed1);
const privateKey2 = BasicSchemeMPL.key_gen(seed2);
const privateKey3 = BasicSchemeMPL.key_gen(seed3);
const privateKey1 = BasicSchemeMPL.keyGen(seed1);
const privateKey2 = BasicSchemeMPL.keyGen(seed2);
const privateKey3 = BasicSchemeMPL.keyGen(seed3);
const publicKey1 = BasicSchemeMPL.sk_to_g1(privateKey1);
const publicKey2 = BasicSchemeMPL.sk_to_g1(privateKey2);
const publicKey3 = BasicSchemeMPL.sk_to_g1(privateKey3);
const publicKey1 = BasicSchemeMPL.skToG1(privateKey1);
const publicKey2 = BasicSchemeMPL.skToG1(privateKey2);
const publicKey3 = BasicSchemeMPL.skToG1(privateKey3);
const sig1 = BasicSchemeMPL.sign(privateKey1, message);
const sig2 = BasicSchemeMPL.sign(privateKey2, message);
@ -89,14 +89,14 @@ describe('Signature', () => {
it('Should aggregate signature', () => {
const {AugSchemeMPL, G2Element, PrivateKey} = blsSignatures;
const sk = AugSchemeMPL.key_gen(makehash(Uint8Array.from([1, 2, 3])));
const pk = AugSchemeMPL.sk_to_g1(sk);
const sk = AugSchemeMPL.keyGen(makehash(Uint8Array.from([1, 2, 3])));
const pk = AugSchemeMPL.skToG1(sk);
const msg1 = Uint8Array.from([3, 4, 5]);
const msg2 = Uint8Array.from([6, 7, 8]);
const sig1 = AugSchemeMPL.sign(sk, msg1);
const sig2 = AugSchemeMPL.sign(sk, msg2);
const aggregatedSig = G2Element.aggregate_sigs([sig1, sig2]);
assert.strictEqual(AugSchemeMPL.aggregate_verify([pk, pk], [msg1, msg2], aggregatedSig), true);
const aggregatedSig = G2Element.aggregateSigs([sig1, sig2]);
assert.strictEqual(AugSchemeMPL.aggregateVerify([pk, pk], [msg1, msg2], aggregatedSig), true);
sk.delete();
pk.delete();
@ -109,7 +109,7 @@ describe('Signature', () => {
it('Should serialize signature to Buffer', () => {
const {AugSchemeMPL, G2Element, PrivateKey} = blsSignatures;
const sk = AugSchemeMPL.key_gen(makehash(Uint8Array.from([1, 2, 3, 4, 5])));
const sk = AugSchemeMPL.keyGen(makehash(Uint8Array.from([1, 2, 3, 4, 5])));
const sig = AugSchemeMPL.sign(sk, Uint8Array.from([100, 2, 254, 88, 90, 45, 23]));
assert(sig instanceof G2Element);
assert.deepStrictEqual(Buffer.from(sig.serialize()).toString('hex'), getSignatureHex());
@ -125,15 +125,15 @@ describe('Signature', () => {
const message = Uint8Array.from(Buffer.from('Message'));
const seed1 = makehash(Buffer.from([1, 2, 3, 4, 5]));
const seed2 = makehash(Buffer.from([1, 2, 3, 4, 6]));
const sk1 = AugSchemeMPL.key_gen(seed1);
const sk2 = AugSchemeMPL.key_gen(seed2);
const pk1 = AugSchemeMPL.sk_to_g1(sk1);
const pk2 = AugSchemeMPL.sk_to_g1(sk2);
const sk1 = AugSchemeMPL.keyGen(seed1);
const sk2 = AugSchemeMPL.keyGen(seed2);
const pk1 = AugSchemeMPL.skToG1(sk1);
const pk2 = AugSchemeMPL.skToG1(sk2);
const sig1 = AugSchemeMPL.sign(sk1, message);
const sig2 = AugSchemeMPL.sign(sk2, message);
const sig = AugSchemeMPL.aggregate([sig1, sig2]);
assert(AugSchemeMPL.aggregate_verify([pk1, pk2], [message, message], sig));
assert(AugSchemeMPL.aggregateVerify([pk1, pk2], [message, message], sig));
sk1.delete();
sk2.delete();
@ -149,8 +149,8 @@ describe('Signature', () => {
const message1 = Uint8Array.from(Buffer.from('Message'));
const message2 = Uint8Array.from(Buffer.from('Nessage'));
const seed = makehash(Buffer.from([1, 2, 3, 4, 5]));
const sk = AugSchemeMPL.key_gen(seed);
const pk = AugSchemeMPL.sk_to_g1(sk);
const sk = AugSchemeMPL.keyGen(seed);
const pk = AugSchemeMPL.skToG1(sk);
const sig = AugSchemeMPL.sign(sk, message1);
assert.strictEqual(AugSchemeMPL.verify(pk, message2, sig), false);

View File

@ -50,7 +50,7 @@ blsjs().then((blsjs) => {
Util
} = blsjs;
function test_schemes() {
function testSchemes() {
var seedArray = [
0, 50, 6, 244, 24, 199, 1, 25, 52, 88, 192, 19, 18, 12, 89, 6,
220, 18, 102, 58, 209, 82, 12, 62, 89, 110, 182, 9, 44, 20, 254, 22
@ -59,8 +59,8 @@ blsjs().then((blsjs) => {
const msg = Buffer.from([100, 2, 254, 88, 90, 45, 23]);
const msg2 = Buffer.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
const sk = BasicSchemeMPL.key_gen(seed);
const pk = sk.get_g1();
const sk = BasicSchemeMPL.keyGen(seed);
const pk = sk.getG1();
//assert(sk == PrivateKey.fromBytes(sk.serialize(), false));
//assert(pk == G1Element.fromBytes(pk.serialize()));
@ -72,49 +72,49 @@ blsjs().then((blsjs) => {
});
var seed = Buffer.concat([Buffer.from([1]), seed.slice(1)]);
const sk1 = BasicSchemeMPL.key_gen(seed);
const pk1 = sk1.get_g1();
const sk1 = BasicSchemeMPL.keyGen(seed);
const pk1 = sk1.getG1();
var seed = Buffer.concat([Buffer.from([2]), seed.slice(1)]);
const sk2 = BasicSchemeMPL.key_gen(seed);
const pk2 = sk2.get_g1();
const sk2 = BasicSchemeMPL.keyGen(seed);
const pk2 = sk2.getG1();
[BasicSchemeMPL, AugSchemeMPL, PopSchemeMPL].map((Scheme) => {
// Aggregate same message
const agg_pk = pk1.add(pk2);
const aggPk = pk1.add(pk2);
var sig1, sig2;
if (Scheme === AugSchemeMPL) {
sig1 = Scheme.sign_prepend(sk1, msg, agg_pk);
sig2 = Scheme.sign_prepend(sk2, msg, agg_pk);
sig1 = Scheme.signPrepend(sk1, msg, aggPk);
sig2 = Scheme.signPrepend(sk2, msg, aggPk);
} else {
sig1 = Scheme.sign(sk1, msg);
sig2 = Scheme.sign(sk2, msg);
}
var agg_sig = Scheme.aggregate([sig1, sig2]);
assert(Scheme.verify(agg_pk, msg, agg_sig));
var aggSig = Scheme.aggregate([sig1, sig2]);
assert(Scheme.verify(aggPk, msg, aggSig));
// Aggregate different message
sig1 = Scheme.sign(sk1, msg)
sig2 = Scheme.sign(sk2, msg2)
agg_sig = Scheme.aggregate([sig1, sig2])
assert(Scheme.aggregate_verify([pk1, pk2], [msg, msg2], agg_sig));
aggSig = Scheme.aggregate([sig1, sig2])
assert(Scheme.aggregateVerify([pk1, pk2], [msg, msg2], aggSig));
// HD keys
const child = Scheme.derive_child_sk(sk1, 123);
const childU = Scheme.derive_child_sk_unhardened(sk1, 123);
const childUPk = Scheme.derive_child_pk_unhardened(pk1, 123);
const child = Scheme.deriveChildSk(sk1, 123);
const childU = Scheme.deriveChildSkUnhardened(sk1, 123);
const childUPk = Scheme.deriveChildPkUnhardened(pk1, 123);
const sig_child = Scheme.sign(child, msg);
assert(Scheme.verify(child.get_g1(), msg, sig_child));
const sigChild = Scheme.sign(child, msg);
assert(Scheme.verify(child.getG1(), msg, sigChild));
const sigU_child = Scheme.sign(childU, msg);
assert(Scheme.verify(childUPk, msg, sigU_child));
const sigUChild = Scheme.sign(childU, msg);
assert(Scheme.verify(childUPk, msg, sigUChild));
});
}
function test_vectors_invalid() {
function testVectorsInvalid() {
// Invalid inputs from https://github.com/algorand/bls_sigs_ref/blob/master/python-impl/serdesZ.py
const invalid_inputs_1 = [
const invalidInputs1 = [
// infinity points: too short
"c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
// infinity points: not all zeros
@ -131,7 +131,7 @@ blsjs().then((blsjs) => {
// invalid elm of Fp --- equal to p (must be strictly less)
"9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
]
const invalid_inputs_2 = [
const invalidInputs2 = [
// infinity points: too short
"c000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
// infinity points: not all zeros
@ -151,36 +151,36 @@ blsjs().then((blsjs) => {
"9a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaaa1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab",
];
let g1_exn_count = 0;
let g2_exn_count = 0;
let g1ExnCount = 0;
let g2ExnCount = 0;
invalid_inputs_1.map((s) => {
invalidInputs1.map((s) => {
const bytes_ = binascii.unhexlify(s);
try {
const g1 = G1Element(bytes_);
console.log(`Failed to disallow creation of G1 element for string ${s}`);
assert(false);
} catch(e) {
g1_exn_count++;
g1ExnCount++;
}
});
invalid_inputs_2.map((s) => {
invalidInputs2.map((s) => {
const bytes_ = binascii.unhexlify(s);
try {
const g2 = G2Element(bytes_);
console.log(`Failed to disallow creation of G2 element for string ${s}`);
assert(false);
} catch(e) {
g2_exn_count++;
g2ExnCount++;
}
});
assert(g1_exn_count == invalid_inputs_1.length);
assert(g2_exn_count == invalid_inputs_2.length);
assert(g1ExnCount == invalidInputs1.length);
assert(g2ExnCount == invalidInputs2.length);
}
function test_vectors_valid() {
function testVectorsValid() {
// The following code was used to generate these vectors
//
// from py_ecc.bls import (
@ -191,8 +191,8 @@ blsjs().then((blsjs) => {
//
// secret1 = bytes([1] * 32)
// secret2 = bytes([x * 314159 % 256 for x in range(32)])
// sk1 = int.from_bytes(secret1, 'big')
// sk2 = int.from_bytes(secret2, 'big')
// sk1 = int.fromBytes(secret1, 'big')
// sk2 = int.fromBytes(secret2, 'big')
// msg = bytes([3, 1, 4, 1, 5, 9])
// pk1 = G2Basic.SkToPk(sk1)
// pk2 = G2Basic.SkToPk(sk2)
@ -207,15 +207,15 @@ blsjs().then((blsjs) => {
//
// Javascript version converts these strings to binascii
const ref_sig1Basic = bytes('96ba34fac33c7f129d602a0bc8a3d43f9abc014eceaab7359146b4b150e57b808645738f35671e9e10e0d862a30cab70074eb5831d13e6a5b162d01eebe687d0164adbd0a864370a7c222a2768d7704da254f1bf1823665bc2361f9dd8c00e99');
const ref_sig2Basic = bytes('a402790932130f766af11ba716536683d8c4cfa51947e4f9081fedd692d6dc0cac5b904bee5ea6e25569e36d7be4ca59069a96e34b7f700758b716f9494aaa59a96e74d14a3b552a9a6bc129e717195b9d6006fd6d5cef4768c022e0f7316abf');
const ref_sigABasic = bytes('987cfd3bcd62280287027483f29c55245ed831f51dd6bd999a6ff1a1f1f1f0b647778b0167359c71505558a76e158e66181ee5125905a642246b01e7fa5ee53d68a4fe9bfb29a8e26601f0b9ad577ddd18876a73317c216ea61f430414ec51c5');
const ref_sig1Aug = bytes('8180f02ccb72e922b152fcedbe0e1d195210354f70703658e8e08cbebf11d4970eab6ac3ccf715f3fb876df9a9797abd0c1af61aaeadc92c2cfe5c0a56c146cc8c3f7151a073cf5f16df38246724c4aed73ff30ef5daa6aacaed1a26ecaa336b');
const ref_sig2Aug = bytes('99111eeafb412da61e4c37d3e806c6fd6ac9f3870e54da9222ba4e494822c5b7656731fa7a645934d04b559e9261b86201bbee57055250a459a2da10e51f9c1a6941297ffc5d970a557236d0bdeb7cf8ff18800b08633871a0f0a7ea42f47480');
const ref_sigAAug = bytes('8c5d03f9dae77e19a5945a06a214836edb8e03b851525d84b9de6440e68fc0ca7303eeed390d863c9b55a8cf6d59140a01b58847881eb5af67734d44b2555646c6616c39ab88d253299acc1eb1b19ddb9bfcbe76e28addf671d116c052bb1847');
const ref_sig1Pop = bytes('9550fb4e7f7e8cc4a90be8560ab5a798b0b23000b6a54a2117520210f986f3f281b376f259c0b78062d1eb3192b3d9bb049f59ecc1b03a7049eb665e0df36494ae4cb5f1136ccaeefc9958cb30c3333d3d43f07148c386299a7b1bfc0dc5cf7c');
const ref_sig2Pop = bytes('a69036bc11ae5efcbf6180afe39addde7e27731ec40257bfdc3c37f17b8df68306a34ebd10e9e32a35253750df5c87c2142f8207e8d5654712b4e554f585fb6846ff3804e429a9f8a1b4c56b75d0869ed67580d789870babe2c7c8a9d51e7b2a');
const ref_sigAPop = bytes('a4ea742bcdc1553e9ca4e560be7e5e6c6efa6a64dddf9ca3bb2854233d85a6aac1b76ec7d103db4e33148b82af9923db05934a6ece9a7101cd8a9d47ce27978056b0f5900021818c45698afdd6cf8a6b6f7fee1f0b43716f55e413d4b87a6039');
const refSig1Basic = bytes('96ba34fac33c7f129d602a0bc8a3d43f9abc014eceaab7359146b4b150e57b808645738f35671e9e10e0d862a30cab70074eb5831d13e6a5b162d01eebe687d0164adbd0a864370a7c222a2768d7704da254f1bf1823665bc2361f9dd8c00e99');
const refSig2Basic = bytes('a402790932130f766af11ba716536683d8c4cfa51947e4f9081fedd692d6dc0cac5b904bee5ea6e25569e36d7be4ca59069a96e34b7f700758b716f9494aaa59a96e74d14a3b552a9a6bc129e717195b9d6006fd6d5cef4768c022e0f7316abf');
const refSigABasic = bytes('987cfd3bcd62280287027483f29c55245ed831f51dd6bd999a6ff1a1f1f1f0b647778b0167359c71505558a76e158e66181ee5125905a642246b01e7fa5ee53d68a4fe9bfb29a8e26601f0b9ad577ddd18876a73317c216ea61f430414ec51c5');
const refSig1Aug = bytes('8180f02ccb72e922b152fcedbe0e1d195210354f70703658e8e08cbebf11d4970eab6ac3ccf715f3fb876df9a9797abd0c1af61aaeadc92c2cfe5c0a56c146cc8c3f7151a073cf5f16df38246724c4aed73ff30ef5daa6aacaed1a26ecaa336b');
const refSig2Aug = bytes('99111eeafb412da61e4c37d3e806c6fd6ac9f3870e54da9222ba4e494822c5b7656731fa7a645934d04b559e9261b86201bbee57055250a459a2da10e51f9c1a6941297ffc5d970a557236d0bdeb7cf8ff18800b08633871a0f0a7ea42f47480');
const refSigAAug = bytes('8c5d03f9dae77e19a5945a06a214836edb8e03b851525d84b9de6440e68fc0ca7303eeed390d863c9b55a8cf6d59140a01b58847881eb5af67734d44b2555646c6616c39ab88d253299acc1eb1b19ddb9bfcbe76e28addf671d116c052bb1847');
const refSig1Pop = bytes('9550fb4e7f7e8cc4a90be8560ab5a798b0b23000b6a54a2117520210f986f3f281b376f259c0b78062d1eb3192b3d9bb049f59ecc1b03a7049eb665e0df36494ae4cb5f1136ccaeefc9958cb30c3333d3d43f07148c386299a7b1bfc0dc5cf7c');
const refSig2Pop = bytes('a69036bc11ae5efcbf6180afe39addde7e27731ec40257bfdc3c37f17b8df68306a34ebd10e9e32a35253750df5c87c2142f8207e8d5654712b4e554f585fb6846ff3804e429a9f8a1b4c56b75d0869ed67580d789870babe2c7c8a9d51e7b2a');
const refSigAPop = bytes('a4ea742bcdc1553e9ca4e560be7e5e6c6efa6a64dddf9ca3bb2854233d85a6aac1b76ec7d103db4e33148b82af9923db05934a6ece9a7101cd8a9d47ce27978056b0f5900021818c45698afdd6cf8a6b6f7fee1f0b43716f55e413d4b87a6039');
const secret1 = Buffer.from(repeat(32,1));
const secret2 = Buffer.from(range(32).map((x) => x * 314159 % 256));
@ -233,18 +233,18 @@ blsjs().then((blsjs) => {
const sig2Pop = PopSchemeMPL.sign(sk2, msg)
const sigAPop = PopSchemeMPL.aggregate([sig1Pop, sig2Pop])
assert(Buffer.from(sig1Basic.serialize()).equals(ref_sig1Basic));
assert(Buffer.from(sig2Basic.serialize()).equals(ref_sig2Basic));
assert(Buffer.from(sigABasic.serialize()).equals(ref_sigABasic));
assert(Buffer.from(sig1Aug.serialize()).equals(ref_sig1Aug));
assert(Buffer.from(sig2Aug.serialize()).equals(ref_sig2Aug));
assert(Buffer.from(sigAAug.serialize()).equals(ref_sigAAug));
assert(Buffer.from(sig1Pop.serialize()).equals(ref_sig1Pop));
assert(Buffer.from(sig2Pop.serialize()).equals(ref_sig2Pop));
assert(Buffer.from(sigAPop.serialize()).equals(ref_sigAPop));
assert(Buffer.from(sig1Basic.serialize()).equals(refSig1Basic));
assert(Buffer.from(sig2Basic.serialize()).equals(refSig2Basic));
assert(Buffer.from(sigABasic.serialize()).equals(refSigABasic));
assert(Buffer.from(sig1Aug.serialize()).equals(refSig1Aug));
assert(Buffer.from(sig2Aug.serialize()).equals(refSig2Aug));
assert(Buffer.from(sigAAug.serialize()).equals(refSigAAug));
assert(Buffer.from(sig1Pop.serialize()).equals(refSig1Pop));
assert(Buffer.from(sig2Pop.serialize()).equals(refSig2Pop));
assert(Buffer.from(sigAPop.serialize()).equals(refSigAPop));
}
function test_readme() {
function testReadme() {
let seed = Buffer.from(
[
0,
@ -281,8 +281,8 @@ blsjs().then((blsjs) => {
22,
]
);
let sk = AugSchemeMPL.key_gen(seed);
let pk = sk.get_g1();
let sk = AugSchemeMPL.keyGen(seed);
let pk = sk.getG1();
const message = Buffer.from([1, 2, 3, 4, 5]);
let signature = AugSchemeMPL.sign(sk, message);
@ -290,107 +290,107 @@ blsjs().then((blsjs) => {
let ok = AugSchemeMPL.verify(pk, message, signature);
assert(ok);
const sk_bytes = sk.serialize(); // 32 bytes
const pk_bytes = pk.serialize(); // 48 bytes
const signature_bytes = signature.serialize(); // 96 bytes
const skBytes = sk.serialize(); // 32 bytes
const pkBytes = pk.serialize(); // 48 bytes
const signatureBytes = signature.serialize(); // 96 bytes
console.log(Buffer.from(sk_bytes).toString('hex'), Buffer.from(pk_bytes).toString('hex'), Buffer.from(signature_bytes).toString('hex'));
console.log(Buffer.from(skBytes).toString('hex'), Buffer.from(pkBytes).toString('hex'), Buffer.from(signatureBytes).toString('hex'));
sk = PrivateKey.fromBytes(sk_bytes, false);
pk = G1Element.fromBytes(pk_bytes);
signature = G2Element.fromBytes(signature_bytes);
sk = PrivateKey.fromBytes(skBytes, false);
pk = G1Element.fromBytes(pkBytes);
signature = G2Element.fromBytes(signatureBytes);
seed = Buffer.concat([Buffer.from([1]), seed.slice(1)]);
const sk1 = AugSchemeMPL.key_gen(seed);
const sk1 = AugSchemeMPL.keyGen(seed);
seed = Buffer.concat([Buffer.from([2]), seed.slice(1)]);
const sk2 = AugSchemeMPL.key_gen(seed);
const sk2 = AugSchemeMPL.keyGen(seed);
const message2 = Buffer.from([1, 2, 3, 4, 5, 6, 7]);
const pk1 = sk1.get_g1();
const pk1 = sk1.getG1();
const sig1 = AugSchemeMPL.sign(sk1, message);
const pk2 = sk2.get_g1();
const pk2 = sk2.getG1();
const sig2 = AugSchemeMPL.sign(sk2, message2);
const agg_sig = AugSchemeMPL.aggregate([sig1, sig2]);
const aggSig = AugSchemeMPL.aggregate([sig1, sig2]);
ok = AugSchemeMPL.aggregate_verify([pk1, pk2], [message, message2], agg_sig);
ok = AugSchemeMPL.aggregateVerify([pk1, pk2], [message, message2], aggSig);
assert(ok);
seed = Buffer.concat([Buffer.from([3]), seed.slice(1)]);
const sk3 = AugSchemeMPL.key_gen(seed);
const pk3 = sk3.get_g1();
const sk3 = AugSchemeMPL.keyGen(seed);
const pk3 = sk3.getG1();
const message3 = Buffer.from([100, 2, 254, 88, 90, 45, 23]);
const sig3 = AugSchemeMPL.sign(sk3, message3);
const agg_sig_final = AugSchemeMPL.aggregate([agg_sig, sig3]);
ok = AugSchemeMPL.aggregate_verify(
[pk1, pk2, pk3], [message, message2, message3], agg_sig_final
const aggSigFinal = AugSchemeMPL.aggregate([aggSig, sig3]);
ok = AugSchemeMPL.aggregateVerify(
[pk1, pk2, pk3], [message, message2, message3], aggSigFinal
);
assert(ok);
const pop_sig1 = PopSchemeMPL.sign(sk1, message);
const pop_sig2 = PopSchemeMPL.sign(sk2, message);
const pop_sig3 = PopSchemeMPL.sign(sk3, message);
const pop1 = PopSchemeMPL.pop_prove(sk1);
const pop2 = PopSchemeMPL.pop_prove(sk2);
const pop3 = PopSchemeMPL.pop_prove(sk3);
const popSig1 = PopSchemeMPL.sign(sk1, message);
const popSig2 = PopSchemeMPL.sign(sk2, message);
const popSig3 = PopSchemeMPL.sign(sk3, message);
const pop1 = PopSchemeMPL.popProve(sk1);
const pop2 = PopSchemeMPL.popProve(sk2);
const pop3 = PopSchemeMPL.popProve(sk3);
ok = PopSchemeMPL.pop_verify(pk1, pop1);
ok = PopSchemeMPL.popVerify(pk1, pop1);
assert(ok);
ok = PopSchemeMPL.pop_verify(pk2, pop2);
ok = PopSchemeMPL.popVerify(pk2, pop2);
assert(ok);
ok = PopSchemeMPL.pop_verify(pk3, pop3);
ok = PopSchemeMPL.popVerify(pk3, pop3);
assert(ok);
const pop_sig_agg = PopSchemeMPL.aggregate([pop_sig1, pop_sig2, pop_sig3]);
const popSigAgg = PopSchemeMPL.aggregate([popSig1, popSig2, popSig3]);
ok = PopSchemeMPL.fast_aggregate_verify([pk1, pk2, pk3], message, pop_sig_agg);
ok = PopSchemeMPL.fastAggregateVerify([pk1, pk2, pk3], message, popSigAgg);
assert(ok);
const pop_agg_pk = pk1.add(pk2).add(pk3);
assert(Buffer.from(pop_agg_pk.serialize()).toString('hex') == '8ffb2a3c4a6ce516febdf1f2a5140c6974cce2530ebc1b56629f078c25d538aa3d8f0cf694516b4bfc8d344bbea829d3');
const t_pop_agg_pk_1 = pk1.add(pk2.add(pk3));
assert(Buffer.from(pop_agg_pk.serialize()).equals(Buffer.from(t_pop_agg_pk_1.serialize())));
const popAggPk = pk1.add(pk2).add(pk3);
assert(Buffer.from(popAggPk.serialize()).toString('hex') == '8ffb2a3c4a6ce516febdf1f2a5140c6974cce2530ebc1b56629f078c25d538aa3d8f0cf694516b4bfc8d344bbea829d3');
const tPopAggPk1 = pk1.add(pk2.add(pk3));
assert(Buffer.from(popAggPk.serialize()).equals(Buffer.from(tPopAggPk1.serialize())));
assert(Buffer.from(pop_sig_agg.serialize()).toString('hex') == 'b3115327c21286b043cf972db56cefe0a745a8091482c9eec47fe5c0dbdb2ffc4d05ae54e7ee45e209135e6c81e8af2212465abffe8ab3166d3f4d5ed1f4d98cb65323d8d1fc210311c7e46a5f637ef7d90b7f3206708dc4bb32a2e1549a3060');
ok = PopSchemeMPL.verify(pop_agg_pk, message, pop_sig_agg);
assert(Buffer.from(popSigAgg.serialize()).toString('hex') == 'b3115327c21286b043cf972db56cefe0a745a8091482c9eec47fe5c0dbdb2ffc4d05ae54e7ee45e209135e6c81e8af2212465abffe8ab3166d3f4d5ed1f4d98cb65323d8d1fc210311c7e46a5f637ef7d90b7f3206708dc4bb32a2e1549a3060');
ok = PopSchemeMPL.verify(popAggPk, message, popSigAgg);
assert(ok);
const pop_agg_sk = PrivateKey.aggregate([sk1, sk2, sk3]);
ok = Buffer.from(PopSchemeMPL.sign(pop_agg_sk, message).serialize()).equals(Buffer.from(pop_sig_agg.serialize()));
const popAggSk = PrivateKey.aggregate([sk1, sk2, sk3]);
ok = Buffer.from(PopSchemeMPL.sign(popAggSk, message).serialize()).equals(Buffer.from(popSigAgg.serialize()));
assert(ok);
const master_sk = AugSchemeMPL.key_gen(seed);
const child = AugSchemeMPL.derive_child_sk(master_sk, 152);
const grandchild = AugSchemeMPL.derive_child_sk(child, 952);
const masterSk = AugSchemeMPL.keyGen(seed);
const child = AugSchemeMPL.deriveChildSk(masterSk, 152);
const grandchild = AugSchemeMPL.deriveChildSk(child, 952);
const master_pk = master_sk.get_g1();
const child_u = AugSchemeMPL.derive_child_sk_unhardened(master_sk, 22);
const grandchild_u = AugSchemeMPL.derive_child_sk_unhardened(child_u, 0);
const masterPk = masterSk.getG1();
const childU = AugSchemeMPL.deriveChildSkUnhardened(masterSk, 22);
const grandchildU = AugSchemeMPL.deriveChildSkUnhardened(childU, 0);
const child_u_pk = AugSchemeMPL.derive_child_pk_unhardened(master_pk, 22);
const grandchild_u_pk = AugSchemeMPL.derive_child_pk_unhardened(child_u_pk, 0);
const childUPk = AugSchemeMPL.deriveChildPkUnhardened(masterPk, 22);
const grandchildUPk = AugSchemeMPL.deriveChildPkUnhardened(childUPk, 0);
ok = Buffer.from(grandchild_u_pk.serialize()).equals(Buffer.from(grandchild_u.get_g1().serialize()));
ok = Buffer.from(grandchildUPk.serialize()).equals(Buffer.from(grandchildU.getG1().serialize()));
assert(ok);
}
function test_aggregate_verify_zero_items() {
assert(AugSchemeMPL.aggregate_verify([], [], new G2Element()));
function testAggregateVerifyZeroItems() {
assert(AugSchemeMPL.aggregateVerify([], [], new G2Element()));
}
function test_bignum() {
function testBignum() {
const mersenne = Bignum.fromString('162259276829213363391578010288127', 10);
assert(mersenne.toString(16).toLowerCase() == '7ffffffffffffffffffffffffff');
}
test_schemes();
test_vectors_invalid();
test_vectors_valid();
test_readme();
test_aggregate_verify_zero_items();
test_bignum();
testSchemes();
testVectorsInvalid();
testVectorsValid();
testReadme();
testAggregateVerifyZeroItems();
testBignum();
}).then(function() {
console.log("\nAll tests passed.");
});

View File

@ -70,9 +70,9 @@ createBlsSignaturesModule().then((blsSignatures) => {
describe('typings', () => {
it('PrivateKey', () => {
strictEqual(PrivateKey.PRIVATE_KEY_SIZE, 32);
const sk = AugSchemeMPL.key_gen(getSkSeed());
const sk = AugSchemeMPL.keyGen(getSkSeed());
const aggSk = PrivateKey.aggregate([sk]);
const pk = sk.get_g1();
const pk = sk.getG1();
const bytes: Uint8Array = sk.serialize();
const sig = AugSchemeMPL.sign(sk, getMessageBytes());
ok(AugSchemeMPL.verify(pk, getMessageBytes(), sig));
@ -83,9 +83,9 @@ createBlsSignaturesModule().then((blsSignatures) => {
it('G1Element', () => {
strictEqual(G1Element.SIZE, 48);
const pk = G1Element.from_bytes(getPkBytes());
const pk = G1Element.fromBytes(getPkBytes());
const aggPk = pk.add(pk);
const fingerprint: number = pk.get_fingerprint();
const fingerprint: number = pk.getFingerprint();
const bytes: Uint8Array = pk.serialize();
pk.delete();
aggPk.delete();
@ -93,10 +93,10 @@ createBlsSignaturesModule().then((blsSignatures) => {
it('G2Element', () => {
strictEqual(G2Element.SIZE, 96);
const pk = G1Element.from_bytes(getPkBytes());
const sig = G2Element.from_bytes(getSignatureBytes());
const pk = G1Element.fromBytes(getPkBytes());
const sig = G2Element.fromBytes(getSignatureBytes());
const aggSig = AugSchemeMPL.aggregate([sig]);
const sig2 = G2Element.from_bytes(getSignatureBytes());
const sig2 = G2Element.fromBytes(getSignatureBytes());
const isValid: boolean =
AugSchemeMPL.verify(pk, getMessageBytes(), sig);
const serialized: Uint8Array = sig.serialize();

18
js_build_docker.sh Executable file
View File

@ -0,0 +1,18 @@
DOCKER_IMAGE=emscripten/emsdk
git submodule update --init --recursive
mkdir js_build
docker run \
--rm \
-v $(pwd):/src \
-w="/src/js_build" \
$DOCKER_IMAGE \
emcmake cmake /src
docker run \
--rm \
-v $(pwd):/src \
-w="/src/js_build" \
$DOCKER_IMAGE \
cmake --build . -- -j10

View File

@ -3,7 +3,7 @@ include(FetchContent)
FetchContent_Declare(
pybind11
GIT_REPOSITORY https://github.com/pybind/pybind11.git
GIT_TAG v2.9.1
GIT_TAG v2.10.0
)
FetchContent_MakeAvailable(pybind11)

View File

@ -196,8 +196,8 @@ if platform.system() == "Windows":
long_description_content_type="text/markdown",
url="https://github.com/Chia-Network/bls-signatures",
python_requires=">=3.7",
setup_requires=["pybind11>=2.5.0"],
install_requires=["pybind11>=2.5.0"],
setup_requires=["pybind11>=2.10.0"],
install_requires=["pybind11>=2.10.0"],
ext_modules=ext_modules,
cmdclass={"build_ext": BuildExt},
zip_safe=False,

View File

@ -78,14 +78,16 @@ void BLS::SetSecureAllocator(
}
void BLS::CheckRelicErrors()
void BLS::CheckRelicErrors(bool should_throw)
{
if (!core_get()) {
throw std::runtime_error("Library not initialized properly. Call BLS::Init()");
}
if (core_get()->code != RLC_OK) {
core_get()->code = RLC_OK;
throw std::invalid_argument("Relic library error");
if (should_throw) {
throw std::invalid_argument("Relic library error");
}
}
}

View File

@ -82,9 +82,7 @@ G1Element G1Element::FromBytesUnchecked(Bytes const bytes, bool fLegacy)
}
}
g1_read_bin(ele.p, buffer, G1Element::SIZE + 1);
if (!fLegacy) {
BLS::CheckRelicErrors();
}
BLS::CheckRelicErrors(!fLegacy);
return ele;
}
@ -293,9 +291,7 @@ G2Element G2Element::FromBytesUnchecked(Bytes const bytes, const bool fLegacy)
}
g2_read_bin(ele.q, buffer, G2Element::SIZE + 1);
if (!fLegacy) {
BLS::CheckRelicErrors();
}
BLS::CheckRelicErrors(!fLegacy);
return ele;
}