Skip to content

feat(sdk-core): add EdDSA MPCv2 DSG helpers and DKG key-share util#8687

Merged
Marzooqa merged 1 commit intomasterfrom
WCI-153
May 7, 2026
Merged

feat(sdk-core): add EdDSA MPCv2 DSG helpers and DKG key-share util#8687
Marzooqa merged 1 commit intomasterfrom
WCI-153

Conversation

@Marzooqa
Copy link
Copy Markdown
Contributor

@Marzooqa Marzooqa commented May 5, 2026

  • Add getSignatureShareRoundOne/Two/Three helpers in sdk-core for building
    PGP-signed MPS broadcast messages per signing round
  • Add verifyBitGoMessageRoundOne/Two helpers for verifying peer PGP signatures
    and deserialising incoming MPS messages
  • Parameterise partyId (default: USER=0) and peerPartyId (type: MPCv2PartiesEnum,
    default: BITGO=2) to support non-user signers without hardcoding
  • Wire eddsaMpcV2 type in sendSignatureShareV2 (common.ts)
  • Add generateEdDsaDKGKeyShares to sdk-lib-mpc MPSUtil with split EdDsaDKGPartySeed
    (encKey / dkgSeed) to eliminate seed dual-use; add length assertions
  • Replace duplicate test-util copy with a re-export from the production source
  • Add unit tests covering all helpers including BACKUP party path, tampered-message
    rejection for both round-1 and round-2 verify, and deterministic-seed behaviour

Co-Authored-By: Claude Sonnet 4.6 noreply@anthropic.com

TICKET: WCI-153

@linear-code
Copy link
Copy Markdown

linear-code Bot commented May 5, 2026

@Marzooqa Marzooqa marked this pull request as ready for review May 5, 2026 10:37
@Marzooqa Marzooqa requested review from a team as code owners May 5, 2026 10:37
@zahin-mohammad zahin-mohammad self-requested a review May 6, 2026 19:29
Copy link
Copy Markdown
Contributor

@zahin-mohammad zahin-mohammad left a comment

Choose a reason for hiding this comment

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

Built and tested locally — tsc --noEmit is clean in both sdk-lib-mpc and sdk-core, and the new sdk-core EdDSA MPCv2 test suite passes (6/6). Confirmed #8697 is the follow-up that wires EddsaMPCv2Utils.signRequestBase into these helpers.

One semantics concern that I think is worth resolving before merge because it freezes on the public surface — MPSUtil.generateEdDsaDKGKeyShares is barrel-exported, so the seed contract becomes part of the SDK API. The rest are follow-up-safe: helper renames (still internal until #8697 lands deep-import callers), test-util consolidation (pure refactor), and a few test/cleanup nits.

See inline comments.

Comment thread modules/sdk-lib-mpc/src/tss/eddsa-mps/util.ts
Comment thread modules/sdk-lib-mpc/src/tss/eddsa-mps/util.ts
Comment thread modules/sdk-core/src/bitgo/tss/eddsa/eddsaMPCv2.ts Outdated
Comment thread modules/sdk-core/src/bitgo/tss/eddsa/eddsaMPCv2.ts Outdated
Comment thread modules/sdk-core/src/bitgo/tss/eddsa/eddsaMPCv2.ts Outdated
Comment thread modules/sdk-core/test/unit/bitgo/utils/tss/eddsa/eddsaMPCv2.ts Outdated
Comment thread modules/sdk-core/test/unit/bitgo/utils/tss/eddsa/eddsaMPCv2.ts
- Add getSignatureShareRoundOne/Two/Three helpers in sdk-core for building
  PGP-signed MPS broadcast messages per signing round
- Add verifyBitGoMessageRoundOne/Two helpers for verifying peer PGP signatures
  and deserialising incoming MPS messages
- Parameterise partyId (default: USER=0) and peerPartyId (type: MPCv2PartiesEnum,
  default: BITGO=2) to support non-user signers without hardcoding
- Wire eddsaMpcV2 type in sendSignatureShareV2 (common.ts)
- Add generateEdDsaDKGKeyShares to sdk-lib-mpc MPSUtil with split EdDsaDKGPartySeed
  (encKey / dkgSeed) to eliminate seed dual-use; add length assertions
- Replace duplicate test-util copy with a re-export from the production source
- Add unit tests covering all helpers including BACKUP party path, tampered-message
  rejection for both round-1 and round-2 verify, and deterministic-seed behaviour

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

TICKET: WCI-153
Copy link
Copy Markdown
Contributor

@zahin-mohammad zahin-mohammad left a comment

Choose a reason for hiding this comment

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

LGTM — all 7 prior comments are resolved in this revision:

  • ✅ Seed dual-use split into EdDsaDKGPartySeed { encKey, dkgSeed } with >= 32 byte asserts (the only blocking item, since MPSUtil.generateEdDsaDKGKeyShares is barrel-exported)
  • ✅ Test-util duplicate replaced with a re-export from the production source
  • ✅ Helpers renamed to match ECDSA convention (getSignatureShareRoundOne/Two/Three, verifyBitGoMessageRoundOne/Two)
  • bitgoGpgKeypeerGpgKey; peerPartyId typed as MPCv2PartiesEnum directly (no more as cast)
  • ✅ Dead void bitgoSignedMsg1 line removed
  • ✅ Test coverage filled: round-2 tampered-signature, BACKUP path for all three rounds, deterministic split-seed test with 3-party public-key agreement assertion

Residual nits — non-blocking, address in a follow-up

  1. verifyBitGoMessage* name vs parameterized peer. The functions accept peerPartyId: MPCv2PartiesEnum, but the name still says BitGo. Default of BITGO keeps it mostly accurate, but if a USER/BACKUP peer ever flows through, the name lies. Consider verifyPeerMessageRoundOne/Two if you want the public surface to match the contract.
  2. Type inconsistency in eddsaMPCv2.ts. Signing helpers use literal partyId: 0 | 1 and otherSignerPartyId: 0 | 1 | 2, while verify helpers use MPCv2PartiesEnum. Unifying on MPCv2PartiesEnum everywhere — optionally with a SignerPartyId = USER | BACKUP alias to enforce non-BITGO origination — would make the contract uniform across the file.
  3. Redundant runtime assert in partyIdToSignatureShareType. The literal 0 | 1 | 2 parameter type already prevents invalid values at compile time, so the assert is dead defensive code. Harmless; remove if you want to keep the file tight.

None of these block merge — happy to approve as-is.

@Marzooqa Marzooqa merged commit 25f7496 into master May 7, 2026
22 checks passed
@Marzooqa Marzooqa deleted the WCI-153 branch May 7, 2026 17:24
export async function verifyBitGoMessageRoundOne(
parsedRound1Output: EddsaMPCv2SignatureShareRound1Output,
peerGpgKey: openpgp.Key,
peerPartyId: MPCv2PartiesEnum = MPCv2PartiesEnum.BITGO
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

function is named verifyBitGoMessageRound* but accepts a peerPartyId param -- should this be verifyPeerMessageRound*, or is it BitGo-only and the param should be removed?

import { generateGPGKeyPair } from '../../../../../../src/bitgo/utils/opengpgUtils';
import { MPCv2PartiesEnum } from '../../../../../../src/bitgo/utils/tss/ecdsa/typesMPCv2';

describe('EdDSA MPS DSG helper functions', async () => {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

mocha describe callbacks shouldn't be async -- can cause tests to silently not run in some versions

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.

3 participants