From e32fb2137cac46b9571e428edff536a5b506ba21 Mon Sep 17 00:00:00 2001 From: Tom Wang Date: Thu, 30 May 2024 16:30:14 +0800 Subject: [PATCH 01/12] feat: add lumos crypto.randomBytes to replace node's --- .changeset/tough-beers-roll.md | 6 +++ .github/workflows/ci.yaml | 8 +-- commitlint.config.js | 1 + .../tests/transaction_collector.unit.test.ts | 2 +- packages/codec/tests/bytes-like.test.ts | 2 +- .../tests/dao-with-custom-lock.test.ts | 2 +- packages/config-manager/tests/refresh.test.ts | 6 +-- packages/crypto/.eslintignore | 1 + packages/crypto/.gitignore | 1 + packages/crypto/CHANGELOG.md | 1 + packages/crypto/READMD.md | 3 ++ packages/crypto/package.json | 50 +++++++++++++++++++ packages/crypto/src/index.ts | 29 +++++++++++ packages/crypto/tests/index.test.ts | 16 ++++++ packages/crypto/tsconfig.json | 8 +++ packages/crypto/typedoc.json | 4 ++ packages/debugger/package.json | 1 + packages/debugger/src/context.ts | 7 ++- packages/debugger/src/executor.ts | 7 +-- packages/debugger/tests/context.test.ts | 2 +- packages/e2e-test/package.json | 1 + packages/e2e-test/src/utils.ts | 3 +- packages/hd/package.json | 3 +- packages/hd/src/keystore.ts | 26 +++++----- packages/hd/src/mnemonic/index.ts | 36 ++++++------- packages/helpers/tests/model_helper.test.ts | 2 +- packages/helpers/tests/refresh.test.ts | 2 +- packages/joyid/tests/script-info.test.ts | 4 +- packages/lumos/package.json | 1 + packages/lumos/src/index.ts | 1 + pnpm-lock.yaml | 14 ++++++ 31 files changed, 198 insertions(+), 52 deletions(-) create mode 100644 .changeset/tough-beers-roll.md create mode 100644 packages/crypto/.eslintignore create mode 100644 packages/crypto/.gitignore create mode 100644 packages/crypto/CHANGELOG.md create mode 100644 packages/crypto/READMD.md create mode 100644 packages/crypto/package.json create mode 100644 packages/crypto/src/index.ts create mode 100644 packages/crypto/tests/index.test.ts create mode 100644 packages/crypto/tsconfig.json create mode 100644 packages/crypto/typedoc.json diff --git a/.changeset/tough-beers-roll.md b/.changeset/tough-beers-roll.md new file mode 100644 index 000000000..f7929843a --- /dev/null +++ b/.changeset/tough-beers-roll.md @@ -0,0 +1,6 @@ +--- +"@ckb-lumos/crypto": minor +"@ckb-lumos/lumos": minor +--- + +feat: add crypto.randomBytes to replace Node's crypto.randomBytes diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 1cc3a1f4e..8ddf65712 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -9,9 +9,10 @@ jobs: - uses: pnpm/action-setup@v2 with: version: 8.6.1 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: cache: "pnpm" + node-version: '20' - name: Install project dependencies and build run: | @@ -38,9 +39,10 @@ jobs: - uses: pnpm/action-setup@v2 with: version: 8.6.1 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: cache: "pnpm" + node-version: '20' - name: Install project dependencies and build run: | @@ -60,7 +62,7 @@ jobs: - uses: pnpm/action-setup@v2 with: version: 8.6.1 - - uses: actions/setup-node@v3 + - uses: actions/setup-node@v4 with: cache: "pnpm" diff --git a/commitlint.config.js b/commitlint.config.js index 414ae5141..2c753961b 100644 --- a/commitlint.config.js +++ b/commitlint.config.js @@ -1,6 +1,7 @@ const scopeEnumValues = [ "base", "bi", + "crypto", "ckb-indexer", "common-scripts", "config-manager", diff --git a/packages/ckb-indexer/tests/transaction_collector.unit.test.ts b/packages/ckb-indexer/tests/transaction_collector.unit.test.ts index 300eafdaf..2b9abe157 100644 --- a/packages/ckb-indexer/tests/transaction_collector.unit.test.ts +++ b/packages/ckb-indexer/tests/transaction_collector.unit.test.ts @@ -1,5 +1,5 @@ -import { randomBytes } from "crypto"; import test from "ava"; +import { randomBytes } from "../../crypto/src"; import { Indexer, TransactionCollector } from "../src"; import { indexerTransactionListThatHaveOneIoTypeInput, diff --git a/packages/codec/tests/bytes-like.test.ts b/packages/codec/tests/bytes-like.test.ts index 6e4adcbf2..cba376a61 100644 --- a/packages/codec/tests/bytes-like.test.ts +++ b/packages/codec/tests/bytes-like.test.ts @@ -1,7 +1,7 @@ import test from "ava"; import { molecule, number } from "../src"; import { Byte32 } from "../src/blockchain"; -import { randomBytes } from "crypto"; +import { randomBytes } from "../../crypto/src"; import { equal, concat, hexify } from "../src/bytes"; import { BI } from "@ckb-lumos/bi"; import { bytify } from "../lib/bytes"; diff --git a/packages/common-scripts/tests/dao-with-custom-lock.test.ts b/packages/common-scripts/tests/dao-with-custom-lock.test.ts index 99ddc9cce..7ae77b781 100644 --- a/packages/common-scripts/tests/dao-with-custom-lock.test.ts +++ b/packages/common-scripts/tests/dao-with-custom-lock.test.ts @@ -13,7 +13,7 @@ import { dao } from "../src"; import { Config, predefined } from "@ckb-lumos/config-manager"; import { hexify } from "@ckb-lumos/codec/lib/bytes"; import { Uint64 } from "@ckb-lumos/codec/lib/number"; -import { randomBytes } from "node:crypto"; +import { randomBytes } from "../../crypto/src"; const { LINA } = predefined; diff --git a/packages/config-manager/tests/refresh.test.ts b/packages/config-manager/tests/refresh.test.ts index 3abec9f7c..21be448e0 100644 --- a/packages/config-manager/tests/refresh.test.ts +++ b/packages/config-manager/tests/refresh.test.ts @@ -1,15 +1,15 @@ import test from "ava"; +import { spy } from "sinon"; import { createLatestTypeIdResolver, createRpcResolver, FetchOutputsByTxHashes, refreshScriptConfigs, } from "../src/refresh"; -import { ScriptConfigs } from "../src"; import { hexify } from "@ckb-lumos/codec/lib/bytes"; -import { randomBytes } from "node:crypto"; import { OutPoint, Output, Script } from "@ckb-lumos/base"; -import { spy } from "sinon"; +import { randomBytes } from "../../crypto/src"; +import { ScriptConfigs } from "../src"; test("refresh without update", async (t) => { const scriptConfigs: ScriptConfigs = { diff --git a/packages/crypto/.eslintignore b/packages/crypto/.eslintignore new file mode 100644 index 000000000..7951405f8 --- /dev/null +++ b/packages/crypto/.eslintignore @@ -0,0 +1 @@ +lib \ No newline at end of file diff --git a/packages/crypto/.gitignore b/packages/crypto/.gitignore new file mode 100644 index 000000000..7951405f8 --- /dev/null +++ b/packages/crypto/.gitignore @@ -0,0 +1 @@ +lib \ No newline at end of file diff --git a/packages/crypto/CHANGELOG.md b/packages/crypto/CHANGELOG.md new file mode 100644 index 000000000..f03c67b22 --- /dev/null +++ b/packages/crypto/CHANGELOG.md @@ -0,0 +1 @@ +# @ckb-lumos/crypto \ No newline at end of file diff --git a/packages/crypto/READMD.md b/packages/crypto/READMD.md new file mode 100644 index 000000000..fd856e73f --- /dev/null +++ b/packages/crypto/READMD.md @@ -0,0 +1,3 @@ +# `@ckb-lumos/crypto` + +Crypto utilities used in Lumos. diff --git a/packages/crypto/package.json b/packages/crypto/package.json new file mode 100644 index 000000000..e1b116137 --- /dev/null +++ b/packages/crypto/package.json @@ -0,0 +1,50 @@ +{ + "name": "@ckb-lumos/crypto", + "version": "0.23.0-next.0", + "description": "Crypto utilities used in Lumos", + "author": "Tom Wang ", + "homepage": "https://github.com/ckb-js/lumos#readme", + "license": "MIT", + "main": "lib/index.js", + "types": "lib/index.d.ts", + "engines": { + "node": ">=20.0.0" + }, + "directories": { + "lib": "lib", + "test": "tests" + }, + "files": [ + "lib", + "index.d.ts" + ], + "repository": { + "type": "git", + "url": "git+https://github.com/ckb-js/lumos.git" + }, + "scripts": { + "build": "pnpm run build:types && pnpm run build:js", + "build:types": "tsc --declaration --emitDeclarationOnly", + "build:js": "babel --root-mode upward src --out-dir lib --extensions .ts -s", + "fmt": "prettier --write \"{src,tests,examples}/**/*.ts\" package.json", + "lint": "eslint -c ../../.eslintrc.js \"{src,tests,examples}/**/*.ts\"", + "clean": "shx rm -rf lib", + "test": "ava **/*.test.{js,ts} --timeout=2m" + }, + "bugs": { + "url": "https://github.com/ckb-js/lumos/issues" + }, + "ava": { + "extensions": [ + "ts", + "js" + ], + "require": [ + "ts-node/register" + ] + }, + "dependencies": {}, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/crypto/src/index.ts b/packages/crypto/src/index.ts new file mode 100644 index 000000000..2c97f64b4 --- /dev/null +++ b/packages/crypto/src/index.ts @@ -0,0 +1,29 @@ +/** + * Generates cryptographically secure random bytes. + * @param size The number of random bytes to generate. The `size` must not be greater than 65536. + * @returns A Uint8Array containing the random bytes. + * @throws {RangeError} If `size` is greater than 65536. + */ +export function randomBytes( + size: number +): Uint8Array & { toString(format?: "hex"): string } { + const MAX_BYTES = 65536; // limit of Crypto.getRandomValues() + if (size > MAX_BYTES) { + throw new RangeError(`size must be less than or equal to ${MAX_BYTES}`); + } + + const bytes = new Uint8Array(size); + crypto.getRandomValues(bytes); + + Object.defineProperty(bytes, "toString", { + value: (format?: "hex") => { + return format === "hex" + ? Array.from(bytes) + .map((byte) => byte.toString(16).padStart(2, "0")) + .join("") + : Uint8Array.prototype.toString.call(bytes); + }, + }); + + return bytes; +} diff --git a/packages/crypto/tests/index.test.ts b/packages/crypto/tests/index.test.ts new file mode 100644 index 000000000..2251d3711 --- /dev/null +++ b/packages/crypto/tests/index.test.ts @@ -0,0 +1,16 @@ +import test from "ava"; +import { randomBytes } from "../src"; +import { hexify } from "../../codec/lib/bytes"; + +test("randomBytes", (t) => { + const size = 32; + const bytes = randomBytes(size); + t.is(bytes.length, size); + t.is(bytes.toString("hex"), hexify(bytes).slice(2)); + + const TOO_MANY_BYTES = 65538; + t.throws(() => randomBytes(TOO_MANY_BYTES), { + instanceOf: RangeError, + message: `size must be less than or equal to 65536`, + }); +}); diff --git a/packages/crypto/tsconfig.json b/packages/crypto/tsconfig.json new file mode 100644 index 000000000..11c2edbdc --- /dev/null +++ b/packages/crypto/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "lib", + "sourceMap": true + }, + "include": ["src"] +} diff --git a/packages/crypto/typedoc.json b/packages/crypto/typedoc.json new file mode 100644 index 000000000..f593f276c --- /dev/null +++ b/packages/crypto/typedoc.json @@ -0,0 +1,4 @@ +{ + "extends": ["../../typedoc.base.json"], + "entryPoints": ["src/index.ts"] +} diff --git a/packages/debugger/package.json b/packages/debugger/package.json index 236a421ec..42bce84c8 100644 --- a/packages/debugger/package.json +++ b/packages/debugger/package.json @@ -24,6 +24,7 @@ "@ckb-lumos/base": "0.23.0-next.0", "@ckb-lumos/bi": "0.23.0-next.0", "@ckb-lumos/codec": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.0", "@ckb-lumos/config-manager": "0.23.0-next.0", "@ckb-lumos/helpers": "0.23.0-next.0", "@ckb-lumos/rpc": "0.23.0-next.0", diff --git a/packages/debugger/src/context.ts b/packages/debugger/src/context.ts index f1a41579e..718f0fe0f 100644 --- a/packages/debugger/src/context.ts +++ b/packages/debugger/src/context.ts @@ -1,5 +1,5 @@ +import { randomBytes } from "@ckb-lumos/crypto"; import { Header, OutPoint } from "@ckb-lumos/base"; -import * as crypto from "crypto"; import { ScriptConfig } from "@ckb-lumos/config-manager"; import { OutputDataLoader } from "./loader"; import { DataLoader, TestContext } from "./types"; @@ -14,9 +14,8 @@ const TRANSACTION_HASH_LENGTH = 32; export function mockOutPoint(): OutPoint { return { - txHash: hexify(crypto.randomBytes(TRANSACTION_HASH_LENGTH)), - index: - "0x" + Uint32.unpack(crypto.randomBytes(Uint32.byteLength)).toString(16), + txHash: hexify(randomBytes(TRANSACTION_HASH_LENGTH)), + index: "0x" + Uint32.unpack(randomBytes(Uint32.byteLength)).toString(16), }; } diff --git a/packages/debugger/src/executor.ts b/packages/debugger/src/executor.ts index 71ec78c4f..0ca1fef47 100644 --- a/packages/debugger/src/executor.ts +++ b/packages/debugger/src/executor.ts @@ -1,12 +1,12 @@ import { DataLoader, ExecuteResult, Executor } from "./types"; import { TransactionSkeletonType } from "@ckb-lumos/helpers"; +import { randomBytes } from "@ckb-lumos/crypto"; import { spawnSync } from "child_process"; import { Hash } from "@ckb-lumos/base"; import * as fs from "fs"; import * as os from "os"; import * as path from "path"; import { parseDebuggerData, parseDebuggerMessage } from "./parse"; -import * as crypto from 'crypto'; interface DebuggerOptions { readonly loader: DataLoader; @@ -51,8 +51,9 @@ export class CKBDebugger implements Executor { */ private saveTmpTxFile(txSkeleton: TransactionSkeletonType): string { const debuggerData = parseDebuggerData(txSkeleton, this.loader); - const randomHex = crypto.randomBytes(18).toString('hex'); - const tempFileName = `lumos-debugger-data-${randomHex}` + // eslint-disable-next-line @typescript-eslint/no-magic-numbers + const randomHex = randomBytes(18).toString("hex"); + const tempFileName = `lumos-debugger-data-${randomHex}`; const tmpTxPath = path.join(os.tmpdir(), `${tempFileName}.json`); fs.writeFileSync(tmpTxPath, JSON.stringify(debuggerData)); diff --git a/packages/debugger/tests/context.test.ts b/packages/debugger/tests/context.test.ts index 867d6f8aa..029bcf451 100644 --- a/packages/debugger/tests/context.test.ts +++ b/packages/debugger/tests/context.test.ts @@ -4,6 +4,7 @@ import { createScriptRegistry, } from "@ckb-lumos/experiment-tx-assembler"; import { computeScriptHash } from "@ckb-lumos/base/lib/utils"; +import { randomBytes } from "@ckb-lumos/crypto"; import { HexString } from "@ckb-lumos/base"; import { CKBDebugger, CKBDebuggerDownloader, DataLoader } from "../src"; import { TransactionSkeleton } from "@ckb-lumos/helpers"; @@ -12,7 +13,6 @@ import { getDefaultConfig, mockOutPoint, } from "../src/context"; -import { randomBytes } from "crypto"; import { privateKeyToBlake160, signRecoverable } from "@ckb-lumos/hd/lib/key"; import { hexify } from "@ckb-lumos/codec/lib/bytes"; import { diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index a6ec85952..fc00cf76e 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -34,6 +34,7 @@ "@ckb-lumos/bi": "0.23.0-next.0", "@ckb-lumos/ckb-indexer": "0.23.0-next.0", "@ckb-lumos/codec": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.0", "@ckb-lumos/common-scripts": "0.23.0-next.0", "@ckb-lumos/config-manager": "0.23.0-next.0", "@ckb-lumos/hd": "0.23.0-next.0", diff --git a/packages/e2e-test/src/utils.ts b/packages/e2e-test/src/utils.ts index 63ae46866..4114eba25 100644 --- a/packages/e2e-test/src/utils.ts +++ b/packages/e2e-test/src/utils.ts @@ -1,11 +1,12 @@ import { Script } from "@ckb-lumos/base"; +import { randomBytes } from "@ckb-lumos/crypto"; import { encodeToAddress } from "@ckb-lumos/helpers"; -import { randomBytes } from "crypto"; import { key } from "@ckb-lumos/hd"; import { getConfig } from "@ckb-lumos/config-manager"; import { hexify } from "@ckb-lumos/codec/lib/bytes"; // secp256k1 private key is 32-bytes length +/* eslint-disable @typescript-eslint/no-magic-numbers */ export const generateRandomPrivateKey = (): string => hexify(randomBytes(32)); export function asyncSleep(ms: number): Promise { diff --git a/packages/hd/package.json b/packages/hd/package.json index 88643096f..bd02af471 100644 --- a/packages/hd/package.json +++ b/packages/hd/package.json @@ -19,8 +19,9 @@ "src" ], "dependencies": { - "@ckb-lumos/base": "0.23.0-next.0", "@ckb-lumos/bi": "0.23.0-next.0", + "@ckb-lumos/base": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.0", "bn.js": "^5.1.3", "elliptic": "^6.5.4", "scrypt-js": "^3.0.1", diff --git a/packages/hd/src/keystore.ts b/packages/hd/src/keystore.ts index 368315644..426538cba 100644 --- a/packages/hd/src/keystore.ts +++ b/packages/hd/src/keystore.ts @@ -1,7 +1,13 @@ -import crypto from "crypto"; +import { + Cipher, + ScryptOptions, + createCipheriv, + createDecipheriv, +} from "crypto"; import { Keccak } from "sha3"; import { v4 as uuid } from "uuid"; import { ExtendedPrivateKey } from "./extended_key"; +import { randomBytes } from "@ckb-lumos/crypto"; import { HexString } from "@ckb-lumos/base"; import { syncScrypt } from "scrypt-js"; @@ -94,8 +100,8 @@ export default class Keystore { // Create an empty keystore object that contains empty private key static createEmpty(): Keystore { const saltSize = 32; - const salt: Buffer = crypto.randomBytes(saltSize); - const iv: Buffer = crypto.randomBytes(16); + const salt: Buffer = Buffer.from(randomBytes(saltSize)); + const iv: Buffer = Buffer.from(randomBytes(16)); const kdfparams: KdfParams = { dklen: 32, salt: salt.toString("hex"), @@ -125,8 +131,8 @@ export default class Keystore { ): Keystore { const saltSize = 32; const ivSize = 16; - const salt: Buffer = options.salt || crypto.randomBytes(saltSize); - const iv: Buffer = options.iv || crypto.randomBytes(ivSize); + const salt: Buffer = options.salt || Buffer.from(randomBytes(saltSize)); + const iv: Buffer = options.iv || Buffer.from(randomBytes(ivSize)); const kdfparams: KdfParams = { dklen: 32, salt: salt.toString("hex"), @@ -145,11 +151,7 @@ export default class Keystore { ) ); - const cipher: crypto.Cipher = crypto.createCipheriv( - CIPHER, - derivedKey.slice(0, 16), - iv - ); + const cipher: Cipher = createCipheriv(CIPHER, derivedKey.slice(0, 16), iv); if (!cipher) { throw new UnsupportedCipher(); } @@ -190,7 +192,7 @@ export default class Keystore { if (Keystore.mac(derivedKey, ciphertext) !== this.crypto.mac) { throw new IncorrectPassword(); } - const decipher = crypto.createDecipheriv( + const decipher = createDecipheriv( this.crypto.cipher, derivedKey.slice(0, 16), Buffer.from(this.crypto.cipherparams.iv, "hex") @@ -239,7 +241,7 @@ export default class Keystore { ); } - static scryptOptions(kdfparams: KdfParams): crypto.ScryptOptions { + static scryptOptions(kdfparams: KdfParams): ScryptOptions { return { N: kdfparams.n, r: kdfparams.r, diff --git a/packages/hd/src/mnemonic/index.ts b/packages/hd/src/mnemonic/index.ts index 0b3f956a4..3ac150685 100644 --- a/packages/hd/src/mnemonic/index.ts +++ b/packages/hd/src/mnemonic/index.ts @@ -1,6 +1,7 @@ -import crypto from "crypto"; -import wordList from "./word_list"; +import { pbkdf2, pbkdf2Sync, createHash } from "crypto"; +import { randomBytes } from "@ckb-lumos/crypto"; import { HexString } from "@ckb-lumos/base"; +import wordList from "./word_list"; const RADIX = 2048; const PBKDF2_ROUNDS = 2048; @@ -30,28 +31,28 @@ if (wordList.length !== RADIX) { function bytesToBinary(bytes: Buffer): string { return bytes.reduce((binary, byte) => { + /* eslint-disable @typescript-eslint/no-magic-numbers */ return binary + byte.toString(2).padStart(8, "0"); }, ""); } function deriveChecksumBits(entropyBuffer: Buffer): string { + /* eslint-disable @typescript-eslint/no-magic-numbers */ const ENT = entropyBuffer.length * 8; + /* eslint-disable @typescript-eslint/no-magic-numbers */ const CS = ENT / 32; - const hash = crypto.createHash("sha256").update(entropyBuffer).digest(); + const hash = createHash("sha256").update(entropyBuffer).digest(); return bytesToBinary(hash).slice(0, CS); } -function salt(password: string = ""): string { +function salt(password = ""): string { return `mnemonic${password}`; } -export function mnemonicToSeedSync( - mnemonic: string = "", - password: string = "" -): Buffer { +export function mnemonicToSeedSync(mnemonic = "", password = ""): Buffer { const mnemonicBuffer = Buffer.from(mnemonic.normalize("NFKD"), "utf8"); const saltBuffer = Buffer.from(salt(password.normalize("NFKD")), "utf8"); - return crypto.pbkdf2Sync( + return pbkdf2Sync( mnemonicBuffer, saltBuffer, PBKDF2_ROUNDS, @@ -60,15 +61,12 @@ export function mnemonicToSeedSync( ); } -export function mnemonicToSeed( - mnemonic: string = "", - password: string = "" -): Promise { +export function mnemonicToSeed(mnemonic = "", password = ""): Promise { return new Promise((resolve, reject) => { try { const mnemonicBuffer = Buffer.from(mnemonic.normalize("NFKD"), "utf8"); const saltBuffer = Buffer.from(salt(password.normalize("NFKD")), "utf8"); - crypto.pbkdf2( + pbkdf2( mnemonicBuffer, saltBuffer, PBKDF2_ROUNDS, @@ -87,7 +85,7 @@ export function mnemonicToSeed( }); } -export function mnemonicToEntropy(mnemonic: string = ""): HexString { +export function mnemonicToEntropy(mnemonic = ""): HexString { const words = mnemonic.normalize("NFKD").split(" "); if (words.length < MIN_WORDS_SIZE) { throw new Error(WORDS_TOO_SHORT); @@ -95,6 +93,7 @@ export function mnemonicToEntropy(mnemonic: string = ""): HexString { if (words.length > MAX_WORDS_SIZE) { throw new Error(WORDS_TOO_LONG); } + /* eslint-disable @typescript-eslint/no-magic-numbers */ if (words.length % 3 !== 0) { throw new Error(INVALID_MNEMONIC); } @@ -104,10 +103,12 @@ export function mnemonicToEntropy(mnemonic: string = ""): HexString { if (index === -1) { throw new Error(INVALID_MNEMONIC); } + /* eslint-disable @typescript-eslint/no-magic-numbers */ return index.toString(2).padStart(11, "0"); }) .join(""); + /* eslint-disable @typescript-eslint/no-magic-numbers */ const dividerIndex = Math.floor(bits.length / 33) * 32; const entropyBits = bits.slice(0, dividerIndex); const checksumBits = bits.slice(dividerIndex); @@ -121,6 +122,7 @@ export function mnemonicToEntropy(mnemonic: string = ""): HexString { if (entropyBytes.length > MAX_ENTROPY_SIZE) { throw new Error(ENTROPY_TOO_LONG); } + /* eslint-disable @typescript-eslint/no-magic-numbers */ if (entropyBytes.length % 4 !== 0) { throw new Error(ENTROPY_NOT_DIVISIBLE); } @@ -143,6 +145,7 @@ export function entropyToMnemonic(entropyStr: HexString): string { if (entropy.length > MAX_ENTROPY_SIZE) { throw new TypeError(ENTROPY_TOO_LONG); } + /* eslint-disable @typescript-eslint/no-magic-numbers */ if (entropy.length % 4 !== 0) { throw new TypeError(ENTROPY_NOT_DIVISIBLE); } @@ -172,8 +175,7 @@ export function validateMnemonic(mnemonic: string): boolean { // Generate 12 words mnemonic code export function generateMnemonic(): string { const entropySize = 16; - const entropy: HexString = - "0x" + crypto.randomBytes(entropySize).toString("hex"); + const entropy: HexString = "0x" + randomBytes(entropySize).toString("hex"); return entropyToMnemonic(entropy); } diff --git a/packages/helpers/tests/model_helper.test.ts b/packages/helpers/tests/model_helper.test.ts index 5f34dec4d..967f88f7c 100644 --- a/packages/helpers/tests/model_helper.test.ts +++ b/packages/helpers/tests/model_helper.test.ts @@ -1,6 +1,6 @@ import test from "ava"; import { cellHelper, encodeToAddress, scriptHelper } from "../src"; -import { randomBytes } from "node:crypto"; +import { randomBytes } from "../../crypto/src"; import { bytes } from "@ckb-lumos/codec"; import { predefined } from "@ckb-lumos/config-manager"; import { defaultDeepClone } from "../src/models/base"; diff --git a/packages/helpers/tests/refresh.test.ts b/packages/helpers/tests/refresh.test.ts index 6371c8121..e9fc401a5 100644 --- a/packages/helpers/tests/refresh.test.ts +++ b/packages/helpers/tests/refresh.test.ts @@ -1,9 +1,9 @@ import test from "ava"; import { refreshTypeIdCellDeps } from "../src/refresh"; +import { randomBytes } from "../../crypto/src"; import { TransactionSkeleton } from "../src"; import { CellDep } from "@ckb-lumos/base"; import { bytes } from "@ckb-lumos/codec"; -import { randomBytes } from "node:crypto"; test("refreshTypeIdCellDeps", async (t) => { const outdatedCellDep: CellDep = { diff --git a/packages/joyid/tests/script-info.test.ts b/packages/joyid/tests/script-info.test.ts index 9cc97e4f8..a6b4893af 100644 --- a/packages/joyid/tests/script-info.test.ts +++ b/packages/joyid/tests/script-info.test.ts @@ -1,4 +1,5 @@ import test from "ava"; +import { spy } from "sinon"; import { createJoyIDScriptInfo } from "../src"; import { Connection, @@ -6,7 +7,6 @@ import { JoyIDScriptInfoConfig, } from "../src/script-info"; import { BytesLike, bytes } from "@ckb-lumos/codec"; -import { randomBytes } from "node:crypto"; import { encodeToAddress, TransactionSkeleton } from "@ckb-lumos/helpers"; import { Cell, @@ -20,7 +20,7 @@ import { common } from "@ckb-lumos/common-scripts"; import { parseUnit } from "@ckb-lumos/bi"; import { getJoyIDLockScript } from "@joyid/ckb"; import { getCotaTypeScript } from "../src/constants"; -import { spy } from "sinon"; +import { randomBytes } from "../../crypto/src"; const joyIdLockScriptTemplate = getJoyIDLockScript(true); const cotaTypeScriptTemplate = getCotaTypeScript(true); diff --git a/packages/lumos/package.json b/packages/lumos/package.json index 9618214c6..ebfa0aff9 100644 --- a/packages/lumos/package.json +++ b/packages/lumos/package.json @@ -29,6 +29,7 @@ "@ckb-lumos/bi": "0.23.0-next.0", "@ckb-lumos/ckb-indexer": "0.23.0-next.0", "@ckb-lumos/codec": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.0", "@ckb-lumos/common-scripts": "0.23.0-next.0", "@ckb-lumos/config-manager": "0.23.0-next.0", "@ckb-lumos/hd": "0.23.0-next.0", diff --git a/packages/lumos/src/index.ts b/packages/lumos/src/index.ts index d192e0608..a5b045f42 100644 --- a/packages/lumos/src/index.ts +++ b/packages/lumos/src/index.ts @@ -31,6 +31,7 @@ export * as config from "./config"; export { RPC } from "@ckb-lumos/rpc"; export * as hd from "@ckb-lumos/hd"; +export * as crypto from "@ckb-lumos/crypto"; export { CellCollector, Indexer } from "@ckb-lumos/ckb-indexer"; export * as helpers from "./helpers"; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9099fb9f9..8e961a938 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -292,6 +292,8 @@ importers: specifier: ^1.1.1 version: 1.1.1 + packages/crypto: {} + packages/debugger: dependencies: '@ckb-lumos/base': @@ -306,6 +308,9 @@ importers: '@ckb-lumos/config-manager': specifier: 0.23.0-next.0 version: link:../config-manager + '@ckb-lumos/crypto': + specifier: 0.23.0-next.0 + version: link:../crypto '@ckb-lumos/helpers': specifier: 0.23.0-next.0 version: link:../helpers @@ -361,6 +366,9 @@ importers: '@ckb-lumos/config-manager': specifier: 0.23.0-next.0 version: link:../config-manager + '@ckb-lumos/crypto': + specifier: 0.23.0-next.0 + version: link:../crypto '@ckb-lumos/hd': specifier: 0.23.0-next.0 version: link:../hd @@ -437,6 +445,9 @@ importers: '@ckb-lumos/bi': specifier: 0.23.0-next.0 version: link:../bi + '@ckb-lumos/crypto': + specifier: 0.23.0-next.0 + version: link:../crypto bn.js: specifier: ^5.1.3 version: 5.2.1 @@ -603,6 +614,9 @@ importers: '@ckb-lumos/config-manager': specifier: 0.23.0-next.0 version: link:../config-manager + '@ckb-lumos/crypto': + specifier: 0.23.0-next.0 + version: link:../crypto '@ckb-lumos/hd': specifier: 0.23.0-next.0 version: link:../hd From ca32f1e3510c4e2de3ab63caa69812bafd7a0822 Mon Sep 17 00:00:00 2001 From: Tom Wang Date: Thu, 30 May 2024 17:17:08 +0800 Subject: [PATCH 02/12] ci: disable codecov/patch --- .github/.codecov.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/.codecov.yml b/.github/.codecov.yml index 51839dda7..2ed6a4d6b 100644 --- a/.github/.codecov.yml +++ b/.github/.codecov.yml @@ -12,6 +12,7 @@ coverage: target: auto threshold: 1% base: auto + patch: off # disable codecov/patch parsers: gcov: From 025ce5791e8aadd16086eca495f6a99310cc22fc Mon Sep 17 00:00:00 2001 From: Tom Wang Date: Fri, 31 May 2024 18:57:10 +0800 Subject: [PATCH 03/12] fix: set node version to 18 and fix imports --- .github/workflows/ci.yaml | 4 ++-- packages/ckb-indexer/package.json | 1 + .../tests/transaction_collector.unit.test.ts | 2 +- packages/codec/package.json | 1 + packages/codec/tests/bytes-like.test.ts | 2 +- packages/common-scripts/package.json | 1 + .../tests/dao-with-custom-lock.test.ts | 2 +- packages/config-manager/package.json | 3 +++ packages/config-manager/tests/refresh.test.ts | 2 +- packages/crypto/package.json | 2 +- packages/crypto/src/index.ts | 21 +++++++------------ packages/crypto/tests/index.test.ts | 4 ++-- packages/debugger/src/executor.ts | 2 +- packages/hd/src/mnemonic/index.ts | 3 ++- packages/helpers/package.json | 3 +++ packages/helpers/tests/model_helper.test.ts | 2 +- packages/helpers/tests/refresh.test.ts | 2 +- packages/joyid/package.json | 1 + packages/joyid/tests/script-info.test.ts | 2 +- pnpm-lock.yaml | 20 ++++++++++++++++++ 20 files changed, 52 insertions(+), 28 deletions(-) diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 8ddf65712..64e7bfa8d 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -12,7 +12,7 @@ jobs: - uses: actions/setup-node@v4 with: cache: "pnpm" - node-version: '20' + node-version: '18' - name: Install project dependencies and build run: | @@ -42,7 +42,7 @@ jobs: - uses: actions/setup-node@v4 with: cache: "pnpm" - node-version: '20' + node-version: '18' - name: Install project dependencies and build run: | diff --git a/packages/ckb-indexer/package.json b/packages/ckb-indexer/package.json index 2ffa61968..5f2ef7f30 100644 --- a/packages/ckb-indexer/package.json +++ b/packages/ckb-indexer/package.json @@ -28,6 +28,7 @@ "events": "^3.3.0" }, "devDependencies": { + "@ckb-lumos/crypto": "0.23.0-next.0", "@ckb-lumos/testkit": "0.23.0-next.0", "@types/lodash.uniqby": "^4.7.7", "@types/request": "^2.48.8", diff --git a/packages/ckb-indexer/tests/transaction_collector.unit.test.ts b/packages/ckb-indexer/tests/transaction_collector.unit.test.ts index e746e2a42..f8b909da4 100644 --- a/packages/ckb-indexer/tests/transaction_collector.unit.test.ts +++ b/packages/ckb-indexer/tests/transaction_collector.unit.test.ts @@ -1,5 +1,5 @@ import test from "ava"; -import { randomBytes } from "../../crypto/src"; +import { randomBytes } from "@ckb-lumos/crypto"; import { Indexer, TransactionCollector } from "../src"; import { indexerTransactionListThatHaveOneIoTypeInput, diff --git a/packages/codec/package.json b/packages/codec/package.json index db5fcc883..bf02e2d29 100644 --- a/packages/codec/package.json +++ b/packages/codec/package.json @@ -45,6 +45,7 @@ ] }, "devDependencies": { + "@ckb-lumos/crypto": "0.23.0-next.0", "escape-string-regexp": "^4.0.0", "js-yaml": "^4.1.0" } diff --git a/packages/codec/tests/bytes-like.test.ts b/packages/codec/tests/bytes-like.test.ts index cba376a61..afed311e4 100644 --- a/packages/codec/tests/bytes-like.test.ts +++ b/packages/codec/tests/bytes-like.test.ts @@ -1,7 +1,7 @@ import test from "ava"; import { molecule, number } from "../src"; import { Byte32 } from "../src/blockchain"; -import { randomBytes } from "../../crypto/src"; +import { randomBytes } from "@ckb-lumos/crypto"; import { equal, concat, hexify } from "../src/bytes"; import { BI } from "@ckb-lumos/bi"; import { bytify } from "../lib/bytes"; diff --git a/packages/common-scripts/package.json b/packages/common-scripts/package.json index b0b5ee48b..b30bb8cec 100644 --- a/packages/common-scripts/package.json +++ b/packages/common-scripts/package.json @@ -55,6 +55,7 @@ ] }, "devDependencies": { + "@ckb-lumos/crypto": "0.23.0-next.0", "@ckb-lumos/debugger": "0.23.0-next.0", "@ckb-lumos/hd": "0.23.0-next.0", "@types/keccak": "^3.0.1", diff --git a/packages/common-scripts/tests/dao-with-custom-lock.test.ts b/packages/common-scripts/tests/dao-with-custom-lock.test.ts index 7ae77b781..8095dc51a 100644 --- a/packages/common-scripts/tests/dao-with-custom-lock.test.ts +++ b/packages/common-scripts/tests/dao-with-custom-lock.test.ts @@ -13,7 +13,7 @@ import { dao } from "../src"; import { Config, predefined } from "@ckb-lumos/config-manager"; import { hexify } from "@ckb-lumos/codec/lib/bytes"; import { Uint64 } from "@ckb-lumos/codec/lib/number"; -import { randomBytes } from "../../crypto/src"; +import { randomBytes } from "@ckb-lumos/crypto"; const { LINA } = predefined; diff --git a/packages/config-manager/package.json b/packages/config-manager/package.json index 845d9d657..fcd4c9d94 100644 --- a/packages/config-manager/package.json +++ b/packages/config-manager/package.json @@ -41,6 +41,9 @@ "@types/deep-freeze-strict": "^1.1.0", "deep-freeze-strict": "^1.1.1" }, + "devDependencies": { + "@ckb-lumos/crypto": "0.23.0-next.0" + }, "publishConfig": { "access": "public" }, diff --git a/packages/config-manager/tests/refresh.test.ts b/packages/config-manager/tests/refresh.test.ts index 21be448e0..773925b64 100644 --- a/packages/config-manager/tests/refresh.test.ts +++ b/packages/config-manager/tests/refresh.test.ts @@ -8,7 +8,7 @@ import { } from "../src/refresh"; import { hexify } from "@ckb-lumos/codec/lib/bytes"; import { OutPoint, Output, Script } from "@ckb-lumos/base"; -import { randomBytes } from "../../crypto/src"; +import { randomBytes } from "@ckb-lumos/crypto"; import { ScriptConfigs } from "../src"; test("refresh without update", async (t) => { diff --git a/packages/crypto/package.json b/packages/crypto/package.json index e1b116137..78f0e8a0e 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -8,7 +8,7 @@ "main": "lib/index.js", "types": "lib/index.d.ts", "engines": { - "node": ">=20.0.0" + "node": ">=18.0.0" }, "directories": { "lib": "lib", diff --git a/packages/crypto/src/index.ts b/packages/crypto/src/index.ts index 2c97f64b4..c73a12be4 100644 --- a/packages/crypto/src/index.ts +++ b/packages/crypto/src/index.ts @@ -4,26 +4,19 @@ * @returns A Uint8Array containing the random bytes. * @throws {RangeError} If `size` is greater than 65536. */ -export function randomBytes( - size: number -): Uint8Array & { toString(format?: "hex"): string } { +export function randomBytes(size: number): Uint8Array { const MAX_BYTES = 65536; // limit of Crypto.getRandomValues() if (size > MAX_BYTES) { throw new RangeError(`size must be less than or equal to ${MAX_BYTES}`); } const bytes = new Uint8Array(size); - crypto.getRandomValues(bytes); - - Object.defineProperty(bytes, "toString", { - value: (format?: "hex") => { - return format === "hex" - ? Array.from(bytes) - .map((byte) => byte.toString(16).padStart(2, "0")) - .join("") - : Uint8Array.prototype.toString.call(bytes); - }, - }); + try { + crypto.getRandomValues(bytes); // Node.js 20+ and modern browsers + } catch { + /* eslint-disable @typescript-eslint/no-var-requires */ + require("crypto").getRandomValues(bytes); // Node.js 18 + } return bytes; } diff --git a/packages/crypto/tests/index.test.ts b/packages/crypto/tests/index.test.ts index 2251d3711..5757dda80 100644 --- a/packages/crypto/tests/index.test.ts +++ b/packages/crypto/tests/index.test.ts @@ -1,12 +1,12 @@ import test from "ava"; import { randomBytes } from "../src"; -import { hexify } from "../../codec/lib/bytes"; test("randomBytes", (t) => { const size = 32; const bytes = randomBytes(size); t.is(bytes.length, size); - t.is(bytes.toString("hex"), hexify(bytes).slice(2)); + t.is(bytes.byteLength, size); + t.is(bytes.constructor, Uint8Array); const TOO_MANY_BYTES = 65538; t.throws(() => randomBytes(TOO_MANY_BYTES), { diff --git a/packages/debugger/src/executor.ts b/packages/debugger/src/executor.ts index 0ca1fef47..4865d4cf0 100644 --- a/packages/debugger/src/executor.ts +++ b/packages/debugger/src/executor.ts @@ -52,7 +52,7 @@ export class CKBDebugger implements Executor { private saveTmpTxFile(txSkeleton: TransactionSkeletonType): string { const debuggerData = parseDebuggerData(txSkeleton, this.loader); // eslint-disable-next-line @typescript-eslint/no-magic-numbers - const randomHex = randomBytes(18).toString("hex"); + const randomHex = Buffer.from(randomBytes(18)).toString("hex"); const tempFileName = `lumos-debugger-data-${randomHex}`; const tmpTxPath = path.join(os.tmpdir(), `${tempFileName}.json`); fs.writeFileSync(tmpTxPath, JSON.stringify(debuggerData)); diff --git a/packages/hd/src/mnemonic/index.ts b/packages/hd/src/mnemonic/index.ts index 3ac150685..93dc42727 100644 --- a/packages/hd/src/mnemonic/index.ts +++ b/packages/hd/src/mnemonic/index.ts @@ -175,7 +175,8 @@ export function validateMnemonic(mnemonic: string): boolean { // Generate 12 words mnemonic code export function generateMnemonic(): string { const entropySize = 16; - const entropy: HexString = "0x" + randomBytes(entropySize).toString("hex"); + const entropy: HexString = + "0x" + Buffer.from(randomBytes(entropySize)).toString("hex"); return entropyToMnemonic(entropy); } diff --git a/packages/helpers/package.json b/packages/helpers/package.json index 55fc8b07b..8ccd8b2ce 100644 --- a/packages/helpers/package.json +++ b/packages/helpers/package.json @@ -43,6 +43,9 @@ "bech32": "^2.0.0", "immutable": "^4.3.0" }, + "devDependencies": { + "@ckb-lumos/crypto": "0.23.0-next.0" + }, "ava": { "extensions": [ "ts" diff --git a/packages/helpers/tests/model_helper.test.ts b/packages/helpers/tests/model_helper.test.ts index 967f88f7c..db845cc10 100644 --- a/packages/helpers/tests/model_helper.test.ts +++ b/packages/helpers/tests/model_helper.test.ts @@ -1,6 +1,6 @@ import test from "ava"; import { cellHelper, encodeToAddress, scriptHelper } from "../src"; -import { randomBytes } from "../../crypto/src"; +import { randomBytes } from "@ckb-lumos/crypto"; import { bytes } from "@ckb-lumos/codec"; import { predefined } from "@ckb-lumos/config-manager"; import { defaultDeepClone } from "../src/models/base"; diff --git a/packages/helpers/tests/refresh.test.ts b/packages/helpers/tests/refresh.test.ts index e9fc401a5..8b1a9cfbd 100644 --- a/packages/helpers/tests/refresh.test.ts +++ b/packages/helpers/tests/refresh.test.ts @@ -1,6 +1,6 @@ import test from "ava"; import { refreshTypeIdCellDeps } from "../src/refresh"; -import { randomBytes } from "../../crypto/src"; +import { randomBytes } from "@ckb-lumos/crypto"; import { TransactionSkeleton } from "../src"; import { CellDep } from "@ckb-lumos/base"; import { bytes } from "@ckb-lumos/codec"; diff --git a/packages/joyid/package.json b/packages/joyid/package.json index ba7e14f85..106253629 100644 --- a/packages/joyid/package.json +++ b/packages/joyid/package.json @@ -30,6 +30,7 @@ }, "devDependencies": { "@ckb-lumos/bi": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.0", "sinon": "^15.0.4" }, "repository": { diff --git a/packages/joyid/tests/script-info.test.ts b/packages/joyid/tests/script-info.test.ts index a6b4893af..74d15aede 100644 --- a/packages/joyid/tests/script-info.test.ts +++ b/packages/joyid/tests/script-info.test.ts @@ -20,7 +20,7 @@ import { common } from "@ckb-lumos/common-scripts"; import { parseUnit } from "@ckb-lumos/bi"; import { getJoyIDLockScript } from "@joyid/ckb"; import { getCotaTypeScript } from "../src/constants"; -import { randomBytes } from "../../crypto/src"; +import { randomBytes } from "@ckb-lumos/crypto"; const joyIdLockScriptTemplate = getJoyIDLockScript(true); const cotaTypeScriptTemplate = getCotaTypeScript(true); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8e961a938..eff2604c9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -181,6 +181,9 @@ importers: specifier: ^3.3.0 version: 3.3.0 devDependencies: + '@ckb-lumos/crypto': + specifier: 0.23.0-next.0 + version: link:../crypto '@ckb-lumos/testkit': specifier: 0.23.0-next.0 version: link:../testkit @@ -212,6 +215,9 @@ importers: specifier: 0.23.0-next.0 version: link:../bi devDependencies: + '@ckb-lumos/crypto': + specifier: 0.23.0-next.0 + version: link:../crypto escape-string-regexp: specifier: ^4.0.0 version: 4.0.0 @@ -252,6 +258,9 @@ importers: specifier: ^4.3.0 version: 4.3.5 devDependencies: + '@ckb-lumos/crypto': + specifier: 0.23.0-next.0 + version: link:../crypto '@ckb-lumos/debugger': specifier: 0.23.0-next.0 version: link:../debugger @@ -291,6 +300,10 @@ importers: deep-freeze-strict: specifier: ^1.1.1 version: 1.1.1 + devDependencies: + '@ckb-lumos/crypto': + specifier: 0.23.0-next.0 + version: link:../crypto packages/crypto: {} @@ -531,6 +544,10 @@ importers: immutable: specifier: ^4.3.0 version: 4.3.5 + devDependencies: + '@ckb-lumos/crypto': + specifier: 0.23.0-next.0 + version: link:../crypto packages/joyid: dependencies: @@ -556,6 +573,9 @@ importers: '@ckb-lumos/bi': specifier: 0.23.0-next.0 version: link:../bi + '@ckb-lumos/crypto': + specifier: 0.23.0-next.0 + version: link:../crypto sinon: specifier: ^15.0.4 version: 15.2.0 From 20007905089c3e68c21211d37bff27fa37b99282 Mon Sep 17 00:00:00 2001 From: Tom Wang Date: Mon, 3 Jun 2024 15:22:45 +0800 Subject: [PATCH 04/12] ci: set codecov/patch threshold to 6% --- .github/.codecov.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.github/.codecov.yml b/.github/.codecov.yml index 2ed6a4d6b..b924db2be 100644 --- a/.github/.codecov.yml +++ b/.github/.codecov.yml @@ -12,7 +12,12 @@ coverage: target: auto threshold: 1% base: auto - patch: off # disable codecov/patch + patch: + default: + # basic settings + target: auto + threshold: 6% + base: auto parsers: gcov: From 671b750c3d21614f825893b00da43d6850ad2680 Mon Sep 17 00:00:00 2001 From: Tom Wang Date: Tue, 4 Jun 2024 10:21:09 +0800 Subject: [PATCH 05/12] fix: ignore crypto module in browsers --- packages/crypto/package.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/crypto/package.json b/packages/crypto/package.json index 78f0e8a0e..dbbc4e8ad 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -10,6 +10,9 @@ "engines": { "node": ">=18.0.0" }, + "browser": { + "crypto": false + }, "directories": { "lib": "lib", "test": "tests" From 04a37007dd686c1b2e836b2bb1642e3f31fa619e Mon Sep 17 00:00:00 2001 From: Tom Wang Date: Wed, 5 Jun 2024 16:48:35 +0800 Subject: [PATCH 06/12] refactor: use randomBytes from @noble/hashes --- packages/crypto/package.json | 4 +++- packages/crypto/src/index.ts | 23 +---------------------- packages/crypto/tests/index.test.ts | 6 ------ pnpm-lock.yaml | 7 +++++-- 4 files changed, 9 insertions(+), 31 deletions(-) diff --git a/packages/crypto/package.json b/packages/crypto/package.json index dbbc4e8ad..c24798f4c 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -46,7 +46,9 @@ "ts-node/register" ] }, - "dependencies": {}, + "dependencies": { + "@noble/hashes": "^1.4.0" + }, "publishConfig": { "access": "public" } diff --git a/packages/crypto/src/index.ts b/packages/crypto/src/index.ts index c73a12be4..53300c4be 100644 --- a/packages/crypto/src/index.ts +++ b/packages/crypto/src/index.ts @@ -1,22 +1 @@ -/** - * Generates cryptographically secure random bytes. - * @param size The number of random bytes to generate. The `size` must not be greater than 65536. - * @returns A Uint8Array containing the random bytes. - * @throws {RangeError} If `size` is greater than 65536. - */ -export function randomBytes(size: number): Uint8Array { - const MAX_BYTES = 65536; // limit of Crypto.getRandomValues() - if (size > MAX_BYTES) { - throw new RangeError(`size must be less than or equal to ${MAX_BYTES}`); - } - - const bytes = new Uint8Array(size); - try { - crypto.getRandomValues(bytes); // Node.js 20+ and modern browsers - } catch { - /* eslint-disable @typescript-eslint/no-var-requires */ - require("crypto").getRandomValues(bytes); // Node.js 18 - } - - return bytes; -} +export { randomBytes } from "@noble/hashes/utils"; diff --git a/packages/crypto/tests/index.test.ts b/packages/crypto/tests/index.test.ts index 5757dda80..f95010537 100644 --- a/packages/crypto/tests/index.test.ts +++ b/packages/crypto/tests/index.test.ts @@ -7,10 +7,4 @@ test("randomBytes", (t) => { t.is(bytes.length, size); t.is(bytes.byteLength, size); t.is(bytes.constructor, Uint8Array); - - const TOO_MANY_BYTES = 65538; - t.throws(() => randomBytes(TOO_MANY_BYTES), { - instanceOf: RangeError, - message: `size must be less than or equal to 65536`, - }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index eff2604c9..7f4cf7179 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -305,7 +305,11 @@ importers: specifier: 0.23.0-next.0 version: link:../crypto - packages/crypto: {} + packages/crypto: + dependencies: + '@noble/hashes': + specifier: ^1.4.0 + version: 1.4.0 packages/debugger: dependencies: @@ -4322,7 +4326,6 @@ packages: /@noble/hashes@1.4.0: resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} engines: {node: '>= 16'} - dev: true /@noble/secp256k1@1.7.1: resolution: {integrity: sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==} From 72c73fe10c5006d1ee0fad25aecc54d0315005d1 Mon Sep 17 00:00:00 2001 From: Tom Wang Date: Wed, 5 Jun 2024 17:09:28 +0800 Subject: [PATCH 07/12] ci: set codecov/patch threshold to 15% --- .github/.codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/.codecov.yml b/.github/.codecov.yml index b924db2be..5d7ab2446 100644 --- a/.github/.codecov.yml +++ b/.github/.codecov.yml @@ -16,7 +16,7 @@ coverage: default: # basic settings target: auto - threshold: 6% + threshold: 15% base: auto parsers: From b39f8a3c7f1619c51648a09ad9197544ab308ba9 Mon Sep 17 00:00:00 2001 From: Tom Wang Date: Wed, 5 Jun 2024 19:04:26 +0800 Subject: [PATCH 08/12] chore: disable no magic numbers rule for mnemonic/index.ts --- packages/hd/src/mnemonic/index.ts | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/packages/hd/src/mnemonic/index.ts b/packages/hd/src/mnemonic/index.ts index 93dc42727..b4a9f13c4 100644 --- a/packages/hd/src/mnemonic/index.ts +++ b/packages/hd/src/mnemonic/index.ts @@ -1,3 +1,4 @@ +/* eslint-disable @typescript-eslint/no-magic-numbers */ import { pbkdf2, pbkdf2Sync, createHash } from "crypto"; import { randomBytes } from "@ckb-lumos/crypto"; import { HexString } from "@ckb-lumos/base"; @@ -31,15 +32,12 @@ if (wordList.length !== RADIX) { function bytesToBinary(bytes: Buffer): string { return bytes.reduce((binary, byte) => { - /* eslint-disable @typescript-eslint/no-magic-numbers */ return binary + byte.toString(2).padStart(8, "0"); }, ""); } function deriveChecksumBits(entropyBuffer: Buffer): string { - /* eslint-disable @typescript-eslint/no-magic-numbers */ const ENT = entropyBuffer.length * 8; - /* eslint-disable @typescript-eslint/no-magic-numbers */ const CS = ENT / 32; const hash = createHash("sha256").update(entropyBuffer).digest(); return bytesToBinary(hash).slice(0, CS); @@ -93,7 +91,6 @@ export function mnemonicToEntropy(mnemonic = ""): HexString { if (words.length > MAX_WORDS_SIZE) { throw new Error(WORDS_TOO_LONG); } - /* eslint-disable @typescript-eslint/no-magic-numbers */ if (words.length % 3 !== 0) { throw new Error(INVALID_MNEMONIC); } @@ -103,12 +100,10 @@ export function mnemonicToEntropy(mnemonic = ""): HexString { if (index === -1) { throw new Error(INVALID_MNEMONIC); } - /* eslint-disable @typescript-eslint/no-magic-numbers */ return index.toString(2).padStart(11, "0"); }) .join(""); - /* eslint-disable @typescript-eslint/no-magic-numbers */ const dividerIndex = Math.floor(bits.length / 33) * 32; const entropyBits = bits.slice(0, dividerIndex); const checksumBits = bits.slice(dividerIndex); @@ -122,7 +117,6 @@ export function mnemonicToEntropy(mnemonic = ""): HexString { if (entropyBytes.length > MAX_ENTROPY_SIZE) { throw new Error(ENTROPY_TOO_LONG); } - /* eslint-disable @typescript-eslint/no-magic-numbers */ if (entropyBytes.length % 4 !== 0) { throw new Error(ENTROPY_NOT_DIVISIBLE); } @@ -145,7 +139,6 @@ export function entropyToMnemonic(entropyStr: HexString): string { if (entropy.length > MAX_ENTROPY_SIZE) { throw new TypeError(ENTROPY_TOO_LONG); } - /* eslint-disable @typescript-eslint/no-magic-numbers */ if (entropy.length % 4 !== 0) { throw new TypeError(ENTROPY_NOT_DIVISIBLE); } From 71cc23ab241f4f4b9878295bb1a428b53f326f96 Mon Sep 17 00:00:00 2001 From: Tom Wang Date: Wed, 5 Jun 2024 19:20:40 +0800 Subject: [PATCH 09/12] ci: set codecov/patch threshold to 1% --- .github/.codecov.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/.codecov.yml b/.github/.codecov.yml index 5d7ab2446..a2ef07946 100644 --- a/.github/.codecov.yml +++ b/.github/.codecov.yml @@ -16,7 +16,7 @@ coverage: default: # basic settings target: auto - threshold: 15% + threshold: 1% base: auto parsers: From 80db0753862a700f877f93e4819af45567797d57 Mon Sep 17 00:00:00 2001 From: Tom Wang Date: Wed, 5 Jun 2024 21:19:58 +0800 Subject: [PATCH 10/12] chore: remove browser field from package.json of lumos crypto --- packages/crypto/package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/packages/crypto/package.json b/packages/crypto/package.json index c24798f4c..ae684058d 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -10,9 +10,6 @@ "engines": { "node": ">=18.0.0" }, - "browser": { - "crypto": false - }, "directories": { "lib": "lib", "test": "tests" From 22cf9be6d9ffc7e12718bd0093a7624cf3e9f69c Mon Sep 17 00:00:00 2001 From: Tom Wang Date: Thu, 6 Jun 2024 11:27:29 +0800 Subject: [PATCH 11/12] chore: set lumos crypto version to 0.23.0-next.1 --- packages/ckb-indexer/package.json | 2 +- packages/codec/package.json | 2 +- packages/common-scripts/package.json | 2 +- packages/config-manager/package.json | 2 +- packages/crypto/package.json | 2 +- packages/debugger/package.json | 2 +- packages/e2e-test/package.json | 2 +- packages/hd/package.json | 2 +- packages/helpers/package.json | 2 +- packages/joyid/package.json | 2 +- packages/lumos/package.json | 2 +- pnpm-lock.yaml | 20 ++++++++++---------- 12 files changed, 21 insertions(+), 21 deletions(-) diff --git a/packages/ckb-indexer/package.json b/packages/ckb-indexer/package.json index 02a0f5ef4..13da80714 100644 --- a/packages/ckb-indexer/package.json +++ b/packages/ckb-indexer/package.json @@ -28,7 +28,7 @@ "events": "^3.3.0" }, "devDependencies": { - "@ckb-lumos/crypto": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.1", "@ckb-lumos/testkit": "0.23.0-next.1", "@types/lodash.uniqby": "^4.7.7", "@types/request": "^2.48.8", diff --git a/packages/codec/package.json b/packages/codec/package.json index 7c23977da..cb8c87ed0 100644 --- a/packages/codec/package.json +++ b/packages/codec/package.json @@ -45,7 +45,7 @@ ] }, "devDependencies": { - "@ckb-lumos/crypto": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.1", "escape-string-regexp": "^4.0.0", "js-yaml": "^4.1.0" } diff --git a/packages/common-scripts/package.json b/packages/common-scripts/package.json index b47576bd7..2c859ae44 100644 --- a/packages/common-scripts/package.json +++ b/packages/common-scripts/package.json @@ -55,7 +55,7 @@ ] }, "devDependencies": { - "@ckb-lumos/crypto": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.1", "@ckb-lumos/debugger": "0.23.0-next.1", "@ckb-lumos/hd": "0.23.0-next.1", "@types/keccak": "^3.0.1", diff --git a/packages/config-manager/package.json b/packages/config-manager/package.json index 541421749..39b893406 100644 --- a/packages/config-manager/package.json +++ b/packages/config-manager/package.json @@ -42,7 +42,7 @@ "deep-freeze-strict": "^1.1.1" }, "devDependencies": { - "@ckb-lumos/crypto": "0.23.0-next.0" + "@ckb-lumos/crypto": "0.23.0-next.1" }, "publishConfig": { "access": "public" diff --git a/packages/crypto/package.json b/packages/crypto/package.json index ae684058d..3e1a87a68 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -1,6 +1,6 @@ { "name": "@ckb-lumos/crypto", - "version": "0.23.0-next.0", + "version": "0.23.0-next.1", "description": "Crypto utilities used in Lumos", "author": "Tom Wang ", "homepage": "https://github.com/ckb-js/lumos#readme", diff --git a/packages/debugger/package.json b/packages/debugger/package.json index 0ab8f16a5..09b8f661c 100644 --- a/packages/debugger/package.json +++ b/packages/debugger/package.json @@ -24,7 +24,7 @@ "@ckb-lumos/base": "0.23.0-next.1", "@ckb-lumos/bi": "0.23.0-next.1", "@ckb-lumos/codec": "0.23.0-next.1", - "@ckb-lumos/crypto": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.1", "@ckb-lumos/config-manager": "0.23.0-next.1", "@ckb-lumos/helpers": "0.23.0-next.1", "@ckb-lumos/rpc": "0.23.0-next.1", diff --git a/packages/e2e-test/package.json b/packages/e2e-test/package.json index 866938ae8..b40b085d4 100644 --- a/packages/e2e-test/package.json +++ b/packages/e2e-test/package.json @@ -34,7 +34,7 @@ "@ckb-lumos/bi": "0.23.0-next.1", "@ckb-lumos/ckb-indexer": "0.23.0-next.1", "@ckb-lumos/codec": "0.23.0-next.1", - "@ckb-lumos/crypto": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.1", "@ckb-lumos/common-scripts": "0.23.0-next.1", "@ckb-lumos/config-manager": "0.23.0-next.1", "@ckb-lumos/hd": "0.23.0-next.1", diff --git a/packages/hd/package.json b/packages/hd/package.json index cedfe91c7..437e8dccb 100644 --- a/packages/hd/package.json +++ b/packages/hd/package.json @@ -21,7 +21,7 @@ "dependencies": { "@ckb-lumos/base": "0.23.0-next.1", "@ckb-lumos/bi": "0.23.0-next.1", - "@ckb-lumos/crypto": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.1", "bn.js": "^5.1.3", "elliptic": "^6.5.4", "scrypt-js": "^3.0.1", diff --git a/packages/helpers/package.json b/packages/helpers/package.json index 813b57f73..4cd554cbb 100644 --- a/packages/helpers/package.json +++ b/packages/helpers/package.json @@ -44,7 +44,7 @@ "immutable": "^4.3.0" }, "devDependencies": { - "@ckb-lumos/crypto": "0.23.0-next.0" + "@ckb-lumos/crypto": "0.23.0-next.1" }, "ava": { "extensions": [ diff --git a/packages/joyid/package.json b/packages/joyid/package.json index a4cf90dd3..83bfbdd67 100644 --- a/packages/joyid/package.json +++ b/packages/joyid/package.json @@ -30,7 +30,7 @@ }, "devDependencies": { "@ckb-lumos/bi": "0.23.0-next.1", - "@ckb-lumos/crypto": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.1", "sinon": "^15.0.4" }, "repository": { diff --git a/packages/lumos/package.json b/packages/lumos/package.json index 1cf7e423d..3477e9e39 100644 --- a/packages/lumos/package.json +++ b/packages/lumos/package.json @@ -29,7 +29,7 @@ "@ckb-lumos/bi": "0.23.0-next.1", "@ckb-lumos/ckb-indexer": "0.23.0-next.1", "@ckb-lumos/codec": "0.23.0-next.1", - "@ckb-lumos/crypto": "0.23.0-next.0", + "@ckb-lumos/crypto": "0.23.0-next.1", "@ckb-lumos/common-scripts": "0.23.0-next.1", "@ckb-lumos/config-manager": "0.23.0-next.1", "@ckb-lumos/hd": "0.23.0-next.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 52573445a..56f8c90a2 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -182,7 +182,7 @@ importers: version: 3.3.0 devDependencies: '@ckb-lumos/crypto': - specifier: 0.23.0-next.0 + specifier: 0.23.0-next.1 version: link:../crypto '@ckb-lumos/testkit': specifier: 0.23.0-next.1 @@ -216,7 +216,7 @@ importers: version: link:../bi devDependencies: '@ckb-lumos/crypto': - specifier: 0.23.0-next.0 + specifier: 0.23.0-next.1 version: link:../crypto escape-string-regexp: specifier: ^4.0.0 @@ -259,7 +259,7 @@ importers: version: 4.3.5 devDependencies: '@ckb-lumos/crypto': - specifier: 0.23.0-next.0 + specifier: 0.23.0-next.1 version: link:../crypto '@ckb-lumos/debugger': specifier: 0.23.0-next.1 @@ -302,7 +302,7 @@ importers: version: 1.1.1 devDependencies: '@ckb-lumos/crypto': - specifier: 0.23.0-next.0 + specifier: 0.23.0-next.1 version: link:../crypto packages/crypto: @@ -326,7 +326,7 @@ importers: specifier: 0.23.0-next.1 version: link:../config-manager '@ckb-lumos/crypto': - specifier: 0.23.0-next.0 + specifier: 0.23.0-next.1 version: link:../crypto '@ckb-lumos/helpers': specifier: 0.23.0-next.1 @@ -384,7 +384,7 @@ importers: specifier: 0.23.0-next.1 version: link:../config-manager '@ckb-lumos/crypto': - specifier: 0.23.0-next.0 + specifier: 0.23.0-next.1 version: link:../crypto '@ckb-lumos/hd': specifier: 0.23.0-next.1 @@ -463,7 +463,7 @@ importers: specifier: 0.23.0-next.1 version: link:../bi '@ckb-lumos/crypto': - specifier: 0.23.0-next.0 + specifier: 0.23.0-next.1 version: link:../crypto bn.js: specifier: ^5.1.3 @@ -550,7 +550,7 @@ importers: version: 4.3.5 devDependencies: '@ckb-lumos/crypto': - specifier: 0.23.0-next.0 + specifier: 0.23.0-next.1 version: link:../crypto packages/joyid: @@ -578,7 +578,7 @@ importers: specifier: 0.23.0-next.1 version: link:../bi '@ckb-lumos/crypto': - specifier: 0.23.0-next.0 + specifier: 0.23.0-next.1 version: link:../crypto sinon: specifier: ^15.0.4 @@ -639,7 +639,7 @@ importers: specifier: 0.23.0-next.1 version: link:../config-manager '@ckb-lumos/crypto': - specifier: 0.23.0-next.0 + specifier: 0.23.0-next.1 version: link:../crypto '@ckb-lumos/hd': specifier: 0.23.0-next.1 From 57977b850f69815077d67d458ed61fb0a78b3268 Mon Sep 17 00:00:00 2001 From: Tom Wang Date: Thu, 6 Jun 2024 14:06:27 +0800 Subject: [PATCH 12/12] chore: set lumos crypto to version 0.23.0 --- packages/codec/package.json | 2 +- packages/config-manager/package.json | 2 +- packages/crypto/package.json | 2 +- packages/helpers/package.json | 2 +- pnpm-lock.yaml | 20 ++++++++++---------- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/codec/package.json b/packages/codec/package.json index 68fa42282..09587705b 100644 --- a/packages/codec/package.json +++ b/packages/codec/package.json @@ -45,7 +45,7 @@ ] }, "devDependencies": { - "@ckb-lumos/crypto": "0.23.0-next.1", + "@ckb-lumos/crypto": "0.23.0", "escape-string-regexp": "^4.0.0", "js-yaml": "^4.1.0" } diff --git a/packages/config-manager/package.json b/packages/config-manager/package.json index 732f60d6a..23483f5be 100644 --- a/packages/config-manager/package.json +++ b/packages/config-manager/package.json @@ -42,7 +42,7 @@ "deep-freeze-strict": "^1.1.1" }, "devDependencies": { - "@ckb-lumos/crypto": "0.23.0-next.1" + "@ckb-lumos/crypto": "0.23.0" }, "publishConfig": { "access": "public" diff --git a/packages/crypto/package.json b/packages/crypto/package.json index 3e1a87a68..8fd595159 100644 --- a/packages/crypto/package.json +++ b/packages/crypto/package.json @@ -1,6 +1,6 @@ { "name": "@ckb-lumos/crypto", - "version": "0.23.0-next.1", + "version": "0.23.0", "description": "Crypto utilities used in Lumos", "author": "Tom Wang ", "homepage": "https://github.com/ckb-js/lumos#readme", diff --git a/packages/helpers/package.json b/packages/helpers/package.json index 3a4316d69..63d369c05 100644 --- a/packages/helpers/package.json +++ b/packages/helpers/package.json @@ -44,7 +44,7 @@ "immutable": "^4.3.0" }, "devDependencies": { - "@ckb-lumos/crypto": "0.23.0-next.1" + "@ckb-lumos/crypto": "0.23.0" }, "ava": { "extensions": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 21b7c2a2d..671deca84 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -182,7 +182,7 @@ importers: version: 3.3.0 devDependencies: '@ckb-lumos/crypto': - specifier: 0.23.0-next.1 + specifier: 0.23.0 version: link:../crypto '@ckb-lumos/testkit': specifier: 0.23.0 @@ -216,7 +216,7 @@ importers: version: link:../bi devDependencies: '@ckb-lumos/crypto': - specifier: 0.23.0-next.1 + specifier: 0.23.0 version: link:../crypto escape-string-regexp: specifier: ^4.0.0 @@ -259,7 +259,7 @@ importers: version: 4.3.5 devDependencies: '@ckb-lumos/crypto': - specifier: 0.23.0-next.1 + specifier: 0.23.0 version: link:../crypto '@ckb-lumos/debugger': specifier: 0.23.0 @@ -302,7 +302,7 @@ importers: version: 1.1.1 devDependencies: '@ckb-lumos/crypto': - specifier: 0.23.0-next.1 + specifier: 0.23.0 version: link:../crypto packages/crypto: @@ -326,7 +326,7 @@ importers: specifier: 0.23.0 version: link:../config-manager '@ckb-lumos/crypto': - specifier: 0.23.0-next.1 + specifier: 0.23.0 version: link:../crypto '@ckb-lumos/helpers': specifier: 0.23.0 @@ -384,7 +384,7 @@ importers: specifier: 0.23.0 version: link:../config-manager '@ckb-lumos/crypto': - specifier: 0.23.0-next.1 + specifier: 0.23.0 version: link:../crypto '@ckb-lumos/hd': specifier: 0.23.0 @@ -463,7 +463,7 @@ importers: specifier: 0.23.0 version: link:../bi '@ckb-lumos/crypto': - specifier: 0.23.0-next.1 + specifier: 0.23.0 version: link:../crypto bn.js: specifier: ^5.1.3 @@ -550,7 +550,7 @@ importers: version: 4.3.5 devDependencies: '@ckb-lumos/crypto': - specifier: 0.23.0-next.1 + specifier: 0.23.0 version: link:../crypto packages/joyid: @@ -578,7 +578,7 @@ importers: specifier: 0.23.0 version: link:../bi '@ckb-lumos/crypto': - specifier: 0.23.0-next.1 + specifier: 0.23.0 version: link:../crypto sinon: specifier: ^15.0.4 @@ -639,7 +639,7 @@ importers: specifier: 0.23.0 version: link:../config-manager '@ckb-lumos/crypto': - specifier: 0.23.0-next.1 + specifier: 0.23.0 version: link:../crypto '@ckb-lumos/hd': specifier: 0.23.0