@bcts/frost-hubert 1.0.0-alpha.23 → 1.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/frost.cjs +345 -71
- package/dist/bin/frost.cjs.map +1 -1
- package/dist/bin/frost.mjs +345 -71
- package/dist/bin/frost.mjs.map +1 -1
- package/dist/busy-DkM2jAIZ.mjs +27 -0
- package/dist/busy-DkM2jAIZ.mjs.map +1 -0
- package/dist/busy-EZU7EKr6.cjs +38 -0
- package/dist/busy-EZU7EKr6.cjs.map +1 -0
- package/dist/cmd/index.cjs +28 -22
- package/dist/cmd/index.d.cts +2 -2
- package/dist/cmd/index.d.mts +2 -2
- package/dist/cmd/index.mjs +7 -3
- package/dist/cmd-Bw9_i2_f.cjs +130 -0
- package/dist/cmd-Bw9_i2_f.cjs.map +1 -0
- package/dist/cmd-CS1uJtuD.mjs +113 -0
- package/dist/cmd-CS1uJtuD.mjs.map +1 -0
- package/dist/common-CvH6dFvQ.mjs +282 -0
- package/dist/common-CvH6dFvQ.mjs.map +1 -0
- package/dist/common-DUWvtc08.mjs +96 -0
- package/dist/common-DUWvtc08.mjs.map +1 -0
- package/dist/common-lKP5EzHy.cjs +372 -0
- package/dist/common-lKP5EzHy.cjs.map +1 -0
- package/dist/common-lThIvJmZ.cjs +114 -0
- package/dist/common-lThIvJmZ.cjs.map +1 -0
- package/dist/dkg/index.cjs +6 -102
- package/dist/dkg/index.cjs.map +1 -1
- package/dist/dkg/index.d.cts +2 -2
- package/dist/dkg/index.d.mts +2 -2
- package/dist/dkg/index.mjs +4 -101
- package/dist/dkg/index.mjs.map +1 -1
- package/dist/finalize-BRgJK-Xv.cjs +402 -0
- package/dist/finalize-BRgJK-Xv.cjs.map +1 -0
- package/dist/finalize-BfLgzn8f.cjs +303 -0
- package/dist/finalize-BfLgzn8f.cjs.map +1 -0
- package/dist/finalize-CNTDj6aS.mjs +389 -0
- package/dist/finalize-CNTDj6aS.mjs.map +1 -0
- package/dist/finalize-EC3ikHQq.mjs +252 -0
- package/dist/finalize-EC3ikHQq.mjs.map +1 -0
- package/dist/finalize-IA01t_Qq.mjs +290 -0
- package/dist/finalize-IA01t_Qq.mjs.map +1 -0
- package/dist/finalize-UPyI1yb1.cjs +265 -0
- package/dist/finalize-UPyI1yb1.cjs.map +1 -0
- package/dist/{index-BkqLimZT.d.mts → index-B3c-80VS.d.cts} +26 -3
- package/dist/index-B3c-80VS.d.cts.map +1 -0
- package/dist/{index-BJlwbPYu.d.cts → index-BgbSGpxn.d.mts} +102 -80
- package/dist/index-BgbSGpxn.d.mts.map +1 -0
- package/dist/{index-BMbPgH0W.d.cts → index-C8QeHNwa.d.cts} +46 -2
- package/dist/{index-BMbPgH0W.d.cts.map → index-C8QeHNwa.d.cts.map} +1 -1
- package/dist/{index-DmxfT59Y.d.cts → index-D3QTWkEm.d.mts} +26 -3
- package/dist/index-D3QTWkEm.d.mts.map +1 -0
- package/dist/{index-DoV5HFvV.d.mts → index-DVbWyOs7.d.mts} +46 -2
- package/dist/{index-DoV5HFvV.d.mts.map → index-DVbWyOs7.d.mts.map} +1 -1
- package/dist/{index-Dzm1v4_4.d.mts → index-F1iNEAJR.d.cts} +102 -80
- package/dist/index-F1iNEAJR.d.cts.map +1 -0
- package/dist/index.cjs +31 -23
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -4
- package/dist/index.d.mts +4 -4
- package/dist/index.mjs +9 -4
- package/dist/index.mjs.map +1 -1
- package/dist/invite-5277FQVT.cjs +274 -0
- package/dist/invite-5277FQVT.cjs.map +1 -0
- package/dist/invite-DUTcfTgX.cjs +109 -0
- package/dist/invite-DUTcfTgX.cjs.map +1 -0
- package/dist/invite-IU4n0dq2.mjs +96 -0
- package/dist/invite-IU4n0dq2.mjs.map +1 -0
- package/dist/invite-RU-OXTNS.mjs +219 -0
- package/dist/invite-RU-OXTNS.mjs.map +1 -0
- package/dist/parallel-D1R6ZGlY.cjs +318 -0
- package/dist/parallel-D1R6ZGlY.cjs.map +1 -0
- package/dist/parallel-D6zc6VW4.mjs +235 -0
- package/dist/parallel-D6zc6VW4.mjs.map +1 -0
- package/dist/proposed-participant-Dm1Eq6mX.cjs +141 -0
- package/dist/proposed-participant-Dm1Eq6mX.cjs.map +1 -0
- package/dist/proposed-participant-cWM7iUrO.mjs +129 -0
- package/dist/proposed-participant-cWM7iUrO.mjs.map +1 -0
- package/dist/receive-CAI-x4II.cjs +213 -0
- package/dist/receive-CAI-x4II.cjs.map +1 -0
- package/dist/receive-D2Nn68L7.mjs +188 -0
- package/dist/receive-D2Nn68L7.mjs.map +1 -0
- package/dist/receive-DA_KQEgk.mjs +177 -0
- package/dist/receive-DA_KQEgk.mjs.map +1 -0
- package/dist/receive-kZMsXhbK.cjs +190 -0
- package/dist/receive-kZMsXhbK.cjs.map +1 -0
- package/dist/registry/index.cjs +85 -10
- package/dist/registry/index.cjs.map +1 -1
- package/dist/registry/index.d.cts +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs +85 -10
- package/dist/registry/index.mjs.map +1 -1
- package/dist/{registry-loI1_Mh1.cjs → registry-9puTaRrD.cjs} +1 -1
- package/dist/{registry-loI1_Mh1.cjs.map → registry-9puTaRrD.cjs.map} +1 -1
- package/dist/{registry-CgrCZ4En.mjs → registry-BpCwtrRt.mjs} +1 -1
- package/dist/{registry-CgrCZ4En.mjs.map → registry-BpCwtrRt.mjs.map} +1 -1
- package/dist/round1-4Hyx8w0x.cjs +422 -0
- package/dist/round1-4Hyx8w0x.cjs.map +1 -0
- package/dist/round1-7v9LlE11.mjs +373 -0
- package/dist/round1-7v9LlE11.mjs.map +1 -0
- package/dist/round1-BHBjru1m.cjs +465 -0
- package/dist/round1-BHBjru1m.cjs.map +1 -0
- package/dist/round1-CMLKN2RR.mjs +195 -0
- package/dist/round1-CMLKN2RR.mjs.map +1 -0
- package/dist/round1-CWSXZx5R.cjs +208 -0
- package/dist/round1-CWSXZx5R.cjs.map +1 -0
- package/dist/round1-CcQCGlIT.mjs +208 -0
- package/dist/round1-CcQCGlIT.mjs.map +1 -0
- package/dist/round1-Cgm7j1kI.mjs +452 -0
- package/dist/round1-Cgm7j1kI.mjs.map +1 -0
- package/dist/round1-DQ0fnc1H.cjs +221 -0
- package/dist/round1-DQ0fnc1H.cjs.map +1 -0
- package/dist/round2-BWz9SQIi.cjs +305 -0
- package/dist/round2-BWz9SQIi.cjs.map +1 -0
- package/dist/round2-BkNRCXgS.mjs +292 -0
- package/dist/round2-BkNRCXgS.mjs.map +1 -0
- package/dist/round2-Bl2uK93U.mjs +450 -0
- package/dist/round2-Bl2uK93U.mjs.map +1 -0
- package/dist/round2-CdUT-AhH.cjs +499 -0
- package/dist/round2-CdUT-AhH.cjs.map +1 -0
- package/dist/round2-DOA3rnV-.mjs +280 -0
- package/dist/round2-DOA3rnV-.mjs.map +1 -0
- package/dist/round2-Dg24w-TU.mjs +397 -0
- package/dist/round2-Dg24w-TU.mjs.map +1 -0
- package/dist/round2-LylCa84n.cjs +293 -0
- package/dist/round2-LylCa84n.cjs.map +1 -0
- package/dist/round2-o2Q-GMbX.cjs +410 -0
- package/dist/round2-o2Q-GMbX.cjs.map +1 -0
- package/dist/storage-B-Gu68-O.cjs +79 -0
- package/dist/storage-B-Gu68-O.cjs.map +1 -0
- package/dist/storage-Bkkliz0K.mjs +74 -0
- package/dist/storage-Bkkliz0K.mjs.map +1 -0
- package/package.json +10 -10
- package/src/bin/frost.ts +849 -128
- package/src/cmd/common.ts +19 -1
- package/src/cmd/dkg/common.ts +97 -10
- package/src/cmd/dkg/coordinator/invite.ts +5 -2
- package/src/cmd/dkg/participant/finalize.ts +51 -17
- package/src/cmd/dkg/participant/round1.ts +39 -38
- package/src/cmd/dkg/participant/round2.ts +60 -26
- package/src/cmd/sign/coordinator/round2.ts +5 -1
- package/src/cmd/sign/participant/finalize.ts +6 -2
- package/src/cmd/sign/participant/receive.ts +5 -2
- package/src/dkg/group-invite.ts +12 -2
- package/src/dkg/proposed-participant.ts +32 -3
- package/src/registry/owner-record.ts +12 -0
- package/src/registry/participant-record.ts +35 -2
- package/src/registry/registry-impl.ts +74 -18
- package/dist/cmd-5yLeC_QL.mjs +0 -4708
- package/dist/cmd-5yLeC_QL.mjs.map +0 -1
- package/dist/cmd-BfZjC3Uh.cjs +0 -4847
- package/dist/cmd-BfZjC3Uh.cjs.map +0 -1
- package/dist/index-BJlwbPYu.d.cts.map +0 -1
- package/dist/index-BkqLimZT.d.mts.map +0 -1
- package/dist/index-DmxfT59Y.d.cts.map +0 -1
- package/dist/index-Dzm1v4_4.d.mts.map +0 -1
package/dist/dkg/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["UR","Envelope","XIDDocument","XIDVerifySignature","SealedRequest","CborDate","Envelope","SealedResponse","EnvelopeFunction","XIDDocument","XIDVerifySignature","ARID"],"sources":["../../src/dkg/proposed-participant.ts","../../src/dkg/group-invite.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG Proposed Participant.\n *\n * Port of dkg/proposed_participant.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { type ARID, type XID } from \"@bcts/components\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { UR } from \"@bcts/uniform-resources\";\nimport { XIDDocument, XIDVerifySignature } from \"@bcts/xid\";\n\n/**\n * A proposed participant in a DKG session.\n *\n * Port of `struct DkgProposedParticipant` from proposed_participant.rs lines 8-13.\n */\nexport class DkgProposedParticipant {\n private readonly _urString: string;\n private readonly _envelope: Envelope;\n private readonly _document: XIDDocument;\n private readonly _responseArid: ARID;\n\n private constructor(\n urString: string,\n envelope: Envelope,\n document: XIDDocument,\n responseArid: ARID,\n ) {\n this._urString = urString;\n this._envelope = envelope;\n this._document = document;\n this._responseArid = responseArid;\n }\n\n /**\n * Create a new DkgProposedParticipant from a UR string and response ARID.\n *\n * Port of `DkgProposedParticipant::new()` from proposed_participant.rs lines 22-26.\n */\n static create(urString: string, responseArid: ARID): DkgProposedParticipant {\n const [envelope, document] = parseXidEnvelope(urString);\n return new DkgProposedParticipant(urString, envelope, document, responseArid);\n }\n\n /**\n * Get the XID of this participant.\n *\n * Port of `DkgProposedParticipant::xid()` from proposed_participant.rs line 28.\n */\n xid(): XID {\n return this._document.xid();\n }\n\n /**\n * Get the XID document of this participant.\n *\n * Port of `DkgProposedParticipant::xid_document()` from proposed_participant.rs line 30.\n */\n xidDocument(): XIDDocument {\n return this._document;\n }\n\n /**\n * Get the UR string of the XID document.\n *\n * Port of `DkgProposedParticipant::xid_document_ur()` from proposed_participant.rs line 32.\n */\n xidDocumentUr(): string {\n return this._urString;\n }\n\n /**\n * Get the envelope containing the XID document.\n *\n * Port of `DkgProposedParticipant::xid_document_envelope()` from proposed_participant.rs line 34.\n */\n xidDocumentEnvelope(): Envelope {\n return this._envelope;\n }\n\n /**\n * Get the response ARID for this participant.\n *\n * Port of `DkgProposedParticipant::response_arid()` from proposed_participant.rs line 36.\n */\n responseArid(): ARID {\n return this._responseArid;\n }\n\n /**\n * Compare participants by XID for sorting.\n */\n compareTo(other: DkgProposedParticipant): number {\n const thisXid = this.xid().toString();\n const otherXid = other.xid().toString();\n return thisXid.localeCompare(otherXid);\n }\n}\n\n/**\n * Parse a XID envelope from a UR string.\n *\n * Port of `parse_xid_envelope()` from proposed_participant.rs lines 39-60.\n */\nfunction parseXidEnvelope(input: string): [Envelope, XIDDocument] {\n const trimmed = input.trim();\n if (trimmed.length === 0) {\n throw new Error(\"XID document is required\");\n }\n\n const ur = UR.fromURString(trimmed);\n const urType = ur.urTypeStr();\n if (urType !== \"xid\" && urType !== \"envelope\") {\n throw new Error(`Expected a ur:xid document, found ur:${urType}`);\n }\n\n const envelopeCbor = ur.cbor();\n // Try tagged CBOR first, then untagged\n let envelope: Envelope;\n try {\n envelope = Envelope.fromTaggedCbor(envelopeCbor);\n } catch {\n envelope = Envelope.fromUntaggedCbor(envelopeCbor);\n }\n\n const document = XIDDocument.fromEnvelope(envelope, undefined, XIDVerifySignature.Inception);\n\n return [envelope, document];\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG Group Invite structures.\n *\n * Port of dkg/group_invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { ARID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope, Function as EnvelopeFunction } from \"@bcts/envelope\";\nimport { SealedRequest, SealedResponse } from \"@bcts/gstp\";\nimport { XIDDocument, XIDVerifySignature } from \"@bcts/xid\";\n\nimport { DkgProposedParticipant } from \"./proposed-participant.js\";\n\n/**\n * Result of a DKG invitation.\n *\n * Port of `enum DkgInvitationResult` from group_invite.rs lines 170-173.\n */\nexport type DkgInvitationResult = { type: \"accepted\" } | { type: \"declined\"; reason: string };\n\n/**\n * Helper to create an accepted result.\n */\nexport function accepted(): DkgInvitationResult {\n return { type: \"accepted\" };\n}\n\n/**\n * Helper to create a declined result.\n */\nexport function declined(reason: string): DkgInvitationResult {\n return { type: \"declined\", reason };\n}\n\n/**\n * DKG Invite - represents an invitation to participate in a DKG session.\n *\n * Port of `struct DkgInvite` from group_invite.rs lines 11-27.\n */\nexport class DkgInvite {\n private readonly _requestId: ARID;\n private readonly _sender: XIDDocument;\n private readonly _groupId: ARID;\n private readonly _date: Date;\n private readonly _validUntil: Date;\n private readonly _minSigners: number;\n private readonly _charter: string;\n private readonly _orderedParticipants: DkgProposedParticipant[];\n\n private constructor(\n requestId: ARID,\n sender: XIDDocument,\n groupId: ARID,\n date: Date,\n validUntil: Date,\n minSigners: number,\n charter: string,\n orderedParticipants: DkgProposedParticipant[],\n ) {\n this._requestId = requestId;\n this._sender = sender;\n this._groupId = groupId;\n this._date = date;\n this._validUntil = validUntil;\n this._minSigners = minSigners;\n this._charter = charter;\n this._orderedParticipants = orderedParticipants;\n }\n\n /**\n * Create a new DKG invite.\n *\n * Port of `DkgInvite::new()` from group_invite.rs lines 30-67.\n */\n static create(\n requestId: ARID,\n sender: XIDDocument,\n groupId: ARID,\n date: Date,\n validUntil: Date,\n minSigners: number,\n charter: string,\n participants: string[],\n responseArids: ARID[],\n ): DkgInvite {\n if (participants.length !== responseArids.length) {\n throw new Error(\n `Number of participants (${participants.length}) does not match number of response ARIDs (${responseArids.length})`,\n );\n }\n\n if (minSigners < 2) {\n throw new Error(\"min_signers must be at least 2\");\n }\n\n const orderedParticipants = participants.map((urString, i) =>\n DkgProposedParticipant.create(urString, responseArids[i]),\n );\n\n if (minSigners > orderedParticipants.length) {\n throw new Error(\"min_signers cannot exceed number of participants\");\n }\n\n // Sort by XID\n orderedParticipants.sort((a, b) => a.compareTo(b));\n\n return new DkgInvite(\n requestId,\n sender,\n groupId,\n date,\n validUntil,\n minSigners,\n charter,\n orderedParticipants,\n );\n }\n\n requestId(): ARID {\n return this._requestId;\n }\n\n sender(): XIDDocument {\n return this._sender;\n }\n\n groupId(): ARID {\n return this._groupId;\n }\n\n date(): Date {\n return this._date;\n }\n\n validUntil(): Date {\n return this._validUntil;\n }\n\n minSigners(): number {\n return this._minSigners;\n }\n\n charter(): string {\n return this._charter;\n }\n\n participants(): DkgProposedParticipant[] {\n return this._orderedParticipants;\n }\n\n /**\n * Create a GSTP sealed request from this invite.\n *\n * Port of `DkgInvite::to_request()` from group_invite.rs lines 87-121.\n */\n toRequest(): SealedRequest {\n let request = SealedRequest.new(\"dkgInvite\", this.requestId(), this.sender())\n .withParameter(\"group\", this.groupId())\n .withParameter(\"minSigners\", BigInt(this.minSigners()))\n .withParameter(\"charter\", this.charter())\n .withDate(this.date())\n .withParameter(\"validUntil\", CborDate.fromDatetime(this.validUntil()));\n\n for (const participant of this.participants()) {\n const xidDocumentEnvelope = participant.xidDocumentEnvelope();\n const responseArid = participant.responseArid();\n const encryptionKey = participant.xidDocument().encryptionKey();\n\n if (encryptionKey === undefined) {\n throw new Error(\"Participant XID document has no encryption key\");\n }\n\n const encryptedResponseArid = Envelope.new(responseArid).encryptToRecipients([encryptionKey]);\n\n const participantEnvelope = xidDocumentEnvelope\n .wrap()\n .addAssertion(\"response_arid\", encryptedResponseArid);\n\n request = request.withParameter(\"participant\", participantEnvelope);\n }\n\n return request;\n }\n\n /**\n * Creates a signed but unencrypted envelope for auditing/preview.\n *\n * Port of `DkgInvite::to_unsealed_envelope()` from group_invite.rs lines 124-139.\n */\n toUnsealedEnvelope(): Envelope {\n const request = this.toRequest();\n const sender = this.sender();\n const signerPrivateKeys = sender.inceptionPrivateKeys();\n\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Sender XID document has no inception signing key\");\n }\n\n return request.toEnvelope(\n this.validUntil(),\n signerPrivateKeys,\n undefined, // No recipient = signed but not encrypted\n );\n }\n\n /**\n * Creates a sealed envelope encrypted to all participants.\n *\n * Port of `DkgInvite::to_envelope()` from group_invite.rs lines 142-166.\n */\n toEnvelope(): Envelope {\n const request = this.toRequest();\n const sender = this.sender();\n const signerPrivateKeys = sender.inceptionPrivateKeys();\n\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Sender XID document has no inception signing key\");\n }\n\n const recipients = this.participants().map((p) => p.xidDocument());\n\n return request.toEnvelopeForRecipients(this.validUntil(), signerPrivateKeys, recipients);\n }\n}\n\n/**\n * DKG Invitation - represents a received invitation from a participant's perspective.\n *\n * Port of `struct DkgInvitation` from group_invite.rs lines 175-186.\n */\nexport class DkgInvitation {\n private readonly _responseArid: ARID;\n private readonly _validUntil: Date;\n private readonly _sender: XIDDocument;\n private readonly _requestId: ARID;\n private readonly _peerContinuation: Envelope | undefined;\n private readonly _minSigners: number;\n private readonly _charter: string;\n private readonly _groupId: ARID;\n\n private constructor(\n responseArid: ARID,\n validUntil: Date,\n sender: XIDDocument,\n requestId: ARID,\n peerContinuation: Envelope | undefined,\n minSigners: number,\n charter: string,\n groupId: ARID,\n ) {\n this._responseArid = responseArid;\n this._validUntil = validUntil;\n this._sender = sender;\n this._requestId = requestId;\n this._peerContinuation = peerContinuation;\n this._minSigners = minSigners;\n this._charter = charter;\n this._groupId = groupId;\n }\n\n responseArid(): ARID {\n return this._responseArid;\n }\n\n validUntil(): Date {\n return this._validUntil;\n }\n\n sender(): XIDDocument {\n return this._sender;\n }\n\n requestId(): ARID {\n return this._requestId;\n }\n\n peerContinuation(): Envelope | undefined {\n return this._peerContinuation;\n }\n\n minSigners(): number {\n return this._minSigners;\n }\n\n charter(): string {\n return this._charter;\n }\n\n groupId(): ARID {\n return this._groupId;\n }\n\n /**\n * Build a GSTP response for this invitation result.\n *\n * Port of `DkgInvitation::to_response()` from group_invite.rs lines 207-224.\n */\n toResponse(response: DkgInvitationResult, recipient: XIDDocument): SealedResponse {\n let base: SealedResponse;\n if (response.type === \"accepted\") {\n base = SealedResponse.newSuccess(this.requestId(), recipient);\n } else {\n base = SealedResponse.newFailure(this.requestId(), recipient).withError(response.reason);\n }\n\n return base.withPeerContinuation(this.peerContinuation());\n }\n\n /**\n * Create a signed/encrypted GSTP envelope containing the response for the coordinator.\n *\n * Port of `DkgInvitation::to_envelope()` from group_invite.rs lines 228-244.\n */\n toEnvelope(response: DkgInvitationResult, recipient: XIDDocument): Envelope {\n const responseObj = this.toResponse(response, recipient);\n const signerPrivateKeys = recipient.inceptionPrivateKeys();\n\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Recipient XID document has no signing keys\");\n }\n\n const recipients = [this.sender()];\n\n return responseObj.toEnvelopeForRecipients(this.validUntil(), signerPrivateKeys, recipients);\n }\n\n /**\n * Parse a DKG invitation from an invite envelope.\n *\n * Port of `DkgInvitation::from_invite()` from group_invite.rs lines 255-344.\n */\n static fromInvite(\n invite: Envelope,\n now: Date,\n expectedSender: XIDDocument | undefined,\n recipient: XIDDocument,\n ): DkgInvitation {\n const recipientPrivateKeys = recipient.inceptionPrivateKeys();\n\n if (recipientPrivateKeys === undefined) {\n throw new Error(\"Recipient XID document has no inception private keys\");\n }\n\n const sealedRequest = SealedRequest.tryFromEnvelope(\n invite,\n undefined,\n now,\n recipientPrivateKeys,\n );\n\n if (expectedSender !== undefined && sealedRequest.sender().xid() !== expectedSender.xid()) {\n throw new Error(\"Invite sender does not match expected sender\");\n }\n\n if (!sealedRequest.request().function().equals(EnvelopeFunction.fromString(\"dkgInvite\"))) {\n throw new Error(\"Unexpected invite function\");\n }\n\n const validUntil = sealedRequest.extractObjectForParameter<Date>(\"validUntil\");\n\n if (validUntil <= now) {\n throw new Error(\"Invitation expired\");\n }\n\n const recipientXid = recipient.xid();\n const minSigners = sealedRequest.extractObjectForParameter<number>(\"minSigners\");\n const charter = sealedRequest.extractObjectForParameter<string>(\"charter\");\n const groupId = sealedRequest.extractObjectForParameter<ARID>(\"group\");\n const participantObjects = sealedRequest.objectsForParameter(\"participant\");\n\n if (minSigners < 2) {\n throw new Error(\"min_signers must be at least 2\");\n }\n\n if (minSigners > participantObjects.length) {\n throw new Error(\"min_signers exceeds participant count\");\n }\n\n for (const participant of participantObjects) {\n const xidDocumentEnvelope = participant.tryUnwrap();\n const xidDocument = XIDDocument.fromEnvelope(\n xidDocumentEnvelope,\n undefined,\n XIDVerifySignature.Inception,\n );\n\n if (xidDocument.xid() !== recipientXid) {\n continue;\n }\n\n const encryptedResponseArid = participant.objectForPredicate(\"response_arid\");\n const responseAridEnvelope = encryptedResponseArid.decryptToRecipient(recipientPrivateKeys);\n const responseArid: ARID = responseAridEnvelope.extractSubject((cbor) =>\n ARID.fromTaggedCbor(cbor),\n );\n\n return new DkgInvitation(\n responseArid,\n validUntil,\n sealedRequest.sender(),\n sealedRequest.request().id(),\n sealedRequest.peerContinuation(),\n minSigners,\n charter,\n groupId,\n );\n }\n\n throw new Error(\"Recipient not found in invite\");\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["DkgProposedParticipant","SealedRequest","CborDate","Envelope","SealedResponse","EnvelopeFunction","XIDDocument","XIDVerifySignature","ARID"],"sources":["../../src/dkg/group-invite.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG Group Invite structures.\n *\n * Port of dkg/group_invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { ARID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope, Function as EnvelopeFunction } from \"@bcts/envelope\";\nimport { SealedRequest, SealedResponse } from \"@bcts/gstp\";\nimport { XIDDocument, XIDVerifySignature } from \"@bcts/xid\";\n\nimport { DkgProposedParticipant } from \"./proposed-participant.js\";\n\n/**\n * Result of a DKG invitation.\n *\n * Port of `enum DkgInvitationResult` from group_invite.rs lines 170-173.\n */\nexport type DkgInvitationResult = { type: \"accepted\" } | { type: \"declined\"; reason: string };\n\n/**\n * Helper to create an accepted result.\n */\nexport function accepted(): DkgInvitationResult {\n return { type: \"accepted\" };\n}\n\n/**\n * Helper to create a declined result.\n */\nexport function declined(reason: string): DkgInvitationResult {\n return { type: \"declined\", reason };\n}\n\n/**\n * DKG Invite - represents an invitation to participate in a DKG session.\n *\n * Port of `struct DkgInvite` from group_invite.rs lines 11-27.\n */\nexport class DkgInvite {\n private readonly _requestId: ARID;\n private readonly _sender: XIDDocument;\n private readonly _groupId: ARID;\n private readonly _date: Date;\n private readonly _validUntil: Date;\n private readonly _minSigners: number;\n private readonly _charter: string;\n private readonly _orderedParticipants: DkgProposedParticipant[];\n\n private constructor(\n requestId: ARID,\n sender: XIDDocument,\n groupId: ARID,\n date: Date,\n validUntil: Date,\n minSigners: number,\n charter: string,\n orderedParticipants: DkgProposedParticipant[],\n ) {\n this._requestId = requestId;\n this._sender = sender;\n this._groupId = groupId;\n this._date = date;\n this._validUntil = validUntil;\n this._minSigners = minSigners;\n this._charter = charter;\n this._orderedParticipants = orderedParticipants;\n }\n\n /**\n * Create a new DKG invite.\n *\n * Port of `DkgInvite::new()` from group_invite.rs lines 30-67.\n */\n static create(\n requestId: ARID,\n sender: XIDDocument,\n groupId: ARID,\n date: Date,\n validUntil: Date,\n minSigners: number,\n charter: string,\n participants: string[],\n responseArids: ARID[],\n ): DkgInvite {\n if (participants.length !== responseArids.length) {\n throw new Error(\n `Number of participants (${participants.length}) does not match number of response ARIDs (${responseArids.length})`,\n );\n }\n\n if (minSigners < 2) {\n throw new Error(\"min_signers must be at least 2\");\n }\n\n const orderedParticipants = participants.map((urString, i) =>\n DkgProposedParticipant.create(urString, responseArids[i]),\n );\n\n if (minSigners > orderedParticipants.length) {\n throw new Error(\"min_signers cannot exceed number of participants\");\n }\n\n // Sort by XID\n orderedParticipants.sort((a, b) => a.compareTo(b));\n\n return new DkgInvite(\n requestId,\n sender,\n groupId,\n date,\n validUntil,\n minSigners,\n charter,\n orderedParticipants,\n );\n }\n\n requestId(): ARID {\n return this._requestId;\n }\n\n sender(): XIDDocument {\n return this._sender;\n }\n\n groupId(): ARID {\n return this._groupId;\n }\n\n date(): Date {\n return this._date;\n }\n\n validUntil(): Date {\n return this._validUntil;\n }\n\n minSigners(): number {\n return this._minSigners;\n }\n\n charter(): string {\n return this._charter;\n }\n\n participants(): DkgProposedParticipant[] {\n return this._orderedParticipants;\n }\n\n /**\n * Create a GSTP sealed request from this invite.\n *\n * Port of `DkgInvite::to_request()` from group_invite.rs lines 87-121.\n */\n toRequest(): SealedRequest {\n let request = SealedRequest.new(\"dkgInvite\", this.requestId(), this.sender())\n .withParameter(\"group\", this.groupId())\n .withParameter(\"minSigners\", BigInt(this.minSigners()))\n .withParameter(\"charter\", this.charter())\n .withDate(this.date())\n .withParameter(\"validUntil\", CborDate.fromDatetime(this.validUntil()));\n\n for (const participant of this.participants()) {\n const xidDocumentEnvelope = participant.xidDocumentEnvelope();\n const responseArid = participant.responseArid();\n const encryptionKey = participant.xidDocument().encryptionKey();\n\n if (encryptionKey === undefined) {\n throw new Error(\"Participant XID document has no encryption key\");\n }\n\n const encryptedResponseArid = Envelope.new(responseArid).encryptToRecipients([encryptionKey]);\n\n const participantEnvelope = xidDocumentEnvelope\n .wrap()\n .addAssertion(\"response_arid\", encryptedResponseArid);\n\n request = request.withParameter(\"participant\", participantEnvelope);\n }\n\n return request;\n }\n\n /**\n * Creates a signed but unencrypted envelope for auditing/preview.\n *\n * Port of `DkgInvite::to_unsealed_envelope()` from group_invite.rs lines 124-139.\n */\n toUnsealedEnvelope(): Envelope {\n const request = this.toRequest();\n const sender = this.sender();\n const signerPrivateKeys = sender.inceptionPrivateKeys();\n\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Sender XID document has no inception signing key\");\n }\n\n return request.toEnvelope(\n this.validUntil(),\n signerPrivateKeys,\n undefined, // No recipient = signed but not encrypted\n );\n }\n\n /**\n * Creates a sealed envelope encrypted to all participants.\n *\n * Port of `DkgInvite::to_envelope()` from group_invite.rs lines 142-166.\n */\n toEnvelope(): Envelope {\n const request = this.toRequest();\n const sender = this.sender();\n const signerPrivateKeys = sender.inceptionPrivateKeys();\n\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Sender XID document has no inception signing key\");\n }\n\n const recipients = this.participants().map((p) => p.xidDocument());\n\n return request.toEnvelopeForRecipients(this.validUntil(), signerPrivateKeys, recipients);\n }\n}\n\n/**\n * DKG Invitation - represents a received invitation from a participant's perspective.\n *\n * Port of `struct DkgInvitation` from group_invite.rs lines 175-186.\n */\nexport class DkgInvitation {\n private readonly _responseArid: ARID;\n private readonly _validUntil: Date;\n private readonly _sender: XIDDocument;\n private readonly _requestId: ARID;\n private readonly _peerContinuation: Envelope | undefined;\n private readonly _minSigners: number;\n private readonly _charter: string;\n private readonly _groupId: ARID;\n\n private constructor(\n responseArid: ARID,\n validUntil: Date,\n sender: XIDDocument,\n requestId: ARID,\n peerContinuation: Envelope | undefined,\n minSigners: number,\n charter: string,\n groupId: ARID,\n ) {\n this._responseArid = responseArid;\n this._validUntil = validUntil;\n this._sender = sender;\n this._requestId = requestId;\n this._peerContinuation = peerContinuation;\n this._minSigners = minSigners;\n this._charter = charter;\n this._groupId = groupId;\n }\n\n responseArid(): ARID {\n return this._responseArid;\n }\n\n validUntil(): Date {\n return this._validUntil;\n }\n\n sender(): XIDDocument {\n return this._sender;\n }\n\n requestId(): ARID {\n return this._requestId;\n }\n\n peerContinuation(): Envelope | undefined {\n return this._peerContinuation;\n }\n\n minSigners(): number {\n return this._minSigners;\n }\n\n charter(): string {\n return this._charter;\n }\n\n groupId(): ARID {\n return this._groupId;\n }\n\n /**\n * Build a GSTP response for this invitation result.\n *\n * Port of `DkgInvitation::to_response()` from group_invite.rs lines 207-224.\n */\n toResponse(response: DkgInvitationResult, recipient: XIDDocument): SealedResponse {\n let base: SealedResponse;\n if (response.type === \"accepted\") {\n base = SealedResponse.newSuccess(this.requestId(), recipient);\n } else {\n base = SealedResponse.newFailure(this.requestId(), recipient).withError(response.reason);\n }\n\n return base.withPeerContinuation(this.peerContinuation());\n }\n\n /**\n * Create a signed/encrypted GSTP envelope containing the response for the coordinator.\n *\n * Port of `DkgInvitation::to_envelope()` from group_invite.rs lines 228-244.\n */\n toEnvelope(response: DkgInvitationResult, recipient: XIDDocument): Envelope {\n const responseObj = this.toResponse(response, recipient);\n const signerPrivateKeys = recipient.inceptionPrivateKeys();\n\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Recipient XID document has no signing keys\");\n }\n\n const recipients = [this.sender()];\n\n return responseObj.toEnvelopeForRecipients(this.validUntil(), signerPrivateKeys, recipients);\n }\n\n /**\n * Parse a DKG invitation from an invite envelope.\n *\n * Port of `DkgInvitation::from_invite()` from group_invite.rs lines 255-344.\n */\n static fromInvite(\n invite: Envelope,\n now: Date,\n expectedSender: XIDDocument | undefined,\n recipient: XIDDocument,\n ): DkgInvitation {\n const recipientPrivateKeys = recipient.inceptionPrivateKeys();\n\n if (recipientPrivateKeys === undefined) {\n throw new Error(\"Recipient XID document has no inception private keys\");\n }\n\n const sealedRequest = SealedRequest.tryFromEnvelope(\n invite,\n undefined,\n now,\n recipientPrivateKeys,\n );\n\n // Rust `group_invite.rs:275-279` uses `!=` on `XID`, which is the\n // derived `PartialEq` (byte-wise compare on the 32-byte ARID). TS\n // `!==` is reference identity — two distinct XID instances with\n // the same bytes would fail. Compare via hex equality instead.\n if (\n expectedSender !== undefined &&\n !sealedRequest.sender().xid().equals(expectedSender.xid())\n ) {\n throw new Error(\"Invite sender does not match expected sender\");\n }\n\n if (!sealedRequest.request().function().equals(EnvelopeFunction.fromString(\"dkgInvite\"))) {\n throw new Error(\"Unexpected invite function\");\n }\n\n const validUntil = sealedRequest.extractObjectForParameter<Date>(\"validUntil\");\n\n if (validUntil <= now) {\n throw new Error(\"Invitation expired\");\n }\n\n const recipientXid = recipient.xid();\n const minSigners = sealedRequest.extractObjectForParameter<number>(\"minSigners\");\n const charter = sealedRequest.extractObjectForParameter<string>(\"charter\");\n const groupId = sealedRequest.extractObjectForParameter<ARID>(\"group\");\n const participantObjects = sealedRequest.objectsForParameter(\"participant\");\n\n if (minSigners < 2) {\n throw new Error(\"min_signers must be at least 2\");\n }\n\n if (minSigners > participantObjects.length) {\n throw new Error(\"min_signers exceeds participant count\");\n }\n\n for (const participant of participantObjects) {\n const xidDocumentEnvelope = participant.tryUnwrap();\n const xidDocument = XIDDocument.fromEnvelope(\n xidDocumentEnvelope,\n undefined,\n XIDVerifySignature.Inception,\n );\n\n // Rust `group_invite.rs` compares via `XID::PartialEq` (byte-wise).\n // TS reference identity would never match for two distinct\n // `XID` instances representing the same identity.\n if (!xidDocument.xid().equals(recipientXid)) {\n continue;\n }\n\n const encryptedResponseArid = participant.objectForPredicate(\"response_arid\");\n const responseAridEnvelope = encryptedResponseArid.decryptToRecipient(recipientPrivateKeys);\n const responseArid: ARID = responseAridEnvelope.extractSubject((cbor) =>\n ARID.fromTaggedCbor(cbor),\n );\n\n return new DkgInvitation(\n responseArid,\n validUntil,\n sealedRequest.sender(),\n sealedRequest.request().id(),\n sealedRequest.peerContinuation(),\n minSigners,\n charter,\n groupId,\n );\n }\n\n throw new Error(\"Recipient not found in invite\");\n }\n}\n"],"mappings":"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"}
|
package/dist/dkg/index.d.cts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as declined, i as accepted, n as DkgInvitationResult, o as DkgProposedParticipant, r as DkgInvite, t as DkgInvitation } from "../index-
|
|
2
|
-
export { DkgInvitation, DkgInvitationResult, DkgInvite, DkgProposedParticipant, accepted, declined };
|
|
1
|
+
import { a as declined, i as accepted, n as DkgInvitationResult, o as DkgProposedParticipant, r as DkgInvite, s as compareXidBytes, t as DkgInvitation } from "../index-B3c-80VS.cjs";
|
|
2
|
+
export { DkgInvitation, DkgInvitationResult, DkgInvite, DkgProposedParticipant, accepted, compareXidBytes, declined };
|
package/dist/dkg/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as declined, i as accepted, n as DkgInvitationResult, o as DkgProposedParticipant, r as DkgInvite, t as DkgInvitation } from "../index-
|
|
2
|
-
export { DkgInvitation, DkgInvitationResult, DkgInvite, DkgProposedParticipant, accepted, declined };
|
|
1
|
+
import { a as declined, i as accepted, n as DkgInvitationResult, o as DkgProposedParticipant, r as DkgInvite, s as compareXidBytes, t as DkgInvitation } from "../index-D3QTWkEm.mjs";
|
|
2
|
+
export { DkgInvitation, DkgInvitationResult, DkgInvite, DkgProposedParticipant, accepted, compareXidBytes, declined };
|
package/dist/dkg/index.mjs
CHANGED
|
@@ -1,106 +1,9 @@
|
|
|
1
|
+
import { n as compareXidBytes, t as DkgProposedParticipant } from "../proposed-participant-cWM7iUrO.mjs";
|
|
1
2
|
import { ARID } from "@bcts/components";
|
|
2
3
|
import { CborDate } from "@bcts/dcbor";
|
|
3
4
|
import { Envelope, Function } from "@bcts/envelope";
|
|
4
5
|
import { SealedRequest, SealedResponse } from "@bcts/gstp";
|
|
5
6
|
import { XIDDocument, XIDVerifySignature } from "@bcts/xid";
|
|
6
|
-
import { UR } from "@bcts/uniform-resources";
|
|
7
|
-
//#region src/dkg/proposed-participant.ts
|
|
8
|
-
/**
|
|
9
|
-
* A proposed participant in a DKG session.
|
|
10
|
-
*
|
|
11
|
-
* Port of `struct DkgProposedParticipant` from proposed_participant.rs lines 8-13.
|
|
12
|
-
*/
|
|
13
|
-
var DkgProposedParticipant = class DkgProposedParticipant {
|
|
14
|
-
_urString;
|
|
15
|
-
_envelope;
|
|
16
|
-
_document;
|
|
17
|
-
_responseArid;
|
|
18
|
-
constructor(urString, envelope, document, responseArid) {
|
|
19
|
-
this._urString = urString;
|
|
20
|
-
this._envelope = envelope;
|
|
21
|
-
this._document = document;
|
|
22
|
-
this._responseArid = responseArid;
|
|
23
|
-
}
|
|
24
|
-
/**
|
|
25
|
-
* Create a new DkgProposedParticipant from a UR string and response ARID.
|
|
26
|
-
*
|
|
27
|
-
* Port of `DkgProposedParticipant::new()` from proposed_participant.rs lines 22-26.
|
|
28
|
-
*/
|
|
29
|
-
static create(urString, responseArid) {
|
|
30
|
-
const [envelope, document] = parseXidEnvelope(urString);
|
|
31
|
-
return new DkgProposedParticipant(urString, envelope, document, responseArid);
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Get the XID of this participant.
|
|
35
|
-
*
|
|
36
|
-
* Port of `DkgProposedParticipant::xid()` from proposed_participant.rs line 28.
|
|
37
|
-
*/
|
|
38
|
-
xid() {
|
|
39
|
-
return this._document.xid();
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Get the XID document of this participant.
|
|
43
|
-
*
|
|
44
|
-
* Port of `DkgProposedParticipant::xid_document()` from proposed_participant.rs line 30.
|
|
45
|
-
*/
|
|
46
|
-
xidDocument() {
|
|
47
|
-
return this._document;
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Get the UR string of the XID document.
|
|
51
|
-
*
|
|
52
|
-
* Port of `DkgProposedParticipant::xid_document_ur()` from proposed_participant.rs line 32.
|
|
53
|
-
*/
|
|
54
|
-
xidDocumentUr() {
|
|
55
|
-
return this._urString;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* Get the envelope containing the XID document.
|
|
59
|
-
*
|
|
60
|
-
* Port of `DkgProposedParticipant::xid_document_envelope()` from proposed_participant.rs line 34.
|
|
61
|
-
*/
|
|
62
|
-
xidDocumentEnvelope() {
|
|
63
|
-
return this._envelope;
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Get the response ARID for this participant.
|
|
67
|
-
*
|
|
68
|
-
* Port of `DkgProposedParticipant::response_arid()` from proposed_participant.rs line 36.
|
|
69
|
-
*/
|
|
70
|
-
responseArid() {
|
|
71
|
-
return this._responseArid;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Compare participants by XID for sorting.
|
|
75
|
-
*/
|
|
76
|
-
compareTo(other) {
|
|
77
|
-
const thisXid = this.xid().toString();
|
|
78
|
-
const otherXid = other.xid().toString();
|
|
79
|
-
return thisXid.localeCompare(otherXid);
|
|
80
|
-
}
|
|
81
|
-
};
|
|
82
|
-
/**
|
|
83
|
-
* Parse a XID envelope from a UR string.
|
|
84
|
-
*
|
|
85
|
-
* Port of `parse_xid_envelope()` from proposed_participant.rs lines 39-60.
|
|
86
|
-
*/
|
|
87
|
-
function parseXidEnvelope(input) {
|
|
88
|
-
const trimmed = input.trim();
|
|
89
|
-
if (trimmed.length === 0) throw new Error("XID document is required");
|
|
90
|
-
const ur = UR.fromURString(trimmed);
|
|
91
|
-
const urType = ur.urTypeStr();
|
|
92
|
-
if (urType !== "xid" && urType !== "envelope") throw new Error(`Expected a ur:xid document, found ur:${urType}`);
|
|
93
|
-
const envelopeCbor = ur.cbor();
|
|
94
|
-
let envelope;
|
|
95
|
-
try {
|
|
96
|
-
envelope = Envelope.fromTaggedCbor(envelopeCbor);
|
|
97
|
-
} catch {
|
|
98
|
-
envelope = Envelope.fromUntaggedCbor(envelopeCbor);
|
|
99
|
-
}
|
|
100
|
-
const document = XIDDocument.fromEnvelope(envelope, void 0, XIDVerifySignature.Inception);
|
|
101
|
-
return [envelope, document];
|
|
102
|
-
}
|
|
103
|
-
//#endregion
|
|
104
7
|
//#region src/dkg/group-invite.ts
|
|
105
8
|
/**
|
|
106
9
|
* Copyright © 2023-2026 Blockchain Commons, LLC
|
|
@@ -311,7 +214,7 @@ var DkgInvitation = class DkgInvitation {
|
|
|
311
214
|
const recipientPrivateKeys = recipient.inceptionPrivateKeys();
|
|
312
215
|
if (recipientPrivateKeys === void 0) throw new Error("Recipient XID document has no inception private keys");
|
|
313
216
|
const sealedRequest = SealedRequest.tryFromEnvelope(invite, void 0, now, recipientPrivateKeys);
|
|
314
|
-
if (expectedSender !== void 0 && sealedRequest.sender().xid()
|
|
217
|
+
if (expectedSender !== void 0 && !sealedRequest.sender().xid().equals(expectedSender.xid())) throw new Error("Invite sender does not match expected sender");
|
|
315
218
|
if (!sealedRequest.request().function().equals(Function.fromString("dkgInvite"))) throw new Error("Unexpected invite function");
|
|
316
219
|
const validUntil = sealedRequest.extractObjectForParameter("validUntil");
|
|
317
220
|
if (validUntil <= now) throw new Error("Invitation expired");
|
|
@@ -324,13 +227,13 @@ var DkgInvitation = class DkgInvitation {
|
|
|
324
227
|
if (minSigners > participantObjects.length) throw new Error("min_signers exceeds participant count");
|
|
325
228
|
for (const participant of participantObjects) {
|
|
326
229
|
const xidDocumentEnvelope = participant.tryUnwrap();
|
|
327
|
-
if (XIDDocument.fromEnvelope(xidDocumentEnvelope, void 0, XIDVerifySignature.Inception).xid()
|
|
230
|
+
if (!XIDDocument.fromEnvelope(xidDocumentEnvelope, void 0, XIDVerifySignature.Inception).xid().equals(recipientXid)) continue;
|
|
328
231
|
return new DkgInvitation(participant.objectForPredicate("response_arid").decryptToRecipient(recipientPrivateKeys).extractSubject((cbor) => ARID.fromTaggedCbor(cbor)), validUntil, sealedRequest.sender(), sealedRequest.request().id(), sealedRequest.peerContinuation(), minSigners, charter, groupId);
|
|
329
232
|
}
|
|
330
233
|
throw new Error("Recipient not found in invite");
|
|
331
234
|
}
|
|
332
235
|
};
|
|
333
236
|
//#endregion
|
|
334
|
-
export { DkgInvitation, DkgInvite, DkgProposedParticipant, accepted, declined };
|
|
237
|
+
export { DkgInvitation, DkgInvite, DkgProposedParticipant, accepted, compareXidBytes, declined };
|
|
335
238
|
|
|
336
239
|
//# sourceMappingURL=index.mjs.map
|
package/dist/dkg/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["EnvelopeFunction"],"sources":["../../src/dkg/proposed-participant.ts","../../src/dkg/group-invite.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG Proposed Participant.\n *\n * Port of dkg/proposed_participant.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { type ARID, type XID } from \"@bcts/components\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { UR } from \"@bcts/uniform-resources\";\nimport { XIDDocument, XIDVerifySignature } from \"@bcts/xid\";\n\n/**\n * A proposed participant in a DKG session.\n *\n * Port of `struct DkgProposedParticipant` from proposed_participant.rs lines 8-13.\n */\nexport class DkgProposedParticipant {\n private readonly _urString: string;\n private readonly _envelope: Envelope;\n private readonly _document: XIDDocument;\n private readonly _responseArid: ARID;\n\n private constructor(\n urString: string,\n envelope: Envelope,\n document: XIDDocument,\n responseArid: ARID,\n ) {\n this._urString = urString;\n this._envelope = envelope;\n this._document = document;\n this._responseArid = responseArid;\n }\n\n /**\n * Create a new DkgProposedParticipant from a UR string and response ARID.\n *\n * Port of `DkgProposedParticipant::new()` from proposed_participant.rs lines 22-26.\n */\n static create(urString: string, responseArid: ARID): DkgProposedParticipant {\n const [envelope, document] = parseXidEnvelope(urString);\n return new DkgProposedParticipant(urString, envelope, document, responseArid);\n }\n\n /**\n * Get the XID of this participant.\n *\n * Port of `DkgProposedParticipant::xid()` from proposed_participant.rs line 28.\n */\n xid(): XID {\n return this._document.xid();\n }\n\n /**\n * Get the XID document of this participant.\n *\n * Port of `DkgProposedParticipant::xid_document()` from proposed_participant.rs line 30.\n */\n xidDocument(): XIDDocument {\n return this._document;\n }\n\n /**\n * Get the UR string of the XID document.\n *\n * Port of `DkgProposedParticipant::xid_document_ur()` from proposed_participant.rs line 32.\n */\n xidDocumentUr(): string {\n return this._urString;\n }\n\n /**\n * Get the envelope containing the XID document.\n *\n * Port of `DkgProposedParticipant::xid_document_envelope()` from proposed_participant.rs line 34.\n */\n xidDocumentEnvelope(): Envelope {\n return this._envelope;\n }\n\n /**\n * Get the response ARID for this participant.\n *\n * Port of `DkgProposedParticipant::response_arid()` from proposed_participant.rs line 36.\n */\n responseArid(): ARID {\n return this._responseArid;\n }\n\n /**\n * Compare participants by XID for sorting.\n */\n compareTo(other: DkgProposedParticipant): number {\n const thisXid = this.xid().toString();\n const otherXid = other.xid().toString();\n return thisXid.localeCompare(otherXid);\n }\n}\n\n/**\n * Parse a XID envelope from a UR string.\n *\n * Port of `parse_xid_envelope()` from proposed_participant.rs lines 39-60.\n */\nfunction parseXidEnvelope(input: string): [Envelope, XIDDocument] {\n const trimmed = input.trim();\n if (trimmed.length === 0) {\n throw new Error(\"XID document is required\");\n }\n\n const ur = UR.fromURString(trimmed);\n const urType = ur.urTypeStr();\n if (urType !== \"xid\" && urType !== \"envelope\") {\n throw new Error(`Expected a ur:xid document, found ur:${urType}`);\n }\n\n const envelopeCbor = ur.cbor();\n // Try tagged CBOR first, then untagged\n let envelope: Envelope;\n try {\n envelope = Envelope.fromTaggedCbor(envelopeCbor);\n } catch {\n envelope = Envelope.fromUntaggedCbor(envelopeCbor);\n }\n\n const document = XIDDocument.fromEnvelope(envelope, undefined, XIDVerifySignature.Inception);\n\n return [envelope, document];\n}\n","/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG Group Invite structures.\n *\n * Port of dkg/group_invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { ARID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope, Function as EnvelopeFunction } from \"@bcts/envelope\";\nimport { SealedRequest, SealedResponse } from \"@bcts/gstp\";\nimport { XIDDocument, XIDVerifySignature } from \"@bcts/xid\";\n\nimport { DkgProposedParticipant } from \"./proposed-participant.js\";\n\n/**\n * Result of a DKG invitation.\n *\n * Port of `enum DkgInvitationResult` from group_invite.rs lines 170-173.\n */\nexport type DkgInvitationResult = { type: \"accepted\" } | { type: \"declined\"; reason: string };\n\n/**\n * Helper to create an accepted result.\n */\nexport function accepted(): DkgInvitationResult {\n return { type: \"accepted\" };\n}\n\n/**\n * Helper to create a declined result.\n */\nexport function declined(reason: string): DkgInvitationResult {\n return { type: \"declined\", reason };\n}\n\n/**\n * DKG Invite - represents an invitation to participate in a DKG session.\n *\n * Port of `struct DkgInvite` from group_invite.rs lines 11-27.\n */\nexport class DkgInvite {\n private readonly _requestId: ARID;\n private readonly _sender: XIDDocument;\n private readonly _groupId: ARID;\n private readonly _date: Date;\n private readonly _validUntil: Date;\n private readonly _minSigners: number;\n private readonly _charter: string;\n private readonly _orderedParticipants: DkgProposedParticipant[];\n\n private constructor(\n requestId: ARID,\n sender: XIDDocument,\n groupId: ARID,\n date: Date,\n validUntil: Date,\n minSigners: number,\n charter: string,\n orderedParticipants: DkgProposedParticipant[],\n ) {\n this._requestId = requestId;\n this._sender = sender;\n this._groupId = groupId;\n this._date = date;\n this._validUntil = validUntil;\n this._minSigners = minSigners;\n this._charter = charter;\n this._orderedParticipants = orderedParticipants;\n }\n\n /**\n * Create a new DKG invite.\n *\n * Port of `DkgInvite::new()` from group_invite.rs lines 30-67.\n */\n static create(\n requestId: ARID,\n sender: XIDDocument,\n groupId: ARID,\n date: Date,\n validUntil: Date,\n minSigners: number,\n charter: string,\n participants: string[],\n responseArids: ARID[],\n ): DkgInvite {\n if (participants.length !== responseArids.length) {\n throw new Error(\n `Number of participants (${participants.length}) does not match number of response ARIDs (${responseArids.length})`,\n );\n }\n\n if (minSigners < 2) {\n throw new Error(\"min_signers must be at least 2\");\n }\n\n const orderedParticipants = participants.map((urString, i) =>\n DkgProposedParticipant.create(urString, responseArids[i]),\n );\n\n if (minSigners > orderedParticipants.length) {\n throw new Error(\"min_signers cannot exceed number of participants\");\n }\n\n // Sort by XID\n orderedParticipants.sort((a, b) => a.compareTo(b));\n\n return new DkgInvite(\n requestId,\n sender,\n groupId,\n date,\n validUntil,\n minSigners,\n charter,\n orderedParticipants,\n );\n }\n\n requestId(): ARID {\n return this._requestId;\n }\n\n sender(): XIDDocument {\n return this._sender;\n }\n\n groupId(): ARID {\n return this._groupId;\n }\n\n date(): Date {\n return this._date;\n }\n\n validUntil(): Date {\n return this._validUntil;\n }\n\n minSigners(): number {\n return this._minSigners;\n }\n\n charter(): string {\n return this._charter;\n }\n\n participants(): DkgProposedParticipant[] {\n return this._orderedParticipants;\n }\n\n /**\n * Create a GSTP sealed request from this invite.\n *\n * Port of `DkgInvite::to_request()` from group_invite.rs lines 87-121.\n */\n toRequest(): SealedRequest {\n let request = SealedRequest.new(\"dkgInvite\", this.requestId(), this.sender())\n .withParameter(\"group\", this.groupId())\n .withParameter(\"minSigners\", BigInt(this.minSigners()))\n .withParameter(\"charter\", this.charter())\n .withDate(this.date())\n .withParameter(\"validUntil\", CborDate.fromDatetime(this.validUntil()));\n\n for (const participant of this.participants()) {\n const xidDocumentEnvelope = participant.xidDocumentEnvelope();\n const responseArid = participant.responseArid();\n const encryptionKey = participant.xidDocument().encryptionKey();\n\n if (encryptionKey === undefined) {\n throw new Error(\"Participant XID document has no encryption key\");\n }\n\n const encryptedResponseArid = Envelope.new(responseArid).encryptToRecipients([encryptionKey]);\n\n const participantEnvelope = xidDocumentEnvelope\n .wrap()\n .addAssertion(\"response_arid\", encryptedResponseArid);\n\n request = request.withParameter(\"participant\", participantEnvelope);\n }\n\n return request;\n }\n\n /**\n * Creates a signed but unencrypted envelope for auditing/preview.\n *\n * Port of `DkgInvite::to_unsealed_envelope()` from group_invite.rs lines 124-139.\n */\n toUnsealedEnvelope(): Envelope {\n const request = this.toRequest();\n const sender = this.sender();\n const signerPrivateKeys = sender.inceptionPrivateKeys();\n\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Sender XID document has no inception signing key\");\n }\n\n return request.toEnvelope(\n this.validUntil(),\n signerPrivateKeys,\n undefined, // No recipient = signed but not encrypted\n );\n }\n\n /**\n * Creates a sealed envelope encrypted to all participants.\n *\n * Port of `DkgInvite::to_envelope()` from group_invite.rs lines 142-166.\n */\n toEnvelope(): Envelope {\n const request = this.toRequest();\n const sender = this.sender();\n const signerPrivateKeys = sender.inceptionPrivateKeys();\n\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Sender XID document has no inception signing key\");\n }\n\n const recipients = this.participants().map((p) => p.xidDocument());\n\n return request.toEnvelopeForRecipients(this.validUntil(), signerPrivateKeys, recipients);\n }\n}\n\n/**\n * DKG Invitation - represents a received invitation from a participant's perspective.\n *\n * Port of `struct DkgInvitation` from group_invite.rs lines 175-186.\n */\nexport class DkgInvitation {\n private readonly _responseArid: ARID;\n private readonly _validUntil: Date;\n private readonly _sender: XIDDocument;\n private readonly _requestId: ARID;\n private readonly _peerContinuation: Envelope | undefined;\n private readonly _minSigners: number;\n private readonly _charter: string;\n private readonly _groupId: ARID;\n\n private constructor(\n responseArid: ARID,\n validUntil: Date,\n sender: XIDDocument,\n requestId: ARID,\n peerContinuation: Envelope | undefined,\n minSigners: number,\n charter: string,\n groupId: ARID,\n ) {\n this._responseArid = responseArid;\n this._validUntil = validUntil;\n this._sender = sender;\n this._requestId = requestId;\n this._peerContinuation = peerContinuation;\n this._minSigners = minSigners;\n this._charter = charter;\n this._groupId = groupId;\n }\n\n responseArid(): ARID {\n return this._responseArid;\n }\n\n validUntil(): Date {\n return this._validUntil;\n }\n\n sender(): XIDDocument {\n return this._sender;\n }\n\n requestId(): ARID {\n return this._requestId;\n }\n\n peerContinuation(): Envelope | undefined {\n return this._peerContinuation;\n }\n\n minSigners(): number {\n return this._minSigners;\n }\n\n charter(): string {\n return this._charter;\n }\n\n groupId(): ARID {\n return this._groupId;\n }\n\n /**\n * Build a GSTP response for this invitation result.\n *\n * Port of `DkgInvitation::to_response()` from group_invite.rs lines 207-224.\n */\n toResponse(response: DkgInvitationResult, recipient: XIDDocument): SealedResponse {\n let base: SealedResponse;\n if (response.type === \"accepted\") {\n base = SealedResponse.newSuccess(this.requestId(), recipient);\n } else {\n base = SealedResponse.newFailure(this.requestId(), recipient).withError(response.reason);\n }\n\n return base.withPeerContinuation(this.peerContinuation());\n }\n\n /**\n * Create a signed/encrypted GSTP envelope containing the response for the coordinator.\n *\n * Port of `DkgInvitation::to_envelope()` from group_invite.rs lines 228-244.\n */\n toEnvelope(response: DkgInvitationResult, recipient: XIDDocument): Envelope {\n const responseObj = this.toResponse(response, recipient);\n const signerPrivateKeys = recipient.inceptionPrivateKeys();\n\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Recipient XID document has no signing keys\");\n }\n\n const recipients = [this.sender()];\n\n return responseObj.toEnvelopeForRecipients(this.validUntil(), signerPrivateKeys, recipients);\n }\n\n /**\n * Parse a DKG invitation from an invite envelope.\n *\n * Port of `DkgInvitation::from_invite()` from group_invite.rs lines 255-344.\n */\n static fromInvite(\n invite: Envelope,\n now: Date,\n expectedSender: XIDDocument | undefined,\n recipient: XIDDocument,\n ): DkgInvitation {\n const recipientPrivateKeys = recipient.inceptionPrivateKeys();\n\n if (recipientPrivateKeys === undefined) {\n throw new Error(\"Recipient XID document has no inception private keys\");\n }\n\n const sealedRequest = SealedRequest.tryFromEnvelope(\n invite,\n undefined,\n now,\n recipientPrivateKeys,\n );\n\n if (expectedSender !== undefined && sealedRequest.sender().xid() !== expectedSender.xid()) {\n throw new Error(\"Invite sender does not match expected sender\");\n }\n\n if (!sealedRequest.request().function().equals(EnvelopeFunction.fromString(\"dkgInvite\"))) {\n throw new Error(\"Unexpected invite function\");\n }\n\n const validUntil = sealedRequest.extractObjectForParameter<Date>(\"validUntil\");\n\n if (validUntil <= now) {\n throw new Error(\"Invitation expired\");\n }\n\n const recipientXid = recipient.xid();\n const minSigners = sealedRequest.extractObjectForParameter<number>(\"minSigners\");\n const charter = sealedRequest.extractObjectForParameter<string>(\"charter\");\n const groupId = sealedRequest.extractObjectForParameter<ARID>(\"group\");\n const participantObjects = sealedRequest.objectsForParameter(\"participant\");\n\n if (minSigners < 2) {\n throw new Error(\"min_signers must be at least 2\");\n }\n\n if (minSigners > participantObjects.length) {\n throw new Error(\"min_signers exceeds participant count\");\n }\n\n for (const participant of participantObjects) {\n const xidDocumentEnvelope = participant.tryUnwrap();\n const xidDocument = XIDDocument.fromEnvelope(\n xidDocumentEnvelope,\n undefined,\n XIDVerifySignature.Inception,\n );\n\n if (xidDocument.xid() !== recipientXid) {\n continue;\n }\n\n const encryptedResponseArid = participant.objectForPredicate(\"response_arid\");\n const responseAridEnvelope = encryptedResponseArid.decryptToRecipient(recipientPrivateKeys);\n const responseArid: ARID = responseAridEnvelope.extractSubject((cbor) =>\n ARID.fromTaggedCbor(cbor),\n );\n\n return new DkgInvitation(\n responseArid,\n validUntil,\n sealedRequest.sender(),\n sealedRequest.request().id(),\n sealedRequest.peerContinuation(),\n minSigners,\n charter,\n groupId,\n );\n }\n\n throw new Error(\"Recipient not found in invite\");\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["EnvelopeFunction"],"sources":["../../src/dkg/group-invite.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG Group Invite structures.\n *\n * Port of dkg/group_invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { ARID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope, Function as EnvelopeFunction } from \"@bcts/envelope\";\nimport { SealedRequest, SealedResponse } from \"@bcts/gstp\";\nimport { XIDDocument, XIDVerifySignature } from \"@bcts/xid\";\n\nimport { DkgProposedParticipant } from \"./proposed-participant.js\";\n\n/**\n * Result of a DKG invitation.\n *\n * Port of `enum DkgInvitationResult` from group_invite.rs lines 170-173.\n */\nexport type DkgInvitationResult = { type: \"accepted\" } | { type: \"declined\"; reason: string };\n\n/**\n * Helper to create an accepted result.\n */\nexport function accepted(): DkgInvitationResult {\n return { type: \"accepted\" };\n}\n\n/**\n * Helper to create a declined result.\n */\nexport function declined(reason: string): DkgInvitationResult {\n return { type: \"declined\", reason };\n}\n\n/**\n * DKG Invite - represents an invitation to participate in a DKG session.\n *\n * Port of `struct DkgInvite` from group_invite.rs lines 11-27.\n */\nexport class DkgInvite {\n private readonly _requestId: ARID;\n private readonly _sender: XIDDocument;\n private readonly _groupId: ARID;\n private readonly _date: Date;\n private readonly _validUntil: Date;\n private readonly _minSigners: number;\n private readonly _charter: string;\n private readonly _orderedParticipants: DkgProposedParticipant[];\n\n private constructor(\n requestId: ARID,\n sender: XIDDocument,\n groupId: ARID,\n date: Date,\n validUntil: Date,\n minSigners: number,\n charter: string,\n orderedParticipants: DkgProposedParticipant[],\n ) {\n this._requestId = requestId;\n this._sender = sender;\n this._groupId = groupId;\n this._date = date;\n this._validUntil = validUntil;\n this._minSigners = minSigners;\n this._charter = charter;\n this._orderedParticipants = orderedParticipants;\n }\n\n /**\n * Create a new DKG invite.\n *\n * Port of `DkgInvite::new()` from group_invite.rs lines 30-67.\n */\n static create(\n requestId: ARID,\n sender: XIDDocument,\n groupId: ARID,\n date: Date,\n validUntil: Date,\n minSigners: number,\n charter: string,\n participants: string[],\n responseArids: ARID[],\n ): DkgInvite {\n if (participants.length !== responseArids.length) {\n throw new Error(\n `Number of participants (${participants.length}) does not match number of response ARIDs (${responseArids.length})`,\n );\n }\n\n if (minSigners < 2) {\n throw new Error(\"min_signers must be at least 2\");\n }\n\n const orderedParticipants = participants.map((urString, i) =>\n DkgProposedParticipant.create(urString, responseArids[i]),\n );\n\n if (minSigners > orderedParticipants.length) {\n throw new Error(\"min_signers cannot exceed number of participants\");\n }\n\n // Sort by XID\n orderedParticipants.sort((a, b) => a.compareTo(b));\n\n return new DkgInvite(\n requestId,\n sender,\n groupId,\n date,\n validUntil,\n minSigners,\n charter,\n orderedParticipants,\n );\n }\n\n requestId(): ARID {\n return this._requestId;\n }\n\n sender(): XIDDocument {\n return this._sender;\n }\n\n groupId(): ARID {\n return this._groupId;\n }\n\n date(): Date {\n return this._date;\n }\n\n validUntil(): Date {\n return this._validUntil;\n }\n\n minSigners(): number {\n return this._minSigners;\n }\n\n charter(): string {\n return this._charter;\n }\n\n participants(): DkgProposedParticipant[] {\n return this._orderedParticipants;\n }\n\n /**\n * Create a GSTP sealed request from this invite.\n *\n * Port of `DkgInvite::to_request()` from group_invite.rs lines 87-121.\n */\n toRequest(): SealedRequest {\n let request = SealedRequest.new(\"dkgInvite\", this.requestId(), this.sender())\n .withParameter(\"group\", this.groupId())\n .withParameter(\"minSigners\", BigInt(this.minSigners()))\n .withParameter(\"charter\", this.charter())\n .withDate(this.date())\n .withParameter(\"validUntil\", CborDate.fromDatetime(this.validUntil()));\n\n for (const participant of this.participants()) {\n const xidDocumentEnvelope = participant.xidDocumentEnvelope();\n const responseArid = participant.responseArid();\n const encryptionKey = participant.xidDocument().encryptionKey();\n\n if (encryptionKey === undefined) {\n throw new Error(\"Participant XID document has no encryption key\");\n }\n\n const encryptedResponseArid = Envelope.new(responseArid).encryptToRecipients([encryptionKey]);\n\n const participantEnvelope = xidDocumentEnvelope\n .wrap()\n .addAssertion(\"response_arid\", encryptedResponseArid);\n\n request = request.withParameter(\"participant\", participantEnvelope);\n }\n\n return request;\n }\n\n /**\n * Creates a signed but unencrypted envelope for auditing/preview.\n *\n * Port of `DkgInvite::to_unsealed_envelope()` from group_invite.rs lines 124-139.\n */\n toUnsealedEnvelope(): Envelope {\n const request = this.toRequest();\n const sender = this.sender();\n const signerPrivateKeys = sender.inceptionPrivateKeys();\n\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Sender XID document has no inception signing key\");\n }\n\n return request.toEnvelope(\n this.validUntil(),\n signerPrivateKeys,\n undefined, // No recipient = signed but not encrypted\n );\n }\n\n /**\n * Creates a sealed envelope encrypted to all participants.\n *\n * Port of `DkgInvite::to_envelope()` from group_invite.rs lines 142-166.\n */\n toEnvelope(): Envelope {\n const request = this.toRequest();\n const sender = this.sender();\n const signerPrivateKeys = sender.inceptionPrivateKeys();\n\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Sender XID document has no inception signing key\");\n }\n\n const recipients = this.participants().map((p) => p.xidDocument());\n\n return request.toEnvelopeForRecipients(this.validUntil(), signerPrivateKeys, recipients);\n }\n}\n\n/**\n * DKG Invitation - represents a received invitation from a participant's perspective.\n *\n * Port of `struct DkgInvitation` from group_invite.rs lines 175-186.\n */\nexport class DkgInvitation {\n private readonly _responseArid: ARID;\n private readonly _validUntil: Date;\n private readonly _sender: XIDDocument;\n private readonly _requestId: ARID;\n private readonly _peerContinuation: Envelope | undefined;\n private readonly _minSigners: number;\n private readonly _charter: string;\n private readonly _groupId: ARID;\n\n private constructor(\n responseArid: ARID,\n validUntil: Date,\n sender: XIDDocument,\n requestId: ARID,\n peerContinuation: Envelope | undefined,\n minSigners: number,\n charter: string,\n groupId: ARID,\n ) {\n this._responseArid = responseArid;\n this._validUntil = validUntil;\n this._sender = sender;\n this._requestId = requestId;\n this._peerContinuation = peerContinuation;\n this._minSigners = minSigners;\n this._charter = charter;\n this._groupId = groupId;\n }\n\n responseArid(): ARID {\n return this._responseArid;\n }\n\n validUntil(): Date {\n return this._validUntil;\n }\n\n sender(): XIDDocument {\n return this._sender;\n }\n\n requestId(): ARID {\n return this._requestId;\n }\n\n peerContinuation(): Envelope | undefined {\n return this._peerContinuation;\n }\n\n minSigners(): number {\n return this._minSigners;\n }\n\n charter(): string {\n return this._charter;\n }\n\n groupId(): ARID {\n return this._groupId;\n }\n\n /**\n * Build a GSTP response for this invitation result.\n *\n * Port of `DkgInvitation::to_response()` from group_invite.rs lines 207-224.\n */\n toResponse(response: DkgInvitationResult, recipient: XIDDocument): SealedResponse {\n let base: SealedResponse;\n if (response.type === \"accepted\") {\n base = SealedResponse.newSuccess(this.requestId(), recipient);\n } else {\n base = SealedResponse.newFailure(this.requestId(), recipient).withError(response.reason);\n }\n\n return base.withPeerContinuation(this.peerContinuation());\n }\n\n /**\n * Create a signed/encrypted GSTP envelope containing the response for the coordinator.\n *\n * Port of `DkgInvitation::to_envelope()` from group_invite.rs lines 228-244.\n */\n toEnvelope(response: DkgInvitationResult, recipient: XIDDocument): Envelope {\n const responseObj = this.toResponse(response, recipient);\n const signerPrivateKeys = recipient.inceptionPrivateKeys();\n\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Recipient XID document has no signing keys\");\n }\n\n const recipients = [this.sender()];\n\n return responseObj.toEnvelopeForRecipients(this.validUntil(), signerPrivateKeys, recipients);\n }\n\n /**\n * Parse a DKG invitation from an invite envelope.\n *\n * Port of `DkgInvitation::from_invite()` from group_invite.rs lines 255-344.\n */\n static fromInvite(\n invite: Envelope,\n now: Date,\n expectedSender: XIDDocument | undefined,\n recipient: XIDDocument,\n ): DkgInvitation {\n const recipientPrivateKeys = recipient.inceptionPrivateKeys();\n\n if (recipientPrivateKeys === undefined) {\n throw new Error(\"Recipient XID document has no inception private keys\");\n }\n\n const sealedRequest = SealedRequest.tryFromEnvelope(\n invite,\n undefined,\n now,\n recipientPrivateKeys,\n );\n\n // Rust `group_invite.rs:275-279` uses `!=` on `XID`, which is the\n // derived `PartialEq` (byte-wise compare on the 32-byte ARID). TS\n // `!==` is reference identity — two distinct XID instances with\n // the same bytes would fail. Compare via hex equality instead.\n if (\n expectedSender !== undefined &&\n !sealedRequest.sender().xid().equals(expectedSender.xid())\n ) {\n throw new Error(\"Invite sender does not match expected sender\");\n }\n\n if (!sealedRequest.request().function().equals(EnvelopeFunction.fromString(\"dkgInvite\"))) {\n throw new Error(\"Unexpected invite function\");\n }\n\n const validUntil = sealedRequest.extractObjectForParameter<Date>(\"validUntil\");\n\n if (validUntil <= now) {\n throw new Error(\"Invitation expired\");\n }\n\n const recipientXid = recipient.xid();\n const minSigners = sealedRequest.extractObjectForParameter<number>(\"minSigners\");\n const charter = sealedRequest.extractObjectForParameter<string>(\"charter\");\n const groupId = sealedRequest.extractObjectForParameter<ARID>(\"group\");\n const participantObjects = sealedRequest.objectsForParameter(\"participant\");\n\n if (minSigners < 2) {\n throw new Error(\"min_signers must be at least 2\");\n }\n\n if (minSigners > participantObjects.length) {\n throw new Error(\"min_signers exceeds participant count\");\n }\n\n for (const participant of participantObjects) {\n const xidDocumentEnvelope = participant.tryUnwrap();\n const xidDocument = XIDDocument.fromEnvelope(\n xidDocumentEnvelope,\n undefined,\n XIDVerifySignature.Inception,\n );\n\n // Rust `group_invite.rs` compares via `XID::PartialEq` (byte-wise).\n // TS reference identity would never match for two distinct\n // `XID` instances representing the same identity.\n if (!xidDocument.xid().equals(recipientXid)) {\n continue;\n }\n\n const encryptedResponseArid = participant.objectForPredicate(\"response_arid\");\n const responseAridEnvelope = encryptedResponseArid.decryptToRecipient(recipientPrivateKeys);\n const responseArid: ARID = responseAridEnvelope.extractSubject((cbor) =>\n ARID.fromTaggedCbor(cbor),\n );\n\n return new DkgInvitation(\n responseArid,\n validUntil,\n sealedRequest.sender(),\n sealedRequest.request().id(),\n sealedRequest.peerContinuation(),\n minSigners,\n charter,\n groupId,\n );\n }\n\n throw new Error(\"Recipient not found in invite\");\n }\n}\n"],"mappings":"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"}
|