From 7c8f6c871539859fc9c547a73d6bf4e05ce7674b Mon Sep 17 00:00:00 2001 From: ian Date: Tue, 9 Jan 2024 17:22:21 +0800 Subject: [PATCH] :sparkles: Migrate to Omnilock What's changed: - Switch to the deployment information of Omnilock - args: append 00. It is the omni lock flag byte, which indicate there's no advanced omni lock features been used. - `WitnessArgs.lock` size: 65 to 85, this is the size of a `OmnilockWitnessLock` to only save a 65-byte signature. - witness: instead of storing the 65-byte signature directly into `WitnessArgs.lock`, pack it into a `OmnilockWitnessLock`. Omnilock Contract Error Codes For Reference: - 8: args format is wrong - 5: `WitnessArgs.lock` is not a valid `OmnilockWitnessLock` --- .gitignore | 2 +- bin/deploy-to-dev-chain.sh | 2 +- bin/dev-faucet.sh | 7 +++++ bin/download-contracts.sh | 3 +- bin/use-env.sh | 10 +++---- docs/dev.md | 2 +- migrations/templates/ckb_auth.toml | 19 ------------ migrations/templates/omnilock.toml | 10 +++++++ src/lib/cobuild/fee-manager.js | 7 +++-- src/lib/cobuild/lock-actions.js | 7 +++-- .../cobuild/react/building-packet-review.js | 10 +++++++ src/lib/config.js | 30 ++++++++----------- .../init-lumos-common-scripts.js | 19 +++++------- .../pay-fee-with-building-packet.js | 4 --- src/lib/wallet/btc-wallet.js | 10 +++---- src/lib/wallet/joyid.js | 1 + src/lib/wallet/omni-lock.js | 29 ++++++++++++++++++ src/lib/wallet/selector.js | 4 +++ src/lib/wallet/unisat.js | 3 +- 19 files changed, 107 insertions(+), 72 deletions(-) create mode 100755 bin/dev-faucet.sh delete mode 100644 migrations/templates/ckb_auth.toml create mode 100644 migrations/templates/omnilock.toml create mode 100644 src/lib/wallet/omni-lock.js diff --git a/.gitignore b/.gitignore index 0b4e30f..7f42068 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ .env.* /migrations/dev /migrations/joyid -/migrations/ckb_auth +/migrations/omnilock # CKB /ckb-miner.toml diff --git a/bin/deploy-to-dev-chain.sh b/bin/deploy-to-dev-chain.sh index fd08994..0ba0351 100755 --- a/bin/deploy-to-dev-chain.sh +++ b/bin/deploy-to-dev-chain.sh @@ -40,7 +40,7 @@ bin/generate-blocks.sh 4 sleep 1 # try twice in case the indexer has not updated yet -deploy ckb_auth || deploy ckb_auth +deploy omnilock || deploy omnilock bin/generate-blocks.sh 4 bin/use-env.sh >.env diff --git a/bin/dev-faucet.sh b/bin/dev-faucet.sh new file mode 100755 index 0000000..5517e3c --- /dev/null +++ b/bin/dev-faucet.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +set -e +set -u +[ -n "${DEBUG:-}" ] && set -x || true + +ckb-cli wallet transfer --skip-check-to-address --to-address "$1" --capacity 300000 --privkey-path specs/miner.key diff --git a/bin/download-contracts.sh b/bin/download-contracts.sh index dc5ce1c..cfdac7c 100755 --- a/bin/download-contracts.sh +++ b/bin/download-contracts.sh @@ -30,5 +30,4 @@ download joyid_dep3 0x95ecf9b41701b45d431657a67bbfa3f07ef7ceb53bf87097f3674e1a4a # download joyid_dep4 0x8f8c79eb6671709633fe6a46de93c0fedc9c1b8a6527a18d3983879542635c9f 3 download joyid_dep5 0x8b3255491f3c4dcc1cfca33d5c6bcaec5409efe4bbda243900f9580c47e0242e 1 -download ckb_auth 0xd4f72f0504373ff8effadf44f92c46a0062774fb585ebcacc24eb47b98e2d66a 0 -download unisat_lock 0xe842b43df31c92d448fa345d60a6df3e03aaab19ef88921654bf95c673a26872 0 +download omnilock 0xff234bf2fb0ad2ab5b356ceda317d3dee3efb2c55b9427ef55d9dcbf6eecbf9f 0 diff --git a/bin/use-env.sh b/bin/use-env.sh index feb0688..c794482 100755 --- a/bin/use-env.sh +++ b/bin/use-env.sh @@ -24,7 +24,7 @@ case "${1:-}" in esac JOYID_INFO_FILE="$(ls migrations/joyid/*.json | grep -v deployment | head -n 1)" -CKB_AUTH_INFO_FILE="$(ls migrations/ckb_auth/*.json | grep -v deployment | head -n 1)" +OMNILOCK_INFO_FILE="$(ls migrations/omnilock/*.json | grep -v deployment | head -n 1)" sed -n \ -e 's/,$//' \ @@ -38,10 +38,10 @@ sed -n \ sed -n \ -e 's/,$//' \ - -e 's/^ *"type_id": "/NEXT_PUBLIC_UNISAT_CODE_HASH="/p' \ - "$CKB_AUTH_INFO_FILE" | head -1 + -e 's/^ *"type_id": "/NEXT_PUBLIC_OMNILOCK_CODE_HASH="/p' \ + "$OMNILOCK_INFO_FILE" | head -1 sed -n \ -e 's/,$//' \ - -e 's/^ *"tx_hash": /NEXT_PUBLIC_AUTH_TX_HASH=/p' \ - "$CKB_AUTH_INFO_FILE" | tail -1 + -e 's/^ *"tx_hash": /NEXT_PUBLIC_OMNILOCK_TX_HASH=/p' \ + "$OMNILOCK_INFO_FILE" | tail -1 diff --git a/docs/dev.md b/docs/dev.md index 82067d5..d24460f 100644 --- a/docs/dev.md +++ b/docs/dev.md @@ -56,7 +56,7 @@ Connect a wallet and copy the CKB address displayed at the top of the page. Transfer some CKB tokens from the miner account to the copied address. Replace `ckbt1qz...` with the real address in the following command. ```bash -ckb-cli wallet transfer --skip-check-to-address --to-address ckt1qz... --capacity 300000 --privkey-path specs/miner.key +bin/dev-faucet.sh ckt1qz... ``` Mine some blocks to commit the transfer transaction. diff --git a/migrations/templates/ckb_auth.toml b/migrations/templates/ckb_auth.toml deleted file mode 100644 index 4d01603..0000000 --- a/migrations/templates/ckb_auth.toml +++ /dev/null @@ -1,19 +0,0 @@ -[[cells]] -name = "ckb_auth" -enable_type_id = false -location = { file = "build/release/ckb_auth" } -[[cells]] -name = "unisat_lock" -enable_type_id = true -location = { file = "build/release/unisat_lock" } - -# Dep group cells -[[dep_groups]] -name = "ckb_auth_locks" -cells = ["ckb_auth", "unisat_lock"] - -# The lock script set to output cells -[lock] -code_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8" -args = "0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7" -hash_type = "type" diff --git a/migrations/templates/omnilock.toml b/migrations/templates/omnilock.toml new file mode 100644 index 0000000..435f86a --- /dev/null +++ b/migrations/templates/omnilock.toml @@ -0,0 +1,10 @@ +[[cells]] +name = "omnilock" +enable_type_id = true +location = { file = "build/release/omnilock" } + +# The lock script set to output cells +[lock] +code_hash = "0x9bd7e06f3ecf4be0f2fcd2188b23f1b9fcc88e5d4b65a8637b17723bbda3cce8" +args = "0xc8328aabcd9b9e8e64fbc566c4385c3bdeb219d7" +hash_type = "type" diff --git a/src/lib/cobuild/fee-manager.js b/src/lib/cobuild/fee-manager.js index cdeae62..16d10da 100644 --- a/src/lib/cobuild/fee-manager.js +++ b/src/lib/cobuild/fee-manager.js @@ -59,12 +59,15 @@ function storeWitnessForFeeEstimation( // Variable length, but 500 is usually enough. () => bytes.hexify(new Uint8Array(500)), ); - } else if (script.codeHash === ckbChainConfig.SCRIPTS.UNISAT.CODE_HASH) { + } else if ( + script.codeHash === ckbChainConfig.SCRIPTS.OMNILOCK_CUSTOM.CODE_HASH + ) { return generalLockActions.storeWitnessForFeeEstimation( buildingPacket, scriptHash, inputIndices, - () => `0x${"0".repeat(65 * 2)}`, + // 85 = 65 signature in OmnilockWitnessLock + () => `0x${"0".repeat(85 * 2)}`, ); } diff --git a/src/lib/cobuild/lock-actions.js b/src/lib/cobuild/lock-actions.js index ca37421..556fae9 100644 --- a/src/lib/cobuild/lock-actions.js +++ b/src/lib/cobuild/lock-actions.js @@ -89,7 +89,9 @@ function dispatchLockActions( }, () => `0x${"0".repeat(129 * 2)}`, ); - } else if (script.codeHash === ckbChainConfig.SCRIPTS.UNISAT.CODE_HASH) { + } else if ( + script.codeHash === ckbChainConfig.SCRIPTS.OMNILOCK_CUSTOM.CODE_HASH + ) { return generalLockActions.prepareLockActionWithWitnessStore( buildingPacket, scriptHash, @@ -99,7 +101,8 @@ function dispatchLockActions( inputIndices, }, }, - () => `0x${"0".repeat(65 * 2)}`, + // 85 = 65 signature in OmnilockWitnessLock + () => `0x${"0".repeat(85 * 2)}`, ); } diff --git a/src/lib/cobuild/react/building-packet-review.js b/src/lib/cobuild/react/building-packet-review.js index bafc583..dd51554 100644 --- a/src/lib/cobuild/react/building-packet-review.js +++ b/src/lib/cobuild/react/building-packet-review.js @@ -199,6 +199,16 @@ export function TxSection({ return (
+ {process.env.DEBUG !== undefined ? ( +
+
Hash
+
+
+              {JSON.stringify(buildingPacket, null, 2)}
+            
+
+
+ ) : null}
Hash
diff --git a/src/lib/config.js b/src/lib/config.js index 6cfd7f6..2476b64 100644 --- a/src/lib/config.js +++ b/src/lib/config.js @@ -6,6 +6,7 @@ const CKB_CHAINS_CONFIGS = { EXPLORER_URL: "https://pudge.explorer.nervos.org", SCRIPTS: { ...predefined.AGGRON4.SCRIPTS, + JOYID: { CODE_HASH: "0xd23761b364210735c19c60561d213fb3beae2fd6172743719eff6920e020baac", @@ -15,18 +16,14 @@ const CKB_CHAINS_CONFIGS = { INDEX: "0x0", DEP_TYPE: "depGroup", }, - AUTH: { - TX_HASH: - "0xd4f72f0504373ff8effadf44f92c46a0062774fb585ebcacc24eb47b98e2d66a", - INDEX: "0x0", - DEP_TYPE: "code", - }, - UNISAT: { + // Disable OMNILOCK bundled in lumos + OMNILOCK: undefined, + OMNILOCK_CUSTOM: { CODE_HASH: - "0xd7aac16927b2d572b3803c1f68e49d082d3acc2af2614c9be752ff9cec5dc3ea", - HASH_TYPE: "data1", + "0xf329effd1c475a2978453c8600e1eaf0bc2087ee093c3ee64cc96ec6847752cb", + HASH_TYPE: "type", TX_HASH: - "0xe842b43df31c92d448fa345d60a6df3e03aaab19ef88921654bf95c673a26872", + "0xff234bf2fb0ad2ab5b356ceda317d3dee3efb2c55b9427ef55d9dcbf6eecbf9f", INDEX: "0x0", DEP_TYPE: "code", }, @@ -62,13 +59,11 @@ function buildCkbChainConfig(ckbChain) { TX_HASH: presence(process.env.NEXT_PUBLIC_JOYID_TX_HASH), }, ); - const UNISAT = assign( - { ...template.SCRIPTS.JOYID }, + const OMNILOCK_CUSTOM = assign( + { ...template.SCRIPTS.OMNILOCK_CUSTOM }, { - CODE_HASH: presence(process.env.NEXT_PUBLIC_UNISAT_CODE_HASH), - HASH_TYPE: "type", - TX_HASH: presence(process.env.NEXT_PUBLIC_AUTH_TX_HASH), - DEP_TYPE: "depGroup", + CODE_HASH: presence(process.env.NEXT_PUBLIC_OMNILOCK_CODE_HASH), + TX_HASH: presence(process.env.NEXT_PUBLIC_OMNILOCK_TX_HASH), }, ); @@ -84,8 +79,7 @@ function buildCkbChainConfig(ckbChain) { EXPLORER_URL: null, SCRIPTS: { JOYID, - UNISAT, - AUTH: template.SCRIPTS.AUTH, + OMNILOCK_CUSTOM, DAO: { ...template.SCRIPTS.DAO, TX_HASH: tx0, diff --git a/src/lib/lumos-adapter/init-lumos-common-scripts.js b/src/lib/lumos-adapter/init-lumos-common-scripts.js index ed83dc1..32d6010 100644 --- a/src/lib/lumos-adapter/init-lumos-common-scripts.js +++ b/src/lib/lumos-adapter/init-lumos-common-scripts.js @@ -8,16 +8,13 @@ export function buildJoyidLockInfo(ckbChainConfig) { return buildLockInfo(ckbChainConfig, ckbChainConfig.SCRIPTS.JOYID, []); } -export function buildUniSatLockInfo(ckbChainConfig) { - const UNISAT = ckbChainConfig.SCRIPTS.UNISAT; - // Require the secp256k1 data cell - const extraScripts = [ckbChainConfig.SCRIPTS.SECP256K1_BLAKE160]; - // if not depGroup, add AUTH as well - if (UNISAT.DEP_TYPE === "code") { - extraScripts.push(ckbChainConfig.SCRIPTS.AUTH); - } - - return buildLockInfo(ckbChainConfig, UNISAT, extraScripts); +export function buildOmniLockInfo(ckbChainConfig) { + return buildLockInfo( + ckbChainConfig, + ckbChainConfig.SCRIPTS.OMNILOCK_CUSTOM, + // Require the secp256k1 data cell + [ckbChainConfig.SCRIPTS.SECP256K1_BLAKE160], + ); } export function buildLockInfo(ckbChainConfig, scriptInfo, extraScripts) { @@ -137,7 +134,7 @@ export default function initLumosCommonScripts(ckbChainConfig) { if (!inited) { commonScripts.registerCustomLockScriptInfos([ buildJoyidLockInfo(ckbChainConfig), - buildUniSatLockInfo(ckbChainConfig), + buildOmniLockInfo(ckbChainConfig), ]); inited = true; } diff --git a/src/lib/lumos-adapter/pay-fee-with-building-packet.js b/src/lib/lumos-adapter/pay-fee-with-building-packet.js index 8454735..5af451e 100644 --- a/src/lib/lumos-adapter/pay-fee-with-building-packet.js +++ b/src/lib/lumos-adapter/pay-fee-with-building-packet.js @@ -3,10 +3,6 @@ import { common as commonScripts } from "@ckb-lumos/common-scripts"; import createBuildingPacketFromSkeleton from "./create-building-packet-from-skeleton"; import createSkeletonFromBuildingPacket from "./create-skeleton-from-building-packet"; -function outPointEqual(a, b) { - return a.txHash === b.txHash && a.index === b.index; -} - // feePayments: [{address, fee?, feeRate?}] export default async function payFeeWithBuildingPacket( buildingPacket, diff --git a/src/lib/wallet/btc-wallet.js b/src/lib/wallet/btc-wallet.js index f250492..b13c3d5 100644 --- a/src/lib/wallet/btc-wallet.js +++ b/src/lib/wallet/btc-wallet.js @@ -1,9 +1,8 @@ +import { bytes } from "@ckb-lumos/codec"; +import * as lumosHelpers from "@ckb-lumos/helpers"; import { bech32 } from "bech32"; import * as bs58 from "bs58"; -import * as lumosHelpers from "@ckb-lumos/helpers"; -import { bytes } from "@ckb-lumos/codec"; - -import { urlSafeBase64Decode } from "@/lib/base64"; +import { packOmnilockWitnessLock } from "./omni-lock"; export function isNativeSegwit(btcAddress) { return btcAddress.startsWith("bc1q") || btcAddress.startsWith("tb1q"); @@ -48,6 +47,7 @@ export function btcAddressToCkbAddress(btcAddress, scriptInfo, ckbChainConfig) { "Please choose an address type that is NOT Taproot (P2TR).", ); } + args += "00"; const script = { codeHash: scriptInfo.CODE_HASH, @@ -72,5 +72,5 @@ export function didSign(btcAddress, signature) { ); } - return bytes.hexify(signature); + return bytes.hexify(packOmnilockWitnessLock(signature)); } diff --git a/src/lib/wallet/joyid.js b/src/lib/wallet/joyid.js index 95ad6cf..135e9a8 100644 --- a/src/lib/wallet/joyid.js +++ b/src/lib/wallet/joyid.js @@ -5,6 +5,7 @@ import * as lumosHelpers from "@ckb-lumos/helpers"; import { urlSafeBase64Decode } from "../base64"; export const title = "Joyid"; +export const lockScriptName = "Joyid Lock"; // Connects to the wallet. export async function connect() { diff --git a/src/lib/wallet/omni-lock.js b/src/lib/wallet/omni-lock.js new file mode 100644 index 0000000..b4d47b4 --- /dev/null +++ b/src/lib/wallet/omni-lock.js @@ -0,0 +1,29 @@ +import { blockchain } from "@ckb-lumos/base"; +import { createFixedBytesCodec, molecule } from "@ckb-lumos/codec"; +const { table } = molecule; +const { BytesOpt } = blockchain; + +const NullCodec = createFixedBytesCodec({ + pack: () => new Uint8Array(0), + unpack: () => null, + byteLength: 0, +}); + +export const OmnilockWitnessLock = table( + { + signature: BytesOpt, + + // Fields not used in PoC + omniIdentity: NullCodec, + preimage: NullCodec, + }, + ["signature", "omniIdentity", "preimage"], +); + +export function packOmnilockWitnessLock(signature) { + return OmnilockWitnessLock.pack({ + signature, + omniIdentity: null, + preimage: null, + }); +} diff --git a/src/lib/wallet/selector.js b/src/lib/wallet/selector.js index b983b1b..45579f8 100644 --- a/src/lib/wallet/selector.js +++ b/src/lib/wallet/selector.js @@ -7,6 +7,10 @@ export function walletName(slug) { return providers[slug].title; } +export function lockScriptName(slug) { + return providers[slug].lockScriptName; +} + export async function connect(slug) { return await providers[slug].connect(); } diff --git a/src/lib/wallet/unisat.js b/src/lib/wallet/unisat.js index d1e0167..de2665d 100644 --- a/src/lib/wallet/unisat.js +++ b/src/lib/wallet/unisat.js @@ -3,6 +3,7 @@ import { urlSafeBase64Decode } from "@/lib/base64"; import { didConnected, didSign, btcAddressToCkbAddress } from "./btc-wallet"; export const title = "UniSat"; +export const lockScriptName = "Omnilock"; // Connects to the wallet. export async function connect() { @@ -18,7 +19,7 @@ export async function connect() { // // Calls this function only when wallet is connected. export function address(btcAddress, ckbChainConfig) { - const scriptInfo = ckbChainConfig.SCRIPTS.UNISAT; + const scriptInfo = ckbChainConfig.SCRIPTS.OMNILOCK_CUSTOM; return btcAddressToCkbAddress(btcAddress, scriptInfo, ckbChainConfig); }