diff --git a/packages/util-crypto/package.json b/packages/util-crypto/package.json index 727b5095e..2ce1770cb 100644 --- a/packages/util-crypto/package.json +++ b/packages/util-crypto/package.json @@ -28,7 +28,7 @@ "@babel/runtime": "^7.16.3", "@polkadot/networks": "7.8.3-36", "@polkadot/util": "7.8.3-36", - "@polkadot/wasm-crypto": "^4.2.1", + "@polkadot/wasm-crypto": "^4.2.2-17", "@polkadot/x-randomvalues": "7.8.3-36", "blakejs": "^1.1.1", "bn.js": "^4.12.0", diff --git a/packages/util-crypto/src/blake2/asU8a.spec.ts b/packages/util-crypto/src/blake2/asU8a.spec.ts index dd6eb9836..42237c71d 100644 --- a/packages/util-crypto/src/blake2/asU8a.spec.ts +++ b/packages/util-crypto/src/blake2/asU8a.spec.ts @@ -58,4 +58,26 @@ describe('blake2AsU8a', (): void => { expect(a).toEqual(b); }); + + it.skip.each([false, true])('performance: onlyJs=%p', (onlyJs): void => { + const label = `blake2AsU8a:onlyJs=${onlyJs.toString()}`; + const test = new Uint8Array([ + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8 + ]); + + console.time(label); + + for (let i = 0; i < 32768; i++) { + blake2AsU8a(test); + } + + console.timeEnd(label); + }); }); diff --git a/packages/util-crypto/src/keccak/asU8a.spec.ts b/packages/util-crypto/src/keccak/asU8a.spec.ts index 4ca9a9736..bf632148b 100644 --- a/packages/util-crypto/src/keccak/asU8a.spec.ts +++ b/packages/util-crypto/src/keccak/asU8a.spec.ts @@ -42,4 +42,26 @@ describe('keccakAsU8a', (): void => { }); }); }); + + it.skip.each([false, true])('performance: onlyJs=%p', (onlyJs): void => { + const label = `keccakAsU8a:onlyJs=${onlyJs.toString()}`; + const test = new Uint8Array([ + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8 + ]); + + console.time(label); + + for (let i = 0; i < 128000; i++) { + keccakAsU8a(test, undefined, onlyJs); + } + + console.timeEnd(label); + }); }); diff --git a/packages/util-crypto/src/keccak/asU8a.ts b/packages/util-crypto/src/keccak/asU8a.ts index a4f6ed7e9..8206870af 100644 --- a/packages/util-crypto/src/keccak/asU8a.ts +++ b/packages/util-crypto/src/keccak/asU8a.ts @@ -6,7 +6,7 @@ import type { HexString } from '@polkadot/util/types'; import js from 'js-sha3'; import { u8aToU8a } from '@polkadot/util'; -import { isReady, keccak256 } from '@polkadot/wasm-crypto'; +import { isReady, keccak256, keccak512 } from '@polkadot/wasm-crypto'; /** * @name keccakAsU8a @@ -24,10 +24,13 @@ import { isReady, keccak256 } from '@polkadot/wasm-crypto'; */ export function keccakAsU8a (value: HexString | Buffer | Uint8Array | string, bitLength: 256 | 512 = 256, onlyJs = false): Uint8Array { const is256 = bitLength === 256; + const u8a = u8aToU8a(value); - return isReady() && is256 && !onlyJs - ? keccak256(u8aToU8a(value)) + return isReady() && !onlyJs + ? is256 + ? keccak256(u8a) + : keccak512(u8a) : new Uint8Array( - (is256 ? js.keccak256 : js.keccak512).update(u8aToU8a(value)).arrayBuffer() + (is256 ? js.keccak256 : js.keccak512).update(u8a).arrayBuffer() ); } diff --git a/packages/util-crypto/src/sha256/asU8a.spec.ts b/packages/util-crypto/src/sha256/asU8a.spec.ts index c4642fb92..95dd90443 100644 --- a/packages/util-crypto/src/sha256/asU8a.spec.ts +++ b/packages/util-crypto/src/sha256/asU8a.spec.ts @@ -2,6 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 import { hexToU8a } from '@polkadot/util'; +import { waitReady } from '@polkadot/wasm-crypto'; import { sha256AsU8a } from '.'; @@ -29,9 +30,37 @@ const TESTS = [ ]; describe('sha256AsU8a', (): void => { - it.each(TESTS)('creates known sha-256 hash', ({ input, output }): void => { - expect( - sha256AsU8a(hexToU8a(input)) - ).toEqual(hexToU8a(output)); + beforeEach(async (): Promise => { + await waitReady(); + }); + + describe.each([false, true])('onlyJs=%p', (onlyJs): void => { + it.each(TESTS)('creates known sha-256 hash', ({ input, output }): void => { + expect( + sha256AsU8a(hexToU8a(input), onlyJs) + ).toEqual(hexToU8a(output)); + }); + }); + + it.skip.each([false, true])('performance: onlyJs=%p', (onlyJs): void => { + const label = `sha256AsU8a:onlyJs=${onlyJs.toString()}`; + const test = new Uint8Array([ + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8 + ]); + + console.time(label); + + for (let i = 0; i < 128000; i++) { + sha256AsU8a(test, onlyJs); + } + + console.timeEnd(label); }); }); diff --git a/packages/util-crypto/src/sha256/asU8a.ts b/packages/util-crypto/src/sha256/asU8a.ts index 503d5f0dc..12452833a 100644 --- a/packages/util-crypto/src/sha256/asU8a.ts +++ b/packages/util-crypto/src/sha256/asU8a.ts @@ -3,15 +3,19 @@ import hash from 'hash.js'; +import { isReady, sha256 } from '@polkadot/wasm-crypto'; + /** * @name sha256AsU8a * @summary Creates sha-256 hash of the input. */ -export function sha256AsU8a (data: Uint8Array): Uint8Array { - return new Uint8Array( - hash - .sha256() - .update(data) - .digest() - ); +export function sha256AsU8a (data: Uint8Array, onlyJs = false): Uint8Array { + return isReady() && !onlyJs + ? sha256(data) + : new Uint8Array( + hash + .sha256() + .update(data) + .digest() + ); } diff --git a/packages/util-crypto/src/sha512/asU8a.spec.ts b/packages/util-crypto/src/sha512/asU8a.spec.ts index 84c673667..a48e5447e 100644 --- a/packages/util-crypto/src/sha512/asU8a.spec.ts +++ b/packages/util-crypto/src/sha512/asU8a.spec.ts @@ -21,4 +21,26 @@ describe('sha512AsU8a', (): void => { ); }); }); + + it.skip.each([false, true])('performance: onlyJs=%p', (onlyJs): void => { + const label = `sha512AsU8a:onlyJs=${onlyJs.toString()}`; + const test = new Uint8Array([ + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8, + 1, 2, 3, 4, 5, 6, 7, 8 + ]); + + console.time(label); + + for (let i = 0; i < 128000; i++) { + sha512AsU8a(test, onlyJs); + } + + console.timeEnd(label); + }); }); diff --git a/packages/util-crypto/src/sha512/asU8a.ts b/packages/util-crypto/src/sha512/asU8a.ts index 90d18d8c4..ad09366f9 100644 --- a/packages/util-crypto/src/sha512/asU8a.ts +++ b/packages/util-crypto/src/sha512/asU8a.ts @@ -1,7 +1,7 @@ // Copyright 2017-2021 @polkadot/util-crypto authors & contributors // SPDX-License-Identifier: Apache-2.0 -import nacl from 'tweetnacl'; +import hash from 'hash.js'; import { isReady, sha512 } from '@polkadot/wasm-crypto'; @@ -22,5 +22,10 @@ import { isReady, sha512 } from '@polkadot/wasm-crypto'; export function sha512AsU8a (data: Uint8Array, onlyJs = false): Uint8Array { return isReady() && !onlyJs ? sha512(data) - : nacl.hash(data); + : new Uint8Array( + hash + .sha512() + .update(data) + .digest() + ); } diff --git a/yarn.lock b/yarn.lock index 977b97e4f..2532b4f30 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1363,7 +1363,7 @@ __metadata: languageName: node linkType: hard -"@babel/runtime@npm:^7.14.8, @babel/runtime@npm:^7.15.3, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.8.4": +"@babel/runtime@npm:^7.14.8, @babel/runtime@npm:^7.16.3, @babel/runtime@npm:^7.8.4": version: 7.16.3 resolution: "@babel/runtime@npm:7.16.3" dependencies: @@ -2086,7 +2086,7 @@ __metadata: "@babel/runtime": ^7.16.3 "@polkadot/networks": 7.8.3-36 "@polkadot/util": 7.8.3-36 - "@polkadot/wasm-crypto": ^4.2.1 + "@polkadot/wasm-crypto": ^4.2.2-17 "@polkadot/x-randomvalues": 7.8.3-36 "@types/bn.js": ^4.11.6 "@types/create-hash": ^1.2.2 @@ -2124,35 +2124,35 @@ __metadata: languageName: unknown linkType: soft -"@polkadot/wasm-crypto-asmjs@npm:^4.2.1": - version: 4.2.1 - resolution: "@polkadot/wasm-crypto-asmjs@npm:4.2.1" +"@polkadot/wasm-crypto-asmjs@npm:^4.2.2-17": + version: 4.2.2-17 + resolution: "@polkadot/wasm-crypto-asmjs@npm:4.2.2-17" dependencies: - "@babel/runtime": ^7.15.3 - checksum: f4c9fed22121eaedeebf7f7bbe3c28e1920f2b84e7a1aea1a9d3807e79d7c236cee71e008527ab2779b079a56d43d6638fe50efa348f918277c65fa083094499 + "@babel/runtime": ^7.16.3 + checksum: e458b3a9c97c2739daf131fc0bfb436c11f40d2bfe821e42771e0b239549366d4e4cd184770feb0fe78784178d5f1cfe8e39dd3e379992e5fc64b9414b3f3a58 languageName: node linkType: hard -"@polkadot/wasm-crypto-wasm@npm:^4.2.1": - version: 4.2.1 - resolution: "@polkadot/wasm-crypto-wasm@npm:4.2.1" +"@polkadot/wasm-crypto-wasm@npm:^4.2.2-17": + version: 4.2.2-17 + resolution: "@polkadot/wasm-crypto-wasm@npm:4.2.2-17" dependencies: - "@babel/runtime": ^7.15.3 - checksum: 2eab39628f34dd64987c4109a7d3ca0376946ace322aa67c10119be36b9eebf0f7c68f2e4aea1510f1fbd469c70dc3e8f1d3bd58799c7dcbc3a1e6cb08a69b5d + "@babel/runtime": ^7.16.3 + checksum: cf4a7ca5a2300a41fb5975fd42e251ea7ccc50680e347c7383c21e8e4111377a0189171e29bef1a6edb364553778b1c662a3ab8939ffbecd978c3f380db33b27 languageName: node linkType: hard -"@polkadot/wasm-crypto@npm:^4.2.1": - version: 4.2.1 - resolution: "@polkadot/wasm-crypto@npm:4.2.1" +"@polkadot/wasm-crypto@npm:^4.2.2-17": + version: 4.2.2-17 + resolution: "@polkadot/wasm-crypto@npm:4.2.2-17" dependencies: - "@babel/runtime": ^7.15.3 - "@polkadot/wasm-crypto-asmjs": ^4.2.1 - "@polkadot/wasm-crypto-wasm": ^4.2.1 + "@babel/runtime": ^7.16.3 + "@polkadot/wasm-crypto-asmjs": ^4.2.2-17 + "@polkadot/wasm-crypto-wasm": ^4.2.2-17 peerDependencies: "@polkadot/util": "*" "@polkadot/x-randomvalues": "*" - checksum: 2ef25ed7dd297c160fafef9198bd23a3ca5fc8c03fd94903fac4fa8fd11ecc74cea935039e61cebf5458e95f3b6a30f21ceb968d5ddf4a488f05e9cf6d093577 + checksum: f441aa5d7e644f36ad4fde231de0f1c148287b5119f1ad776962111647db7f54ee116091a3694a6cfa5083d7d2586faf953f1e931a7d550a099609979cb54bb7 languageName: node linkType: hard