Skip to content

feat: DKLs23 threshold-ECDSA backend with key refresh - #170

Open
vietddude wants to merge 12 commits into
masterfrom
feat/dkls23
Open

vietddude wants to merge 12 commits into
masterfrom
feat/dkls23

Conversation

@vietddude

@vietddude vietddude commented Oct 15, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Adds DKLs23 as an opt-in threshold-ECDSA backend (secp256k1), selected per request with types.ProtocolDkls23.

  • Rust library via cgo behind the dkls build tag (submodule third_party/dkls23); the default build is unchanged.
  • Dedicated subjects mpc:dkls:generate, mpc:dkls:sign, mpc:dkls:refresh; results reuse the existing result events (DKLSPubKey, DKLSChainCode on keygen).
  • Non-hardened BIP-32 derivation (DerivationPath) on sign.
  • Key refresh (RefreshDkls): rotates every share, keeps the public key and chain code. All participants must be online.
  • CLI benchmarks (keygen-dkls, sign-dkls23), a runnable example, and a DKLs23 vs tss-lib comparison in benchmark/results.

Notes

  • Independent of the cosigner work: the branch is rebased onto master.
  • third_party/dkls23 points to fystack/DKLs23@17d3b91 (adds the RefreshSession binding), already pushed to dev.
  • Not supported for DKLs23 wallets: EdDSA and resharing (changing committee or threshold).
  • Two races fixed along the way: a sign arriving before a node finished saving its share after keygen, and a sign mixing old and new shares during a refresh (per-wallet read/write lock).

Test plan

  • go test -tags dkls ./pkg/mpc/dkls/... ./pkg/eventconsumer/... ./pkg/client/... ./pkg/types/...
  • E2E_DKLS=1 go test -run TestDklsSigning ./e2e (3 nodes: keygen, sign, child-key sign, refresh, sign after refresh, refresh on an unknown wallet, refresh with a node offline), 3 runs in a row
  • CI does not run the DKLs e2e yet: the e2e job builds mpcium without the dkls tag, so the test skips there

@vietddude
vietddude requested a review from anhthii October 15, 2026 06:51
…ning identity

- Protocol field on GenerateKeyMessage/SignTxMessage; client CreateWalletWithProtocol
- DklsMessage binary frame; signature covers route, recipient, sender, phase and payload
- identity Sign/VerifyDklsMessage; keygen result carries the DKLs23 public key and chain code
- Session runs keygen/sign rounds; Service wires sessions to a node's pubsub, key store and peers
- Router gives one wildcard subscription per node and buffers early bundles, so no peer-ready barrier
- Per-recipient binary bundles, HD derivation for non-hardened paths, typed signatures
- Behind the dkls build tag; make targets for the Rust library, tests and benchmarks
- Signing/keygen wrapper consumers publish DKLs23 requests to their own subjects
- DklsConsumer handles verify, dedupe with TTL, result publishing and retry-later
- DKLs23 signing runs concurrently; tss-lib keeps its serial handling
- cmd/mpcium starts the backend through a dkls build-tag pair
- keygen-dkls and sign-dkls23 commands; keygen-dkls prints the wallet ID and waits for the DKLs23 result
- examples/dkls: keygen, sign with master and child key, verify both locally
- benchmark/dklsvstss: in-process tss-lib vs DKLs23 benchmark
- benchmark/results: report, CSV, chart and raw runs (1000 tx, VPS and local)
Key info lives in shared Consul while shares are local, so a sign request
could reach a node that had not finished saving its share after keygen.
Opt-in via E2E_DKLS=1; needs an mpcium binary built with -tags dkls.
Rotates every share while keeping the public key and chain code. Refresh
excludes signing per wallet so a sign never mixes old and new shares.
Requests go through mpc:dkls:refresh and results arrive on the reshare
result subject.
@vietddude
vietddude changed the base branch from feat/relay-cosigner to master October 15, 2026 06:55
@sonarqubecloud

Copy link
Copy Markdown

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.

1 participant