From 0b2b5cd2030a5553685edb7bb5607984ec12c5b1 Mon Sep 17 00:00:00 2001 From: homura Date: Thu, 30 May 2024 13:50:09 +0900 Subject: [PATCH 1/6] feat(common-scripts): disallow p2sh converting by default since risky --- .changeset/cyan-geese-relate.md | 5 -- .changeset/green-pumpkins-build.md | 5 ++ .../common-scripts/src/omnilock-bitcoin.ts | 80 +++++++------------ packages/common-scripts/src/omnilock.ts | 67 +++------------- .../tests/omnilock-bitcoin.test.ts | 27 +++++-- website/docs/migrations/migrate-to-v0.23.md | 15 ++++ 6 files changed, 84 insertions(+), 115 deletions(-) delete mode 100644 .changeset/cyan-geese-relate.md create mode 100644 .changeset/green-pumpkins-build.md diff --git a/.changeset/cyan-geese-relate.md b/.changeset/cyan-geese-relate.md deleted file mode 100644 index e86d32e1d..000000000 --- a/.changeset/cyan-geese-relate.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -"@ckb-lumos/common-scripts": minor ---- - -feat: deprecated omnilock btc auth with p2sh diff --git a/.changeset/green-pumpkins-build.md b/.changeset/green-pumpkins-build.md new file mode 100644 index 000000000..e751b6fce --- /dev/null +++ b/.changeset/green-pumpkins-build.md @@ -0,0 +1,5 @@ +--- +"@ckb-lumos/common-scripts": minor +--- + +**BREAKING CHANGE**: `allowP2SH` is required in `createOmnilockScript` to convert p2sh addresses diff --git a/packages/common-scripts/src/omnilock-bitcoin.ts b/packages/common-scripts/src/omnilock-bitcoin.ts index 8097079e7..f3457c8c6 100644 --- a/packages/common-scripts/src/omnilock-bitcoin.ts +++ b/packages/common-scripts/src/omnilock-bitcoin.ts @@ -7,69 +7,49 @@ const BTC_PREFIX = "CKB (Bitcoin Layer) transaction: 0x"; /** * Decode bitcoin address to public key hash in bytes - * @deprecated please migrate to {@link parseAddressToPublicKeyHash} * @see https://en.bitcoin.it/wiki/List_of_address_prefixes * @param address + * @param allowP2SH defaults to false */ -export function decodeAddress(address: string): ArrayLike { +export function decodeAddress( + address: string, + allowP2SH?: boolean +): ArrayLike { const btcAddressFlagSize = 1; const hashSize = 20; - try { - // Bech32 - if (address.startsWith("bc1q")) { - return bech32.fromWords(bech32.decode(address).words.slice(1)); - } - - // P2PKH - if (address.startsWith("1")) { - return bs58 - .decode(address) - .slice(btcAddressFlagSize, btcAddressFlagSize + hashSize); - } - - // P2SH - if (address.startsWith("3")) { - return bs58 - .decode(address) - .slice(btcAddressFlagSize, btcAddressFlagSize + hashSize); - } - } catch { - // https://bitcoin.design/guide/glossary/address/#taproot-address---p2tr - if (address.startsWith("bc1p")) { - throw new Error("Taproot address is not supported yet."); - } + if (isP2wpkhAddress(address)) { + return bech32.fromWords(bech32.decode(address).words.slice(1)); } - throw new Error( - `Unsupported bitcoin address ${address}, only 1...(P2PKH) 3...(P2SH), and bc1...(Bech32) are supported.` - ); -} + if (isP2pkhAddress(address)) { + return bs58 + .decode(address) + .slice(btcAddressFlagSize, btcAddressFlagSize + hashSize); + } -export function parseAddressToPublicKeyHash( - address: string -): ArrayLike { - try { - // Bech32 - if (isP2wpkhAddress(address)) { - return bech32.fromWords(bech32.decode(address).words.slice(1)); + if (isP2shAddress(address)) { + if (!allowP2SH) { + throw new Error( + "'allowP2SH' must be true to enable decoding the P2SH address" + ); } - // P2PKH - if (isP2pkhAddress(address)) { - const networkSize = 1; - const pubkeyHashSize = 20; - // public key hash - // a P2PKH address is composed of network(1 byte) + pubkey hash(20 bytes) - return bs58 - .decode(address) - .slice(networkSize, networkSize + pubkeyHashSize); - } - } catch { - // do nothing here, throw an error below + return bs58 + .decode(address) + .slice(btcAddressFlagSize, btcAddressFlagSize + hashSize); } - throw new Error("Only supports Native Segwit(P2WPKH) and Legacy(P2PKH)"); + // https://bitcoin.design/guide/glossary/address/#taproot-address---p2tr + if (address.startsWith("bc1p")) { + throw new Error("Taproot address is not supported yet."); + } + + throw new Error( + "Unsupported address: " + + address + + "Only Native SegWit(P2WPKH) and Legacy(P2PKH) addresses are supported" + ); } export interface Provider { diff --git a/packages/common-scripts/src/omnilock.ts b/packages/common-scripts/src/omnilock.ts index a88ff4330..8bd5a7efe 100644 --- a/packages/common-scripts/src/omnilock.ts +++ b/packages/common-scripts/src/omnilock.ts @@ -75,6 +75,14 @@ export type IdentityBitcoin = { * `Bech32(bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4)` */ content: string; + + /** + * defaults to false. + * when it is true, the P2SH address will be allowed for an Omnilock. + * make sure that the P2SH address is a P2SH-P2WPKH address, + * or the script CANNOT be unlocked + */ + allowP2SH?: boolean; }; export type IdentitySolana = { @@ -111,7 +119,6 @@ const ED25519_SIGNATURE_PLACEHOLDER_LENGTH = 96; /** * Create an Omnilock script based on other networks' wallet - * @deprecated please migrate to {@link createSimplePublicKeyBasedOmnilockScript} * @see https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0042-omnilock/0042-omnilock.md * @param omnilockInfo * @param options @@ -137,58 +144,6 @@ export function createOmnilockScript( ): Script { const config = options?.config || getConfig(); const omnilockConfig = config.SCRIPTS.OMNILOCK; - - if (!omnilockConfig) { - throw new Error("OMNILOCK script config not found."); - } - - const defaultOmnilockArgs = 0b00000000; - const omnilockArgs = [defaultOmnilockArgs]; - - if (omnilockInfo.auth.flag === "BITCOIN") { - return { - codeHash: omnilockConfig.CODE_HASH, - hashType: omnilockConfig.HASH_TYPE, - args: bytes.hexify( - bytes.concat( - [IdentityFlagsType.IdentityFlagsBitcoin], - bitcoin.decodeAddress(omnilockInfo.auth.content), - omnilockArgs - ) - ), - }; - } - - return createSimplePublicKeyBasedOmnilockScript(omnilockInfo, options); -} - -/** - * Create an Omnilock script based on other networks' wallet - * @see https://github.com/nervosnetwork/rfcs/blob/master/rfcs/0042-omnilock/0042-omnilock.md - * @param omnilockInfo - * @param options - * @returns - * @example - * // create an omnilock to work with MetaMask wallet - * createOmnilockScript({ - * auth: { - * flag: "ETHEREUM", - * content: "an ethereum address here", - * }, { config }) - * // or we can create an omnilock to work with UniSat wallet - * createOmnilockScript({ - * auth: { - * flag: "BITCOIN", - * content: "a bitcoin address here", - * } - * }, {config}) - */ -export function createSimplePublicKeyBasedOmnilockScript( - omnilockInfo: OmnilockInfo, - options?: Options -): Script { - const config = options?.config || getConfig(); - const omnilockConfig = config.SCRIPTS.OMNILOCK; if (!omnilockConfig) { throw new Error("OMNILOCK script config not found."); } @@ -229,7 +184,10 @@ export function createSimplePublicKeyBasedOmnilockScript( return bytes.hexify( bytes.concat( [IdentityFlagsType.IdentityFlagsBitcoin], - bitcoin.parseAddressToPublicKeyHash(omnilockInfo.auth.content), + bitcoin.decodeAddress( + omnilockInfo.auth.content, + omnilockInfo.auth.allowP2SH + ), omnilockArgs ) ); @@ -506,5 +464,4 @@ export default { CellCollector, OmnilockWitnessLock, createOmnilockScript, - createSimplePublicKeyBasedOmnilockScript, }; diff --git a/packages/common-scripts/tests/omnilock-bitcoin.test.ts b/packages/common-scripts/tests/omnilock-bitcoin.test.ts index 1c9e3c4eb..5c033024c 100644 --- a/packages/common-scripts/tests/omnilock-bitcoin.test.ts +++ b/packages/common-scripts/tests/omnilock-bitcoin.test.ts @@ -9,14 +9,12 @@ import { blockchain, utils } from "@ckb-lumos/base"; import { bytes } from "@ckb-lumos/codec"; import { common } from "../src"; import { mockOutPoint } from "@ckb-lumos/debugger/lib/context"; -import { - createSimplePublicKeyBasedOmnilockScript, - OmnilockWitnessLock, -} from "../src/omnilock"; +import { createOmnilockScript, OmnilockWitnessLock } from "../src/omnilock"; import { address, AddressType, core, keyring } from "@unisat/wallet-sdk"; import { NetworkType } from "@unisat/wallet-sdk/lib/network"; import { Provider, signMessage } from "../src/omnilock-bitcoin"; import { SimpleKeyring } from "@unisat/wallet-sdk/lib/keyring"; +import { randomBytes } from "node:crypto"; test.before(async () => { await new CKBDebuggerDownloader().downloadIfNotExists(); @@ -106,7 +104,7 @@ function makeProvider( async function setupTxSkeleton(addr: string) { const txSkeleton = TransactionSkeleton().asMutable(); - const lock = createSimplePublicKeyBasedOmnilockScript( + const lock = createOmnilockScript( { auth: { flag: "BITCOIN", content: addr } }, { config: managerConfig } ); @@ -125,3 +123,22 @@ async function setupTxSkeleton(addr: string) { common.prepareSigningEntries(txSkeleton, { config: managerConfig }); return { txSkeleton: txSkeleton, lock }; } + +test.serial("Omnilock#Bitcoin P2SH", (t) => { + const p2shAddr = address.publicKeyToAddress( + // 02 indicates that the pubkey is compressed + "02" + randomBytes(32).toString("hex"), + AddressType.P2SH_P2WPKH, + NetworkType.MAINNET + ); + + t.throws(() => + createOmnilockScript({ auth: { flag: "BITCOIN", content: p2shAddr } }) + ); + + t.notThrows(() => + createOmnilockScript({ + auth: { flag: "BITCOIN", content: p2shAddr, allowP2SH: true }, + }) + ); +}); diff --git a/website/docs/migrations/migrate-to-v0.23.md b/website/docs/migrations/migrate-to-v0.23.md index b062d63bb..d415d4c00 100644 --- a/website/docs/migrations/migrate-to-v0.23.md +++ b/website/docs/migrations/migrate-to-v0.23.md @@ -28,6 +28,21 @@ Please migrate to `loadFromKeystoreJson` + JSON.parse(fs.readFileSync(path).toString()) ``` +## P2SH Address To Omnilock Is Not Allowed By Default + +Converting a P2SH address to an Omnilock script is not allowed by default in Lumos because it is risky. It cannot be unlocked if a P2SH is not a P2SH-P2WPKH address. + +```diff +createOmnilockScript({ + auth: { + flag: "BITCOIN", + content: "3...", // P2SH address ++ allowP2SH: true, + } +}) + +``` + --- ## Common Methods For CKB-Related Objects From d99ac4a1df918f6d2760e137ed8722d8487a73b7 Mon Sep 17 00:00:00 2001 From: homura Date: Thu, 30 May 2024 14:18:25 +0900 Subject: [PATCH 2/6] test(common-scripts): cases for unsupported btc addr --- .../tests/omnilock-bitcoin.test.ts | 32 ++++++++++++++++--- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/packages/common-scripts/tests/omnilock-bitcoin.test.ts b/packages/common-scripts/tests/omnilock-bitcoin.test.ts index 5c033024c..2a7eb581e 100644 --- a/packages/common-scripts/tests/omnilock-bitcoin.test.ts +++ b/packages/common-scripts/tests/omnilock-bitcoin.test.ts @@ -14,7 +14,6 @@ import { address, AddressType, core, keyring } from "@unisat/wallet-sdk"; import { NetworkType } from "@unisat/wallet-sdk/lib/network"; import { Provider, signMessage } from "../src/omnilock-bitcoin"; import { SimpleKeyring } from "@unisat/wallet-sdk/lib/keyring"; -import { randomBytes } from "node:crypto"; test.before(async () => { await new CKBDebuggerDownloader().downloadIfNotExists(); @@ -124,10 +123,13 @@ async function setupTxSkeleton(addr: string) { return { txSkeleton: txSkeleton, lock }; } -test.serial("Omnilock#Bitcoin P2SH", (t) => { +// 02 indicates that the pubkey is compressed +const pubkey = + "02b602ad190efb7b4f520068e3f8ecf573823d9e2557c5229231b4e14b79bbc0d8"; + +test("Omnilock#Bitcoin P2SH", (t) => { const p2shAddr = address.publicKeyToAddress( - // 02 indicates that the pubkey is compressed - "02" + randomBytes(32).toString("hex"), + pubkey, AddressType.P2SH_P2WPKH, NetworkType.MAINNET ); @@ -142,3 +144,25 @@ test.serial("Omnilock#Bitcoin P2SH", (t) => { }) ); }); + +test("Unsupported BTC address", (t) => { + const p2trAddr = address.publicKeyToAddress( + pubkey, + AddressType.P2TR, + NetworkType.MAINNET + ); + + t.throws(() => + createOmnilockScript({ auth: { flag: "BITCOIN", content: p2trAddr } }) + ); + + const unknownAddr = address.publicKeyToAddress( + pubkey, + AddressType.UNKNOWN, + NetworkType.MAINNET + ); + + t.throws(() => + createOmnilockScript({ auth: { flag: "BITCOIN", content: unknownAddr } }) + ); +}); From a169d35d4e841c9f76d67dcc6fa0607b94d2b5c4 Mon Sep 17 00:00:00 2001 From: homura Date: Thu, 13 Jun 2024 17:17:57 +0900 Subject: [PATCH 3/6] feat(common-scripts): whitelist to disallow p2sh by default --- .changeset/green-pumpkins-build.md | 2 +- .eslintrc.next.js | 1 + .../common-scripts/src/omnilock-bitcoin.ts | 24 ++++++++++--------- packages/common-scripts/src/omnilock.ts | 13 +++++----- .../tests/omnilock-bitcoin.test.ts | 21 ++++++++++------ website/docs/migrations/migrate-to-v0.24.md | 19 +++++++++++++++ 6 files changed, 55 insertions(+), 25 deletions(-) create mode 100644 website/docs/migrations/migrate-to-v0.24.md diff --git a/.changeset/green-pumpkins-build.md b/.changeset/green-pumpkins-build.md index e751b6fce..d022cc0a9 100644 --- a/.changeset/green-pumpkins-build.md +++ b/.changeset/green-pumpkins-build.md @@ -2,4 +2,4 @@ "@ckb-lumos/common-scripts": minor --- -**BREAKING CHANGE**: `allowP2SH` is required in `createOmnilockScript` to convert p2sh addresses +**BREAKING CHANGE**: `createOmnilockScript` uses the `allow` option to restrict allowed btc addresses diff --git a/.eslintrc.next.js b/.eslintrc.next.js index 240fa6c24..7905fb589 100644 --- a/.eslintrc.next.js +++ b/.eslintrc.next.js @@ -23,6 +23,7 @@ module.exports = { -1, // index -1 is not found 0, // first element of an array 1, // common for i + 1 in a loop + 2, // slice(2) for string that starts with "0x" is common to work with 3rd-party libs 16, // toString(16) 1000, // second to millisecond ], diff --git a/packages/common-scripts/src/omnilock-bitcoin.ts b/packages/common-scripts/src/omnilock-bitcoin.ts index f3457c8c6..a250294c0 100644 --- a/packages/common-scripts/src/omnilock-bitcoin.ts +++ b/packages/common-scripts/src/omnilock-bitcoin.ts @@ -2,6 +2,8 @@ import { bytes, BytesLike } from "@ckb-lumos/codec"; import { bech32 } from "bech32"; import bs58 from "bs58"; +export type SupportedBtcAddressType = "P2SH-P2WPKH" | "P2WPKH" | "P2PKH"; + // https://github.com/cryptape/omnilock/blob/9419b7795641da0ade25a04127e25d8a0b709077/c/ckb_identity.h#L28 const BTC_PREFIX = "CKB (Bitcoin Layer) transaction: 0x"; @@ -9,35 +11,35 @@ const BTC_PREFIX = "CKB (Bitcoin Layer) transaction: 0x"; * Decode bitcoin address to public key hash in bytes * @see https://en.bitcoin.it/wiki/List_of_address_prefixes * @param address - * @param allowP2SH defaults to false + * @param allows */ export function decodeAddress( address: string, - allowP2SH?: boolean + allows: SupportedBtcAddressType[] ): ArrayLike { const btcAddressFlagSize = 1; const hashSize = 20; - if (isP2wpkhAddress(address)) { + if (isP2wpkhAddress(address) && allows.includes("P2WPKH")) { return bech32.fromWords(bech32.decode(address).words.slice(1)); } - if (isP2pkhAddress(address)) { + if (isP2pkhAddress(address) && allows.includes("P2PKH")) { return bs58 .decode(address) .slice(btcAddressFlagSize, btcAddressFlagSize + hashSize); } if (isP2shAddress(address)) { - if (!allowP2SH) { - throw new Error( - "'allowP2SH' must be true to enable decoding the P2SH address" - ); + if (allows.includes("P2SH-P2WPKH")) { + return bs58 + .decode(address) + .slice(btcAddressFlagSize, btcAddressFlagSize + hashSize); } - return bs58 - .decode(address) - .slice(btcAddressFlagSize, btcAddressFlagSize + hashSize); + throw new Error( + "'P2SH-P2WPKH' must be included in the 'allows' for the P2SH address" + ); } // https://bitcoin.design/guide/glossary/address/#taproot-address---p2tr diff --git a/packages/common-scripts/src/omnilock.ts b/packages/common-scripts/src/omnilock.ts index 8bd5a7efe..241601607 100644 --- a/packages/common-scripts/src/omnilock.ts +++ b/packages/common-scripts/src/omnilock.ts @@ -38,6 +38,7 @@ import * as bitcoin from "./omnilock-bitcoin"; import * as solana from "./omnilock-solana"; import { decode as bs58Decode } from "bs58"; import { ckbHash } from "@ckb-lumos/base/lib/utils"; +import { SupportedBtcAddressType } from "./omnilock-bitcoin"; const { ScriptValue } = values; @@ -66,6 +67,7 @@ export type IdentityEthereum = { */ content: BytesLike; }; + export type IdentityBitcoin = { flag: "BITCOIN"; /** @@ -77,12 +79,11 @@ export type IdentityBitcoin = { content: string; /** - * defaults to false. - * when it is true, the P2SH address will be allowed for an Omnilock. - * make sure that the P2SH address is a P2SH-P2WPKH address, - * or the script CANNOT be unlocked + * Allows the P2PKH and P2WPKH by default. + * To allow the P2SH-P2WPKH address, + * change this option to `["P2PKH", "P2WPKH", "P2SH-P2WPKH"]` */ - allowP2SH?: boolean; + allows?: SupportedBtcAddressType[]; }; export type IdentitySolana = { @@ -186,7 +187,7 @@ export function createOmnilockScript( [IdentityFlagsType.IdentityFlagsBitcoin], bitcoin.decodeAddress( omnilockInfo.auth.content, - omnilockInfo.auth.allowP2SH + omnilockInfo.auth.allows || ["P2WPKH", "P2PKH"] ), omnilockArgs ) diff --git a/packages/common-scripts/tests/omnilock-bitcoin.test.ts b/packages/common-scripts/tests/omnilock-bitcoin.test.ts index 806f07123..415255b63 100644 --- a/packages/common-scripts/tests/omnilock-bitcoin.test.ts +++ b/packages/common-scripts/tests/omnilock-bitcoin.test.ts @@ -12,7 +12,11 @@ import { mockOutPoint } from "@ckb-lumos/debugger/lib/context"; import { createOmnilockScript, OmnilockWitnessLock } from "../src/omnilock"; import { address, AddressType, core, keyring } from "@unisat/wallet-sdk"; import { NetworkType } from "@unisat/wallet-sdk/lib/network"; -import { Provider, signMessage } from "../src/omnilock-bitcoin"; +import { + Provider, + signMessage, + SupportedBtcAddressType, +} from "../src/omnilock-bitcoin"; import { SimpleKeyring } from "@unisat/wallet-sdk/lib/keyring"; test.before(async () => { @@ -41,15 +45,15 @@ test.serial("Omnilock#Bitcoin P2WPKH", async (t) => { test.serial("Omnilock#Bitcoin P2SH_P2WPKH", async (t) => { const { provider } = makeProvider(AddressType.P2SH_P2WPKH); - const result = await execute(provider); + const result = await execute(provider, ["P2SH-P2WPKH"]); t.is(result.code, 0, result.message); }); -async function execute(provider: Provider) { +async function execute(provider: Provider, allows?: SupportedBtcAddressType[]) { const addr = (await provider.requestAccounts())[0]; - const { txSkeleton, lock } = await setupTxSkeleton(addr); + const { txSkeleton, lock } = await setupTxSkeleton(addr, allows); const message = txSkeleton.get("signingEntries").get(0)!.message; const signature = await signMessage(message, "ecdsa", provider); @@ -95,11 +99,14 @@ function makeProvider(addressType: AddressType): { }; } -async function setupTxSkeleton(addr: string) { +async function setupTxSkeleton( + addr: string, + allows?: SupportedBtcAddressType[] +) { const txSkeleton = TransactionSkeleton().asMutable(); const lock = createOmnilockScript( - { auth: { flag: "BITCOIN", content: addr } }, + { auth: { flag: "BITCOIN", content: addr, allows } }, { config: managerConfig } ); @@ -135,7 +142,7 @@ test("Omnilock#Bitcoin P2SH", (t) => { t.notThrows(() => createOmnilockScript({ - auth: { flag: "BITCOIN", content: p2shAddr, allowP2SH: true }, + auth: { flag: "BITCOIN", content: p2shAddr, allows: ["P2SH-P2WPKH"] }, }) ); }); diff --git a/website/docs/migrations/migrate-to-v0.24.md b/website/docs/migrations/migrate-to-v0.24.md new file mode 100644 index 000000000..faf4b1df6 --- /dev/null +++ b/website/docs/migrations/migrate-to-v0.24.md @@ -0,0 +1,19 @@ +# Migrate to Lumos v0.24 + +## Disallow the Omnilock P2SH Address by Default + +The default options of `createOmnilockScript` disallows the use of P2SH addresses for security reasons. +Not all P2SH addresses are P2SH-P2WPKH addresses. +This means that developers may unintentionally use a non-P2SH-P2WPKH address to convert to an Omnilock script, +which can lead to the script not being lockable. +If you still need to use a P2SH address, use the following code + +```diff +createOmnilockScript({ + auth: { + flag: "BITCOIN", + content: addr, ++ allows: ["P2WPKH", "P2PKH", "P2SH-P2WPKH"] + } +}) +``` From 664e8104e2a077e2294cf7b0c0990e1a2cd4aa39 Mon Sep 17 00:00:00 2001 From: homura Date: Thu, 13 Jun 2024 18:37:26 +0900 Subject: [PATCH 4/6] chore: typo in changeset --- .changeset/green-pumpkins-build.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.changeset/green-pumpkins-build.md b/.changeset/green-pumpkins-build.md index d022cc0a9..82f4b422c 100644 --- a/.changeset/green-pumpkins-build.md +++ b/.changeset/green-pumpkins-build.md @@ -2,4 +2,4 @@ "@ckb-lumos/common-scripts": minor --- -**BREAKING CHANGE**: `createOmnilockScript` uses the `allow` option to restrict allowed btc addresses +**BREAKING CHANGE**: `createOmnilockScript` uses the `allows` option to restrict allowed btc addresses From 1737c2ffa308183bd6ac7c64c63d3f97ad1c0b14 Mon Sep 17 00:00:00 2001 From: homura Date: Fri, 14 Jun 2024 09:39:20 +0900 Subject: [PATCH 5/6] refactor(common-scripts): default allowlist for bitcoin address decoder --- packages/common-scripts/src/omnilock-bitcoin.ts | 2 +- packages/common-scripts/src/omnilock.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/common-scripts/src/omnilock-bitcoin.ts b/packages/common-scripts/src/omnilock-bitcoin.ts index a250294c0..718ba7e96 100644 --- a/packages/common-scripts/src/omnilock-bitcoin.ts +++ b/packages/common-scripts/src/omnilock-bitcoin.ts @@ -15,7 +15,7 @@ const BTC_PREFIX = "CKB (Bitcoin Layer) transaction: 0x"; */ export function decodeAddress( address: string, - allows: SupportedBtcAddressType[] + allows: SupportedBtcAddressType[] = ["P2WPKH", "P2PKH"] ): ArrayLike { const btcAddressFlagSize = 1; const hashSize = 20; diff --git a/packages/common-scripts/src/omnilock.ts b/packages/common-scripts/src/omnilock.ts index 241601607..c1d6dc5d8 100644 --- a/packages/common-scripts/src/omnilock.ts +++ b/packages/common-scripts/src/omnilock.ts @@ -187,7 +187,7 @@ export function createOmnilockScript( [IdentityFlagsType.IdentityFlagsBitcoin], bitcoin.decodeAddress( omnilockInfo.auth.content, - omnilockInfo.auth.allows || ["P2WPKH", "P2PKH"] + omnilockInfo.auth.allows ), omnilockArgs ) From b6845aca394f238055883aaa5c3e137f93b8e5f3 Mon Sep 17 00:00:00 2001 From: homura Date: Fri, 14 Jun 2024 09:41:21 +0900 Subject: [PATCH 6/6] refactor(common-scripts): friendly error message --- .../common-scripts/src/omnilock-bitcoin.ts | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/packages/common-scripts/src/omnilock-bitcoin.ts b/packages/common-scripts/src/omnilock-bitcoin.ts index 718ba7e96..d576dcee9 100644 --- a/packages/common-scripts/src/omnilock-bitcoin.ts +++ b/packages/common-scripts/src/omnilock-bitcoin.ts @@ -20,26 +20,23 @@ export function decodeAddress( const btcAddressFlagSize = 1; const hashSize = 20; - if (isP2wpkhAddress(address) && allows.includes("P2WPKH")) { + if (isP2wpkhAddress(address)) { + assertAddressType(allows, "P2WPKH"); return bech32.fromWords(bech32.decode(address).words.slice(1)); } - if (isP2pkhAddress(address) && allows.includes("P2PKH")) { + if (isP2pkhAddress(address)) { + assertAddressType(allows, "P2PKH"); return bs58 .decode(address) .slice(btcAddressFlagSize, btcAddressFlagSize + hashSize); } if (isP2shAddress(address)) { - if (allows.includes("P2SH-P2WPKH")) { - return bs58 - .decode(address) - .slice(btcAddressFlagSize, btcAddressFlagSize + hashSize); - } - - throw new Error( - "'P2SH-P2WPKH' must be included in the 'allows' for the P2SH address" - ); + assertAddressType(allows, "P2SH-P2WPKH"); + return bs58 + .decode(address) + .slice(btcAddressFlagSize, btcAddressFlagSize + hashSize); } // https://bitcoin.design/guide/glossary/address/#taproot-address---p2tr @@ -54,6 +51,17 @@ export function decodeAddress( ); } +function assertAddressType( + allows: SupportedBtcAddressType[], + usingAddressType: SupportedBtcAddressType +): void { + if (!allows.includes(usingAddressType)) { + throw new Error( + `'${usingAddressType}' must be included in the 'allows' for the address` + ); + } +} + export interface Provider { requestAccounts(): Promise; signMessage(message: string, type?: "ecdsa"): Promise;