Repository navigation
build: DKLs23 0.6.1 and FROST 3.0.0; DKLs23 refresh, key import and BOLT 3 - #12
Merged
Merged
Conversation
Depend on dkls23-secp256k1 and dkls23-secp256r1 0.6.1 instead of the DKLs23 git main branch, and move k256 and p256 from release candidates to 0.14. Update the spec's DKLs23 version and encoding references.
Depend on the FROST 3.0.0 release instead of the FROST git main branch, which moved to rand_core 0.10 and no longer accepts OsRng. A fresh dependency resolution (as in libtss-wasm, which has no lockfile) now builds again. Reported in #11.
CI runs clippy on the latest stable with -D warnings, and that version rejects uninlined format args, so every pull request fails before its own changes are even checked. Inlines the four format! calls it flags, in the tokio example, the FFI memory hardening test and the protocol tests.
A wallet service hands out a new address for every customer or payment, and today each one needs every party to run derive_child. The group key plus the chain code make a BIP-32 xpub, so a server can derive addresses on its own, and they match the ones the parties later sign for. Adds chain_code() to the key share handle, in Rust, the C API (tss_handle_chain_code) and every binding. DKLs23 returns the chain code made at DKG; FROST Taproot returns the value derive.rs already uses, through one shared helper. Other suites return ProtocolMismatch. Tests check child keys against a separate BIP-32 implementation, and the FFI tests get a shared DKG and signing driver.
GenerateDealer returns (Handles, PublicKeyPackage) and takes no out parameter, so the memory-hardening tests no longer compiled.
RefreshSession::new_dkls runs a DKLs23 complete refresh across all n parties: every share moves by a share of zero, the group key stays the same and the pairwise OT and zero-share state is regenerated. The refresh is written once, generic over the curve, and updates the public key package with DKLs23's PublicKeyPackage::refresh, which verifies every proof commitment. A failed round ends the session. Adds tss_refresh_new_dkls to the C API, NewRefreshSessionDKLs and the Secp256r1ECDSA ciphersuite to the Go binding, tests in Rust, the FFI and Go, and updates the spec. Based on the refresh in #8. Co-authored-by: José A.P <53834183+Jossec101@users.noreply.github.com>
dkls_import::dkls_split_key splits a secp256k1 or secp256r1 secret key into DKLs23 shares through DKLs23 re_key (trusted dealer) with a fresh random session id. The group key is the key's own public key, and an existing BIP-32 chain code can be kept so derived addresses match. The secret must be a canonical non-zero scalar. The documented follow-up is a complete refresh, so the dealer-generated OT state is replaced. C API tss_dkls_split_key; bindings for the DKLs23 split and the complete refresh in Go, Node, Python and .NET (Node also gains Secp256r1ECDSA). Tests in Rust, the FFI and every binding. Binding fixes found by the new tests: - .NET: the *_next calls marshalled out_complete as bool*, which .NET rejects, so no DKG, sign or refresh session could advance; pass a byte. - Node: koffi registers struct names process-wide, so loading the bindings from a second test file failed; reuse the registered type. Closes #10.
libtss::bolt3 wraps DKLs23's BOLT 3 derivations: bolt3_derive (localpubkey-style), bolt3_derive_revocation (revocationpubkey, given the revealed per-commitment secret) and their public-key-package variants. Each party computes the tweak from public points; no raw scalar tweak is exposed. Derived shares keep the base share's OT state, which the docs call out for bans. C API tss_bolt3_derive, tss_bolt3_derive_revocation and the *_pubkey_package variants; bindings in Go, Node, Python and .NET. Tests check the BOLT 3 Appendix E vectors and sign under the derived keys. Replaces the raw tweaks proposed in #9. Co-authored-by: José A.P <53834183+Jossec101@users.noreply.github.com>
- Abort culprits name the accused counterparty from the AbortReason, not the reporting party; local-state errors and session mismatches accuse no one. Affects DKG, signing and refresh. - A failed DKLs23 refresh round ends the session (is_complete() is true). - Refresh fragments and parsed secret bytes are zeroized on every exit. - FFI handle getters clear the out buffer before failing. - Node and Python validate DKLs23 thresholds before narrowing and wipe the secret on every path. - Bindings document that a Taproot chain code matches an external CKDpub at depth 1 only; BOLT 3 docs no longer list remotepubkey as derived. - Frozen pre-upgrade key-share fixtures, a tampered-proof refresh test and threshold tests.
- Importing a DKLs23 share checks that the party's threshold and share count match its public key package. - BOLT 3 public-key-package derivation requires verifying shares indexed 1..=n. - The C API serializes the public key package before handing out split handles (DKLs23 and FROST), so a failure leaks no handles; Go frees the key share when a completed step's package fails to decode. - Bindings wipe the per-commitment secret after the BOLT 3 revocation call; Python's FROST split wipes the secret on early errors too. - React Native gains the Secp256r1ECDSA ciphersuite; WASM and spec docs match the implementation.
Instrumented debug builds run the refresh and import end-to-end tests past tarpaulin's 300 s per-test timeout. cargo test still runs them; cfg(tarpaulin) is declared for check-cfg.
This was referenced Oct 21, 2026
This was referenced Oct 21, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Moves libtss to the DKLs23 0.6.1 and FROST 3.0.0 releases. Folds in the open PRs and issue #10.
dkls23-secp256k1/dkls23-secp256r10.6.1 and FROST 3.0.0 from crates.io instead of the gitmainbranches;k256/p256stable0.14.mainmoved torand_core0.10) by pinning the FROST 3.0.0 release instead of trackingmain.libtss-wasm(no lockfile) builds again from a fresh resolution.chain_code(),tss_handle_chain_code, every binding), cherry-picked with authorship; reads DKLs23Party::chain_code().RefreshSession::new_dkls,tss_refresh_new_dkls, Go/Node/Python/.NET. Written once, generic over the curve; the public key package is updated with DKLs23PublicKeyPackage::refresh, which verifies every proof commitment. Share repair itself moves to DKLs23, as discussed on #8 (released later in DKLs23 0.6.2).re_key:dkls_split_key,tss_dkls_split_key, Go/Node/Python/.NET. Keeps the key's public key and, optionally, its BIP-32 chain code. Documented follow-up: a complete refresh.bolt3_derive,bolt3_derive_revocationand their public-key-package variants,tss_bolt3_*, Go/Node/Python/.NET. Checked against the BOLT 3 Appendix E vectors.Fixes from review (codex, agy) and from the new tests:
culpritsnamed the reporting party instead of the accused one (DKG, signing, refresh), so an application following the spec ("exclude the culprit and retry") would exclude an honest party. Culprits now come from theAbortReason; local-state errors and session mismatches accuse no one.*_nextmarshalledout_completeasbool*, which .NET rejects, so no DKG, sign or refresh session could advance. It is now abyte.Secp256r1ECDSAciphersuite.Not folded:
Compatibility
mainimport and sign. Tested by exporting 2-of-3 secp256k1/secp256r1 shares frommainand signing with them here.RefreshSession::new_dkls) after upgrading, so OT state created before DKLs23 0.5.2 is regenerated.Test plan
cargo fmt --check,cargo clippy --workspace --all-targets -D warningscargo test --workspace(release): 222 tests, including frozen pre-upgrade key-share fixturesgo test ./...andgo vetjest: 40 testspytest: 49 testsdotnet test: 49 testswasm-pack test --node --features testingjest: 25 testslibtss/tests/fixtures/dkls23-0.4)Follow-ups
re_keyandrefresh_complete_phase1did not zeroize their temporary polynomials (fixed in DKLs23 0.6.2; libtss moves to it in a follow-up PR).spec/08-serialization.mdis out of date.