Skip to content

feat(core): extract SignerMultisigCkbBase for Omnilock multisig#360

Draft
phroi wants to merge 6 commits intockb-devrel:releases/nextfrom
phroi:omnilock-multisig-signer
Draft

feat(core): extract SignerMultisigCkbBase for Omnilock multisig#360
phroi wants to merge 6 commits intockb-devrel:releases/nextfrom
phroi:omnilock-multisig-signer

Conversation

@phroi
Copy link
Contributor

@phroi phroi commented Mar 2, 2026

Why

The CKB multisig signer and Omnilock multisig signer share ~46% of their code. The only real differences are witness encoding (plain multisig bytes vs. OmniLockWitnessLock envelope) and script cardinality (multiple variants vs. one).

Changes

  • Extract MultisigCkbWitness entity into standalone module
  • Create abstract SignerMultisigCkbBase with encodeWitnessLock/decodeWitnessLock template methods
  • Slim SignerMultisigCkbReadonly to thin subclass
  • Add SignerMultisigOmniLockReadonly and SignerMultisigOmniLockPrivateKey for Omnilock auth flag 0x06
  • Add OmniLockWitnessLock molecule encoding utility

Builds on #349.

@changeset-bot
Copy link

changeset-bot bot commented Mar 2, 2026

🦋 Changeset detected

Latest commit: a770d52

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 20 packages
Name Type
@ckb-ccc/core Minor
@ckb-ccc/did-ckb Patch
@ckb-ccc/eip6963 Patch
@ckb-ccc/joy-id Patch
@ckb-ccc/lumos-patches Patch
@ckb-ccc/nip07 Patch
@ckb-ccc/okx Patch
@ckb-ccc/rei Patch
@ckb-ccc/shell Patch
@ckb-ccc/spore Patch
@ckb-ccc/ssri Patch
@ckb-ccc/type-id Patch
@ckb-ccc/udt Patch
@ckb-ccc/uni-sat Patch
@ckb-ccc/utxo-global Patch
@ckb-ccc/xverse Patch
@ckb-ccc/ccc Patch
ckb-ccc Patch
@ckb-ccc/connector Patch
@ckb-ccc/connector-react Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@netlify
Copy link

netlify bot commented Mar 2, 2026

Deploy Preview for apiccc ready!

Name Link
🔨 Latest commit a770d52
🔍 Latest deploy log https://app.netlify.com/projects/apiccc/deploys/69a4e76a2d93c70008bb2400
😎 Deploy Preview https://deploy-preview-360--apiccc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 81 (🔴 down 1 from production)
Accessibility: 100 (no change from production)
Best Practices: 100 (no change from production)
SEO: 95 (🟢 up 1 from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Mar 2, 2026

Deploy Preview for liveccc ready!

Name Link
🔨 Latest commit a770d52
🔍 Latest deploy log https://app.netlify.com/projects/liveccc/deploys/69a4e76aed6eb7000846a2f8
😎 Deploy Preview https://deploy-preview-360--liveccc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 40 (🟢 up 3 from production)
Accessibility: 88 (no change from production)
Best Practices: 92 (🔴 down 8 from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@netlify
Copy link

netlify bot commented Mar 2, 2026

Deploy Preview for appccc ready!

Name Link
🔨 Latest commit a770d52
🔍 Latest deploy log https://app.netlify.com/projects/appccc/deploys/69a4e76a2f26da0008fc3c20
😎 Deploy Preview https://deploy-preview-360--appccc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 58 (🔴 down 28 from production)
Accessibility: 89 (🟢 up 1 from production)
Best Practices: 92 (🔴 down 8 from production)
SEO: 100 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly enhances the CKB multisig and Omnilock support by refactoring shared logic into a new abstract base class and introducing dedicated signer implementations for Omnilock. It centralizes cryptographic utilities, updates core dependencies, and improves the build system, laying a more robust foundation for advanced CKB interactions. The changes aim to streamline development and ensure compatibility with the latest CKB script versions.

Highlights

  • Multisig and Omnilock Signer Refactoring: Extracted common CKB multisig logic into an abstract SignerMultisigCkbBase class, enabling shared witness preparation and signature aggregation. This base class is now extended by SignerMultisigCkbReadonly and new Omnilock-specific signers.
  • Omnilock Multisig Support: Introduced SignerMultisigOmniLockReadonly and SignerMultisigOmniLockPrivateKey to support Omnilock cells with CKB multisig authentication (auth flag 0x06), including handling of ACP modes and specific witness encoding.
  • Modular Secp256k1 Signing Utilities: Moved core secp256k1 signing, verification, and public key recovery logic into a new secp256k1Signing.ts module, centralizing cryptographic operations and improving reusability across different signers.
  • Build System and Dependency Updates: Migrated the build process to tsdown for improved efficiency and updated @noble/ciphers, @noble/curves, and @noble/hashes packages to their latest versions, ensuring up-to-date cryptographic primitives.
  • Enhanced Transaction Witness Handling: Added a new Transaction.getWitnessArgsAtUnsafe method that throws an error on decoding failure, complementing the existing getWitnessArgsAt which returns undefined for graceful error handling.
  • New Multisig Script Information: Added Secp256k1MultisigV2Beta script information to both Mainnet and Testnet configurations, supporting a specific CKB system script variant.
Changelog
  • .changeset/fuzzy-years-add.md
    • Added a changeset entry for relaxing @ccc.codec's type restriction.
  • .changeset/little-zebras-pump.md
    • Added a changeset entry for multisig Signers.
  • .changeset/orange-goats-float.md
    • Added a changeset entry for Transaction.getWitnessArgsAtUnsafe.
  • .changeset/vast-trees-film.md
    • Added a changeset entry for bumping @noble packages.
  • packages/core/package.json
    • Updated module export paths to use .mjs for ESM imports.
    • Replaced rimraf and copyfiles with tsdown in the build script and dev dependencies.
    • Updated @noble/ciphers, @noble/curves, and @noble/hashes dependencies to newer versions.
    • Added a types field to specify the declaration file location.
  • packages/core/src/ckb/transaction.ts
    • Refactored getWitnessArgsAt to internally use a new getWitnessArgsAtUnsafe method, providing a safe fallback for decoding errors.
  • packages/core/src/client/clientPublicMainnet.advanced.ts
    • Added Secp256k1MultisigV2Beta script information for the Mainnet configuration.
  • packages/core/src/client/clientPublicTestnet.advanced.ts
    • Added Secp256k1MultisigV2Beta script information for the Testnet configuration.
  • packages/core/src/client/knownScript.ts
    • Added Secp256k1MultisigV2Beta to the KnownScript enum.
  • packages/core/src/codec/entity.ts
    • Imported bytesFrom for byte conversion.
    • Relaxed the type definition for the codec decorator to allow more flexible codec objects.
    • Modified Constructor.decode and Constructor.fromBytes to use bytesFrom for consistent byte handling.
  • packages/core/src/hasher/advanced.ts
    • Converted CKB_BLAKE2B_PERSONAL from a string to a Bytes object for consistency.
  • packages/core/src/hasher/hasherCkb.ts
    • Updated the import path for blake2b from @noble/hashes/blake2b to @noble/hashes/blake2.js.
    • Added HASH_CKB_LENGTH and HASH_CKB_SHORT_LENGTH constants for hash length definitions.
  • packages/core/src/hasher/hasherKeecak256.ts
    • Updated the import path for keccak_256 from @noble/hashes/sha3 to @noble/hashes/sha3.js.
  • packages/core/src/keystore/index.ts
    • Updated @noble package imports to use .js extensions for better module resolution.
  • packages/core/src/molecule/codec.ts
    • Reordered and updated deprecated exports related to CodecLike, DecodedType, EncodableType, uint, and uintNumber.
  • packages/core/src/signer/btc/verify.ts
    • Updated the import path for secp256k1 from @noble/curves/secp256k1 to @noble/curves/secp256k1.js.
    • Added { prehash: false } option to secp256k1.verify calls for correct pre-hashing behavior.
  • packages/core/src/signer/ckb/index.ts
    • Exported new modules for multisig CKB witness, Omnilock witness lock, and secp256k1 signing.
    • Exported new multisig CKB and Omnilock signer classes.
    • Removed the export for verifyCkbSecp256k1.js as its functionality was moved.
  • packages/core/src/signer/ckb/multisigCkbWitness.ts
    • Added MultisigCkbWitness class for managing CKB multisig information, including encoding, decoding, and script argument generation.
  • packages/core/src/signer/ckb/omniLockWitnessLock.ts
    • Added OmniLockWitnessLock utilities for encoding and decoding molecule table formats, specifically for Omnilock signatures.
  • packages/core/src/signer/ckb/secp256k1Signing.test.ts
    • Added new test file for secp256k1Signing functions, covering signing, verification, and public key recovery.
  • packages/core/src/signer/ckb/secp256k1Signing.ts
    • Added new module providing signMessageSecp256k1, verifyMessageSecp256k1, recoverMessageSecp256k1, messageHashCkbSecp256k1, and verifyMessageCkbSecp256k1 functions.
  • packages/core/src/signer/ckb/signerCkbPrivateKey.ts
    • Updated @noble package imports to use .js extensions.
    • Refactored _signMessage to utilize the new signMessageSecp256k1 function.
    • Updated the import path for messageHashCkbSecp256k1.
  • packages/core/src/signer/ckb/signerCkbPublicKey.ts
    • Imported HASH_CKB_SHORT_LENGTH and SECP256K1_SIGNATURE_LENGTH constants.
    • Updated public key hash slicing to use HASH_CKB_SHORT_LENGTH.
    • Updated prepareSighashAllWitness to use SECP256K1_SIGNATURE_LENGTH.
  • packages/core/src/signer/ckb/signerMultisigCkb.test.ts
    • Added new test file for MultisigCkbWitness and SignerMultisigCkbReadonly.
  • packages/core/src/signer/ckb/signerMultisigCkbBase.ts
    • Added SignerMultisigCkbBase abstract class, providing foundational logic for CKB multisig signers.
  • packages/core/src/signer/ckb/signerMultisigCkbPrivateKey.ts
    • Added SignerMultisigCkbPrivateKey class, extending SignerMultisigCkbReadonly to enable private key signing for CKB multisig.
  • packages/core/src/signer/ckb/signerMultisigCkbReadonly.ts
    • Added SignerMultisigCkbReadonly class, extending SignerMultisigCkbBase for read-only CKB multisig operations.
  • packages/core/src/signer/ckb/signerMultisigOmniLockPrivateKey.ts
    • Added SignerMultisigOmniLockPrivateKey class, extending SignerMultisigOmniLockReadonly for signing Omnilock cells with CKB multisig auth.
  • packages/core/src/signer/ckb/signerMultisigOmniLockReadonly.ts
    • Added SignerMultisigOmniLockReadonly class, extending SignerMultisigCkbBase for read-only Omnilock cells with CKB multisig auth.
  • packages/core/src/signer/ckb/verifyCkbSecp256k1.test.ts
    • Removed the test file as its functionality was integrated into secp256k1Signing.test.ts.
  • packages/core/src/signer/ckb/verifyCkbSecp256k1.ts
    • Removed the module as its functionality was integrated into secp256k1Signing.ts.
  • packages/core/src/signer/doge/signerDogePrivateKey.ts
    • Updated @noble package imports to use .js extensions.
    • Modified _signMessage to use format: "recovered", prehash: false options for secp256k1.sign.
  • packages/core/src/signer/doge/verify.ts
    • Updated @noble package imports to use .js extensions.
    • Modified verifyMessageDogeEcdsa to use secp256k1.recoverPublicKey with { prehash: false }.
  • packages/core/src/signer/nostr/signerNostrPrivateKey.ts
    • Updated @noble package imports to use .js extensions.
    • Changed the privateKey type to Bytes and adjusted schnorr.getPublicKey and schnorr.sign calls accordingly.
  • packages/core/src/signer/nostr/verify.ts
    • Updated @noble package imports to use .js extensions.
    • Adjusted schnorr.verify to accept Bytes for signature and public key arguments.
  • packages/core/src/signer/signer/index.ts
    • Updated the import path for verifyMessageCkbSecp256k1.
    • Added a new abstract class SignerMultisig for multisignature operations.
  • packages/core/tsdown.config.mts
    • Added tsdown.config.mts for configuring the new tsdown build tool.
  • packages/docs/docs/code-examples.md
    • Added new code examples for DID operations (create, destroy, transfer) and multisig transactions (transfer from, aggregate, transfer to).
  • packages/examples/package.json
    • Updated @noble/curves and @noble/hashes dependencies to newer versions.
  • packages/examples/src/createDidWithLocalId.ts
    • Updated @noble package imports to use .js extensions.
    • Adjusted plcSign to use format: "compact", prehash: false options for secp256k1.sign.
  • packages/examples/src/transferFromMultisig.ts
    • Added new example demonstrating transfer from a multisig address.
  • packages/examples/src/transferFromMultisigAggregateTxs.ts
    • Added new example demonstrating transfer from a multisig address with aggregated transactions.
  • packages/examples/src/transferToMultisig.ts
    • Added new example demonstrating transfer to a multisig address.
  • packages/playground/next.config.mjs
    • Updated EXTRA_SOURCES regex to include .d.mts files for Monaco editor type resolution.
  • packages/playground/package.json
    • Updated @noble/curves and @noble/hashes dependencies to newer versions.
  • packages/playground/src/app/components/Editor.tsx
    • Updated EXTRA_SOURCES regex to include .d.mts files for type definitions.
    • Changed TypeScript moduleResolution to Bundler in Monaco editor configuration.
  • packages/playground/src/app/execute/index.tsx
    • Updated @noble package imports to use .js extensions for better module resolution.
  • packages/tests/package.json
    • Added @ckb-ccc/ccc as a dev dependency.
    • Removed @ckb-ccc/ccc from the root level dependencies.
  • packages/tests/tests/esm.test.mts
    • Updated path resolution logic for import.meta.resolve to correctly locate ESM modules.
  • pnpm-lock.yaml
    • Updated various @noble package versions (@noble/ciphers, @noble/curves, @noble/hashes).
    • Removed copyfiles and rimraf dependencies.
    • Added tsdown dependency.
    • Updated @babel/types versions across several packages.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@netlify
Copy link

netlify bot commented Mar 2, 2026

Deploy Preview for docsccc ready!

Name Link
🔨 Latest commit a770d52
🔍 Latest deploy log https://app.netlify.com/projects/docsccc/deploys/69a4e76a5a5636000960f4ec
😎 Deploy Preview https://deploy-preview-360--docsccc.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 67 (no change from production)
Accessibility: 88 (no change from production)
Best Practices: 92 (no change from production)
SEO: 92 (no change from production)
PWA: -
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a significant and well-executed refactoring to support multisig wallets for CKB and Omnilock. The core of the change is the extraction of a common SignerMultisigCkbBase class, which greatly improves code reuse and maintainability. The PR also adds several new signer classes for both CKB multisig and Omnilock multisig, complete with corresponding tests and usage examples.

A notable part of this work is the update of @noble dependencies to new major versions, with the codebase being correctly adapted to the new APIs. The build process has also been modernized by migrating to tsdown. Overall, the changes are extensive, covering new features, refactoring, dependency updates, and build improvements, and the code quality is high. I have reviewed the changes and found no issues.

@phroi phroi mentioned this pull request Mar 2, 2026
1 task
Extract shared multisig logic into abstract SignerMultisigCkbBase with
encodeWitnessLock/decodeWitnessLock template methods. CKB multisig and
Omnilock multisig are thin subclasses differing only in witness encoding.

MultisigCkbWitness entity moved to its own module. OmniLockWitnessLock
molecule encoding added as standalone utility.
@phroi phroi force-pushed the omnilock-multisig-signer branch from f3e9823 to a770d52 Compare March 2, 2026 01:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants