diff --git a/package.json b/package.json index 78196489..f59f0e81 100644 --- a/package.json +++ b/package.json @@ -24,7 +24,7 @@ }, "devDependencies": { "@babel/core": "^7.12.9", - "@polkadot/dev": "^0.60.12" + "@polkadot/dev": "^0.60.14" }, "version": "2.0.2-4" } diff --git a/packages/unused/.skip-build b/packages/unused/.skip-build new file mode 100644 index 00000000..e69de29b diff --git a/packages/unused/.skip-npm b/packages/unused/.skip-npm new file mode 100644 index 00000000..e69de29b diff --git a/packages/unused/package.json b/packages/unused/package.json new file mode 100644 index 00000000..2ca96c2b --- /dev/null +++ b/packages/unused/package.json @@ -0,0 +1,12 @@ +{ + "name": "@polkadot/unused", + "version": "0.2.8", + "description": "Dummy", + "main": "index.js", + "author": "Jaco Greeff ", + "maintainers": [], + "contributors": [], + "license": "Apache-2.0", + "bugs": "https://github.com/polkadot-js/wasm/issues", + "homepage": "https://github.com/polkadot-js/wasm" +} diff --git a/packages/unused/src/dummy.ts b/packages/unused/src/dummy.ts new file mode 100644 index 00000000..bc5b467f --- /dev/null +++ b/packages/unused/src/dummy.ts @@ -0,0 +1,10 @@ +// Copyright 2020 @polkadot/wasm authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +export interface Dummy { + dummy: string; +} + +export default function dummy (): void { + console.error('unused'); +} diff --git a/packages/wasm-crypto/package.json b/packages/wasm-crypto/package.json index 9706e821..88cbc226 100644 --- a/packages/wasm-crypto/package.json +++ b/packages/wasm-crypto/package.json @@ -6,9 +6,8 @@ "./wasm/asm-empty.js": "./wasm/asm.js" }, "main": "index.js", - "types": "index.d.ts", "devDependencies": { - "@polkadot/dev": "^0.60.12", + "@polkadot/dev": "^0.60.14", "@polkadot/util": "^4.2.1", "@polkadot/x-randomvalues": "^4.2.1", "override-require": "^1.1.1" diff --git a/packages/wasm-crypto/src/bridge.js b/packages/wasm-crypto/src/bridge.js deleted file mode 100644 index b2bdfb5d..00000000 --- a/packages/wasm-crypto/src/bridge.js +++ /dev/null @@ -1,103 +0,0 @@ -// Copyright 2019-2020 @polkadot/wasm-crypto authors & contributors -// SPDX-License-Identifier: Apache-2.0 - -const { assert, stringToU8a, u8aToString } = require('@polkadot/util'); - -let wasm; -let cachegetInt32 = null; -let cachegetUint8 = null; - -async function initWasm (wasmBytes, asmFn, wbg) { - try { - assert(typeof WebAssembly !== 'undefined' && wasmBytes && wasmBytes.length, 'WebAssembly is not available in your environment'); - - const source = await WebAssembly.instantiate(wasmBytes, { wbg }); - - wasm = source.instance.exports; - } catch (error) { - // if we have a valid supplied asm.js, return that - if (asmFn) { - wasm = asmFn(wbg); - } else { - console.error('ERROR: Unable to initialize @polkadot/wasm-crypto'); - console.error(error); - - wasm = null; - } - } -} - -function withWasm (fn) { - return (...params) => { - assert(wasm, '@polkadot/wasm-crypto has not been initialized. Ensure that you wait for the initialization Promise with waitReady() (or cryptoWaitReady() from @polkadot/util-crypto) before attempting to use WASM-only interfaces.'); - - return fn(wasm, ...params); - }; -} - -function getWasm () { - return wasm; -} - -function getInt32 () { - if (cachegetInt32 === null || cachegetInt32.buffer !== wasm.memory.buffer) { - cachegetInt32 = new Int32Array(wasm.memory.buffer); - } - - return cachegetInt32; -} - -function getUint8 () { - if (cachegetUint8 === null || cachegetUint8.buffer !== wasm.memory.buffer) { - cachegetUint8 = new Uint8Array(wasm.memory.buffer); - } - - return cachegetUint8; -} - -function getU8a (ptr, len) { - return getUint8().subarray(ptr / 1, ptr / 1 + len); -} - -function getString (ptr, len) { - return u8aToString(getU8a(ptr, len)); -} - -function allocU8a (arg) { - const ptr = wasm.__wbindgen_malloc(arg.length * 1); - - getUint8().set(arg, ptr / 1); - - return [ptr, arg.length]; -} - -function allocString (arg) { - return allocU8a(stringToU8a(arg)); -} - -function resultU8a () { - const r0 = getInt32()[8 / 4 + 0]; - const r1 = getInt32()[8 / 4 + 1]; - const ret = getU8a(r0, r1).slice(); - - wasm.__wbindgen_free(r0, r1 * 1); - - return ret; -} - -function resultString () { - return u8aToString(resultU8a()); -} - -module.exports = { - allocString, - allocU8a, - getInt32, - getString, - getU8a, - getWasm, - initWasm, - resultString, - resultU8a, - withWasm -}; diff --git a/packages/wasm-crypto/src/bridge.ts b/packages/wasm-crypto/src/bridge.ts new file mode 100644 index 00000000..a44fd0c1 --- /dev/null +++ b/packages/wasm-crypto/src/bridge.ts @@ -0,0 +1,96 @@ +// Copyright 2019-2020 @polkadot/wasm-crypto authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +/* eslint-disable @typescript-eslint/no-non-null-assertion */ + +import type { AsmCreator, WasmCryptoInstance } from './wasm/types'; + +import { assert, stringToU8a, u8aToString } from '@polkadot/util'; + +let wasm: WasmCryptoInstance | null = null; +let cachegetInt32: Int32Array | null = null; +let cachegetUint8: Uint8Array | null = null; + +export async function initWasm (wasmBytes: Uint8Array | null, asmFn: AsmCreator | null, wbg: Record): Promise { + try { + assert(typeof WebAssembly !== 'undefined' && wasmBytes && wasmBytes.length, 'WebAssembly is not available in your environment'); + + const source = await WebAssembly.instantiate(wasmBytes, { wbg }); + + wasm = source.instance.exports as unknown as WasmCryptoInstance; + } catch (error) { + // if we have a valid supplied asm.js, return that + if (asmFn) { + wasm = asmFn(wbg); + } else { + console.error('FATAL: Unable to initialize @polkadot/wasm-crypto'); + console.error(error); + + wasm = null; + } + } +} + +// FIXME We really would love to clean this up and have a sign like (wasm, ...params) => T +// Alas, TypeScript foo is not that great today, so we sadly have an extra closure here +export function withWasm T> (fn: (wasm: WasmCryptoInstance) => F): F { + return ((...params: never[]): T => { + assert(wasm, 'The WASM interface has not been initialized. Ensure that you wait for the initialization Promise with waitReady() from @polkadot/wasm-crypto (or cryptoWaitReady() from @polkadot/util-crypto) before attempting to use WASM-only interfaces.'); + + return fn(wasm)(...params); + }) as unknown as F; +} + +export function getWasm (): WasmCryptoInstance { + return wasm!; +} + +export function getInt32 (): Int32Array { + if (cachegetInt32 === null || cachegetInt32.buffer !== wasm!.memory.buffer) { + cachegetInt32 = new Int32Array(wasm!.memory.buffer); + } + + return cachegetInt32; +} + +export function getUint8 (): Uint8Array { + if (cachegetUint8 === null || cachegetUint8.buffer !== wasm!.memory.buffer) { + cachegetUint8 = new Uint8Array(wasm!.memory.buffer); + } + + return cachegetUint8; +} + +export function getU8a (ptr: number, len: number): Uint8Array { + return getUint8().subarray(ptr / 1, ptr / 1 + len); +} + +export function getString (ptr: number, len: number): string { + return u8aToString(getU8a(ptr, len)); +} + +export function allocU8a (arg: Uint8Array): [number, number] { + const ptr = wasm!.__wbindgen_malloc(arg.length * 1); + + getUint8().set(arg, ptr / 1); + + return [ptr, arg.length]; +} + +export function allocString (arg: string): [number, number] { + return allocU8a(stringToU8a(arg)); +} + +export function resultU8a (): Uint8Array { + const r0 = getInt32()[8 / 4 + 0]; + const r1 = getInt32()[8 / 4 + 1]; + const ret = getU8a(r0, r1).slice(); + + wasm!.__wbindgen_free(r0, r1 * 1); + + return ret; +} + +export function resultString (): string { + return u8aToString(resultU8a()); +} diff --git a/packages/wasm-crypto/src/imports.js b/packages/wasm-crypto/src/imports.js deleted file mode 100644 index 702c7ccf..00000000 --- a/packages/wasm-crypto/src/imports.js +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright 2019-2020 @polkadot/wasm-crypto authors & contributors -// SPDX-License-Identifier: Apache-2.0 - -const getRandomValues = require('@polkadot/x-randomvalues').default; - -const { getString, getU8a } = require('./bridge'); - -const DEFAULT_SELF = { crypto: { getRandomValues } }; - -const heap = new Array(32).fill(undefined).concat(undefined, null, true, false); -let heapNext = heap.length; - -function getObject (idx) { - return heap[idx]; -} - -function dropObject (idx) { - if (idx < 36) { - return; - } - - heap[idx] = heapNext; - heapNext = idx; -} - -function takeObject (idx) { - const ret = getObject(idx); - - dropObject(idx); - - return ret; -} - -function addObject (obj) { - if (heapNext === heap.length) { - heap.push(heap.length + 1); - } - - const idx = heapNext; - - heapNext = heap[idx]; - heap[idx] = obj; - - return idx; -} - -module.exports.__wbindgen_is_undefined = function (arg0) { - return getObject(arg0) === undefined; -}; - -module.exports.__wbg_self_1b7a39e3a92c949c = function () { - return addObject(DEFAULT_SELF); -}; - -module.exports.__wbg_require_604837428532a733 = function (arg0, arg1) { - throw new Error(`Unable to import ${getString(arg0, arg1)}`); -}; - -module.exports.__wbg_crypto_968f1772287e2df0 = function (arg0) { - return addObject(getObject(arg0).crypto); -}; - -module.exports.__wbg_getRandomValues_a3d34b4fee3c2869 = function (arg0) { - return addObject(getObject(arg0).getRandomValues); -}; - -module.exports.__wbg_getRandomValues_f5e14ab7ac8e995d = function (arg0, arg1, arg2) { - getObject(arg0).getRandomValues(getU8a(arg1, arg2)); -}; - -module.exports.__wbg_randomFillSync_d5bd2d655fdf256a = function (arg0, arg1, arg2) { - getObject(arg0).randomFillSync(getU8a(arg1, arg2)); -}; - -module.exports.__wbindgen_object_drop_ref = function (arg0) { - takeObject(arg0); -}; - -module.exports.abort = function () { - throw new Error('abort'); -}; diff --git a/packages/wasm-crypto/src/imports.ts b/packages/wasm-crypto/src/imports.ts new file mode 100644 index 00000000..005a6e05 --- /dev/null +++ b/packages/wasm-crypto/src/imports.ts @@ -0,0 +1,90 @@ +// Copyright 2019-2020 @polkadot/wasm-crypto authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +/* eslint-disable camelcase */ + +import getRandomValues from '@polkadot/x-randomvalues'; + +import { getString, getU8a } from './bridge'; + +const DEFAULT_CRYPTO = { getRandomValues }; +const DEFAULT_SELF = { crypto: DEFAULT_CRYPTO }; + +const heap: Array = new Array(32).fill(undefined).concat(undefined, null, true, false); +let heapNext = heap.length; + +function getObject (idx: number): unknown { + return heap[idx]; +} + +function dropObject (idx: number) { + if (idx < 36) { + return; + } + + heap[idx] = heapNext; + heapNext = idx; +} + +function takeObject (idx: number): unknown { + const ret = getObject(idx); + + dropObject(idx); + + return ret; +} + +function addObject (obj: unknown): number { + if (heapNext === heap.length) { + heap.push(heap.length + 1); + } + + const idx = heapNext; + + heapNext = heap[idx] as number; + heap[idx] = obj; + + return idx; +} + +export function __wbindgen_is_undefined (idx: number): boolean { + return getObject(idx) === undefined; +} + +export function __wbg_self_1b7a39e3a92c949c (): number { + return addObject(DEFAULT_SELF); +} + +export function __wbg_require_604837428532a733 (ptr: number, len: number): never { + throw new Error(`Unable to require ${getString(ptr, len)}`); +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export function __wbg_crypto_968f1772287e2df0 (_idx: number): number { + return addObject(DEFAULT_CRYPTO); +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export function __wbg_getRandomValues_a3d34b4fee3c2869 (_idx: number): number { + return addObject(DEFAULT_CRYPTO.getRandomValues); +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export function __wbg_getRandomValues_f5e14ab7ac8e995d (_arg0: number, ptr: number, len: number): void { + DEFAULT_CRYPTO.getRandomValues(getU8a(ptr, len)); +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +export function __wbg_randomFillSync_d5bd2d655fdf256a (_idx: number, _ptr: number, _len: number): never { + throw new Error('randomFillsync is not available'); + + // getObject(idx).randomFillSync(getU8a(ptr, len)); +} + +export function __wbindgen_object_drop_ref (idx: number): void { + takeObject(idx); +} + +export function abort (): never { + throw new Error('abort'); +} diff --git a/packages/wasm-crypto/src/index.d.ts b/packages/wasm-crypto/src/index.d.ts deleted file mode 100644 index 2a21ebfb..00000000 --- a/packages/wasm-crypto/src/index.d.ts +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2019-2020 @polkadot/wasm-crypto authors & contributors -// SPDX-License-Identifier: Apache-2.0 - -export function bip39Generate (words: 12 | 15 | 18 | 21 | 24): string; -export function bip39ToEntropy (phrase: string): Uint8Array; -export function bip39ToMiniSecret (phrase: string, password: string): Uint8Array; -export function bip39ToSeed (phrase: string, password: string): Uint8Array; -export function bip39Validate (phrase: string): boolean; - -export function ed25519KeypairFromSeed (seed: Uint8Array): Uint8Array; -export function ed25519Sign (publicKey: Uint8Array, secretKey: Uint8Array, message: Uint8Array): Uint8Array; -export function ed25519Verify (signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): boolean; - -export function sr25519DeriveKeypairHard (pair: Uint8Array, chainCode: Uint8Array): Uint8Array; -export function sr25519DeriveKeypairSoft (pair: Uint8Array, chainCode: Uint8Array): Uint8Array; -export function sr25519DerivePublicSoft (publicKey: Uint8Array, chainCode: Uint8Array): Uint8Array; -export function sr25519KeypairFromSeed (seed: Uint8Array): Uint8Array; -export function sr25519Sign (publicKey: Uint8Array, secretKey: Uint8Array, message: Uint8Array): Uint8Array; -export function sr25519Verify (signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): boolean; - -export function blake2b (data: Uint8Array, key: Uint8Array, byteSize: number): Uint8Array; -export function keccak256 (data: Uint8Array): Uint8Array; -export function pbkdf2 (data: Uint8Array, salt: Uint8Array, rounds: number): Uint8Array; -export function scrypt (password: Uint8Array, salt: Uint8Array, log2N: number, r: number, p: number): Uint8Array; -// export function secp256k1IsRecoverable (message: Uint8Array, signature: Uint8Array): number; -// export function secp256k1Recover (message: Uint8Array, signature: Uint8Array): Uint8Array; -export function sha512 (data: Uint8Array): Uint8Array; -export function twox (data: Uint8Array, rounds: number): Uint8Array; - -export function isReady (): boolean; -export function waitReady (): Promise; diff --git a/packages/wasm-crypto/src/index.js b/packages/wasm-crypto/src/index.js deleted file mode 100644 index 72464665..00000000 --- a/packages/wasm-crypto/src/index.js +++ /dev/null @@ -1,188 +0,0 @@ -// Copyright 2019-2020 @polkadot/wasm-crypto authors & contributors -// SPDX-License-Identifier: Apache-2.0 - -const asmFallback = require('./wasm/asm-empty'); -const wasmBytes = require('./wasm/bytes'); -const { allocString, allocU8a, getWasm, initWasm, resultString, resultU8a, withWasm } = require('./bridge'); -const imports = require('./imports'); - -const wasmPromise = initWasm(wasmBytes, asmFallback, imports).catch(() => null); - -module.exports.bip39Generate = withWasm((wasm, words) => { - wasm.ext_bip39_generate(8, words); - - return resultString(); -}); - -module.exports.bip39ToEntropy = withWasm((wasm, phrase) => { - const [ptr0, len0] = allocString(phrase); - - wasm.ext_bip39_to_entropy(8, ptr0, len0); - - return resultU8a(); -}); - -module.exports.bip39ToMiniSecret = withWasm((wasm, phrase, password) => { - const [ptr0, len0] = allocString(phrase); - const [ptr1, len1] = allocString(password); - - wasm.ext_bip39_to_mini_secret(8, ptr0, len0, ptr1, len1); - - return resultU8a(); -}); - -module.exports.bip39ToSeed = withWasm((wasm, phrase, password) => { - const [ptr0, len0] = allocString(phrase); - const [ptr1, len1] = allocString(password); - - wasm.ext_bip39_to_seed(8, ptr0, len0, ptr1, len1); - - return resultU8a(); -}); - -module.exports.bip39Validate = withWasm((wasm, phrase) => { - const [ptr0, len0] = allocString(phrase); - const ret = wasm.ext_bip39_validate(ptr0, len0); - - return ret !== 0; -}); - -module.exports.ed25519KeypairFromSeed = withWasm((wasm, seed) => { - const [ptr0, len0] = allocU8a(seed); - - wasm.ext_ed_from_seed(8, ptr0, len0); - - return resultU8a(); -}); - -module.exports.ed25519Sign = withWasm((wasm, pubkey, seckey, message) => { - const [ptr0, len0] = allocU8a(pubkey); - const [ptr1, len1] = allocU8a(seckey); - const [ptr2, len2] = allocU8a(message); - - wasm.ext_ed_sign(8, ptr0, len0, ptr1, len1, ptr2, len2); - - return resultU8a(); -}); - -module.exports.ed25519Verify = withWasm((wasm, signature, message, pubkey) => { - const [ptr0, len0] = allocU8a(signature); - const [ptr1, len1] = allocU8a(message); - const [ptr2, len2] = allocU8a(pubkey); - const ret = wasm.ext_ed_verify(ptr0, len0, ptr1, len1, ptr2, len2); - - return ret !== 0; -}); - -module.exports.blake2b = withWasm((wasm, data, key, size) => { - const [ptr0, len0] = allocU8a(data); - const [ptr1, len1] = allocU8a(key); - - wasm.ext_blake2b(8, ptr0, len0, ptr1, len1, size); - - return resultU8a(); -}); - -module.exports.keccak256 = withWasm((wasm, data) => { - const [ptr0, len0] = allocU8a(data); - - wasm.ext_keccak256(8, ptr0, len0); - - return resultU8a(); -}); - -module.exports.pbkdf2 = withWasm((wasm, data, salt, rounds) => { - const [ptr0, len0] = allocU8a(data); - const [ptr1, len1] = allocU8a(salt); - - wasm.ext_pbkdf2(8, ptr0, len0, ptr1, len1, rounds); - - return resultU8a(); -}); - -module.exports.scrypt = withWasm((wasm, password, salt, log2n, r, p) => { - const [ptr0, len0] = allocU8a(password); - const [ptr1, len1] = allocU8a(salt); - - wasm.ext_scrypt(8, ptr0, len0, ptr1, len1, log2n, r, p); - - return resultU8a(); -}); - -module.exports.sha512 = withWasm((wasm, data) => { - const [ptr0, len0] = allocU8a(data); - - wasm.ext_sha512(8, ptr0, len0); - - return resultU8a(); -}); - -module.exports.twox = withWasm((wasm, data, rounds) => { - const [ptr0, len0] = allocU8a(data); - - wasm.ext_twox(8, ptr0, len0, rounds); - - return resultU8a(); -}); - -module.exports.sr25519DeriveKeypairHard = withWasm((wasm, pair, cc) => { - const [ptr0, len0] = allocU8a(pair); - const [ptr1, len1] = allocU8a(cc); - - wasm.ext_sr_derive_keypair_hard(8, ptr0, len0, ptr1, len1); - - return resultU8a(); -}); - -module.exports.sr25519DeriveKeypairSoft = withWasm((wasm, pair, cc) => { - const [ptr0, len0] = allocU8a(pair); - const [ptr1, len1] = allocU8a(cc); - - wasm.ext_sr_derive_keypair_soft(8, ptr0, len0, ptr1, len1); - - return resultU8a(); -}); - -module.exports.sr25519DerivePublicSoft = withWasm((wasm, pubkey, cc) => { - const [ptr0, len0] = allocU8a(pubkey); - const [ptr1, len1] = allocU8a(cc); - - wasm.ext_sr_derive_public_soft(8, ptr0, len0, ptr1, len1); - - return resultU8a(); -}); - -module.exports.sr25519KeypairFromSeed = withWasm((wasm, seed) => { - const [ptr0, len0] = allocU8a(seed); - - wasm.ext_sr_from_seed(8, ptr0, len0); - - return resultU8a(); -}); - -module.exports.sr25519Sign = withWasm((wasm, pubkey, secret, message) => { - const [ptr0, len0] = allocU8a(pubkey); - const [ptr1, len1] = allocU8a(secret); - const [ptr2, len2] = allocU8a(message); - - wasm.ext_sr_sign(8, ptr0, len0, ptr1, len1, ptr2, len2); - - return resultU8a(); -}); - -module.exports.sr25519Verify = withWasm((wasm, signature, message, pubkey) => { - const [ptr0, len0] = allocU8a(signature); - const [ptr1, len1] = allocU8a(message); - const [ptr2, len2] = allocU8a(pubkey); - const ret = wasm.ext_sr_verify(ptr0, len0, ptr1, len1, ptr2, len2); - - return ret !== 0; -}); - -module.exports.isReady = function () { - return !!getWasm(); -}; - -module.exports.waitReady = function () { - return wasmPromise.then(() => !!getWasm()); -}; diff --git a/packages/wasm-crypto/src/index.ts b/packages/wasm-crypto/src/index.ts new file mode 100644 index 00000000..7bdee801 --- /dev/null +++ b/packages/wasm-crypto/src/index.ts @@ -0,0 +1,226 @@ +// Copyright 2019-2020 @polkadot/wasm-crypto authors & contributors +// SPDX-License-Identifier: Apache-2.0 + +import asmFallback from './wasm/asm-empty'; +import wasmBytes from './wasm/bytes'; +import { allocString, allocU8a, getWasm, initWasm, resultString, resultU8a, withWasm } from './bridge'; +import * as imports from './imports'; + +const wasmPromise = initWasm(wasmBytes, asmFallback, imports).catch(() => null); + +export const bip39Generate = withWasm((wasm) => + (words: 12 | 15 | 18 | 21 | 24): string => { + wasm.ext_bip39_generate(8, words); + + return resultString(); + } +); + +export const bip39ToEntropy = withWasm((wasm) => + (phrase: string): Uint8Array => { + const [ptr0, len0] = allocString(phrase); + + wasm.ext_bip39_to_entropy(8, ptr0, len0); + + return resultU8a(); + } +); + +export const bip39ToMiniSecret = withWasm((wasm) => + (phrase: string, password: string): Uint8Array => { + const [ptr0, len0] = allocString(phrase); + const [ptr1, len1] = allocString(password); + + wasm.ext_bip39_to_mini_secret(8, ptr0, len0, ptr1, len1); + + return resultU8a(); + } +); + +export const bip39ToSeed = withWasm((wasm) => + (phrase: string, password: string): Uint8Array => { + const [ptr0, len0] = allocString(phrase); + const [ptr1, len1] = allocString(password); + + wasm.ext_bip39_to_seed(8, ptr0, len0, ptr1, len1); + + return resultU8a(); + } +); + +export const bip39Validate = withWasm((wasm) => + (phrase: string): boolean => { + const [ptr0, len0] = allocString(phrase); + const ret = wasm.ext_bip39_validate(ptr0, len0); + + return ret !== 0; + } +); + +export const ed25519KeypairFromSeed = withWasm((wasm) => + (seed: Uint8Array): Uint8Array => { + const [ptr0, len0] = allocU8a(seed); + + wasm.ext_ed_from_seed(8, ptr0, len0); + + return resultU8a(); + } +); + +export const ed25519Sign = withWasm((wasm) => + (pubkey: Uint8Array, seckey: Uint8Array, message: Uint8Array): Uint8Array => { + const [ptr0, len0] = allocU8a(pubkey); + const [ptr1, len1] = allocU8a(seckey); + const [ptr2, len2] = allocU8a(message); + + wasm.ext_ed_sign(8, ptr0, len0, ptr1, len1, ptr2, len2); + + return resultU8a(); + } +); + +export const ed25519Verify = withWasm((wasm) => + (signature: Uint8Array, message: Uint8Array, pubkey: Uint8Array): boolean => { + const [ptr0, len0] = allocU8a(signature); + const [ptr1, len1] = allocU8a(message); + const [ptr2, len2] = allocU8a(pubkey); + const ret = wasm.ext_ed_verify(ptr0, len0, ptr1, len1, ptr2, len2); + + return ret !== 0; + } +); + +export const sr25519DeriveKeypairHard = withWasm((wasm) => + (pair: Uint8Array, cc: Uint8Array): Uint8Array => { + const [ptr0, len0] = allocU8a(pair); + const [ptr1, len1] = allocU8a(cc); + + wasm.ext_sr_derive_keypair_hard(8, ptr0, len0, ptr1, len1); + + return resultU8a(); + } +); + +export const sr25519DeriveKeypairSoft = withWasm((wasm) => (pair, cc): Uint8Array => { + const [ptr0, len0] = allocU8a(pair); + const [ptr1, len1] = allocU8a(cc); + + wasm.ext_sr_derive_keypair_soft(8, ptr0, len0, ptr1, len1); + + return resultU8a(); +}); + +export const sr25519DerivePublicSoft = withWasm((wasm) => + (pubkey: Uint8Array, cc: Uint8Array): Uint8Array => { + const [ptr0, len0] = allocU8a(pubkey); + const [ptr1, len1] = allocU8a(cc); + + wasm.ext_sr_derive_public_soft(8, ptr0, len0, ptr1, len1); + + return resultU8a(); + } +); + +export const sr25519KeypairFromSeed = withWasm((wasm) => + (seed: Uint8Array): Uint8Array => { + const [ptr0, len0] = allocU8a(seed); + + wasm.ext_sr_from_seed(8, ptr0, len0); + + return resultU8a(); + } +); + +export const sr25519Sign = withWasm((wasm) => + (pubkey: Uint8Array, secret: Uint8Array, message: Uint8Array): Uint8Array => { + const [ptr0, len0] = allocU8a(pubkey); + const [ptr1, len1] = allocU8a(secret); + const [ptr2, len2] = allocU8a(message); + + wasm.ext_sr_sign(8, ptr0, len0, ptr1, len1, ptr2, len2); + + return resultU8a(); + } +); + +export const sr25519Verify = withWasm((wasm) => + (signature: Uint8Array, message: Uint8Array, pubkey: Uint8Array): boolean => { + const [ptr0, len0] = allocU8a(signature); + const [ptr1, len1] = allocU8a(message); + const [ptr2, len2] = allocU8a(pubkey); + const ret = wasm.ext_sr_verify(ptr0, len0, ptr1, len1, ptr2, len2); + + return ret !== 0; + } +); + +export const blake2b = withWasm((wasm) => + (data: Uint8Array, key: Uint8Array, size: number): Uint8Array => { + const [ptr0, len0] = allocU8a(data); + const [ptr1, len1] = allocU8a(key); + + wasm.ext_blake2b(8, ptr0, len0, ptr1, len1, size); + + return resultU8a(); + } +); + +export const keccak256 = withWasm((wasm) => + (data: Uint8Array): Uint8Array => { + const [ptr0, len0] = allocU8a(data); + + wasm.ext_keccak256(8, ptr0, len0); + + return resultU8a(); + } +); + +export const pbkdf2 = withWasm((wasm) => + (data: Uint8Array, salt: Uint8Array, rounds: number): Uint8Array => { + const [ptr0, len0] = allocU8a(data); + const [ptr1, len1] = allocU8a(salt); + + wasm.ext_pbkdf2(8, ptr0, len0, ptr1, len1, rounds); + + return resultU8a(); + } +); + +export const scrypt = withWasm((wasm) => + (password: Uint8Array, salt: Uint8Array, log2n: number, r: number, p: number): Uint8Array => { + const [ptr0, len0] = allocU8a(password); + const [ptr1, len1] = allocU8a(salt); + + wasm.ext_scrypt(8, ptr0, len0, ptr1, len1, log2n, r, p); + + return resultU8a(); + } +); + +export const sha512 = withWasm((wasm) => + (data: Uint8Array): Uint8Array => { + const [ptr0, len0] = allocU8a(data); + + wasm.ext_sha512(8, ptr0, len0); + + return resultU8a(); + } +); + +export const twox = withWasm((wasm) => + (data: Uint8Array, rounds: number) => { + const [ptr0, len0] = allocU8a(data); + + wasm.ext_twox(8, ptr0, len0, rounds); + + return resultU8a(); + } +); + +export function isReady (): boolean { + return !!getWasm(); +} + +export function waitReady (): Promise { + return wasmPromise.then(() => !!getWasm()); +} diff --git a/packages/wasm-crypto/src/wasm/asm-empty.js b/packages/wasm-crypto/src/wasm/asm-empty.ts similarity index 82% rename from packages/wasm-crypto/src/wasm/asm-empty.js rename to packages/wasm-crypto/src/wasm/asm-empty.ts index ef37d141..a18cea5d 100644 --- a/packages/wasm-crypto/src/wasm/asm-empty.js +++ b/packages/wasm-crypto/src/wasm/asm-empty.ts @@ -1,4 +1,4 @@ // Copyright 2019-2020 @polkadot/wasm-crypto authors & contributors // SPDX-License-Identifier: Apache-2.0 -module.exports = null; +export default null; diff --git a/packages/wasm-crypto/src/wasm/asm.js b/packages/wasm-crypto/src/wasm/asm.ts similarity index 72% rename from packages/wasm-crypto/src/wasm/asm.js rename to packages/wasm-crypto/src/wasm/asm.ts index 41a01742..16807ffe 100644 --- a/packages/wasm-crypto/src/wasm/asm.js +++ b/packages/wasm-crypto/src/wasm/asm.ts @@ -3,4 +3,6 @@ // Stub replaced at build time -module.exports = require('./asm-empty'); +import asm from './asm-empty'; + +export default asm; diff --git a/packages/wasm-crypto/src/wasm/bytes-empty.js b/packages/wasm-crypto/src/wasm/bytes-empty.ts similarity index 82% rename from packages/wasm-crypto/src/wasm/bytes-empty.js rename to packages/wasm-crypto/src/wasm/bytes-empty.ts index ef37d141..a18cea5d 100644 --- a/packages/wasm-crypto/src/wasm/bytes-empty.js +++ b/packages/wasm-crypto/src/wasm/bytes-empty.ts @@ -1,4 +1,4 @@ // Copyright 2019-2020 @polkadot/wasm-crypto authors & contributors // SPDX-License-Identifier: Apache-2.0 -module.exports = null; +export default null; diff --git a/packages/wasm-crypto/src/wasm/bytes.js b/packages/wasm-crypto/src/wasm/bytes.ts similarity index 70% rename from packages/wasm-crypto/src/wasm/bytes.js rename to packages/wasm-crypto/src/wasm/bytes.ts index eb4a71c1..ef18233f 100644 --- a/packages/wasm-crypto/src/wasm/bytes.js +++ b/packages/wasm-crypto/src/wasm/bytes.ts @@ -3,4 +3,6 @@ // Stub replaced at build time -module.exports = require('./bytes-empty'); +import bytes from './bytes-empty'; + +export default bytes; diff --git a/packages/wasm-crypto/src/wasm/types.ts b/packages/wasm-crypto/src/wasm/types.ts index 30ac945c..e5de10e9 100644 --- a/packages/wasm-crypto/src/wasm/types.ts +++ b/packages/wasm-crypto/src/wasm/types.ts @@ -33,3 +33,5 @@ export interface WasmCryptoInstance { ext_sr_sign(a: number, b: number, c: number, d: number, e: number, f: number, g: number): void; ext_sr_verify(a: number, b: number, c: number, d: number, e: number, f: number): number; } + +export type AsmCreator = (wbg: Record) => WasmCryptoInstance; diff --git a/scripts/build-js.sh b/scripts/build-js.sh new file mode 100755 index 00000000..07efa729 --- /dev/null +++ b/scripts/build-js.sh @@ -0,0 +1,11 @@ +#!/usr/bin/env bash +# Copyright 2019-2020 @polkadot/wasm authors & contributors +# This software may be modified and distributed under the terms +# of the Apache-2.0 license. See the LICENSE file for details. + +set -e + +DEST=packages/wasm-crypto/build/esm + +./scripts/clean-js.sh +yarn polkadot-dev-build-ts diff --git a/scripts/build-package.sh b/scripts/build-wasm.sh similarity index 83% rename from scripts/build-package.sh rename to scripts/build-wasm.sh index 37ebe5a1..464a020b 100755 --- a/scripts/build-package.sh +++ b/scripts/build-wasm.sh @@ -12,19 +12,6 @@ WSM=pkg/wasm_bg.wasm OPT=pkg/wasm_opt.wasm ASM=build/wasm/asm.js -echo "*** Building package" - -# cleanup old -echo "*** Cleaning old builds" -rm -rf ./build ./pkg -mkdir -p build/wasm - -# copy our package interfaces -echo "*** Copying package sources" -cp package.json build/ -cp src/index.d.ts src/*.js build/ -cp src/wasm/* build/wasm/ - # build new via wasm-pack echo "*** Building WASM output" rustup run $RUST_VER xargo build --target wasm32-unknown-unknown --release diff --git a/scripts/build.sh b/scripts/build.sh index bb14f56a..a723fb5d 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -5,10 +5,13 @@ set -e -echo "*** Building packages" +echo "*** Building JavaScript" +./scripts/build-js.sh + +echo "*** Building WASM" cd packages/wasm-crypto -../../scripts/build-package.sh +../../scripts/build-wasm.sh yarn test:wasm:js diff --git a/scripts/clean-js.sh b/scripts/clean-js.sh new file mode 100755 index 00000000..1e118d95 --- /dev/null +++ b/scripts/clean-js.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# Copyright 2019-2020 @polkadot/wasm authors & contributors +# This software may be modified and distributed under the terms +# of the Apache-2.0 license. See the LICENSE file for details. + +set -e + +# cleanup old +echo "*** Cleaning old builds" +rm -rf packages/wasm-crypto/build packages/wasm-crypto/pkg diff --git a/scripts/clean.sh b/scripts/clean.sh index e1db42d3..65c75ceb 100755 --- a/scripts/clean.sh +++ b/scripts/clean.sh @@ -5,10 +5,11 @@ set -e -echo "*** Cleaning packages" +./scripts/clean-js.sh + +echo "*** Cleaning wasm" cd packages/wasm-crypto -rm -rf build cargo clean cd ../.. diff --git a/scripts/pack-wasm-base.js b/scripts/pack-wasm-base.js index 18a9b591..6e3c3c3e 100755 --- a/scripts/pack-wasm-base.js +++ b/scripts/pack-wasm-base.js @@ -3,9 +3,20 @@ const fs = require('fs'); -const buffer = fs.readFileSync('./pkg/wasm_opt.wasm'); +const HDR = `// Generated as part of the build, do not edit +`; +const FTR = ''; -fs.writeFileSync('./build/wasm/bytes.js', `// Generated as part of the build, do not edit +fs.writeFileSync('./build/wasm/bytes.js', `${HDR} +module.exports = Buffer.from('${fs.readFileSync('./pkg/wasm_opt.wasm').toString('base64')}', 'base64'); +${FTR}`); -module.exports = Buffer.from('${buffer.toString('base64')}', 'base64'); -`); +fs.writeFileSync('./build/esm/wasm/asm.js', `${HDR} +import asm from '../../wasm/asm.js'; +export default asm; +${FTR}`); + +fs.writeFileSync('./build/esm/wasm/bytes.js', `${HDR} +import bytes from '../../wasm/bytes.js'; +export default bytes; +${FTR}`); diff --git a/yarn.lock b/yarn.lock index 8525a4f3..e16eaa0e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1712,9 +1712,9 @@ __metadata: languageName: node linkType: hard -"@polkadot/dev@npm:^0.60.12": - version: 0.60.12 - resolution: "@polkadot/dev@npm:0.60.12" +"@polkadot/dev@npm:^0.60.14": + version: 0.60.14 + resolution: "@polkadot/dev@npm:0.60.14" dependencies: "@babel/cli": ^7.12.8 "@babel/core": ^7.12.9 @@ -1801,10 +1801,16 @@ __metadata: polkadot-exec-typedoc: scripts/polkadot-exec-typedoc.cjs polkadot-exec-vuepress: scripts/polkadot-exec-vuepress.cjs polkadot-exec-webpack: scripts/polkadot-exec-webpack.cjs - checksum: 13f7153ccc62fc62c4823946175845f8c6b50b1e20e9321ce607ea23a0b8b39f3359e707997a62ce31a44c6ea8b9a134b206e3aecd970ff9c3b040d3cd79f06e + checksum: 1a7f21b8dca7775e0f7ec85f6f925f7a0ed1c6acd86d74e2da2ef25dacd754b68af348a79de03cc2f0611e998e4c91c10184580d9b113cf708472b9c05060606 languageName: node linkType: hard +"@polkadot/unused@workspace:packages/unused": + version: 0.0.0-use.local + resolution: "@polkadot/unused@workspace:packages/unused" + languageName: unknown + linkType: soft + "@polkadot/util@npm:^4.2.1": version: 4.2.1 resolution: "@polkadot/util@npm:4.2.1" @@ -1824,7 +1830,7 @@ __metadata: version: 0.0.0-use.local resolution: "@polkadot/wasm-crypto@workspace:packages/wasm-crypto" dependencies: - "@polkadot/dev": ^0.60.12 + "@polkadot/dev": ^0.60.14 "@polkadot/util": ^4.2.1 "@polkadot/x-randomvalues": ^4.2.1 override-require: ^1.1.1 @@ -8566,7 +8572,7 @@ fsevents@~2.1.2: resolution: "root-workspace-0b6124@workspace:." dependencies: "@babel/core": ^7.12.9 - "@polkadot/dev": ^0.60.12 + "@polkadot/dev": ^0.60.14 languageName: unknown linkType: soft