@bcts/frost-hubert 1.0.0-alpha.17
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/LICENSE +48 -0
- package/README.md +35 -0
- package/dist/bin/frost.cjs +109 -0
- package/dist/bin/frost.cjs.map +1 -0
- package/dist/bin/frost.d.cts +1 -0
- package/dist/bin/frost.d.mts +1 -0
- package/dist/bin/frost.mjs +109 -0
- package/dist/bin/frost.mjs.map +1 -0
- package/dist/chunk-CQwRTUmo.cjs +53 -0
- package/dist/chunk-D3JzZLW2.mjs +21 -0
- package/dist/cmd/index.cjs +45 -0
- package/dist/cmd/index.d.cts +4 -0
- package/dist/cmd/index.d.mts +4 -0
- package/dist/cmd/index.mjs +7 -0
- package/dist/cmd-C8pmNd28.mjs +4664 -0
- package/dist/cmd-C8pmNd28.mjs.map +1 -0
- package/dist/cmd-CxUgryx_.cjs +4803 -0
- package/dist/cmd-CxUgryx_.cjs.map +1 -0
- package/dist/dkg/index.cjs +7 -0
- package/dist/dkg/index.d.cts +2 -0
- package/dist/dkg/index.d.mts +2 -0
- package/dist/dkg/index.mjs +3 -0
- package/dist/dkg-D4RcblWl.cjs +364 -0
- package/dist/dkg-D4RcblWl.cjs.map +1 -0
- package/dist/dkg-DqGrAV81.mjs +334 -0
- package/dist/dkg-DqGrAV81.mjs.map +1 -0
- package/dist/frost/index.cjs +37 -0
- package/dist/frost/index.d.cts +207 -0
- package/dist/frost/index.d.cts.map +1 -0
- package/dist/frost/index.d.mts +207 -0
- package/dist/frost/index.d.mts.map +1 -0
- package/dist/frost/index.mjs +3 -0
- package/dist/frost-CMH1K0Cw.cjs +511 -0
- package/dist/frost-CMH1K0Cw.cjs.map +1 -0
- package/dist/frost-Csp0IOrd.mjs +326 -0
- package/dist/frost-Csp0IOrd.mjs.map +1 -0
- package/dist/index-BGVoWW5P.d.cts +172 -0
- package/dist/index-BGVoWW5P.d.cts.map +1 -0
- package/dist/index-BJeUYrdE.d.mts +396 -0
- package/dist/index-BJeUYrdE.d.mts.map +1 -0
- package/dist/index-ByMDUYKw.d.mts +1098 -0
- package/dist/index-ByMDUYKw.d.mts.map +1 -0
- package/dist/index-DejLkr_F.d.mts +172 -0
- package/dist/index-DejLkr_F.d.mts.map +1 -0
- package/dist/index-Dib1OE-e.d.cts +1098 -0
- package/dist/index-Dib1OE-e.d.cts.map +1 -0
- package/dist/index-DnvBKgec.d.cts +396 -0
- package/dist/index-DnvBKgec.d.cts.map +1 -0
- package/dist/index.cjs +85 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +15 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +15 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +24 -0
- package/dist/index.mjs.map +1 -0
- package/dist/registry/index.cjs +13 -0
- package/dist/registry/index.d.cts +2 -0
- package/dist/registry/index.d.mts +2 -0
- package/dist/registry/index.mjs +3 -0
- package/dist/registry-CBjRRqNv.mjs +144 -0
- package/dist/registry-CBjRRqNv.mjs.map +1 -0
- package/dist/registry-CWp2amuo.mjs +789 -0
- package/dist/registry-CWp2amuo.mjs.map +1 -0
- package/dist/registry-D5yh293y.cjs +857 -0
- package/dist/registry-D5yh293y.cjs.map +1 -0
- package/dist/registry-DNUNW6SH.cjs +163 -0
- package/dist/registry-DNUNW6SH.cjs.map +1 -0
- package/package.json +119 -0
- package/src/bin/frost.ts +218 -0
- package/src/cmd/busy.ts +64 -0
- package/src/cmd/check.ts +20 -0
- package/src/cmd/common.ts +40 -0
- package/src/cmd/dkg/common.ts +275 -0
- package/src/cmd/dkg/coordinator/finalize.ts +592 -0
- package/src/cmd/dkg/coordinator/index.ts +12 -0
- package/src/cmd/dkg/coordinator/invite.ts +217 -0
- package/src/cmd/dkg/coordinator/round1.ts +889 -0
- package/src/cmd/dkg/coordinator/round2.ts +959 -0
- package/src/cmd/dkg/index.ts +11 -0
- package/src/cmd/dkg/participant/finalize.ts +575 -0
- package/src/cmd/dkg/participant/index.ts +12 -0
- package/src/cmd/dkg/participant/receive.ts +348 -0
- package/src/cmd/dkg/participant/round1.ts +464 -0
- package/src/cmd/dkg/participant/round2.ts +627 -0
- package/src/cmd/index.ts +18 -0
- package/src/cmd/parallel.ts +334 -0
- package/src/cmd/registry/index.ts +88 -0
- package/src/cmd/registry/owner/index.ts +9 -0
- package/src/cmd/registry/owner/set.ts +70 -0
- package/src/cmd/registry/participant/add.ts +70 -0
- package/src/cmd/registry/participant/index.ts +9 -0
- package/src/cmd/sign/common.ts +108 -0
- package/src/cmd/sign/coordinator/index.ts +11 -0
- package/src/cmd/sign/coordinator/invite.ts +431 -0
- package/src/cmd/sign/coordinator/round1.ts +751 -0
- package/src/cmd/sign/coordinator/round2.ts +836 -0
- package/src/cmd/sign/index.ts +11 -0
- package/src/cmd/sign/participant/finalize.ts +823 -0
- package/src/cmd/sign/participant/index.ts +12 -0
- package/src/cmd/sign/participant/receive.ts +378 -0
- package/src/cmd/sign/participant/round1.ts +479 -0
- package/src/cmd/sign/participant/round2.ts +748 -0
- package/src/cmd/storage.ts +116 -0
- package/src/dkg/group-invite.ts +414 -0
- package/src/dkg/index.ts +10 -0
- package/src/dkg/proposed-participant.ts +132 -0
- package/src/frost/index.ts +456 -0
- package/src/index.ts +45 -0
- package/src/registry/group-record.ts +392 -0
- package/src/registry/index.ts +12 -0
- package/src/registry/owner-record.ts +146 -0
- package/src/registry/participant-record.ts +186 -0
- package/src/registry/registry-impl.ts +364 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cmd-C8pmNd28.mjs","names":["resolveSenderName","invite","validateCoordinator","JSONWrapper","printSummaryParallel","round1","validateCoordinator","round2","validateCoordinator","finalize","resolveInviteEnvelope","EnvelopeFunction","resolveSenderXidDocument","receive","resolveSenderName","buildResponseBody","JSONWrapper","round1","hexToBytes","EnvelopeFunction","JSONWrapper","buildResponseBody","round2","hexToBytes","EnvelopeFunction","JSONWrapper","buildResponseBody","finalize","loadStartState","ARIDClass","XIDClass","JSONClass","round1","ARIDClass","XIDClass","JSONComponent","aggregateAndVerifySignature","loadPublicKeyPackage","xidIdentifierMap","commitmentsWithIdentifiers","round2","loadReceiveState","EnvelopeFunction","buildResponseBody","JSONWrapper","round1","loadReceiveState","ARIDClass","XIDClass","EnvelopeFunction","JSONComponent","xidIdentifierMap","commitmentsWithIdentifiers","round2","hexToBytes"],"sources":["../src/cmd/common.ts","../src/cmd/busy.ts","../src/cmd/parallel.ts","../src/cmd/storage.ts","../src/cmd/check.ts","../src/cmd/dkg/common.ts","../src/cmd/dkg/coordinator/invite.ts","../src/cmd/dkg/coordinator/round1.ts","../src/cmd/dkg/coordinator/round2.ts","../src/cmd/dkg/coordinator/finalize.ts","../src/cmd/dkg/coordinator/index.ts","../src/cmd/dkg/participant/receive.ts","../src/cmd/dkg/participant/round1.ts","../src/cmd/dkg/participant/round2.ts","../src/cmd/dkg/participant/finalize.ts","../src/cmd/dkg/participant/index.ts","../src/cmd/dkg/index.ts","../src/cmd/sign/common.ts","../src/cmd/sign/coordinator/invite.ts","../src/cmd/sign/coordinator/round1.ts","../src/cmd/sign/coordinator/round2.ts","../src/cmd/sign/coordinator/index.ts","../src/cmd/sign/participant/receive.ts","../src/cmd/sign/participant/round1.ts","../src/cmd/sign/participant/round2.ts","../src/cmd/sign/participant/finalize.ts","../src/cmd/sign/participant/index.ts","../src/cmd/sign/index.ts"],"sourcesContent":["/**\n * Common utilities for commands.\n *\n * Port of cmd/common.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as path from \"node:path\";\n\n/**\n * Get the group state directory for a given registry path and group ID.\n *\n * Port of `group_state_dir()` from cmd/common.rs.\n */\nexport function groupStateDir(registryPath: string, groupIdHex: string): string {\n const base = path.dirname(registryPath);\n return path.join(base, \"group-state\", groupIdHex);\n}\n\n/**\n * Global verbose flag.\n */\nlet verboseFlag = false;\n\n/**\n * Set the verbose flag.\n */\nexport function setVerbose(value: boolean): void {\n verboseFlag = value;\n}\n\n/**\n * Check if verbose mode is enabled.\n *\n * Port of `is_verbose()` from cmd/common.rs.\n */\nexport function isVerbose(): boolean {\n return verboseFlag;\n}\n","/**\n * Progress indicator utilities.\n *\n * Port of cmd/busy.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { type ARID } from \"@bcts/components\";\nimport { type Envelope } from \"@bcts/envelope\";\n\nimport { type StorageClient } from \"./storage.js\";\n\n/**\n * Put an envelope to storage with a progress indicator.\n *\n * Port of `put_with_indicator()` from cmd/busy.rs.\n */\nexport async function putWithIndicator(\n client: StorageClient,\n arid: ARID,\n envelope: Envelope,\n message: string,\n verbose: boolean,\n): Promise<void> {\n if (verbose) {\n console.log(`${message}...`);\n }\n\n await client.put(arid, envelope);\n\n if (verbose) {\n console.log(`${message}... done`);\n }\n}\n\n/**\n * Get an envelope from storage with a progress indicator.\n *\n * Port of `get_with_indicator()` from cmd/busy.rs.\n */\nexport async function getWithIndicator(\n client: StorageClient,\n arid: ARID,\n message: string,\n timeoutSeconds: number | undefined,\n verbose: boolean,\n): Promise<Envelope | undefined> {\n if (verbose) {\n console.log(`${message}...`);\n }\n\n const envelope = await client.get(arid, timeoutSeconds);\n\n if (verbose) {\n if (envelope) {\n console.log(`${message}... found`);\n } else {\n console.log(`${message}... not found`);\n }\n }\n\n return envelope;\n}\n","/**\n * Parallel fetch and send utilities for coordinator commands.\n *\n * This module provides utilities for fetching responses from multiple\n * participants in parallel with progress display.\n *\n * Port of cmd/parallel.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { type ARID, type XID } from \"@bcts/components\";\nimport { type Envelope } from \"@bcts/envelope\";\n\nimport { type StorageClient } from \"./storage.js\";\n\n/**\n * Status of a participant's response fetch.\n *\n * Port of `enum FetchStatus` from cmd/parallel.rs.\n */\nexport type FetchStatus =\n | { type: \"Pending\" }\n | { type: \"Success\"; envelope: Envelope }\n | { type: \"Rejected\"; reason: string }\n | { type: \"Error\"; error: string }\n | { type: \"Timeout\" };\n\n/**\n * Create a Pending status.\n */\nexport function fetchStatusPending(): FetchStatus {\n return { type: \"Pending\" };\n}\n\n/**\n * Create a Success status.\n */\nexport function fetchStatusSuccess(envelope: Envelope): FetchStatus {\n return { type: \"Success\", envelope };\n}\n\n/**\n * Create a Rejected status.\n */\nexport function fetchStatusRejected(reason: string): FetchStatus {\n return { type: \"Rejected\", reason };\n}\n\n/**\n * Create an Error status.\n */\nexport function fetchStatusError(error: string): FetchStatus {\n return { type: \"Error\", error };\n}\n\n/**\n * Create a Timeout status.\n */\nexport function fetchStatusTimeout(): FetchStatus {\n return { type: \"Timeout\" };\n}\n\n/**\n * Direction of the operation (get or put).\n *\n * Port of `enum Direction` from cmd/parallel.rs.\n */\nexport enum Direction {\n /** Downloading from storage */\n Get = \"Get\",\n /** Uploading to storage */\n Put = \"Put\",\n}\n\n/**\n * Get the emoji for a direction.\n *\n * Port of `Direction::emoji()` from cmd/parallel.rs.\n */\nexport function directionEmoji(direction: Direction): string {\n switch (direction) {\n case Direction.Get:\n return \"⬇️\";\n case Direction.Put:\n return \"⬆️\";\n }\n}\n\n/**\n * Configuration for parallel fetch operations.\n *\n * Port of `struct ParallelFetchConfig` from cmd/parallel.rs.\n */\nexport interface ParallelFetchConfig {\n /** Maximum time to wait for all responses (in seconds) */\n timeoutSeconds?: number | undefined;\n /** Whether to show verbose output */\n verbose?: boolean | undefined;\n}\n\n/**\n * Default timeout in seconds (10 minutes).\n */\nexport const DEFAULT_TIMEOUT_SECONDS = 600;\n\n/**\n * Create a config with the specified timeout.\n */\nexport function parallelFetchConfigWithTimeout(timeoutSeconds?: number): ParallelFetchConfig {\n return { timeoutSeconds };\n}\n\n/**\n * Result of collecting responses from multiple participants.\n *\n * Port of `struct CollectionResult` from cmd/parallel.rs.\n */\nexport class CollectionResult<T> {\n /** Successful responses as [XID, T] tuples */\n successes: [XID, T][];\n /** Participants who explicitly rejected as [XID, reason] tuples */\n rejections: [XID, string][];\n /** Participants with network/parsing errors as [XID, error] tuples */\n errors: [XID, string][];\n /** Participants who timed out */\n timeouts: XID[];\n\n constructor() {\n this.successes = [];\n this.rejections = [];\n this.errors = [];\n this.timeouts = [];\n }\n\n /**\n * Check if enough responses were received to proceed.\n *\n * Port of `CollectionResult::can_proceed()` from cmd/parallel.rs.\n */\n canProceed(minRequired: number): boolean {\n return this.successes.length >= minRequired;\n }\n\n /**\n * Total number of participants.\n *\n * Port of `CollectionResult::total()` from cmd/parallel.rs.\n */\n total(): number {\n return (\n this.successes.length + this.rejections.length + this.errors.length + this.timeouts.length\n );\n }\n\n /**\n * Check if all responses succeeded.\n *\n * Port of `CollectionResult::all_succeeded()` from cmd/parallel.rs.\n */\n allSucceeded(): boolean {\n return this.rejections.length === 0 && this.errors.length === 0 && this.timeouts.length === 0;\n }\n}\n\n/**\n * Create an empty collection result.\n */\nexport function emptyCollectionResult<T>(): CollectionResult<T> {\n return new CollectionResult<T>();\n}\n\n/**\n * Helper to build request tuples from pending requests and registry.\n *\n * Port of `build_fetch_requests()` from cmd/parallel.rs.\n */\nexport function buildFetchRequests(\n pending: Iterable<[XID, ARID]>,\n getName: (xid: XID) => string,\n): [XID, ARID, string][] {\n const requests: [XID, ARID, string][] = [];\n for (const [xid, arid] of pending) {\n const name = getName(xid);\n requests.push([xid, arid, name]);\n }\n return requests;\n}\n\n/**\n * Simple progress output for non-interactive terminals.\n */\nfunction logProgress(\n direction: Direction,\n name: string,\n status: \"success\" | \"error\" | \"timeout\",\n message?: string,\n): void {\n const emoji = directionEmoji(direction);\n switch (status) {\n case \"success\":\n console.error(`${emoji} ✅ ${name}`);\n break;\n case \"error\":\n console.error(`${emoji} ❌ ${name}: ${message ?? \"Error\"}`);\n break;\n case \"timeout\":\n console.error(`${emoji} ❌ ${name}: Timeout`);\n break;\n }\n}\n\n/**\n * Fetch messages from multiple ARIDs in parallel.\n *\n * Port of `parallel_fetch()` from cmd/parallel.rs.\n */\nexport async function parallelFetch<T>(\n client: StorageClient,\n requests: [XID, ARID, string][],\n validate: (envelope: Envelope, xid: XID) => T | { rejected: string },\n config: ParallelFetchConfig,\n): Promise<CollectionResult<T>> {\n const result = new CollectionResult<T>();\n const timeoutSeconds = config.timeoutSeconds ?? DEFAULT_TIMEOUT_SECONDS;\n\n if (config.verbose === true) {\n console.error(`Waiting for ${requests.length} responses...`);\n }\n\n const promises = requests.map(async ([xid, arid, name]) => {\n try {\n const envelope = await client.get(arid, timeoutSeconds);\n\n if (!envelope) {\n result.timeouts.push(xid);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"timeout\");\n }\n return;\n }\n\n const parsed = validate(envelope, xid);\n\n if (parsed !== null && typeof parsed === \"object\" && \"rejected\" in parsed) {\n result.rejections.push([xid, parsed.rejected]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"error\", parsed.rejected);\n }\n } else {\n result.successes.push([xid, parsed]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"success\");\n }\n }\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n if (errorMessage.includes(\"Timeout\") || errorMessage.includes(\"timeout\")) {\n result.timeouts.push(xid);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"timeout\");\n }\n } else {\n result.errors.push([xid, `${name}: ${errorMessage}`]);\n if (config.verbose === true) {\n logProgress(Direction.Get, name, \"error\", errorMessage);\n }\n }\n }\n });\n\n await Promise.all(promises);\n\n if (config.verbose === true) {\n console.error(`Collected ${result.successes.length} responses`);\n if (result.rejections.length > 0) {\n console.error(` ${result.rejections.length} rejections`);\n }\n if (result.errors.length > 0) {\n console.error(` ${result.errors.length} errors`);\n }\n if (result.timeouts.length > 0) {\n console.error(` ${result.timeouts.length} timeouts`);\n }\n }\n\n return result;\n}\n\n/**\n * Send messages to multiple ARIDs in parallel.\n *\n * Port of `parallel_send()` from cmd/parallel.rs.\n */\nexport async function parallelSend(\n client: StorageClient,\n messages: [XID, ARID, Envelope, string][],\n verbose?: boolean,\n): Promise<[XID, Error | null][]> {\n const results: [XID, Error | null][] = [];\n\n if (verbose === true) {\n console.error(`Sending to ${messages.length} participants...`);\n }\n\n const promises = messages.map(async ([xid, arid, envelope, name]) => {\n try {\n await client.put(arid, envelope);\n results.push([xid, null]);\n if (verbose === true) {\n logProgress(Direction.Put, name, \"success\");\n }\n } catch (error) {\n const err = error instanceof Error ? error : new Error(String(error));\n results.push([xid, err]);\n if (verbose === true) {\n logProgress(Direction.Put, name, \"error\", err.message);\n }\n }\n });\n\n await Promise.all(promises);\n\n if (verbose === true) {\n const successes = results.filter(([_, err]) => err === null).length;\n const failures = results.length - successes;\n console.error(`Sent ${successes} messages`);\n if (failures > 0) {\n console.error(` ${failures} failed`);\n }\n }\n\n return results;\n}\n","/**\n * Storage client abstraction for Hubert.\n *\n * Port of cmd/storage.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { type ARID } from \"@bcts/components\";\nimport { type Envelope } from \"@bcts/envelope\";\n\n/**\n * Storage backend selection.\n *\n * Port of `enum StorageSelection` from cmd/storage.rs.\n */\nexport type StorageSelection = \"server\" | \"mainline\" | \"ipfs\" | \"hybrid\";\n\n/**\n * Storage client interface for Hubert operations.\n *\n * Port of `struct StorageClient` from cmd/storage.rs.\n */\nexport interface StorageClient {\n /**\n * Put an envelope at the given ARID.\n */\n put(arid: ARID, envelope: Envelope): Promise<void>;\n\n /**\n * Get an envelope from the given ARID.\n */\n get(arid: ARID, timeoutSeconds?: number): Promise<Envelope | undefined>;\n\n /**\n * Check if an envelope exists at the given ARID.\n */\n exists(arid: ARID): Promise<boolean>;\n}\n\n/**\n * Create a storage client based on the selection.\n *\n * Port of storage client creation from cmd/storage.rs.\n */\nexport async function createStorageClient(\n selection: StorageSelection,\n serverUrl?: string,\n): Promise<StorageClient> {\n switch (selection) {\n case \"server\": {\n const { ServerKvClient } = await import(\"@bcts/hubert/server\");\n const client = new ServerKvClient(serverUrl ?? \"http://localhost:8080\");\n return {\n async put(arid: ARID, envelope: Envelope): Promise<void> {\n await client.put(arid, envelope);\n },\n async get(arid: ARID, timeoutSeconds?: number): Promise<Envelope | undefined> {\n const result = await client.get(arid, timeoutSeconds);\n return result ?? undefined;\n },\n exists(arid: ARID): Promise<boolean> {\n return client.exists(arid);\n },\n };\n }\n case \"mainline\": {\n const { MainlineDhtKv } = await import(\"@bcts/hubert/mainline\");\n const client = await MainlineDhtKv.create();\n return {\n async put(arid: ARID, envelope: Envelope): Promise<void> {\n await client.put(arid, envelope);\n },\n async get(arid: ARID, timeoutSeconds?: number): Promise<Envelope | undefined> {\n const result = await client.get(arid, timeoutSeconds);\n return result ?? undefined;\n },\n exists(arid: ARID): Promise<boolean> {\n return client.exists(arid);\n },\n };\n }\n case \"ipfs\": {\n const { IpfsKv } = await import(\"@bcts/hubert/ipfs\");\n const client = new IpfsKv(\"http://127.0.0.1:5001\");\n return {\n async put(arid: ARID, envelope: Envelope): Promise<void> {\n await client.put(arid, envelope);\n },\n async get(arid: ARID, timeoutSeconds?: number): Promise<Envelope | undefined> {\n const result = await client.get(arid, timeoutSeconds);\n return result ?? undefined;\n },\n exists(arid: ARID): Promise<boolean> {\n return client.exists(arid);\n },\n };\n }\n case \"hybrid\": {\n const { HybridKv } = await import(\"@bcts/hubert/hybrid\");\n const client = await HybridKv.create(\"http://127.0.0.1:5001\");\n return {\n async put(arid: ARID, envelope: Envelope): Promise<void> {\n await client.put(arid, envelope);\n },\n async get(arid: ARID, timeoutSeconds?: number): Promise<Envelope | undefined> {\n const result = await client.get(arid, timeoutSeconds);\n return result ?? undefined;\n },\n exists(arid: ARID): Promise<boolean> {\n return client.exists(arid);\n },\n };\n }\n }\n}\n","/**\n * Check command utilities.\n *\n * Port of cmd/check.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { type ARID } from \"@bcts/components\";\n\nimport { type StorageClient } from \"./storage.js\";\n\n/**\n * Check if an ARID exists in storage.\n *\n * Port of check functionality from cmd/check.rs.\n */\nexport async function checkAridExists(client: StorageClient, arid: ARID): Promise<boolean> {\n return client.exists(arid);\n}\n","/**\n * Common utilities for DKG commands.\n *\n * Port of cmd/dkg/common.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as path from \"node:path\";\n\nimport { type ARID, type XID } from \"@bcts/components\";\nimport { type Envelope } from \"@bcts/envelope\";\nimport { UR } from \"@bcts/uniform-resources\";\nimport { type XIDDocument } from \"@bcts/xid\";\n\nimport {\n GroupParticipant,\n type OwnerRecord,\n type ParticipantRecord,\n type Registry,\n} from \"../../registry/index.js\";\n\n// Re-export cross-cutting utilities for convenience\nexport { groupStateDir } from \"../common.js\";\n\n/**\n * Parse an ARID from a UR string.\n *\n * Port of `parse_arid_ur()` from cmd/dkg/common.rs.\n */\nexport function parseAridUr(urString: string): ARID {\n const ur = UR.fromURString(urString.trim());\n\n if (ur.urTypeStr() !== \"arid\") {\n throw new Error(`Expected ur:arid, found ur:${ur.urTypeStr()}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef\n const { ARID: ARIDClass } = require(\"@bcts/components\");\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n return ARIDClass.fromCbor(ur.cbor());\n}\n\n/**\n * Parse an envelope from a UR string.\n *\n * Port of `parse_envelope_ur()` from cmd/dkg/common.rs.\n */\nexport function parseEnvelopeUr(urString: string): Envelope {\n const ur = UR.fromURString(urString.trim());\n\n if (ur.urTypeStr() !== \"envelope\") {\n throw new Error(`Expected ur:envelope, found ur:${ur.urTypeStr()}`);\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef\n const { Envelope: EnvelopeClass } = require(\"@bcts/envelope\");\n // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n return EnvelopeClass.fromCbor(ur.cbor());\n}\n\n/**\n * Resolve the sender XID document from the registry.\n *\n * Port of `resolve_sender()` from cmd/dkg/common.rs.\n */\nexport function resolveSender(registry: Registry): XIDDocument {\n const owner = registry.owner();\n\n if (!owner) {\n throw new Error(\"No owner set in registry. Run 'registry owner set' first.\");\n }\n\n return owner.xidDocument();\n}\n\n// -----------------------------------------------------------------------------\n// Participant resolution\n// -----------------------------------------------------------------------------\n\n/**\n * Resolve participant identifiers (XID URs or pet names) to records.\n *\n * Port of `resolve_participants()` from cmd/dkg/common.rs lines 29-74.\n */\nexport function resolveParticipants(\n registry: Registry,\n inputs: string[],\n): [XID, ParticipantRecord][] {\n const seenArgs = new Set<string>();\n const seenXids = new Set<string>();\n const resolved: [XID, ParticipantRecord][] = [];\n\n for (const raw of inputs) {\n const trimmed = raw.trim();\n if (trimmed === \"\") {\n throw new Error(\"Participant identifier cannot be empty\");\n }\n if (seenArgs.has(trimmed)) {\n throw new Error(`Duplicate participant argument: ${trimmed}`);\n }\n seenArgs.add(trimmed);\n\n let xid: XID;\n let record: ParticipantRecord;\n\n // Try parsing as XID UR first\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef\n const { XID: XIDClass } = require(\"@bcts/components\");\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n xid = XIDClass.fromURString(trimmed) as XID;\n\n const foundRecord = registry.participant(xid);\n if (!foundRecord) {\n throw new Error(`Participant with XID ${xid.urString()} not found in registry`);\n }\n record = foundRecord;\n } catch {\n // Try looking up by pet name\n const result = registry.participantByPetName(trimmed);\n if (!result) {\n throw new Error(`Participant with pet name '${trimmed}' not found`);\n }\n [xid, record] = result;\n }\n\n const xidUr = xid.urString();\n if (seenXids.has(xidUr)) {\n throw new Error(`Duplicate participant specified; multiple inputs resolve to ${xidUr}`);\n }\n seenXids.add(xidUr);\n\n resolved.push([xid, record]);\n }\n\n return resolved;\n}\n\n/**\n * Get display name for sender from registry.\n *\n * Port of `resolve_sender_name()` from cmd/dkg/common.rs lines 96-116.\n */\nexport function resolveSenderName(registry: Registry, sender: XIDDocument): string | undefined {\n const owner = registry.owner();\n const senderXid = sender.xid();\n\n // Check if sender is the owner\n if (owner?.xidDocument().xid().urString() === senderXid.urString()) {\n const name = owner.petName() ?? senderXid.urString();\n return formatNameWithOwnerMarker(name, true);\n }\n\n // Look up in participants\n const record = registry.participant(senderXid);\n if (record) {\n const name = record.petName() ?? record.xid().urString();\n return formatNameWithOwnerMarker(name, false);\n }\n\n return undefined;\n}\n\n// -----------------------------------------------------------------------------\n// Group participant building\n// -----------------------------------------------------------------------------\n\n/**\n * Build GroupParticipant[] from XIDDocuments using registry lookups.\n *\n * Port of `build_group_participants()` from cmd/dkg/common.rs lines 122-131.\n */\nexport function buildGroupParticipants(\n registry: Registry,\n owner: OwnerRecord,\n participants: XIDDocument[],\n): GroupParticipant[] {\n return participants.map((doc) => groupParticipantFromRegistry(registry, owner, doc));\n}\n\n/**\n * Create a GroupParticipant from a XIDDocument, validating against the registry.\n *\n * Port of `group_participant_from_registry()` from cmd/dkg/common.rs lines 133-149.\n */\nexport function groupParticipantFromRegistry(\n registry: Registry,\n owner: OwnerRecord,\n document: XIDDocument,\n): GroupParticipant {\n const xid = document.xid();\n\n // If the document is the owner, allow it\n if (xid.urString() === owner.xid().urString()) {\n return new GroupParticipant(xid);\n }\n\n // Otherwise, verify the participant is in the registry\n if (!registry.participant(xid)) {\n throw new Error(`Invite participant not found in registry: ${xid.urString()}`);\n }\n\n return new GroupParticipant(xid);\n}\n\n// -----------------------------------------------------------------------------\n// Name formatting\n// -----------------------------------------------------------------------------\n\n/**\n * Format a participant name with owner marker if applicable.\n *\n * Port of `format_name_with_owner_marker()` from cmd/dkg/common.rs lines 155-157.\n */\nexport function formatNameWithOwnerMarker(name: string, isOwner: boolean): string {\n return isOwner ? `* ${name}` : name;\n}\n\n/**\n * Get display names for participants, sorted by XID, with owner marked.\n *\n * Port of `participant_names_from_registry()` from cmd/dkg/common.rs lines 159-191.\n */\nexport function participantNamesFromRegistry(\n registry: Registry,\n participants: XIDDocument[],\n ownerXid: XID,\n ownerPetName: string | undefined,\n): string[] {\n // Sort by XID UR string\n const sorted = [...participants].sort((a, b) =>\n a.xid().urString().localeCompare(b.xid().urString()),\n );\n\n return sorted.map((document) => {\n const xid = document.xid();\n const isOwner = xid.urString() === ownerXid.urString();\n\n let name: string;\n if (isOwner) {\n name = ownerPetName ?? xid.urString();\n } else {\n const record = registry.participant(xid);\n if (!record) {\n throw new Error(`Invite participant not found in registry: ${xid.urString()}`);\n }\n name = record.petName() ?? xid.urString();\n }\n\n return formatNameWithOwnerMarker(name, isOwner);\n });\n}\n\n/**\n * Get the DKG state directory for a given registry path and group ID.\n *\n * Port of `dkg_state_dir()` from cmd/dkg/common.rs.\n */\nexport function dkgStateDir(registryPath: string, groupIdHex: string): string {\n const base = path.dirname(registryPath);\n return path.join(base, \"group-state\", groupIdHex, \"dkg\");\n}\n\n/**\n * Convert a verifying key bytes to a SigningPublicKey.\n *\n * Port of `signing_key_from_verifying()` from cmd/dkg/common.rs.\n */\nexport function signingKeyFromVerifying(verifyingKeyBytes: Uint8Array): unknown {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef\n const { SigningPublicKey: SigningPublicKeyClass } = require(\"@bcts/components\");\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n return SigningPublicKeyClass.fromBytes(verifyingKeyBytes);\n}\n","/**\n * DKG coordinator invite command.\n *\n * Port of cmd/dkg/coordinator/invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, type XID } from \"@bcts/components\";\n\nimport { DkgInvite } from \"../../../dkg/index.js\";\nimport {\n GroupParticipant,\n GroupRecord,\n PendingRequests,\n Registry,\n resolveRegistryPath,\n} from \"../../../registry/index.js\";\nimport { putWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { dkgStateDir, resolveParticipants, resolveSender } from \"../common.js\";\n\n/**\n * Options for the DKG invite command.\n */\nexport interface DkgInviteOptions {\n registryPath?: string;\n minSigners?: number;\n charter: string;\n validDays: number;\n participantNames: string[];\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG invite command.\n */\nexport interface DkgInviteResult {\n groupId: ARID;\n requestId: ARID;\n envelopeUr: string;\n}\n\n/**\n * Internal data structure for building an invite.\n *\n * Port of `InviteData` struct from cmd/dkg/coordinator/invite.rs lines 122-126.\n */\ninterface InviteData {\n invite: DkgInvite;\n participantXids: XID[];\n pendingRequests: PendingRequests;\n}\n\n/**\n * Build the DKG invite with validation.\n *\n * Port of `build_invite()` from cmd/dkg/coordinator/invite.rs lines 128-181.\n */\nfunction buildInvite(\n registry: Registry,\n minSignersArg: number | undefined,\n charter: string,\n participantNames: string[],\n validDays: number,\n): InviteData {\n // Resolve participants using the common utility\n const resolved = resolveParticipants(registry, participantNames);\n const participantDocs: string[] = resolved.map(([, record]) => record.xidDocumentUr());\n const participantXids: XID[] = resolved.map(([xid]) => xid);\n\n // These are the ARIDs where participants will post their invite responses\n const collectFromArids: ARID[] = participantDocs.map(() => ARID.new());\n\n // Build pending_requests: coordinator will collect invite responses from these ARIDs\n const pendingRequests = new PendingRequests();\n for (let i = 0; i < participantXids.length; i++) {\n pendingRequests.addCollectOnly(participantXids[i], collectFromArids[i]);\n }\n\n // Validate participant count\n const participantCount = participantDocs.length;\n if (participantCount < 2) {\n throw new Error(\"At least two participants are required for a DKG invite\");\n }\n\n // Validate and default minSigners\n const minSigners = minSignersArg ?? participantCount;\n if (minSigners < 2) {\n throw new Error(\"--min-signers must be at least 2\");\n }\n if (minSigners > participantCount) {\n throw new Error(\"--min-signers cannot exceed participant count\");\n }\n\n // Get sender (registry owner)\n const sender = resolveSender(registry);\n\n // Calculate dates\n const now = new Date();\n const validUntil = new Date(Date.now() + validDays * 24 * 60 * 60 * 1000);\n\n // Create the invite\n const invite = DkgInvite.create(\n ARID.new(), // requestId\n sender,\n ARID.new(), // groupId\n now,\n validUntil,\n minSigners,\n charter,\n participantDocs,\n collectFromArids,\n );\n\n return { invite, participantXids, pendingRequests };\n}\n\n/**\n * Execute the DKG invite command.\n *\n * Port of `invite()` from cmd/dkg/coordinator/invite.rs.\n */\nexport async function invite(\n client: StorageClient,\n options: DkgInviteOptions,\n cwd: string,\n): Promise<DkgInviteResult> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n // Build the invite with validation\n const inviteData = buildInvite(\n registry,\n options.minSigners,\n options.charter,\n options.participantNames,\n options.validDays,\n );\n\n const { invite: dkgInvite, participantXids, pendingRequests } = inviteData;\n const groupId = dkgInvite.groupId();\n const requestId = dkgInvite.requestId();\n\n // Create sealed envelope\n const envelope = dkgInvite.toEnvelope();\n\n // Send to storage\n const startArid = ARID.new();\n await putWithIndicator(\n client,\n startArid,\n envelope,\n \"Sending DKG invite\",\n options.verbose ?? false,\n );\n\n // Save group record to registry\n const owner = registry.owner();\n if (!owner) {\n throw new Error(\"Registry owner is required to issue invites\");\n }\n\n const coordinator = new GroupParticipant(owner.xid());\n const groupParticipants = participantXids.map((xid) => new GroupParticipant(xid));\n\n const groupRecord = new GroupRecord(\n options.charter,\n dkgInvite.minSigners(),\n coordinator,\n groupParticipants,\n );\n\n // Track pending requests\n groupRecord.setPendingRequests(pendingRequests);\n\n // Use recordGroup() for proper merge behavior\n registry.recordGroup(groupId, groupRecord);\n registry.save(registryPath);\n\n // Save invite state\n const stateDir = dkgStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const inviteState: {\n group: string;\n request_id: string;\n start_arid: string;\n valid_until: string;\n participants: { xid: string; response_arid: string }[];\n } = {\n group: groupId.urString(),\n request_id: requestId.urString(),\n start_arid: startArid.urString(),\n valid_until: dkgInvite.validUntil().toISOString(),\n participants: dkgInvite.participants().map((p) => ({\n xid: p.xid().urString(),\n response_arid: p.responseArid().urString(),\n })),\n };\n\n fs.writeFileSync(path.join(stateDir, \"invite.json\"), JSON.stringify(inviteState, null, 2));\n\n if (options.verbose === true) {\n console.log(`Group ID: ${groupId.urString()}`);\n console.log(`Start ARID: ${startArid.urString()}`);\n }\n\n return {\n groupId,\n requestId,\n envelopeUr: envelope.urString(),\n };\n}\n","/**\n * DKG coordinator round 1 command.\n *\n * Port of cmd/dkg/coordinator/round1.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, JSON as JSONWrapper, type PrivateKeys, type XID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { SealedRequest, SealedResponse } from \"@bcts/gstp\";\nimport type { XIDDocument } from \"@bcts/xid\";\n\nimport {\n type GroupRecord,\n type OwnerRecord,\n PendingRequests,\n Registry,\n resolveRegistryPath,\n} from \"../../../registry/index.js\";\nimport { getWithIndicator, putWithIndicator } from \"../../busy.js\";\nimport { groupStateDir, isVerbose } from \"../../common.js\";\nimport {\n type CollectionResult,\n parallelFetch,\n parallelSend,\n type ParallelFetchConfig,\n} from \"../../parallel.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { parseAridUr } from \"../common.js\";\nimport { type DkgRound1Package } from \"../../../frost/index.js\";\nimport { serde } from \"@frosts/ed25519\";\n\n/**\n * Options for the DKG round1 command.\n */\nexport interface DkgRound1Options {\n registryPath?: string;\n groupId: string;\n parallel?: boolean;\n timeoutSeconds?: number;\n preview?: boolean;\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG round1 command.\n */\nexport interface DkgRound1Result {\n accepted: number;\n rejected: number;\n errors: number;\n timeouts: number;\n}\n\n// -----------------------------------------------------------------------------\n// Context and result types\n// -----------------------------------------------------------------------------\n\n/**\n * Context for round 1 collection operations.\n */\ninterface Round1Context {\n client: StorageClient;\n registryPath: string;\n registry: Registry;\n ownerDoc: XIDDocument;\n groupId: ARID;\n}\n\n/**\n * Type alias for a round 1 package entry.\n */\ntype Round1Package = [XID, DkgRound1Package];\n\n/**\n * Type alias for next response ARID entry.\n */\ntype NextResponseArid = [XID, ARID];\n\n/**\n * Result of collecting round 1 responses.\n */\ninterface Round1Collection {\n packages: Round1Package[];\n nextResponseArids: NextResponseArid[];\n displayPath: string;\n}\n\n/**\n * Data extracted from a successful Round 1 response.\n */\ninterface Round1ResponseData {\n package: DkgRound1Package;\n nextResponseArid: ARID;\n}\n\n// -----------------------------------------------------------------------------\n// Validation\n// -----------------------------------------------------------------------------\n\n/**\n * Validate that the owner is the coordinator for this group.\n *\n * Port of `validate_coordinator()` from cmd/dkg/coordinator/round1.rs lines 201-214.\n */\nfunction validateCoordinator(groupRecord: GroupRecord, owner: OwnerRecord): void {\n if (groupRecord.coordinator().xid().urString() !== owner.xid().urString()) {\n throw new Error(\n `Only the coordinator can collect and send Round 2 requests. ` +\n `Coordinator: ${groupRecord.coordinator().xid().urString()}, ` +\n `Owner: ${owner.xid().urString()}`,\n );\n }\n}\n\n// -----------------------------------------------------------------------------\n// Sequential fetch implementation\n// -----------------------------------------------------------------------------\n\n/**\n * Fetch a single round 1 response from storage.\n *\n * Port of `fetch_and_validate_response()` from cmd/dkg/coordinator/round1.rs lines 512-566.\n */\nasync function fetchRound1Response(\n client: StorageClient,\n responseArid: ARID,\n timeout: number | undefined,\n coordinator: XIDDocument,\n expectedGroupId: ARID,\n participantName: string,\n): Promise<[DkgRound1Package, ARID]> {\n const envelope = await getWithIndicator(\n client,\n responseArid,\n participantName,\n timeout,\n isVerbose(),\n );\n\n if (envelope === undefined) {\n throw new Error(\"Response not found in Hubert storage\");\n }\n\n const coordinatorPrivateKeys = coordinator.inceptionPrivateKeys();\n if (coordinatorPrivateKeys === undefined) {\n throw new Error(\"Coordinator XID document has no inception private keys\");\n }\n\n const now = CborDate.now().datetime();\n const sealedResponse = SealedResponse.tryFromEncryptedEnvelope(\n envelope,\n undefined,\n now,\n coordinatorPrivateKeys,\n );\n\n if (sealedResponse.isErr()) {\n const error = sealedResponse.error();\n const reasonEnvelope = error.objectForPredicate(\"reason\");\n const reason =\n reasonEnvelope !== undefined\n ? reasonEnvelope.extractSubject((cbor) => cbor.toText())\n : \"unknown reason\";\n throw new Error(`Participant rejected invite: ${reason}`);\n }\n\n const result = sealedResponse.result();\n validateRound1Response(result, expectedGroupId);\n\n const nextResponseArid = result.tryObjectForPredicate<ARID>(\"response_arid\", (cbor) => {\n return ARID.fromTaggedCbor(cbor);\n });\n\n const round1Package = extractRound1Package(result);\n\n return [round1Package, nextResponseArid];\n}\n\n/**\n * Validate a round 1 response envelope.\n *\n * Port of `validate_round1_response()` from cmd/dkg/coordinator/round1.rs lines 568-586.\n */\nfunction validateRound1Response(result: Envelope, expectedGroupId: ARID): void {\n result.checkSubjectUnit();\n result.checkType(\"dkgRound1Response\");\n\n const groupId = result.tryObjectForPredicate<ARID>(\"group\", (cbor) => {\n return ARID.fromTaggedCbor(cbor);\n });\n\n if (groupId.urString() !== expectedGroupId.urString()) {\n throw new Error(\n `Response group ID ${groupId.urString()} does not match expected ${expectedGroupId.urString()}`,\n );\n }\n}\n\n/**\n * Extract a round 1 package from a response envelope.\n *\n * Port of `extract_round1_package()` from cmd/dkg/coordinator/round1.rs lines 588-598.\n */\nfunction extractRound1Package(result: Envelope): DkgRound1Package {\n const round1Envelope = result.objectForPredicate(\"round1_package\");\n if (round1Envelope === undefined) {\n throw new Error(\"round1_package missing from response\");\n }\n\n const round1Json = round1Envelope.extractSubject<JSONWrapper>((cbor) => {\n return JSONWrapper.fromTaggedCbor(cbor);\n });\n\n const jsonStr = new TextDecoder().decode(round1Json.asBytes());\n const jsonObj = globalThis.JSON.parse(jsonStr) as Record<string, unknown>;\n return serde.round1PackageFromJson(jsonObj);\n}\n\n/**\n * Validate and extract data from a round 1 response (for parallel fetch).\n *\n * Port of `validate_and_extract_round1_response()` from cmd/dkg/coordinator/round1.rs lines 674-707.\n */\nfunction validateAndExtractRound1Response(\n envelope: Envelope,\n coordinatorKeys: PrivateKeys,\n expectedGroupId: ARID,\n): Round1ResponseData | { rejected: string } {\n const now = CborDate.now().datetime();\n const sealedResponse = SealedResponse.tryFromEncryptedEnvelope(\n envelope,\n undefined,\n now,\n coordinatorKeys,\n );\n\n if (sealedResponse.isErr()) {\n const error = sealedResponse.error();\n const reasonEnvelope = error.objectForPredicate(\"reason\");\n const reason =\n reasonEnvelope !== undefined\n ? reasonEnvelope.extractSubject((cbor) => cbor.toText())\n : \"unknown reason\";\n return { rejected: `Participant rejected invite: ${reason}` };\n }\n\n const result = sealedResponse.result();\n validateRound1Response(result, expectedGroupId);\n\n const nextResponseArid = result.tryObjectForPredicate<ARID>(\"response_arid\", (cbor) => {\n return ARID.fromTaggedCbor(cbor);\n });\n\n const pkg = extractRound1Package(result);\n\n return { package: pkg, nextResponseArid };\n}\n\n// -----------------------------------------------------------------------------\n// Parallel collection\n// -----------------------------------------------------------------------------\n\n/**\n * Collect Round 1 responses in parallel with progress display.\n *\n * Port of `collect_round1_responses_parallel()` from cmd/dkg/coordinator/round1.rs lines 636-671.\n */\nasync function collectRound1Parallel(\n client: StorageClient,\n registry: Registry,\n pendingRequests: PendingRequests,\n coordinator: XIDDocument,\n expectedGroupId: ARID,\n timeout: number | undefined,\n): Promise<CollectionResult<Round1ResponseData>> {\n const requests: [XID, ARID, string][] = [];\n for (const [xid, arid] of pendingRequests.iterCollect()) {\n const participant = registry.participant(xid);\n const name = participant?.petName() ?? xid.urString();\n requests.push([xid, arid, name]);\n }\n\n const coordinatorKeys = coordinator.inceptionPrivateKeys();\n if (coordinatorKeys === undefined) {\n throw new Error(\"Missing coordinator private keys\");\n }\n\n const config: ParallelFetchConfig = { timeoutSeconds: timeout };\n const groupId = expectedGroupId;\n\n return parallelFetch(\n client,\n requests,\n (envelope: Envelope, _xid: XID) => {\n return validateAndExtractRound1Response(envelope, coordinatorKeys, groupId);\n },\n config,\n );\n}\n\n// -----------------------------------------------------------------------------\n// Round 2 request building\n// -----------------------------------------------------------------------------\n\n/**\n * Build a Round 2 request for a single participant.\n *\n * Port of `build_round2_request_for_participant()` from cmd/dkg/coordinator/round1.rs lines 604-623.\n */\nfunction buildRound2RequestForParticipant(\n sender: XIDDocument,\n groupId: ARID,\n round1Packages: Round1Package[],\n responseArid: ARID,\n): SealedRequest {\n let request = SealedRequest.new(\"dkgRound2\", ARID.new(), sender)\n .withParameter(\"group\", groupId)\n .withParameter(\"responseArid\", responseArid);\n\n for (const [xid, pkg] of round1Packages) {\n const packageJson = serde.round1PackageToJson(pkg);\n const jsonStr = globalThis.JSON.stringify(packageJson);\n const jsonBytes = new TextEncoder().encode(jsonStr);\n const jsonWrapper = JSONWrapper.fromData(jsonBytes);\n const packageEnvelope = Envelope.new(jsonWrapper).addAssertion(\"participant\", xid);\n request = request.withParameter(\"round1Package\", packageEnvelope);\n }\n\n return request;\n}\n\n/**\n * Dispatch Round 2 requests in parallel.\n *\n * Port of `dispatch_round2_requests_parallel()` from cmd/dkg/coordinator/round1.rs lines 729-844.\n */\nasync function dispatchRound2RequestsParallel(\n client: StorageClient,\n registry: Registry,\n registryPath: string,\n coordinator: XIDDocument,\n groupId: ARID,\n successes: [XID, Round1ResponseData][],\n preview: boolean,\n): Promise<[string, string] | undefined> {\n const signerPrivateKeys = coordinator.inceptionPrivateKeys();\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Coordinator XID document has no signing keys\");\n }\n\n const validUntil = new Date(Date.now() + 60 * 60 * 1000); // 1 hour from now\n\n // Build round1 packages list for request building\n const round1Packages: Round1Package[] = successes.map(([xid, data]) => [xid, data.package]);\n\n // Build participant info and messages\n const messages: [XID, ARID, Envelope, string][] = [];\n const collectArids: [XID, ARID][] = [];\n let previewOutput: [string, string] | undefined;\n\n for (const [xid, data] of successes) {\n const participant = registry.participant(xid);\n if (participant === undefined) {\n throw new Error(`Participant ${xid.urString()} not found in registry`);\n }\n const recipientDoc = participant.xidDocument();\n const participantName = participant.petName() ?? xid.urString();\n\n const collectFromArid = ARID.new();\n collectArids.push([xid, collectFromArid]);\n\n const request = buildRound2RequestForParticipant(\n coordinator,\n groupId,\n round1Packages,\n collectFromArid,\n );\n\n if (preview && previewOutput === undefined) {\n const unsealedEnvelope = request.toEnvelope(validUntil, signerPrivateKeys, undefined);\n previewOutput = [participantName, unsealedEnvelope.urString()];\n }\n\n const sealedEnvelope = request.toEnvelope(validUntil, signerPrivateKeys, recipientDoc);\n\n messages.push([xid, data.nextResponseArid, sealedEnvelope, participantName]);\n }\n\n // Blank line to separate get phase from put phase\n console.error();\n\n // Send all messages in parallel\n const sendResults = await parallelSend(client, messages, isVerbose());\n\n // Check for send failures\n const failures: [XID, string][] = [];\n for (const [xid, err] of sendResults) {\n if (err !== null) {\n failures.push([xid, err.message]);\n }\n }\n\n if (failures.length > 0) {\n for (const [xid, error] of failures) {\n console.error(`Failed to send to ${xid.urString()}: ${error}`);\n }\n throw new Error(`Failed to send Round 2 requests to ${failures.length} participants`);\n }\n\n // Update pending requests for Round 2 collection\n const newPendingRequests = new PendingRequests();\n for (const [xid, collectFromArid] of collectArids) {\n newPendingRequests.addCollectOnly(xid, collectFromArid);\n }\n const groupRecord = registry.groupMut(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n groupRecord.setPendingRequests(newPendingRequests);\n registry.save(registryPath);\n\n return previewOutput;\n}\n\n// -----------------------------------------------------------------------------\n// Pending request updates\n// -----------------------------------------------------------------------------\n\n/**\n * Update pending requests from parallel collection results.\n *\n * Port of `update_pending_for_round2_from_collection()` from cmd/dkg/coordinator/round1.rs lines 710-726.\n */\nfunction updatePendingForRound2FromCollection(\n registry: Registry,\n registryPath: string,\n groupId: ARID,\n successes: [XID, Round1ResponseData][],\n): void {\n const newPending = new PendingRequests();\n for (const [xid, data] of successes) {\n newPending.addSendOnly(xid, data.nextResponseArid);\n }\n const groupRecord = registry.groupMut(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n groupRecord.setPendingRequests(newPending);\n registry.save(registryPath);\n}\n\n// -----------------------------------------------------------------------------\n// Persistence\n// -----------------------------------------------------------------------------\n\n/**\n * Persist collected round 1 packages to disk.\n *\n * Port of `persist_round1_packages()` from cmd/dkg/coordinator/round1.rs lines 301-340.\n */\nfunction persistRound1Packages(\n registryPath: string,\n groupId: ARID,\n packages: Round1Package[],\n): string {\n const packagesDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(packagesDir, { recursive: true });\n\n const round1PackagesPath = path.join(packagesDir, \"collected_round1.json\");\n const packagesJson: Record<string, unknown> = {};\n\n for (const [xid, pkg] of packages) {\n packagesJson[xid.urString()] = serde.round1PackageToJson(pkg);\n }\n\n fs.writeFileSync(round1PackagesPath, globalThis.JSON.stringify(packagesJson, null, 2));\n\n // Return display path (relative to cwd if possible)\n const cwd = process.cwd();\n if (round1PackagesPath.startsWith(cwd)) {\n return round1PackagesPath.slice(cwd.length + 1);\n }\n return round1PackagesPath;\n}\n\n// -----------------------------------------------------------------------------\n// Sequential collection\n// -----------------------------------------------------------------------------\n\n/**\n * Fetch all round 1 packages sequentially.\n *\n * Port of `fetch_all_round1_packages()` from cmd/dkg/coordinator/round1.rs lines 243-299.\n */\nasync function fetchAllRound1Packages(\n ctx: Round1Context,\n pendingRequests: PendingRequests,\n timeout: number | undefined,\n): Promise<[Round1Package[], NextResponseArid[]]> {\n const round1Packages: Round1Package[] = [];\n const nextResponseArids: NextResponseArid[] = [];\n const errors: [XID, string][] = [];\n\n for (const [participantXid, collectFromArid] of pendingRequests.iterCollect()) {\n const participant = ctx.registry.participant(participantXid);\n const participantName = participant?.petName() ?? participantXid.urString();\n\n try {\n const [pkg, nextArid] = await fetchRound1Response(\n ctx.client,\n collectFromArid,\n timeout,\n ctx.ownerDoc,\n ctx.groupId,\n participantName,\n );\n round1Packages.push([participantXid, pkg]);\n nextResponseArids.push([participantXid, nextArid]);\n } catch (e) {\n errors.push([participantXid, e instanceof Error ? e.message : String(e)]);\n }\n }\n\n if (errors.length > 0) {\n if (isVerbose()) {\n console.error();\n console.error(`Failed to collect from ${errors.length} participants:`);\n }\n for (const [xid, error] of errors) {\n console.error(` ${xid.urString()}: ${error}`);\n }\n throw new Error(\n `Round 1 collection incomplete: ${errors.length} of ${pendingRequests.len()} responses failed`,\n );\n }\n\n return [round1Packages, nextResponseArids];\n}\n\n/**\n * Collect round 1 responses sequentially.\n *\n * Port of `collect_round1_responses()` from cmd/dkg/coordinator/round1.rs lines 220-241.\n */\nasync function collectRound1Responses(\n ctx: Round1Context,\n pendingRequests: PendingRequests,\n timeout: number | undefined,\n): Promise<Round1Collection> {\n if (isVerbose()) {\n console.error(`Collecting Round 1 responses from ${pendingRequests.len()} participants...`);\n }\n\n const [packages, nextResponseArids] = await fetchAllRound1Packages(ctx, pendingRequests, timeout);\n\n const displayPath = persistRound1Packages(ctx.registryPath, ctx.groupId, packages);\n\n updatePendingForRound2(ctx, nextResponseArids);\n\n return { packages, nextResponseArids, displayPath };\n}\n\n/**\n * Update pending requests for round 2 (sequential path).\n *\n * Port of `update_pending_for_round2()` from cmd/dkg/coordinator/round1.rs lines 342-357.\n */\nfunction updatePendingForRound2(ctx: Round1Context, nextResponseArids: NextResponseArid[]): void {\n const newPending = new PendingRequests();\n for (const [xid, sendToArid] of nextResponseArids) {\n newPending.addSendOnly(xid, sendToArid);\n }\n const groupRecord = ctx.registry.groupMut(ctx.groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n groupRecord.setPendingRequests(newPending);\n ctx.registry.save(ctx.registryPath);\n}\n\n// -----------------------------------------------------------------------------\n// Round 2 dispatch (sequential)\n// -----------------------------------------------------------------------------\n\n/**\n * Build participant info for round 2 dispatch.\n *\n * Port of `build_round2_participant_info()` from cmd/dkg/coordinator/round1.rs lines 438-458.\n */\nfunction buildRound2ParticipantInfo(\n registry: Registry,\n nextResponseArids: NextResponseArid[],\n): [XID, XIDDocument, ARID, ARID][] {\n return nextResponseArids.map(([xid, sendToArid]) => {\n const participant = registry.participant(xid);\n if (participant === undefined) {\n throw new Error(`Participant ${xid.urString()} not found in registry`);\n }\n const doc = participant.xidDocument();\n const collectFromArid = ARID.new();\n return [xid, doc, sendToArid, collectFromArid];\n });\n}\n\n/**\n * Update pending for round 2 collection (sequential path).\n *\n * Port of `update_pending_for_round2_collection()` from cmd/dkg/coordinator/round1.rs lines 460-475.\n */\nfunction updatePendingForRound2Collection(\n ctx: Round1Context,\n participantInfo: [XID, XIDDocument, ARID, ARID][],\n): void {\n const newPendingRequests = new PendingRequests();\n for (const [xid, , , collectFromArid] of participantInfo) {\n newPendingRequests.addCollectOnly(xid, collectFromArid);\n }\n const groupRecord = ctx.registry.groupMut(ctx.groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n groupRecord.setPendingRequests(newPendingRequests);\n ctx.registry.save(ctx.registryPath);\n}\n\n/**\n * Dispatch Round 2 requests sequentially.\n *\n * Port of `dispatch_round2_requests()` from cmd/dkg/coordinator/round1.rs lines 363-436.\n */\nasync function dispatchRound2Requests(\n ctx: Round1Context,\n collection: Round1Collection,\n preview: boolean,\n): Promise<[string, string] | undefined> {\n const signerPrivateKeys = ctx.ownerDoc.inceptionPrivateKeys();\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Coordinator XID document has no signing keys\");\n }\n\n const validUntil = new Date(Date.now() + 60 * 60 * 1000); // 1 hour from now\n\n const participantInfo = buildRound2ParticipantInfo(ctx.registry, collection.nextResponseArids);\n\n if (isVerbose()) {\n console.error(`Sending Round 2 requests to ${participantInfo.length} participants...`);\n } else {\n // Blank line to separate get phase from put phase\n console.error();\n }\n\n let previewOutput: [string, string] | undefined;\n\n for (const [xid, recipientDoc, sendToArid, collectFromArid] of participantInfo) {\n const participant = ctx.registry.participant(xid);\n const participantName = participant?.petName() ?? xid.urString();\n\n const request = buildRound2RequestForParticipant(\n ctx.ownerDoc,\n ctx.groupId,\n collection.packages,\n collectFromArid,\n );\n\n if (preview && previewOutput === undefined) {\n const unsealedEnvelope = request.toEnvelope(validUntil, signerPrivateKeys, undefined);\n previewOutput = [participantName, unsealedEnvelope.urString()];\n }\n\n const sealedEnvelope = request.toEnvelope(validUntil, signerPrivateKeys, recipientDoc);\n\n await putWithIndicator(ctx.client, sendToArid, sealedEnvelope, participantName, isVerbose());\n }\n\n updatePendingForRound2Collection(ctx, participantInfo);\n\n return previewOutput;\n}\n\n// -----------------------------------------------------------------------------\n// Output\n// -----------------------------------------------------------------------------\n\n/**\n * Print summary for sequential collection.\n *\n * Port of `print_summary()` from cmd/dkg/coordinator/round1.rs lines 481-506.\n */\nfunction printSummary(collection: Round1Collection, preview: [string, string] | undefined): void {\n if (preview !== undefined) {\n const [participantName, ur] = preview;\n if (isVerbose()) {\n console.error(`# Round 2 preview for ${participantName}`);\n console.error();\n }\n console.error(\n `Collected ${collection.packages.length} Round 1 packages to ${collection.displayPath} ` +\n `and sent ${collection.nextResponseArids.length} Round 2 requests.`,\n );\n console.log(ur);\n } else if (isVerbose()) {\n console.error();\n console.error(\n `Collected ${collection.packages.length} Round 1 packages to ${collection.displayPath} ` +\n `and sent ${collection.nextResponseArids.length} Round 2 requests.`,\n );\n }\n}\n\n/**\n * Print summary for parallel collection.\n *\n * Port of `print_summary_parallel()` from cmd/dkg/coordinator/round1.rs lines 847-901.\n */\nfunction printSummaryParallel(\n collection: CollectionResult<Round1ResponseData>,\n displayPath: string,\n preview: [string, string] | undefined,\n): void {\n // Report any failures\n if (collection.rejections.length > 0) {\n console.error();\n console.error(\"Rejections:\");\n for (const [xid, reason] of collection.rejections) {\n console.error(` ${xid.urString()}: ${reason}`);\n }\n }\n if (collection.errors.length > 0) {\n console.error();\n console.error(\"Errors:\");\n for (const [xid, error] of collection.errors) {\n console.error(` ${xid.urString()}: ${error}`);\n }\n }\n if (collection.timeouts.length > 0) {\n console.error();\n console.error(\"Timeouts:\");\n for (const xid of collection.timeouts) {\n console.error(` ${xid.urString()}`);\n }\n }\n\n if (!collection.allSucceeded()) {\n console.error();\n bailWithCollectionSummary(collection);\n }\n\n if (preview !== undefined) {\n const [participantName, ur] = preview;\n if (isVerbose()) {\n console.error(`# Round 2 preview for ${participantName}`);\n console.error();\n }\n console.error(\n `Collected ${collection.successes.length} Round 1 packages to ${displayPath} ` +\n `and sent ${collection.successes.length} Round 2 requests.`,\n );\n console.log(ur);\n } else if (isVerbose()) {\n console.error();\n console.error(\n `Collected ${collection.successes.length} Round 1 packages to ${displayPath} ` +\n `and sent ${collection.successes.length} Round 2 requests.`,\n );\n }\n}\n\n/**\n * Print collection summary and throw error.\n *\n * Port of `bail_with_collection_summary()` from cmd/dkg/coordinator/round1.rs lines 903-913.\n */\nfunction bailWithCollectionSummary(collection: CollectionResult<Round1ResponseData>): never {\n const msg =\n `Round 1 collection incomplete: ${collection.successes.length} succeeded, ` +\n `${collection.rejections.length} rejected, ${collection.errors.length} errors, ` +\n `${collection.timeouts.length} timeouts`;\n console.error(msg);\n throw new Error(msg);\n}\n\n// -----------------------------------------------------------------------------\n// Main entry point\n// -----------------------------------------------------------------------------\n\n/**\n * Execute the DKG coordinator round 1 command.\n *\n * Collects commitment packages from participants.\n *\n * Port of `CommandArgs::exec()` from cmd/dkg/coordinator/round1.rs lines 59-173.\n */\nexport async function round1(\n client: StorageClient,\n options: DkgRound1Options,\n cwd: string,\n): Promise<DkgRound1Result> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n const ownerDoc = owner.xidDocument();\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(`Group ${options.groupId} not found in registry`);\n }\n\n validateCoordinator(groupRecord, owner);\n\n const pendingRequests = groupRecord.pendingRequests();\n if (pendingRequests.isEmpty()) {\n throw new Error(\"No pending requests for this group. Round 1 may already be collected.\");\n }\n\n if (options.parallel === true) {\n // Parallel path with progress display\n const collection = await collectRound1Parallel(\n client,\n registry,\n pendingRequests,\n ownerDoc,\n groupId,\n options.timeoutSeconds,\n );\n\n // Extract packages for persistence\n const packages: Round1Package[] = collection.successes.map(([xid, data]) => [\n xid,\n data.package,\n ]);\n\n const displayPath = persistRound1Packages(registryPath, groupId, packages);\n\n updatePendingForRound2FromCollection(registry, registryPath, groupId, collection.successes);\n\n const preview = await dispatchRound2RequestsParallel(\n client,\n registry,\n registryPath,\n ownerDoc,\n groupId,\n collection.successes,\n options.preview ?? false,\n );\n\n printSummaryParallel(collection, displayPath, preview);\n\n return {\n accepted: collection.successes.length,\n rejected: collection.rejections.length,\n errors: collection.errors.length,\n timeouts: collection.timeouts.length,\n };\n } else {\n // Sequential path (original behavior)\n const ctx: Round1Context = {\n client,\n registryPath,\n registry,\n ownerDoc,\n groupId,\n };\n\n const collection = await collectRound1Responses(ctx, pendingRequests, options.timeoutSeconds);\n\n const preview = await dispatchRound2Requests(ctx, collection, options.preview ?? false);\n\n printSummary(collection, preview);\n\n return {\n accepted: collection.packages.length,\n rejected: 0,\n errors: 0,\n timeouts: 0,\n };\n }\n}\n","/**\n * DKG coordinator round 2 command.\n *\n * Port of cmd/dkg/coordinator/round2.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, type PrivateKeys, XID } from \"@bcts/components\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { SealedRequest, SealedResponse } from \"@bcts/gstp\";\nimport type { XIDDocument } from \"@bcts/xid\";\n\nimport {\n type GroupRecord,\n PendingRequests,\n Registry,\n resolveRegistryPath,\n} from \"../../../registry/index.js\";\nimport { groupStateDir, isVerbose } from \"../../common.js\";\nimport {\n type CollectionResult,\n parallelFetch,\n parallelSend,\n type ParallelFetchConfig,\n parallelFetchConfigWithTimeout,\n} from \"../../parallel.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { getWithIndicator, putWithIndicator } from \"../../busy.js\";\nimport { parseAridUr } from \"../common.js\";\n\n// -----------------------------------------------------------------------------\n// Types\n// -----------------------------------------------------------------------------\n\n/**\n * Options for the DKG round2 command.\n */\nexport interface DkgRound2Options {\n registryPath?: string;\n groupId: string;\n parallel?: boolean;\n timeoutSeconds?: number;\n verbose?: boolean;\n preview?: boolean;\n}\n\n/**\n * Result of the DKG round2 command.\n */\nexport interface DkgRound2Result {\n accepted: number;\n rejected: number;\n errors: number;\n timeouts: number;\n displayPath?: string;\n}\n\n/**\n * Data extracted from a successful Round 2 response.\n *\n * Port of `struct Round2ResponseData` from round2.rs lines 601-604.\n */\nexport interface Round2ResponseData {\n packages: [XID, unknown][];\n nextResponseArid: ARID;\n}\n\n/**\n * Round 2 collection result (for sequential path).\n *\n * Port of `struct Round2Collection` from round2.rs lines 206-213.\n */\ninterface Round2Collection {\n packages: Map<string, [XID, unknown][]>; // Map<XID.urString(), [recipient XID, package][]>\n nextResponseArids: [XID, ARID][];\n displayPath: string;\n}\n\n/**\n * Entry for a collected Round 2 response.\n *\n * Port of `struct CollectedRound2Entry` from round2.rs lines 359-362.\n */\ninterface CollectedRound2Entry {\n packages: [XID, unknown][];\n nextResponseArid: ARID;\n}\n\n// -----------------------------------------------------------------------------\n// Validation\n// -----------------------------------------------------------------------------\n\n/**\n * Validate that the owner is the coordinator of the group.\n *\n * Port of coordinator check from round2.rs lines 86-94.\n */\nfunction validateCoordinator(groupRecord: GroupRecord, ownerXid: XID): void {\n if (groupRecord.coordinator().xid().urString() !== ownerXid.urString()) {\n throw new Error(\n `Only the coordinator can collect Round 2 responses and send finalize packages. ` +\n `Coordinator: ${groupRecord.coordinator().xid().urString()}, Owner: ${ownerXid.urString()}`,\n );\n }\n}\n\n// -----------------------------------------------------------------------------\n// Response validation and extraction\n// -----------------------------------------------------------------------------\n\n/**\n * Validate envelope and extract Round 2 data (for parallel fetch).\n *\n * Port of `validate_and_extract_round2_response()` from round2.rs lines 646-708.\n */\nexport function validateAndExtractRound2Response(\n envelope: Envelope,\n coordinatorKeys: PrivateKeys,\n expectedGroupId: ARID,\n expectedSender: XID,\n): Round2ResponseData | { rejected: string } {\n const now = new Date();\n\n let sealed: SealedResponse;\n try {\n sealed = SealedResponse.tryFromEncryptedEnvelope(envelope, undefined, now, coordinatorKeys);\n } catch (err) {\n return {\n rejected: `Failed to decrypt/parse response: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Check for error response\n if (!sealed.isOk()) {\n try {\n const error = sealed.error();\n const reasonEnv = error.optionalObjectForPredicate(\"reason\");\n const reason = reasonEnv?.extractString() ?? \"unknown reason\";\n return { rejected: `Participant reported error: ${reason}` };\n } catch {\n return { rejected: \"Participant reported error: unknown reason\" };\n }\n }\n\n // Get and validate result\n let result: Envelope;\n try {\n result = sealed.result();\n } catch {\n return { rejected: \"Response has no result envelope\" };\n }\n\n // Validate response type\n try {\n result.checkSubjectUnit();\n result.checkType(\"dkgRound2Response\");\n } catch (err) {\n return {\n rejected: `Invalid response type: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Validate group ID\n try {\n const groupEnv = result.objectForPredicate(\"group\");\n const groupId = groupEnv.extractSubject<ARID>((cbor) => ARID.fromTaggedCbor(cbor));\n if (groupId.urString() !== expectedGroupId.urString()) {\n return {\n rejected: `Response group ID ${groupId.urString()} does not match expected ${expectedGroupId.urString()}`,\n };\n }\n } catch (err) {\n return {\n rejected: `Failed to extract group: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Validate participant/sender\n try {\n const participantEnv = result.objectForPredicate(\"participant\");\n const senderXid = participantEnv.extractSubject<XID>((cbor) => XID.fromTaggedCbor(cbor));\n if (senderXid.urString() !== expectedSender.urString()) {\n return {\n rejected: `Response participant ${senderXid.urString()} does not match expected ${expectedSender.urString()}`,\n };\n }\n } catch (err) {\n return {\n rejected: `Failed to extract participant: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Extract next response ARID\n let nextResponseArid: ARID;\n try {\n const responseAridEnv = result.objectForPredicate(\"response_arid\");\n nextResponseArid = responseAridEnv.extractSubject<ARID>((cbor) => ARID.fromTaggedCbor(cbor));\n } catch (err) {\n return {\n rejected: `Failed to extract response_arid: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Extract round2 packages\n const packages: [XID, unknown][] = [];\n try {\n const pkgEnvelopes = result.objectsForPredicate(\"round2Package\");\n for (const pkgEnv of pkgEnvelopes) {\n const recipientEnv = pkgEnv.objectForPredicate(\"recipient\");\n const recipient = recipientEnv.extractSubject<XID>((cbor) => XID.fromTaggedCbor(cbor));\n const pkgJsonStr = pkgEnv.extractString();\n const pkg: unknown = JSON.parse(pkgJsonStr);\n packages.push([recipient, pkg]);\n }\n } catch (err) {\n return {\n rejected: `Failed to extract round2 packages: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n return { packages, nextResponseArid };\n}\n\n// -----------------------------------------------------------------------------\n// Sequential collection\n// -----------------------------------------------------------------------------\n\n/**\n * Fetch a Round 2 response sequentially.\n *\n * Port of `fetch_round2_response()` from round2.rs lines 364-442.\n */\nasync function fetchRound2Response(\n client: StorageClient,\n arid: ARID,\n timeout: number | undefined,\n coordinatorKeys: PrivateKeys,\n expectedGroup: ARID,\n expectedSender: XID,\n): Promise<CollectedRound2Entry> {\n const envelope = await getWithIndicator(\n client,\n arid,\n expectedSender.urString(),\n timeout,\n isVerbose(),\n );\n\n if (envelope === null || envelope === undefined) {\n throw new Error(\"Response not found in Hubert storage\");\n }\n\n const result = validateAndExtractRound2Response(\n envelope,\n coordinatorKeys,\n expectedGroup,\n expectedSender,\n );\n\n if (\"rejected\" in result) {\n throw new Error(result.rejected);\n }\n\n return {\n packages: result.packages,\n nextResponseArid: result.nextResponseArid,\n };\n}\n\n/**\n * Collect Round 2 responses sequentially.\n *\n * Port of `collect_round2()` from round2.rs lines 216-357.\n */\nasync function collectRound2(\n client: StorageClient,\n registryPath: string,\n registry: Registry,\n coordinatorKeys: PrivateKeys,\n groupId: ARID,\n pendingRequests: PendingRequests,\n timeout: number | undefined,\n): Promise<Round2Collection> {\n if (isVerbose()) {\n console.error(`Collecting Round 2 responses from ${pendingRequests.len()} participants...`);\n }\n\n const allPackages = new Map<string, [XID, unknown][]>();\n const nextResponseArids: [XID, ARID][] = [];\n const errors: [XID, string][] = [];\n\n for (const [participantXid, collectFromArid] of pendingRequests.iterCollect()) {\n const participantRecord = registry.participant(participantXid);\n const participantName = participantRecord?.petName() ?? participantXid.urString();\n\n if (isVerbose()) {\n console.error(`${participantName}...`);\n }\n\n try {\n const collected = await fetchRound2Response(\n client,\n collectFromArid,\n timeout,\n coordinatorKeys,\n groupId,\n participantXid,\n );\n allPackages.set(participantXid.urString(), collected.packages);\n nextResponseArids.push([participantXid, collected.nextResponseArid]);\n } catch (err) {\n if (isVerbose()) {\n console.error(`error: ${err instanceof Error ? err.message : String(err)}`);\n }\n errors.push([participantXid, err instanceof Error ? err.message : String(err)]);\n }\n }\n\n if (errors.length > 0) {\n if (isVerbose()) {\n console.error();\n console.error(`Failed to collect from ${errors.length} participants:`);\n }\n for (const [xid, error] of errors) {\n console.error(` ${xid.urString()}: ${error}`);\n }\n throw new Error(\n `Round 2 collection incomplete: ${errors.length} of ${pendingRequests.len()} responses failed`,\n );\n }\n\n // Persist collected round2 packages\n const displayPath = persistRound2PackagesFromMap(\n registryPath,\n groupId,\n allPackages,\n nextResponseArids,\n );\n\n // Update pending requests\n const newPending = new PendingRequests();\n for (const [xid, sendToArid] of nextResponseArids) {\n newPending.addSendOnly(xid, sendToArid);\n }\n const groupRecord = registry.group(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n groupRecord.setPendingRequests(newPending);\n registry.save(registryPath);\n\n return {\n packages: allPackages,\n nextResponseArids,\n displayPath,\n };\n}\n\n/**\n * Persist Round 2 packages from a Map (sequential collection).\n */\nfunction persistRound2PackagesFromMap(\n registryPath: string,\n groupId: ARID,\n allPackages: Map<string, [XID, unknown][]>,\n nextResponseArids: [XID, ARID][],\n): string {\n const stateDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const collectedPath = path.join(stateDir, \"collected_round2.json\");\n const root: Record<string, unknown> = {};\n\n for (const [senderUrString, packages] of allPackages) {\n const senderMap: Record<string, unknown> = {};\n\n // Find response_arid for this sender\n const responseArid = nextResponseArids.find(([xid]) => xid.urString() === senderUrString)?.[1];\n\n if (responseArid !== undefined) {\n senderMap[\"response_arid\"] = responseArid.urString();\n }\n\n const packagesJson: Record<string, unknown> = {};\n for (const [recipient, pkg] of packages) {\n packagesJson[recipient.urString()] = pkg;\n }\n senderMap[\"packages\"] = packagesJson;\n\n root[senderUrString] = senderMap;\n }\n\n fs.writeFileSync(collectedPath, JSON.stringify(root, null, 2));\n\n // Return relative path if possible\n const cwd = process.cwd();\n if (collectedPath.startsWith(cwd)) {\n return collectedPath.slice(cwd.length + 1);\n }\n return collectedPath;\n}\n\n// -----------------------------------------------------------------------------\n// Parallel collection\n// -----------------------------------------------------------------------------\n\n/**\n * Collect Round 2 responses in parallel with progress display.\n *\n * Port of `collect_round2_parallel()` from round2.rs lines 607-643.\n */\nexport async function collectRound2Parallel(\n client: StorageClient,\n registry: Registry,\n pendingRequests: PendingRequests,\n coordinatorKeys: PrivateKeys,\n expectedGroupId: ARID,\n timeout: number | undefined,\n): Promise<CollectionResult<Round2ResponseData>> {\n const requests: [XID, ARID, string][] = [];\n\n for (const [xid, arid] of pendingRequests.iterCollect()) {\n const record = registry.participant(xid);\n const name = record?.petName() ?? xid.urString();\n requests.push([xid, arid, name]);\n }\n\n const config: ParallelFetchConfig = parallelFetchConfigWithTimeout(timeout);\n\n return parallelFetch(\n client,\n requests,\n (envelope: Envelope, xid: XID) =>\n validateAndExtractRound2Response(envelope, coordinatorKeys, expectedGroupId, xid),\n config,\n );\n}\n\n// -----------------------------------------------------------------------------\n// Persist Round 2 packages (parallel)\n// -----------------------------------------------------------------------------\n\n/**\n * Persist Round 2 packages from parallel collection results.\n *\n * Port of `persist_round2_packages()` from round2.rs lines 712-758.\n */\nexport function persistRound2Packages(\n registryPath: string,\n groupId: ARID,\n successes: [XID, Round2ResponseData][],\n): string {\n const stateDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const collectedPath = path.join(stateDir, \"collected_round2.json\");\n const root: Record<string, unknown> = {};\n\n for (const [sender, data] of successes) {\n const senderMap: Record<string, unknown> = {};\n senderMap[\"response_arid\"] = data.nextResponseArid.urString();\n\n const packagesJson: Record<string, unknown> = {};\n for (const [recipient, pkg] of data.packages) {\n packagesJson[recipient.urString()] = pkg;\n }\n senderMap[\"packages\"] = packagesJson;\n\n root[sender.urString()] = senderMap;\n }\n\n fs.writeFileSync(collectedPath, JSON.stringify(root, null, 2));\n\n // Return relative path if possible\n const cwd = process.cwd();\n if (collectedPath.startsWith(cwd)) {\n return collectedPath.slice(cwd.length + 1);\n }\n return collectedPath;\n}\n\n// -----------------------------------------------------------------------------\n// Update pending requests (parallel)\n// -----------------------------------------------------------------------------\n\n/**\n * Update pending requests from parallel collection results.\n *\n * Port of `update_pending_for_finalize_from_collection()` from round2.rs lines 761-777.\n */\nexport function updatePendingForFinalizeFromCollection(\n registry: Registry,\n registryPath: string,\n groupId: ARID,\n successes: [XID, Round2ResponseData][],\n): void {\n const newPending = new PendingRequests();\n for (const [xid, data] of successes) {\n newPending.addSendOnly(xid, data.nextResponseArid);\n }\n\n const groupRecord = registry.group(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n groupRecord.setPendingRequests(newPending);\n registry.save(registryPath);\n}\n\n// -----------------------------------------------------------------------------\n// Finalize request building\n// -----------------------------------------------------------------------------\n\n/**\n * Gather packages FOR a specific recipient (from all other senders).\n *\n * Port of `gather_packages_for_recipient()` from round2.rs lines 552-571.\n */\nfunction gatherPackagesForRecipient(\n recipient: XID,\n allPackages: Map<string, [XID, unknown][]>,\n): [XID, unknown][] {\n const result: [XID, unknown][] = [];\n\n for (const [senderUrString, packages] of allPackages) {\n for (const [rcpt, pkg] of packages) {\n if (rcpt.urString() === recipient.urString()) {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef\n const { XID: XIDClass } = require(\"@bcts/components\");\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n const sender = XIDClass.fromURString(senderUrString) as XID;\n result.push([sender, pkg]);\n }\n }\n }\n\n if (result.length === 0) {\n throw new Error(`No round2 packages found for recipient ${recipient.urString()}`);\n }\n\n return result;\n}\n\n/**\n * Build a finalize request for a participant.\n *\n * Port of `build_finalize_request_for_participant()` from round2.rs lines 575-594.\n */\nexport function buildFinalizeRequestForParticipant(\n sender: XIDDocument,\n groupId: ARID,\n responseArid: ARID,\n packages: [XID, unknown][],\n): SealedRequest {\n let request = SealedRequest.new(\"dkgFinalize\", ARID.new(), sender)\n .withParameter(\"group\", groupId)\n .withParameter(\"responseArid\", responseArid);\n\n for (const [pkgSender, pkg] of packages) {\n const encoded = JSON.stringify(pkg);\n const pkgEnvelope = Envelope.new(encoded).addAssertion(\"sender\", pkgSender);\n request = request.withParameter(\"round2Package\", pkgEnvelope);\n }\n\n return request;\n}\n\n// -----------------------------------------------------------------------------\n// Send finalize requests (sequential)\n// -----------------------------------------------------------------------------\n\n/**\n * Send finalize requests sequentially.\n *\n * Port of `send_finalize_requests()` from round2.rs lines 444-550.\n */\nasync function sendFinalizeRequests(\n client: StorageClient,\n registryPath: string,\n registry: Registry,\n coordinator: XIDDocument,\n groupId: ARID,\n collection: Round2Collection,\n preview: boolean,\n): Promise<[string, string] | undefined> {\n const signerPrivateKeys = coordinator.inceptionPrivateKeys();\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Coordinator XID document has no signing keys\");\n }\n\n const validUntil = new Date(Date.now() + 60 * 60 * 1000); // 1 hour\n\n // Build participant info: [XID, XIDDocument, sendToArid, collectFromArid]\n const participantInfo: [XID, XIDDocument, ARID, ARID][] = [];\n\n for (const [xid, sendToArid] of collection.nextResponseArids) {\n const record = registry.participant(xid);\n if (record === undefined) {\n throw new Error(`Participant ${xid.urString()} not found in registry`);\n }\n const collectFromArid = ARID.new();\n participantInfo.push([xid, record.xidDocument(), sendToArid, collectFromArid]);\n }\n\n if (isVerbose()) {\n console.error(`Sending finalize packages to ${participantInfo.length} participants...`);\n } else {\n console.error(); // Blank line to separate get phase from put phase\n }\n\n let previewOutput: [string, string] | undefined;\n\n for (const [xid, recipientDoc, sendToArid, collectFromArid] of participantInfo) {\n const record = registry.participant(xid);\n const participantName = record?.petName() ?? xid.urString();\n\n if (isVerbose()) {\n console.error(`${participantName}...`);\n }\n\n // Gather packages FOR this recipient\n const packagesForRecipient = gatherPackagesForRecipient(xid, collection.packages);\n\n const request = buildFinalizeRequestForParticipant(\n coordinator,\n groupId,\n collectFromArid,\n packagesForRecipient,\n );\n\n if (preview && previewOutput === undefined) {\n const unsealedEnvelope = request.toEnvelope(validUntil, signerPrivateKeys, undefined);\n previewOutput = [participantName, unsealedEnvelope.urString()];\n }\n\n const sealedEnvelope = request.toEnvelopeForRecipients(validUntil, signerPrivateKeys, [\n recipientDoc,\n ]);\n\n await putWithIndicator(client, sendToArid, sealedEnvelope, participantName, isVerbose());\n }\n\n // Build pending requests for finalize response collection\n const newPendingRequests = new PendingRequests();\n for (const [xid, , , collectFromArid] of participantInfo) {\n newPendingRequests.addCollectOnly(xid, collectFromArid);\n }\n const groupRecord = registry.group(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n groupRecord.setPendingRequests(newPendingRequests);\n registry.save(registryPath);\n\n return previewOutput;\n}\n\n// -----------------------------------------------------------------------------\n// Dispatch finalize requests (parallel)\n// -----------------------------------------------------------------------------\n\n/**\n * Dispatch finalize requests in parallel.\n *\n * Port of `dispatch_finalize_requests_parallel()` from round2.rs lines 780-900.\n */\nexport async function dispatchFinalizeRequestsParallel(\n client: StorageClient,\n registry: Registry,\n registryPath: string,\n coordinator: XIDDocument,\n groupId: ARID,\n successes: [XID, Round2ResponseData][],\n preview: boolean,\n): Promise<[string, string] | undefined> {\n const signerPrivateKeys = coordinator.inceptionPrivateKeys();\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Coordinator XID document has no signing keys\");\n }\n\n const validUntil = new Date(Date.now() + 60 * 60 * 1000); // 1 hour\n\n // Build all_packages map for gatherPackagesForRecipient\n const allPackages = new Map<string, [XID, unknown][]>();\n for (const [xid, data] of successes) {\n allPackages.set(xid.urString(), data.packages);\n }\n\n // Build messages\n const messages: [XID, ARID, Envelope, string][] = [];\n const collectArids: [XID, ARID][] = [];\n let previewOutput: [string, string] | undefined;\n\n for (const [xid, data] of successes) {\n const record = registry.participant(xid);\n if (record === undefined) {\n throw new Error(`Participant ${xid.urString()} not found in registry`);\n }\n const recipientDoc = record.xidDocument();\n const participantName = record.petName() ?? xid.urString();\n\n const collectFromArid = ARID.new();\n collectArids.push([xid, collectFromArid]);\n\n const packagesForRecipient = gatherPackagesForRecipient(xid, allPackages);\n\n const request = buildFinalizeRequestForParticipant(\n coordinator,\n groupId,\n collectFromArid,\n packagesForRecipient,\n );\n\n if (preview && previewOutput === undefined) {\n const unsealedEnvelope = request.toEnvelope(validUntil, signerPrivateKeys, undefined);\n previewOutput = [participantName, unsealedEnvelope.urString()];\n }\n\n const sealedEnvelope = request.toEnvelopeForRecipients(validUntil, signerPrivateKeys, [\n recipientDoc,\n ]);\n\n messages.push([xid, data.nextResponseArid, sealedEnvelope, participantName]);\n }\n\n // Blank line to separate get phase from put phase\n console.error();\n\n // Send all messages in parallel\n const sendResults = await parallelSend(client, messages, isVerbose());\n\n // Check for send failures\n const failures = sendResults.filter(([, err]) => err !== null);\n\n if (failures.length > 0) {\n for (const [xid, error] of failures) {\n if (error !== null) {\n console.error(`Failed to send to ${xid.urString()}: ${error.message}`);\n }\n }\n throw new Error(`Failed to send finalize requests to ${failures.length} participants`);\n }\n\n // Update pending requests for finalize response collection\n const newPendingRequests = new PendingRequests();\n for (const [xid, collectFromArid] of collectArids) {\n newPendingRequests.addCollectOnly(xid, collectFromArid);\n }\n const groupRecord = registry.group(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n groupRecord.setPendingRequests(newPendingRequests);\n registry.save(registryPath);\n\n return previewOutput;\n}\n\n// -----------------------------------------------------------------------------\n// Summary printing\n// -----------------------------------------------------------------------------\n\n/**\n * Print summary for parallel collection.\n *\n * Port of `print_summary_parallel()` from round2.rs lines 903-964.\n */\nfunction printSummaryParallel(\n collection: CollectionResult<Round2ResponseData>,\n displayPath: string,\n preview: [string, string] | undefined,\n): void {\n // Report any failures\n if (collection.rejections.length > 0) {\n console.error();\n console.error(\"Rejections:\");\n for (const [xid, reason] of collection.rejections) {\n console.error(` ${xid.urString()}: ${reason}`);\n }\n }\n if (collection.errors.length > 0) {\n console.error();\n console.error(\"Errors:\");\n for (const [xid, error] of collection.errors) {\n console.error(` ${xid.urString()}: ${error}`);\n }\n }\n if (collection.timeouts.length > 0) {\n console.error();\n console.error(\"Timeouts:\");\n for (const xid of collection.timeouts) {\n console.error(` ${xid.urString()}`);\n }\n }\n\n if (!collection.allSucceeded()) {\n console.error();\n console.error(\n `Round 2 collection incomplete: ${collection.successes.length} succeeded, ` +\n `${collection.rejections.length} rejected, ${collection.errors.length} errors, ` +\n `${collection.timeouts.length} timeouts`,\n );\n return;\n }\n\n if (preview !== undefined) {\n const [participantName, ur] = preview;\n if (isVerbose()) {\n console.error(`# Finalize preview for ${participantName}`);\n console.error();\n }\n console.error(\n `Collected ${collection.successes.length} Round 2 responses to ${displayPath} and sent ${collection.successes.length} finalize requests.`,\n );\n console.log(ur);\n } else if (isVerbose()) {\n console.error();\n console.error(\n `Collected ${collection.successes.length} Round 2 responses to ${displayPath} and sent ${collection.successes.length} finalize requests.`,\n );\n }\n}\n\n// -----------------------------------------------------------------------------\n// Main entry point\n// -----------------------------------------------------------------------------\n\n/**\n * Execute the DKG coordinator round 2 command.\n *\n * Collects Round 2 responses and sends finalize packages.\n *\n * Port of `CommandArgs::exec()` from cmd/dkg/coordinator/round2.rs lines 59-203.\n */\nexport async function round2(\n client: StorageClient,\n options: DkgRound2Options,\n cwd: string,\n): Promise<DkgRound2Result> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n const ownerDoc = owner.xidDocument();\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(`Group ${options.groupId} not found in registry`);\n }\n\n // Verify we are the coordinator\n validateCoordinator(groupRecord, owner.xid());\n\n const pendingRequests = groupRecord.pendingRequests();\n if (pendingRequests.isEmpty()) {\n throw new Error(\n \"No pending requests for this group. Did you run 'frost dkg coordinator round1'?\",\n );\n }\n\n const coordinatorKeys = ownerDoc.inceptionPrivateKeys();\n if (coordinatorKeys === undefined) {\n throw new Error(\"Coordinator XID document has no private keys\");\n }\n\n if (options.parallel === true) {\n // Parallel path with progress display\n const collection = await collectRound2Parallel(\n client,\n registry,\n pendingRequests,\n coordinatorKeys,\n groupId,\n options.timeoutSeconds,\n );\n\n // Persist collected data\n const displayPath = persistRound2Packages(registryPath, groupId, collection.successes);\n\n updatePendingForFinalizeFromCollection(registry, registryPath, groupId, collection.successes);\n\n const preview = await dispatchFinalizeRequestsParallel(\n client,\n registry,\n registryPath,\n ownerDoc,\n groupId,\n collection.successes,\n options.preview ?? false,\n );\n\n printSummaryParallel(collection, displayPath, preview);\n\n return {\n accepted: collection.successes.length,\n rejected: collection.rejections.length,\n errors: collection.errors.length,\n timeouts: collection.timeouts.length,\n displayPath,\n };\n } else {\n // Sequential path (original behavior)\n // Phase 1: Collect Round 2 responses\n const collection = await collectRound2(\n client,\n registryPath,\n registry,\n coordinatorKeys,\n groupId,\n pendingRequests,\n options.timeoutSeconds,\n );\n\n // Phase 2: Send finalize packages\n const preview = await sendFinalizeRequests(\n client,\n registryPath,\n registry,\n ownerDoc,\n groupId,\n collection,\n options.preview ?? false,\n );\n\n if (preview !== undefined) {\n const [participantName, ur] = preview;\n if (isVerbose()) {\n console.error(`# Finalize preview for ${participantName}`);\n console.error();\n }\n console.error(\n `Collected ${collection.packages.size} Round 2 responses to ${collection.displayPath} and sent ${collection.nextResponseArids.length} finalize requests.`,\n );\n console.log(ur);\n } else if (isVerbose()) {\n console.error();\n console.error(\n `Collected ${collection.packages.size} Round 2 responses to ${collection.displayPath} and sent ${collection.nextResponseArids.length} finalize requests.`,\n );\n }\n\n return {\n accepted: collection.packages.size,\n rejected: 0,\n errors: 0,\n timeouts: 0,\n displayPath: collection.displayPath,\n };\n }\n}\n","/**\n * DKG coordinator finalize command.\n *\n * Port of cmd/dkg/coordinator/finalize.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { type ARID, type PrivateKeys, type SigningPublicKey, type XID } from \"@bcts/components\";\nimport { type Envelope } from \"@bcts/envelope\";\nimport { SealedResponse } from \"@bcts/gstp\";\n\nimport {\n type GroupRecord,\n type PendingRequests,\n Registry,\n resolveRegistryPath,\n} from \"../../../registry/index.js\";\nimport { groupStateDir, isVerbose } from \"../../common.js\";\nimport {\n type CollectionResult,\n parallelFetch,\n type ParallelFetchConfig,\n parallelFetchConfigWithTimeout,\n} from \"../../parallel.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { getWithIndicator } from \"../../busy.js\";\nimport { parseAridUr, signingKeyFromVerifying } from \"../common.js\";\n\n/**\n * Options for the DKG finalize command.\n */\nexport interface DkgFinalizeOptions {\n registryPath?: string;\n groupId: string;\n parallel?: boolean;\n timeoutSeconds?: number;\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG finalize command.\n */\nexport interface DkgFinalizeResult {\n verifyingKey: string;\n collected: number;\n rejected: number;\n errors: number;\n timeouts: number;\n}\n\n/**\n * Data extracted from a successful finalize response.\n *\n * Port of `struct FinalizeResponseData` from finalize.rs.\n */\ninterface FinalizeResponseData {\n keyPackage: unknown;\n publicKeyPackage: unknown;\n}\n\n/**\n * Entry for a collected finalize response.\n *\n * Port of `struct FinalizeEntry` from finalize.rs.\n */\ninterface FinalizeEntry {\n participant: XID;\n keyPackage: unknown;\n publicKeyPackage: unknown;\n}\n\n/**\n * Validate that the owner is the coordinator of the group.\n *\n * Port of coordinator check from finalize.rs lines 76-82.\n */\nfunction validateCoordinator(groupRecord: GroupRecord, ownerXid: XID): void {\n if (groupRecord.coordinator().xid().urString() !== ownerXid.urString()) {\n throw new Error(\n `Only the coordinator can collect finalize responses. Coordinator: ${groupRecord.coordinator().xid().urString()}, Owner: ${ownerXid.urString()}`,\n );\n }\n}\n\n/**\n * Validate envelope and extract finalize data (for parallel fetch).\n *\n * Port of `validate_and_extract_finalize_response()` from finalize.rs lines 407-466.\n */\nfunction validateAndExtractFinalizeResponse(\n envelope: Envelope,\n coordinatorKeys: PrivateKeys,\n expectedGroupId: ARID,\n expectedParticipant: XID,\n): FinalizeResponseData | { rejected: string } {\n const now = new Date();\n\n let sealed: SealedResponse;\n try {\n sealed = SealedResponse.tryFromEncryptedEnvelope(envelope, undefined, now, coordinatorKeys);\n } catch (err) {\n return {\n rejected: `Failed to decrypt/parse response: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Check for error response\n if (!sealed.isOk()) {\n try {\n const error = sealed.error();\n const reasonEnv = error.optionalObjectForPredicate(\"reason\");\n const reason = reasonEnv?.extractString() ?? \"unknown reason\";\n return { rejected: `Participant reported error: ${reason}` };\n } catch {\n return { rejected: \"Participant reported error: unknown reason\" };\n }\n }\n\n // Get and validate result\n let result: Envelope;\n try {\n result = sealed.result();\n } catch {\n return { rejected: \"Finalize response has no result\" };\n }\n\n // Validate response type\n try {\n result.checkSubjectUnit();\n result.checkType(\"dkgFinalizeResponse\");\n } catch (err) {\n return {\n rejected: `Invalid response type: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Validate group ID\n try {\n const groupEnv = result.objectForPredicate(\"group\");\n const groupIdStr = groupEnv.extractString();\n const groupId = parseAridUr(groupIdStr);\n if (groupId.urString() !== expectedGroupId.urString()) {\n return {\n rejected: `Group ${groupId.urString()} does not match expected ${expectedGroupId.urString()}`,\n };\n }\n } catch (err) {\n return {\n rejected: `Failed to extract group: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Validate participant\n try {\n const participantEnv = result.objectForPredicate(\"participant\");\n const participantStr = participantEnv.extractString();\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef\n const { XID: XIDClass } = require(\"@bcts/components\");\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n const participantXid = XIDClass.fromURString(participantStr) as XID;\n if (participantXid.urString() !== expectedParticipant.urString()) {\n return {\n rejected: `Participant ${participantXid.urString()} does not match expected ${expectedParticipant.urString()}`,\n };\n }\n } catch (err) {\n return {\n rejected: `Failed to extract participant: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Extract key packages\n let keyPackage: unknown;\n let publicKeyPackage: unknown;\n\n try {\n const keyJsonEnv = result.objectForPredicate(\"key_package\");\n const keyJsonStr = keyJsonEnv.extractString();\n keyPackage = JSON.parse(keyJsonStr);\n } catch (err) {\n return {\n rejected: `Failed to parse key_package: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n try {\n const pubJsonEnv = result.objectForPredicate(\"public_key_package\");\n const pubJsonStr = pubJsonEnv.extractString();\n publicKeyPackage = JSON.parse(pubJsonStr);\n } catch (err) {\n return {\n rejected: `Failed to parse public_key_package: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n return { keyPackage, publicKeyPackage };\n}\n\n/**\n * Fetch a finalize response sequentially.\n *\n * Port of `fetch_finalize_response()` from finalize.rs lines 282-358.\n */\nasync function fetchFinalizeResponse(\n client: StorageClient,\n responseArid: ARID,\n timeout: number | undefined,\n coordinatorKeys: PrivateKeys,\n expectedGroup: ARID,\n expectedParticipant: XID,\n participantName: string,\n): Promise<FinalizeEntry> {\n const envelope = await getWithIndicator(\n client,\n responseArid,\n participantName,\n timeout,\n isVerbose(),\n );\n\n if (envelope === null || envelope === undefined) {\n throw new Error(\"Finalize response not found in Hubert storage\");\n }\n\n const result = validateAndExtractFinalizeResponse(\n envelope,\n coordinatorKeys,\n expectedGroup,\n expectedParticipant,\n );\n\n if (\"rejected\" in result) {\n throw new Error(result.rejected);\n }\n\n return {\n participant: expectedParticipant,\n keyPackage: result.keyPackage,\n publicKeyPackage: result.publicKeyPackage,\n };\n}\n\n/**\n * Collect finalize responses in parallel with progress display.\n *\n * Port of `collect_finalize_parallel()` from finalize.rs lines 371-404.\n */\nasync function collectFinalizeParallel(\n client: StorageClient,\n registry: Registry,\n pendingRequests: PendingRequests,\n coordinatorKeys: PrivateKeys,\n expectedGroupId: ARID,\n timeout: number | undefined,\n): Promise<CollectionResult<FinalizeResponseData>> {\n const requests: [XID, ARID, string][] = [];\n\n for (const [xid, arid] of pendingRequests.iterCollect()) {\n const record = registry.participant(xid);\n const name = record?.petName() ?? xid.urString();\n requests.push([xid, arid, name]);\n }\n\n const config: ParallelFetchConfig = parallelFetchConfigWithTimeout(timeout);\n\n return parallelFetch(\n client,\n requests,\n (envelope: Envelope, xid: XID) =>\n validateAndExtractFinalizeResponse(envelope, coordinatorKeys, expectedGroupId, xid),\n config,\n );\n}\n\n/**\n * Finalize collection results: persist, update registry, print summary.\n *\n * Port of `finalize_collection_results()` from finalize.rs lines 469-590.\n */\nfunction finalizeFinalizeCollectionResults(\n collection: CollectionResult<FinalizeResponseData>,\n registryPath: string,\n registry: Registry,\n groupId: ARID,\n): SigningPublicKey | undefined {\n // Report any failures\n if (collection.rejections.length > 0) {\n console.error();\n console.error(\"Rejections:\");\n for (const [xid, reason] of collection.rejections) {\n console.error(` ${xid.urString()}: ${reason}`);\n }\n }\n if (collection.errors.length > 0) {\n console.error();\n console.error(\"Errors:\");\n for (const [xid, error] of collection.errors) {\n console.error(` ${xid.urString()}: ${error}`);\n }\n }\n if (collection.timeouts.length > 0) {\n console.error();\n console.error(\"Timeouts:\");\n for (const xid of collection.timeouts) {\n console.error(` ${xid.urString()}`);\n }\n }\n\n if (!collection.allSucceeded()) {\n throw new Error(\n `Finalize collection incomplete: ${collection.successes.length} succeeded, ` +\n `${collection.rejections.length} rejected, ${collection.errors.length} errors, ` +\n `${collection.timeouts.length} timeouts`,\n );\n }\n\n // Validate group verifying key consistency\n let groupVerifyingKey: SigningPublicKey | undefined;\n\n for (const [xid, data] of collection.successes) {\n // Extract verifying_key from public_key_package\n const pubKeyPkg = data.publicKeyPackage as { verifying_key?: string };\n if (!pubKeyPkg.verifying_key) {\n throw new Error(\n `Failed to extract verifying key for ${xid.urString()}: missing verifying_key field`,\n );\n }\n\n // The verifying key is typically hex-encoded\n let signingKey: SigningPublicKey;\n try {\n const verifyingKeyBytes = hexToBytes(pubKeyPkg.verifying_key);\n signingKey = signingKeyFromVerifying(verifyingKeyBytes) as SigningPublicKey;\n } catch (err) {\n throw new Error(\n `Failed to extract verifying key for ${xid.urString()}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n if (groupVerifyingKey !== undefined) {\n if (groupVerifyingKey.urString() !== signingKey.urString()) {\n throw new Error(`Group verifying key mismatch for participant ${xid.urString()}`);\n }\n } else {\n groupVerifyingKey = signingKey;\n }\n }\n\n // Persist collected finalize data\n const stateDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const collectedPath = path.join(stateDir, \"collected_finalize.json\");\n const root: Record<string, { key_package: unknown; public_key_package: unknown }> = {};\n\n for (const [xid, data] of collection.successes) {\n root[xid.urString()] = {\n key_package: data.keyPackage,\n public_key_package: data.publicKeyPackage,\n };\n }\n\n fs.writeFileSync(collectedPath, JSON.stringify(root, null, 2));\n\n // Update registry\n const groupRecord = registry.group(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n if (groupVerifyingKey !== undefined) {\n groupRecord.setVerifyingKey(groupVerifyingKey);\n }\n groupRecord.clearPendingRequests();\n registry.save(registryPath);\n\n if (isVerbose()) {\n console.error();\n console.error(\n `Collected ${collection.successes.length} finalize responses. Saved to ${collectedPath}`,\n );\n if (groupVerifyingKey !== undefined) {\n console.error(groupVerifyingKey.urString());\n }\n } else if (groupVerifyingKey !== undefined) {\n console.log(groupVerifyingKey.urString());\n }\n\n return groupVerifyingKey;\n}\n\n/**\n * Helper to convert hex string to bytes.\n */\nfunction hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n}\n\n/**\n * Execute the DKG coordinator finalize command.\n *\n * Collects finalize responses (key/public key packages) from all participants.\n *\n * Port of `finalize()` from cmd/dkg/coordinator/finalize.rs.\n */\nexport async function finalize(\n client: StorageClient,\n options: DkgFinalizeOptions,\n cwd: string,\n): Promise<DkgFinalizeResult> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(`Group ${options.groupId} not found in registry`);\n }\n\n // Validate that owner is the coordinator\n validateCoordinator(groupRecord, owner.xid());\n\n const pendingRequests = groupRecord.pendingRequests();\n if (pendingRequests.isEmpty()) {\n throw new Error(\n \"No pending requests for this group. Did you run 'frost dkg coordinator finalize send'?\",\n );\n }\n\n const coordinatorKeys = owner.xidDocument().inceptionPrivateKeys();\n if (coordinatorKeys === undefined) {\n throw new Error(\"Coordinator XID document has no private keys\");\n }\n\n let verifyingKey: SigningPublicKey | undefined;\n let collected = 0;\n let rejected = 0;\n let errors = 0;\n let timeouts = 0;\n\n if (options.parallel === true) {\n // Parallel path with progress display\n const collection = await collectFinalizeParallel(\n client,\n registry,\n pendingRequests,\n coordinatorKeys,\n groupId,\n options.timeoutSeconds,\n );\n\n verifyingKey = finalizeFinalizeCollectionResults(collection, registryPath, registry, groupId);\n\n collected = collection.successes.length;\n rejected = collection.rejections.length;\n errors = collection.errors.length;\n timeouts = collection.timeouts.length;\n } else {\n // Sequential path (original behavior)\n const collectedEntries: FinalizeEntry[] = [];\n const errorEntries: [XID, string][] = [];\n let groupVerifyingKey: SigningPublicKey | undefined;\n\n if (isVerbose()) {\n console.error(`Collecting finalize responses from ${pendingRequests.len()} participants...`);\n }\n\n for (const [participantXid, collectFromArid] of pendingRequests.iterCollect()) {\n const record = registry.participant(participantXid);\n const name = record?.petName() ?? participantXid.urString();\n\n try {\n const entry = await fetchFinalizeResponse(\n client,\n collectFromArid,\n options.timeoutSeconds,\n coordinatorKeys,\n groupId,\n participantXid,\n name,\n );\n\n // Extract verifying key from public_key_package\n const pubKeyPkg = entry.publicKeyPackage as { verifying_key?: string };\n if (!pubKeyPkg.verifying_key) {\n throw new Error(\"missing verifying_key field\");\n }\n\n const verifyingKeyBytes = hexToBytes(pubKeyPkg.verifying_key);\n const signingKey = signingKeyFromVerifying(verifyingKeyBytes) as SigningPublicKey;\n\n if (groupVerifyingKey !== undefined) {\n if (groupVerifyingKey.urString() !== signingKey.urString()) {\n if (isVerbose()) {\n console.error(\"error: group verifying key mismatch\");\n }\n errorEntries.push([participantXid, \"Group verifying key mismatch across responses\"]);\n continue;\n }\n } else {\n groupVerifyingKey = signingKey;\n }\n\n collectedEntries.push(entry);\n } catch (err) {\n if (isVerbose()) {\n console.error(`error: ${err instanceof Error ? err.message : String(err)}`);\n }\n errorEntries.push([participantXid, err instanceof Error ? err.message : String(err)]);\n }\n }\n\n if (errorEntries.length > 0) {\n if (isVerbose()) {\n console.error();\n console.error(`Failed to collect from ${errorEntries.length} participants:`);\n for (const [xid, error] of errorEntries) {\n console.error(` ${xid.urString()}: ${error}`);\n }\n }\n throw new Error(\n `Finalize collection incomplete: ${errorEntries.length} of ${pendingRequests.len()} responses failed`,\n );\n }\n\n // Persist collected finalize data\n const stateDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const collectedPath = path.join(stateDir, \"collected_finalize.json\");\n const root: Record<string, { key_package: unknown; public_key_package: unknown }> = {};\n\n for (const entry of collectedEntries) {\n root[entry.participant.urString()] = {\n key_package: entry.keyPackage,\n public_key_package: entry.publicKeyPackage,\n };\n }\n\n fs.writeFileSync(collectedPath, JSON.stringify(root, null, 2));\n\n // Update registry pending requests cleared\n const groupRecordMut = registry.group(groupId);\n if (groupRecordMut === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n if (groupVerifyingKey !== undefined) {\n groupRecordMut.setVerifyingKey(groupVerifyingKey);\n }\n groupRecordMut.clearPendingRequests();\n registry.save(registryPath);\n\n if (isVerbose()) {\n console.error();\n console.error(\n `Collected ${collectedEntries.length} finalize responses. Saved to ${collectedPath}`,\n );\n if (groupVerifyingKey !== undefined) {\n console.error(groupVerifyingKey.urString());\n }\n } else if (groupVerifyingKey !== undefined) {\n console.log(groupVerifyingKey.urString());\n }\n\n verifyingKey = groupVerifyingKey;\n collected = collectedEntries.length;\n errors = errorEntries.length;\n }\n\n return {\n verifyingKey: verifyingKey?.urString() ?? \"\",\n collected,\n rejected,\n errors,\n timeouts,\n };\n}\n","/**\n * DKG coordinator commands.\n *\n * Port of cmd/dkg/coordinator/mod.rs from frost-hubert-rust.\n *\n * @module\n */\n\nexport * from \"./invite.js\";\nexport * from \"./round1.js\";\nexport * from \"./round2.js\";\nexport * from \"./finalize.js\";\n","/**\n * DKG participant receive command.\n *\n * Port of cmd/dkg/participant/receive.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, XID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { type Envelope, Function as EnvelopeFunction } from \"@bcts/envelope\";\nimport { SealedRequest } from \"@bcts/gstp\";\nimport { XIDDocument, XIDVerifySignature } from \"@bcts/xid\";\n\nimport { DkgInvitation } from \"../../../dkg/index.js\";\nimport { Registry, resolveRegistryPath } from \"../../../registry/index.js\";\nimport { getWithIndicator } from \"../../busy.js\";\nimport { createStorageClient, type StorageClient, type StorageSelection } from \"../../storage.js\";\nimport {\n dkgStateDir,\n parseAridUr,\n parseEnvelopeUr,\n participantNamesFromRegistry,\n resolveSenderName,\n} from \"../common.js\";\n\n/**\n * Options for the DKG receive command.\n */\nexport interface DkgReceiveOptions {\n registryPath?: string;\n timeoutSeconds?: number;\n noEnvelope?: boolean;\n info?: boolean;\n sender?: string;\n invite: string;\n storageSelection?: StorageSelection;\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG receive command.\n */\nexport interface DkgReceiveResult {\n groupId: string;\n requestId: string;\n minSigners: number;\n charter: string;\n validUntil: string;\n responseArid: string;\n envelopeUr?: string | undefined;\n coordinatorName?: string | undefined;\n participantNames?: string[] | undefined;\n}\n\n/**\n * Details extracted from a DKG invite.\n *\n * Port of `struct InviteDetails` from cmd/dkg/participant/receive.rs lines 117-120.\n */\nexport interface InviteDetails {\n invitation: DkgInvitation;\n participants: XIDDocument[];\n}\n\n/**\n * Resolve an invite envelope from either storage (ARID) or direct UR.\n *\n * Port of `resolve_invite_envelope()` from cmd/dkg/participant/receive.rs lines 122-152.\n */\nexport async function resolveInviteEnvelope(\n selection: StorageSelection | undefined,\n invite: string,\n timeout?: number,\n): Promise<Envelope> {\n if (selection !== undefined) {\n // Try to parse as ARID\n try {\n const arid = parseAridUr(invite);\n const client = await createStorageClient(selection);\n const envelope = await getWithIndicator(client, arid, \"Invite\", timeout, false);\n if (envelope === null || envelope === undefined) {\n throw new Error(\"Invite not found in Hubert storage\");\n }\n return envelope;\n } catch (e) {\n // Not an ARID, fall through to envelope parsing\n if (e instanceof Error && e.message.includes(\"Invite not found in Hubert storage\")) {\n throw e;\n }\n }\n\n if (timeout !== undefined) {\n throw new Error(\"--timeout is only valid when retrieving invites from Hubert\");\n }\n\n return parseEnvelopeUr(invite);\n }\n\n // No storage selection\n try {\n parseAridUr(invite);\n throw new Error(\"Hubert storage parameters are required to retrieve invites by ARID\");\n } catch (e) {\n // Not an ARID, parse as envelope\n if (e instanceof Error && e.message.includes(\"Hubert storage parameters are required\")) {\n throw e;\n }\n }\n\n return parseEnvelopeUr(invite);\n}\n\n/**\n * Decode and validate invite details from an envelope.\n *\n * Port of `decode_invite_details()` from cmd/dkg/participant/receive.rs lines 154-256.\n */\nexport function decodeInviteDetails(\n invite: Envelope,\n now: Date,\n registry: Registry,\n recipient: XIDDocument,\n expectedSender?: XIDDocument,\n): InviteDetails {\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(invite, undefined, now, recipientPrivateKeys);\n\n const senderDocument = sealedRequest.sender();\n if (expectedSender !== undefined) {\n if (senderDocument.xid().urString() !== expectedSender.xid().urString()) {\n throw new Error(\"Invite sender does not match expected sender\");\n }\n } else {\n const senderXid = senderDocument.xid();\n const owner = registry.owner();\n const knownOwner = owner?.xidDocument().xid().urString() === senderXid.urString();\n const knownParticipant = registry.participant(senderXid) !== undefined;\n\n if (!knownOwner && !knownParticipant) {\n throw new Error(`Invite sender not found in registry: ${senderXid.urString()}`);\n }\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 if (validUntil <= now) {\n throw new Error(\"Invitation expired\");\n }\n\n const minSigners = sealedRequest.extractObjectForParameter<number>(\"minSigners\");\n sealedRequest.extractObjectForParameter<string>(\"charter\");\n 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 const participantDocs: XIDDocument[] = [];\n let responseArid: ARID | undefined;\n const recipientXid = recipient.xid();\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().urString() === recipientXid.urString()) {\n const encryptedResponseArid = participant.objectForPredicate(\"response_arid\");\n const responseAridEnvelope = encryptedResponseArid.decryptToRecipient(recipientPrivateKeys);\n responseArid = responseAridEnvelope.extractSubject((cbor) => ARID.fromTaggedCbor(cbor));\n }\n\n participantDocs.push(xidDocument);\n }\n\n const invitation = DkgInvitation.fromInvite(invite, now, expectedSender, recipient);\n\n if (responseArid === undefined) {\n throw new Error(\"Invite does not include a response ARID for this recipient\");\n }\n\n return { invitation, participants: participantDocs };\n}\n\n/**\n * Resolve a sender XID document from the registry by UR or pet name.\n *\n * Port of `resolve_sender()` usage in receive.rs for expected sender.\n */\nfunction resolveSenderXidDocument(registry: Registry, raw: string): XIDDocument {\n // Try parsing as XID UR first\n try {\n const xid = XID.fromURString(raw.trim());\n const record = registry.participant(xid);\n if (record) {\n return record.xidDocument();\n }\n const owner = registry.owner();\n if (owner?.xid().urString() === xid.urString()) {\n return owner.xidDocument();\n }\n throw new Error(`Sender with XID ${xid.urString()} not found in registry`);\n } catch {\n // Try looking up by pet name\n const result = registry.participantByPetName(raw.trim());\n if (result) {\n const [, record] = result;\n return record.xidDocument();\n }\n const owner = registry.owner();\n if (owner?.petName() === raw.trim()) {\n return owner.xidDocument();\n }\n throw new Error(`Sender '${raw}' not found in registry`);\n }\n}\n\n/**\n * Execute the DKG participant receive command.\n *\n * Fetches and validates a DKG invite from the coordinator.\n *\n * Port of `receive()` from cmd/dkg/participant/receive.rs.\n */\nexport async function receive(\n _client: StorageClient | undefined,\n options: DkgReceiveOptions,\n cwd: string,\n): Promise<DkgReceiveResult> {\n if (options.storageSelection === undefined && options.timeoutSeconds !== undefined) {\n throw new Error(\"--timeout requires Hubert storage parameters\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (!owner) {\n throw new Error(\"Registry owner with private keys is required\");\n }\n\n const expectedSender = options.sender\n ? resolveSenderXidDocument(registry, options.sender)\n : undefined;\n\n const inviteEnvelope = await resolveInviteEnvelope(\n options.storageSelection,\n options.invite,\n options.timeoutSeconds,\n );\n\n const now = CborDate.now().datetime();\n const details = decodeInviteDetails(\n inviteEnvelope,\n now,\n registry,\n owner.xidDocument(),\n expectedSender,\n );\n\n const participantNames = participantNamesFromRegistry(\n registry,\n details.participants,\n owner.xid(),\n owner.petName(),\n );\n\n const coordinatorName = resolveSenderName(registry, details.invitation.sender());\n\n // Save receive state\n const stateDir = dkgStateDir(registryPath, details.invitation.groupId().hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const validUntilStr: string = (\n details.invitation.validUntil() as { toString(): string }\n ).toString();\n const receiveState = {\n group: details.invitation.groupId().urString(),\n request_id: details.invitation.requestId().urString(),\n response_arid: details.invitation.responseArid().urString(),\n valid_until: validUntilStr,\n min_signers: details.invitation.minSigners(),\n charter: details.invitation.charter(),\n sender: details.invitation.sender().xid().urString(),\n };\n\n fs.writeFileSync(path.join(stateDir, \"receive.json\"), JSON.stringify(receiveState, null, 2));\n\n // Output based on options\n let envelopeUr: string | undefined;\n if (options.noEnvelope !== true) {\n envelopeUr = inviteEnvelope.urString();\n console.log(envelopeUr);\n }\n\n if (options.info === true) {\n console.error(`Charter: ${details.invitation.charter()}`);\n console.error(`Min signers: ${details.invitation.minSigners()}`);\n if (coordinatorName !== undefined) {\n console.error(`Coordinator: ${coordinatorName}`);\n }\n console.error(`Participants: ${participantNames.join(\", \")}`);\n }\n\n if (options.verbose === true) {\n console.log(`Group ID: ${details.invitation.groupId().urString()}`);\n console.log(`Min signers: ${details.invitation.minSigners()}`);\n console.log(`Charter: ${details.invitation.charter()}`);\n console.log(`Valid until: ${String(details.invitation.validUntil())}`);\n console.log(`Response ARID: ${details.invitation.responseArid().urString()}`);\n }\n\n const resultValidUntilStr: string = (\n details.invitation.validUntil() as { toString(): string }\n ).toString();\n\n return {\n groupId: details.invitation.groupId().urString(),\n requestId: details.invitation.requestId().urString(),\n minSigners: details.invitation.minSigners(),\n charter: details.invitation.charter(),\n validUntil: resultValidUntilStr,\n responseArid: details.invitation.responseArid().urString(),\n envelopeUr,\n coordinatorName,\n participantNames,\n };\n}\n","/**\n * DKG participant round 1 command.\n *\n * Port of cmd/dkg/participant/round1.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, JSON as JSONWrapper, XID } from \"@bcts/components\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { SealedResponse } from \"@bcts/gstp\";\nimport type { XIDDocument } from \"@bcts/xid\";\n\nimport {\n ContributionPaths,\n GroupRecord,\n Registry,\n resolveRegistryPath,\n} from \"../../../registry/index.js\";\nimport { getWithIndicator, putWithIndicator } from \"../../busy.js\";\nimport { createStorageClient, type StorageClient, type StorageSelection } from \"../../storage.js\";\nimport { groupStateDir } from \"../../common.js\";\nimport {\n buildGroupParticipants,\n groupParticipantFromRegistry,\n parseAridUr,\n parseEnvelopeUr,\n} from \"../common.js\";\nimport {\n dkgPart1,\n identifierFromU16,\n createRng,\n bytesToHex,\n type DkgRound1Package,\n type DkgRound1SecretPackage,\n} from \"../../../frost/index.js\";\nimport { Ed25519Sha512, serde } from \"@frosts/ed25519\";\nimport { decodeInviteDetails } from \"./receive.js\";\nimport { CborDate } from \"@bcts/dcbor\";\n\n/**\n * Options for the DKG round1 command.\n */\nexport interface DkgRound1Options {\n registryPath?: string;\n timeoutSeconds?: number;\n responseArid?: string;\n preview?: boolean;\n rejectReason?: string;\n sender?: string;\n invite: string;\n storageSelection?: StorageSelection;\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG round1 command.\n */\nexport interface DkgRound1Result {\n accepted: boolean;\n listeningArid?: string;\n envelopeUr?: string;\n}\n\n/**\n * Resolve an invite envelope from either storage (ARID) or direct UR.\n *\n * Port of `resolve_invite_envelope()` from cmd/dkg/participant/round1.rs lines 256-288.\n */\nasync function resolveInviteEnvelope(\n selection: StorageSelection | undefined,\n invite: string,\n timeout?: number,\n): Promise<Envelope> {\n if (selection !== undefined) {\n // Try to parse as ARID\n try {\n const arid = parseAridUr(invite);\n const client = await createStorageClient(selection);\n const envelope = await getWithIndicator(client, arid, \"Invite\", timeout, false);\n if (envelope === null || envelope === undefined) {\n throw new Error(\"Invite not found in Hubert storage\");\n }\n return envelope;\n } catch (e) {\n // Not an ARID, fall through to envelope parsing\n if (e instanceof Error && e.message.includes(\"Invite not found in Hubert storage\")) {\n throw e;\n }\n }\n\n if (timeout !== undefined) {\n throw new Error(\"--timeout is only valid when retrieving invites from Hubert\");\n }\n\n return parseEnvelopeUr(invite);\n }\n\n // No storage selection\n try {\n parseAridUr(invite);\n throw new Error(\"Hubert storage parameters are required to retrieve invites by ARID\");\n } catch (e) {\n // Not an ARID, parse as envelope\n if (e instanceof Error && e.message.includes(\"Hubert storage parameters are required\")) {\n throw e;\n }\n }\n\n return parseEnvelopeUr(invite);\n}\n\n/**\n * Build the response body envelope.\n *\n * Port of `build_response_body()` from cmd/dkg/participant/round1.rs lines 290-308.\n */\nfunction buildResponseBody(\n groupId: ARID,\n participant: XID,\n responseArid: ARID,\n round1Package: DkgRound1Package | undefined,\n): Envelope {\n let envelope = Envelope.unit()\n .addType(\"dkgRound1Response\")\n .addAssertion(\"group\", groupId)\n .addAssertion(\"participant\", participant)\n .addAssertion(\"response_arid\", responseArid);\n\n if (round1Package !== undefined) {\n // Serialize the package to JSON and wrap as CBOR JSON\n const packageJson = serde.round1PackageToJson(round1Package);\n const jsonStr = globalThis.JSON.stringify(packageJson);\n const jsonBytes = new TextEncoder().encode(jsonStr);\n const jsonWrapper = JSONWrapper.fromData(jsonBytes);\n // Pass the JSONWrapper directly - it implements CborTaggedEncodable\n envelope = envelope.addAssertion(\"round1_package\", jsonWrapper);\n }\n\n return envelope;\n}\n\n/**\n * Serialize round 1 secret package to JSON-compatible format.\n *\n * The @frosts/ed25519 serde module doesn't provide a serializer for SecretPackage,\n * so we manually serialize it here.\n */\nfunction serializeRound1SecretPackage(secret: DkgRound1SecretPackage): Record<string, unknown> {\n // Access the coefficients and serialize them\n const coefficients = secret.coefficients();\n const serializedCoefficients = coefficients.map((c: unknown) =>\n bytesToHex(\n Ed25519Sha512.serializeScalar(c as Parameters<typeof Ed25519Sha512.serializeScalar>[0]),\n ),\n );\n\n // Get the commitment coefficients\n const commitment = secret.commitment;\n const commitmentCoefficients = commitment.serialize().map((c: Uint8Array) => bytesToHex(c));\n\n return {\n header: serde.DEFAULT_HEADER,\n identifier: bytesToHex(secret.identifier.serialize()),\n coefficients: serializedCoefficients,\n commitment: commitmentCoefficients,\n min_signers: secret.minSigners,\n max_signers: secret.maxSigners,\n };\n}\n\n/**\n * Persist round 1 state to disk.\n *\n * Port of `persist_round1_state()` from cmd/dkg/participant/round1.rs lines 310-337.\n */\nfunction persistRound1State(\n registryPath: string,\n groupId: ARID,\n round1Secret: DkgRound1SecretPackage,\n round1Package: DkgRound1Package,\n): ContributionPaths {\n const dir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(dir, { recursive: true });\n\n const secretPath = path.join(dir, \"round1_secret.json\");\n const packagePath = path.join(dir, \"round1_package.json\");\n\n // Serialize the secret package manually since serde doesn't provide it\n const secretJson = serializeRound1SecretPackage(round1Secret);\n // Serialize the public package using the standard serde function\n const packageJson = serde.round1PackageToJson(round1Package);\n\n fs.writeFileSync(secretPath, globalThis.JSON.stringify(secretJson, null, 2));\n fs.writeFileSync(packagePath, globalThis.JSON.stringify(packageJson, null, 2));\n\n return new ContributionPaths({\n round1Secret: secretPath,\n round1Package: packagePath,\n round2Secret: undefined,\n keyPackage: undefined,\n });\n}\n\n/**\n * Execute the DKG participant round 1 command.\n *\n * Responds to the DKG invite with commitment packages.\n *\n * Port of `CommandArgs::exec()` from cmd/dkg/participant/round1.rs lines 66-254.\n */\nexport async function round1(\n _client: StorageClient | undefined,\n options: DkgRound1Options,\n cwd: string,\n): Promise<DkgRound1Result> {\n // Validate options\n if (options.storageSelection === undefined && options.timeoutSeconds !== undefined) {\n throw new Error(\"--timeout requires Hubert storage parameters\");\n }\n if (options.storageSelection !== undefined && options.preview === true) {\n throw new Error(\"--preview cannot be used with Hubert storage options\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (!owner) {\n throw new Error(\"Registry owner with private keys is required\");\n }\n\n // Resolve expected sender if provided\n let expectedSender: XIDDocument | undefined;\n if (options.sender !== undefined) {\n expectedSender = resolveSenderXidDocument(registry, options.sender);\n }\n\n const nextResponseArid =\n options.responseArid !== undefined ? parseAridUr(options.responseArid) : ARID.new();\n\n // Resolve the invite envelope\n const inviteEnvelope = await resolveInviteEnvelope(\n options.storageSelection,\n options.invite,\n options.timeoutSeconds,\n );\n\n // Decode the invite details\n const now = CborDate.now().datetime();\n const details = decodeInviteDetails(\n inviteEnvelope,\n now,\n registry,\n owner.xidDocument(),\n expectedSender,\n );\n\n // Sort participants by XID and find our position\n const sortedParticipants = [...details.participants].sort((a, b) =>\n a.xid().urString().localeCompare(b.xid().urString()),\n );\n\n const ownerIndex = sortedParticipants.findIndex(\n (doc) => doc.xid().urString() === owner.xid().urString(),\n );\n if (ownerIndex === -1) {\n throw new Error(\"Invite does not include the registry owner\");\n }\n\n const identifierIndex = ownerIndex + 1; // FROST uses 1-indexed identifiers\n if (identifierIndex > 65535) {\n throw new Error(\"Too many participants for identifiers\");\n }\n const identifier = identifierFromU16(identifierIndex);\n\n const total = sortedParticipants.length;\n if (total > 65535) {\n throw new Error(\"Too many participants for FROST identifiers\");\n }\n\n const minSigners = details.invitation.minSigners();\n if (minSigners > 65535) {\n throw new Error(\"min_signers does not fit into identifier space\");\n }\n\n // Build group participants for the registry\n const groupParticipants = buildGroupParticipants(registry, owner, sortedParticipants);\n const coordinator = groupParticipantFromRegistry(registry, owner, details.invitation.sender());\n\n // Check if we're posting to storage\n const isPosting = options.storageSelection !== undefined;\n\n // Build the response body\n let responseBody: Envelope;\n let contributions: ContributionPaths | undefined;\n\n if (options.rejectReason === undefined && isPosting) {\n // Actually posting - generate and persist round1 state\n const [round1Secret, round1Package] = dkgPart1(identifier, total, minSigners, createRng());\n\n contributions = persistRound1State(\n registryPath,\n details.invitation.groupId(),\n round1Secret,\n round1Package,\n );\n\n responseBody = buildResponseBody(\n details.invitation.groupId(),\n owner.xid(),\n nextResponseArid,\n round1Package,\n );\n\n // Create and save group record\n const groupRecord = new GroupRecord(\n details.invitation.charter(),\n details.invitation.minSigners(),\n coordinator,\n groupParticipants,\n );\n groupRecord.setContributions(contributions);\n groupRecord.setListeningAtArid(nextResponseArid);\n\n registry.recordGroup(details.invitation.groupId(), groupRecord);\n registry.save(registryPath);\n } else if (options.rejectReason === undefined) {\n // Preview mode - generate dummy round1 for envelope structure only\n const [, round1Package] = dkgPart1(identifier, total, minSigners, createRng());\n\n responseBody = buildResponseBody(\n details.invitation.groupId(),\n owner.xid(),\n nextResponseArid,\n round1Package,\n );\n } else {\n // Rejecting - no round1 needed\n responseBody = buildResponseBody(\n details.invitation.groupId(),\n owner.xid(),\n nextResponseArid,\n undefined,\n );\n }\n\n // Build the sealed response\n const signerPrivateKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Owner XID document has no signing keys\");\n }\n\n let sealed: SealedResponse;\n if (options.rejectReason !== undefined) {\n // Build rejection error body\n const errorBody = Envelope.new(\"dkgInviteReject\")\n .addAssertion(\"group\", details.invitation.groupId())\n .addAssertion(\"response_arid\", nextResponseArid)\n .addAssertion(\"reason\", options.rejectReason);\n\n sealed = SealedResponse.newFailure(details.invitation.requestId(), owner.xidDocument())\n .withError(errorBody)\n .withState(nextResponseArid);\n } else {\n sealed = SealedResponse.newSuccess(details.invitation.requestId(), owner.xidDocument())\n .withResult(responseBody)\n .withState(nextResponseArid);\n }\n\n // Add peer continuation if present\n const peerContinuation = details.invitation.peerContinuation();\n if (peerContinuation !== undefined) {\n sealed = sealed.withPeerContinuation(peerContinuation);\n }\n\n // Handle output based on storage selection\n if (options.storageSelection !== undefined) {\n const responseEnvelope = sealed.toEnvelope(\n details.invitation.validUntil(),\n signerPrivateKeys,\n details.invitation.sender(),\n );\n\n const responseTarget = details.invitation.responseArid();\n const client = await createStorageClient(options.storageSelection);\n\n await putWithIndicator(\n client,\n responseTarget,\n responseEnvelope,\n \"Round 1 Response\",\n options.verbose ?? false,\n );\n\n if (options.verbose === true) {\n console.log(`Sent round 1 response`);\n console.log(`Listening at: ${nextResponseArid.urString()}`);\n }\n\n return {\n accepted: options.rejectReason === undefined,\n listeningArid: nextResponseArid.urString(),\n };\n } else if (options.preview === true) {\n // Show the GSTP response structure without encryption\n const unsealedEnvelope = sealed.toEnvelope(undefined, signerPrivateKeys, undefined);\n const envelopeUr = unsealedEnvelope.urString();\n console.log(envelopeUr);\n\n return {\n accepted: options.rejectReason === undefined,\n envelopeUr,\n };\n } else {\n // Print the sealed envelope\n const responseEnvelope = sealed.toEnvelope(\n details.invitation.validUntil(),\n signerPrivateKeys,\n details.invitation.sender(),\n );\n const envelopeUr = responseEnvelope.urString();\n console.log(envelopeUr);\n\n return {\n accepted: options.rejectReason === undefined,\n envelopeUr,\n };\n }\n}\n\n/**\n * Resolve a sender XID document from the registry by UR or pet name.\n */\nfunction resolveSenderXidDocument(registry: Registry, raw: string): XIDDocument {\n // Try parsing as XID UR first\n try {\n const xid = XID.fromURString(raw.trim());\n const record = registry.participant(xid);\n if (record) {\n return record.xidDocument();\n }\n const owner = registry.owner();\n if (owner?.xid().urString() === xid.urString()) {\n return owner.xidDocument();\n }\n throw new Error(`Sender with XID ${xid.urString()} not found in registry`);\n } catch {\n // Try looking up by pet name\n const result = registry.participantByPetName(raw.trim());\n if (result) {\n const [, record] = result;\n return record.xidDocument();\n }\n const owner = registry.owner();\n if (owner?.petName() === raw.trim()) {\n return owner.xidDocument();\n }\n throw new Error(`Sender '${raw}' not found in registry`);\n }\n}\n","/**\n * DKG participant round 2 command.\n *\n * Port of cmd/dkg/participant/round2.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, JSON as JSONWrapper, XID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope, Function as EnvelopeFunction } from \"@bcts/envelope\";\nimport { SealedRequest, SealedResponse } from \"@bcts/gstp\";\nimport type { XIDDocument } from \"@bcts/xid\";\n\nimport { type GroupRecord, Registry, resolveRegistryPath } from \"../../../registry/index.js\";\nimport { getWithIndicator, putWithIndicator } from \"../../busy.js\";\nimport { groupStateDir, isVerbose } from \"../../common.js\";\nimport { createStorageClient, type StorageClient, type StorageSelection } from \"../../storage.js\";\nimport { parseAridUr } from \"../common.js\";\nimport {\n dkgPart2,\n serializeDkgRound2Package,\n identifierFromU16,\n identifierToHex,\n hexToBytes,\n bytesToHex,\n type DkgRound1Package,\n type DkgRound1SecretPackage,\n type DkgRound2SecretPackage,\n type FrostIdentifier,\n} from \"../../../frost/index.js\";\nimport { Ed25519Sha512, serde } from \"@frosts/ed25519\";\nimport { round1, CoefficientCommitment, VerifiableSecretSharingCommitment } from \"@frosts/core\";\n\n/**\n * Options for the DKG round2 command.\n */\nexport interface DkgRound2Options {\n registryPath?: string;\n groupId: string;\n timeoutSeconds?: number;\n preview?: boolean;\n storageSelection?: StorageSelection;\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG round2 command.\n */\nexport interface DkgRound2Result {\n listeningArid: string;\n envelopeUr?: string;\n}\n\n/**\n * Persisted round 1 state loaded from disk.\n */\ninterface Round1State {\n secretPackage: DkgRound1SecretPackage;\n ourRound1Package: DkgRound1Package;\n}\n\n/**\n * Extracted round 1 packages from coordinator request.\n */\ntype Round1Packages = [Map<FrostIdentifier, DkgRound1Package>, [XID, DkgRound1Package][]];\n\n/**\n * Load persisted round 1 state from disk.\n *\n * Port of round1_secret loading from cmd/dkg/participant/round2.rs lines 86-97.\n */\nfunction loadRound1State(registryPath: string, groupId: ARID): Round1State {\n const packagesDir = groupStateDir(registryPath, groupId.hex());\n const round1SecretPath = path.join(packagesDir, \"round1_secret.json\");\n\n if (!fs.existsSync(round1SecretPath)) {\n throw new Error(\n `Round 1 secret not found at ${round1SecretPath}. Did you respond to the invite?`,\n );\n }\n\n const secretJson = JSON.parse(fs.readFileSync(round1SecretPath, \"utf-8\")) as {\n header: { version: number; ciphersuite: string };\n identifier: string;\n coefficients: string[];\n commitment: string[];\n min_signers: number;\n max_signers: number;\n };\n\n // Deserialize coefficients (scalars)\n const coefficients = secretJson.coefficients.map((hex) =>\n Ed25519Sha512.deserializeScalar(hexToBytes(hex)),\n );\n\n // Deserialize commitment (coefficient commitments)\n const coefficientCommitments = secretJson.commitment.map((hex) =>\n CoefficientCommitment.deserialize(Ed25519Sha512, hexToBytes(hex)),\n );\n\n const commitment = new VerifiableSecretSharingCommitment(Ed25519Sha512, coefficientCommitments);\n\n // Create the secret package\n // Need to find the actual identifier u16 value from the coefficients array length or saved state\n // The identifier is typically serialized as a scalar, but we need the u16 value\n // Parse it from the hex string - first 2 bytes as little-endian u16\n const idBytes = hexToBytes(secretJson.identifier);\n let identifierU16 = 1;\n if (idBytes.length >= 2) {\n identifierU16 = idBytes[0] | (idBytes[1] << 8);\n }\n if (identifierU16 === 0) {\n identifierU16 = 1; // Default to 1 if parsing failed\n }\n\n const parsedIdentifier = identifierFromU16(identifierU16);\n\n const secretPackage: DkgRound1SecretPackage = new round1.SecretPackage(\n Ed25519Sha512,\n parsedIdentifier,\n coefficients,\n commitment,\n secretJson.min_signers,\n secretJson.max_signers,\n );\n\n // Load the round 1 package as well\n const round1PackagePath = path.join(packagesDir, \"round1_package.json\");\n const packageJson = JSON.parse(fs.readFileSync(round1PackagePath, \"utf-8\")) as {\n header: { version: number; ciphersuite: string };\n commitment: string[];\n proof_of_knowledge: string;\n };\n\n const ourRound1Package = serde.round1PackageFromJson(packageJson);\n\n return { secretPackage, ourRound1Package };\n}\n\n/**\n * Validate the round 2 request from the coordinator.\n *\n * Port of request validation from cmd/dkg/participant/round2.rs lines 118-158.\n */\nfunction validateRound2Request(\n sealedRequest: SealedRequest,\n groupId: ARID,\n expectedCoordinator: XID,\n): ARID {\n // Validate the request function\n if (!sealedRequest.function().equals(EnvelopeFunction.fromString(\"dkgRound2\"))) {\n throw new Error(`Unexpected request function: ${sealedRequest.function().toString()}`);\n }\n\n // Validate the sender is the expected coordinator\n if (sealedRequest.sender().xid().urString() !== expectedCoordinator.urString()) {\n throw new Error(\n `Unexpected request sender: ${sealedRequest.sender().xid().urString()} ` +\n `(expected coordinator ${expectedCoordinator.urString()})`,\n );\n }\n\n // Validate the group ID matches\n const requestGroupIdEnvelope = sealedRequest.objectForParameter(\"group\");\n if (requestGroupIdEnvelope === undefined) {\n throw new Error(\"Request missing group parameter\");\n }\n const requestGroupId = requestGroupIdEnvelope.extractSubject((cbor) => ARID.fromTaggedCbor(cbor));\n if (requestGroupId.urString() !== groupId.urString()) {\n throw new Error(\n `Request group ID ${requestGroupId.urString()} does not match expected ${groupId.urString()}`,\n );\n }\n\n // Extract where we should post our response\n const responseAridEnvelope = sealedRequest.objectForParameter(\"responseArid\");\n if (responseAridEnvelope === undefined) {\n throw new Error(\"Request missing responseArid parameter\");\n }\n const responseArid = responseAridEnvelope.extractSubject((cbor) => ARID.fromTaggedCbor(cbor));\n\n return responseArid;\n}\n\n/**\n * Extract round 1 packages from the request and convert to Map<Identifier, Package>.\n *\n * Port of `extract_round1_packages()` from cmd/dkg/participant/round2.rs lines 291-366.\n */\nfunction extractRound1Packages(\n request: SealedRequest,\n groupRecord: GroupRecord,\n ownerXid: XID,\n): Round1Packages {\n // Build XID -> Identifier mapping based on sorted participant order\n const sortedXids: XID[] = groupRecord.participants().map((p) => p.xid());\n\n // Add owner if not already in list\n const ownerUrString = ownerXid.urString();\n if (!sortedXids.some((xid) => xid.urString() === ownerUrString)) {\n sortedXids.push(ownerXid);\n }\n\n // Sort by XID UR string\n sortedXids.sort((a, b) => a.urString().localeCompare(b.urString()));\n\n // Deduplicate\n const deduped: XID[] = [];\n for (const xid of sortedXids) {\n if (deduped.length === 0 || deduped[deduped.length - 1].urString() !== xid.urString()) {\n deduped.push(xid);\n }\n }\n\n // Build XID -> Identifier mapping (1-indexed)\n const xidToIdentifier = new Map<string, FrostIdentifier>();\n for (let i = 0; i < deduped.length; i++) {\n const identifier = identifierFromU16(i + 1);\n xidToIdentifier.set(deduped[i].urString(), identifier);\n }\n\n const myXidStr = ownerXid.urString();\n\n // Extract all round1Package parameters\n const packages = new Map<FrostIdentifier, DkgRound1Package>();\n const packagesByXid: [XID, DkgRound1Package][] = [];\n\n const packageEnvelopes = request.objectsForParameter(\"round1Package\");\n for (const packageEnvelope of packageEnvelopes) {\n // Extract participant XID from the envelope\n const participantEnvelope = packageEnvelope.objectForPredicate(\"participant\");\n if (participantEnvelope === undefined) {\n throw new Error(\"round1Package missing participant predicate\");\n }\n const participantXid = participantEnvelope.extractSubject((cbor) => XID.fromTaggedCbor(cbor));\n\n // Skip our own package\n if (participantXid.urString() === myXidStr) {\n continue;\n }\n\n // Extract the package bytes (stored as JSON tag)\n const packageJson = packageEnvelope.extractSubject((cbor) => JSONWrapper.fromTaggedCbor(cbor));\n const packageData = JSON.parse(new TextDecoder().decode(packageJson.toData())) as {\n header: { version: number; ciphersuite: string };\n commitment: string[];\n proof_of_knowledge: string;\n };\n\n const pkg = serde.round1PackageFromJson(packageData);\n\n // Get the identifier for this participant\n const identifier = xidToIdentifier.get(participantXid.urString());\n if (identifier === undefined) {\n throw new Error(`Unknown participant XID in round1Package: ${participantXid.urString()}`);\n }\n\n packages.set(identifier, pkg);\n packagesByXid.push([participantXid, pkg]);\n }\n\n // Validate we have the expected number of packages\n const expectedPackages = xidToIdentifier.size - 1; // Exclude ourselves\n if (packages.size !== expectedPackages) {\n throw new Error(`Expected ${expectedPackages} Round 1 packages, found ${packages.size}`);\n }\n\n return [packages, packagesByXid];\n}\n\n/**\n * Build the response body containing Round 2 packages.\n *\n * Port of `build_response_body()` from cmd/dkg/participant/round2.rs lines 373-425.\n */\nfunction buildResponseBody(\n groupId: ARID,\n participantXid: XID,\n responseArid: ARID,\n round2Packages: Map<FrostIdentifier, unknown>,\n groupRecord: GroupRecord,\n): Envelope {\n // Build Identifier -> XID mapping\n const sortedXids: XID[] = groupRecord.participants().map((p) => p.xid());\n\n // Add participant if not already in list\n const participantUrString = participantXid.urString();\n if (!sortedXids.some((xid) => xid.urString() === participantUrString)) {\n sortedXids.push(participantXid);\n }\n\n // Sort by XID UR string\n sortedXids.sort((a, b) => a.urString().localeCompare(b.urString()));\n\n // Deduplicate\n const deduped: XID[] = [];\n for (const xid of sortedXids) {\n if (deduped.length === 0 || deduped[deduped.length - 1].urString() !== xid.urString()) {\n deduped.push(xid);\n }\n }\n\n // Build Identifier -> XID mapping (1-indexed)\n const identifierToXid = new Map<string, XID>();\n for (let i = 0; i < deduped.length; i++) {\n const identifier = identifierFromU16(i + 1);\n identifierToXid.set(identifierToHex(identifier), deduped[i]);\n }\n\n let envelope = Envelope.unit()\n .addType(\"dkgRound2Response\")\n .addAssertion(\"group\", groupId)\n .addAssertion(\"participant\", participantXid)\n .addAssertion(\"response_arid\", responseArid);\n\n // Add each Round 2 package with the recipient's XID\n for (const [identifier, pkg] of round2Packages) {\n const idHex = identifierToHex(identifier);\n const recipientXid = identifierToXid.get(idHex);\n if (recipientXid === undefined) {\n throw new Error(\"Unknown identifier in round2_packages\");\n }\n\n // Serialize package to JSON and wrap in CBOR JSON tag\n const serialized = serializeDkgRound2Package(\n pkg as Parameters<typeof serializeDkgRound2Package>[0],\n );\n const jsonStr = JSON.stringify(serialized);\n const jsonBytes = new TextEncoder().encode(jsonStr);\n const jsonWrapper = JSONWrapper.fromData(jsonBytes);\n\n const packageEnvelope = Envelope.new(jsonWrapper).addAssertion(\"recipient\", recipientXid);\n\n envelope = envelope.addAssertion(\"round2Package\", packageEnvelope);\n }\n\n return envelope;\n}\n\n/**\n * Serialize round 2 secret package to JSON format for persistence.\n *\n * The format matches what finalize.ts expects to deserialize.\n */\nfunction serializeRound2SecretPackage(\n secret: DkgRound2SecretPackage,\n participantIndex: number,\n): Record<string, unknown> {\n // Get the commitment coefficients\n const commitment = secret.commitment;\n const commitmentCoefficients = commitment.serialize().map((c: Uint8Array) => bytesToHex(c));\n\n // Serialize the secret share\n const secretShare = bytesToHex(Ed25519Sha512.serializeScalar(secret.secretShare()));\n\n return {\n identifier: participantIndex,\n commitment: {\n coefficients: commitmentCoefficients,\n },\n secretShare,\n minSigners: secret.minSigners,\n maxSigners: secret.maxSigners,\n };\n}\n\n/**\n * Persist round 2 state to disk.\n *\n * Port of round 2 secret persistence from cmd/dkg/participant/round2.rs lines 229-251.\n */\nfunction persistRound2State(\n registryPath: string,\n groupId: ARID,\n round2Secret: DkgRound2SecretPackage,\n round1PackagesByXid: [XID, DkgRound1Package][],\n participantIndex: number,\n): string {\n const packagesDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(packagesDir, { recursive: true });\n\n // Persist Round 2 secret\n const round2SecretPath = path.join(packagesDir, \"round2_secret.json\");\n const round2SecretJson = serializeRound2SecretPackage(round2Secret, participantIndex);\n fs.writeFileSync(round2SecretPath, JSON.stringify(round2SecretJson, null, 2));\n\n // Persist received Round 1 packages for finalize phase\n const round1PackagesPath = path.join(packagesDir, \"collected_round1.json\");\n const round1Json: Record<string, unknown> = {};\n for (const [xid, pkg] of round1PackagesByXid) {\n const packageJson = serde.round1PackageToJson(pkg);\n round1Json[xid.urString()] = packageJson;\n }\n fs.writeFileSync(round1PackagesPath, JSON.stringify(round1Json, null, 2));\n\n return round2SecretPath;\n}\n\n/**\n * Execute the DKG participant round 2 command.\n *\n * Responds to the Round 2 request from the coordinator, runs FROST DKG part2\n * to generate Round 2 packages, and posts the response back.\n *\n * Port of `CommandArgs::exec()` from cmd/dkg/participant/round2.rs lines 55-288.\n */\nexport async function round2(\n _client: StorageClient | undefined,\n options: DkgRound2Options,\n cwd: string,\n): Promise<DkgRound2Result> {\n if (options.storageSelection === undefined) {\n throw new Error(\"Hubert storage is required for round2\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n // Get the ARID where we're listening for the Round 2 request\n const listeningAtArid = groupRecord.listeningAtArid();\n if (listeningAtArid === undefined) {\n throw new Error(\"No listening ARID for this group. Did you respond to the invite?\");\n }\n\n // Load our Round 1 secret\n const round1State = loadRound1State(registryPath, groupId);\n\n if (isVerbose() || options.verbose === true) {\n console.error(\"Fetching Round 2 request from Hubert...\");\n }\n\n const client = await createStorageClient(options.storageSelection);\n\n // Fetch the Round 2 request from where we're listening\n const requestEnvelope = await getWithIndicator(\n client,\n listeningAtArid,\n \"Round 2 request\",\n options.timeoutSeconds,\n options.verbose ?? false,\n );\n\n if (requestEnvelope === null || requestEnvelope === undefined) {\n throw new Error(\"Round 2 request not found in Hubert storage\");\n }\n\n // Decrypt and validate the request\n const ownerPrivateKeys = owner.xidDocument().inceptionPrivateKeys();\n if (ownerPrivateKeys === undefined) {\n throw new Error(\"Owner XID document has no private keys\");\n }\n\n const now = CborDate.now().datetime();\n const sealedRequest = SealedRequest.tryFromEnvelope(\n requestEnvelope,\n undefined,\n now,\n ownerPrivateKeys,\n );\n\n // Validate the request and extract response ARID\n const expectedCoordinator = groupRecord.coordinator().xid();\n const responseArid = validateRound2Request(sealedRequest, groupId, expectedCoordinator);\n\n // Extract Round 1 packages from the request\n const [round1Packages, round1PackagesByXid] = extractRound1Packages(\n sealedRequest,\n groupRecord,\n owner.xid(),\n );\n\n if (isVerbose() || options.verbose === true) {\n console.error(`Received ${round1Packages.size} Round 1 packages. Running DKG part2...`);\n }\n\n // Allocate next response ARID for the finalize phase\n const nextResponseArid = ARID.new();\n\n // Run FROST DKG part2\n // Convert Map<Identifier, Package> to Map<string, Package> for dkgPart2\n const round1PackagesHex = new Map<string, DkgRound1Package>();\n for (const [id, pkg] of round1Packages) {\n round1PackagesHex.set(identifierToHex(id), pkg);\n }\n\n const [round2Secret, round2Packages] = dkgPart2(round1State.secretPackage, round1PackagesHex);\n\n if (isVerbose() || options.verbose === true) {\n console.error(`Generated ${round2Packages.size} Round 2 packages.`);\n }\n\n // Convert round2Packages back to use Identifier keys for buildResponseBody\n const round2PackagesById = new Map<FrostIdentifier, unknown>();\n for (const [idHex, pkg] of round2Packages) {\n // Find the identifier that matches this hex\n for (const [id] of round1Packages) {\n if (identifierToHex(id) === idHex) {\n round2PackagesById.set(id, pkg);\n break;\n }\n }\n }\n\n // Build response with Round 2 packages\n const responseBody = buildResponseBody(\n groupId,\n owner.xid(),\n nextResponseArid,\n round2PackagesById,\n groupRecord,\n );\n\n const signerPrivateKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Owner XID document has no signing keys\");\n }\n\n // Get coordinator's XID document for encryption\n const coordinatorXid = groupRecord.coordinator().xid();\n const coordinatorRecord = registry.participant(coordinatorXid);\n let coordinatorDoc: XIDDocument;\n if (coordinatorRecord !== undefined) {\n coordinatorDoc = coordinatorRecord.xidDocument();\n } else {\n // Check if coordinator is the owner\n if (owner.xid().urString() === coordinatorXid.urString()) {\n coordinatorDoc = owner.xidDocument();\n } else {\n throw new Error(`Coordinator ${coordinatorXid.urString()} not found in registry`);\n }\n }\n\n // Get peer continuation from the request\n const peerContinuation = sealedRequest.peerContinuation();\n\n let sealed = SealedResponse.newSuccess(sealedRequest.id(), owner.xidDocument()).withResult(\n responseBody,\n );\n\n if (peerContinuation !== undefined) {\n sealed = sealed.withPeerContinuation(peerContinuation);\n }\n\n if (options.preview === true) {\n // Show the response envelope structure without encryption\n const unsealedEnvelope = sealed.toEnvelope(\n undefined, // No expiration for responses\n signerPrivateKeys,\n undefined,\n );\n const envelopeUr = unsealedEnvelope.urString();\n console.log(envelopeUr);\n\n return {\n listeningArid: nextResponseArid.urString(),\n envelopeUr,\n };\n }\n\n // Calculate participant index for serialization\n // Sort participants by XID to find our position\n const sortedXids = groupRecord.participants().map((p) => p.xid().urString());\n const ownerXidStr = owner.xid().urString();\n if (!sortedXids.includes(ownerXidStr)) {\n sortedXids.push(ownerXidStr);\n }\n sortedXids.sort();\n const participantIndex = sortedXids.indexOf(ownerXidStr) + 1; // 1-indexed\n\n // Persist Round 2 secret and collected round1 packages\n const round2SecretPath = persistRound2State(\n registryPath,\n groupId,\n round2Secret,\n round1PackagesByXid,\n participantIndex,\n );\n\n const responseEnvelope = sealed.toEnvelope(\n undefined, // No expiration for responses\n signerPrivateKeys,\n coordinatorDoc,\n );\n\n // Post the response\n await putWithIndicator(\n client,\n responseArid,\n responseEnvelope,\n \"Round 2 Response\",\n options.verbose ?? false,\n );\n\n // Update contributions in registry\n const updatedGroupRecord = registry.group(groupId);\n if (updatedGroupRecord !== undefined) {\n const contributions = updatedGroupRecord.contributions();\n contributions.round2Secret = round2SecretPath;\n updatedGroupRecord.setContributions(contributions);\n // Set new listening ARID for finalize phase\n updatedGroupRecord.setListeningAtArid(nextResponseArid);\n registry.save(registryPath);\n }\n\n if (isVerbose() || options.verbose === true) {\n console.error(`Posted Round 2 response to ${responseArid.urString()}`);\n }\n\n return {\n listeningArid: nextResponseArid.urString(),\n };\n}\n","/**\n * DKG participant finalize command.\n *\n * Port of cmd/dkg/participant/finalize.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, JSON as JSONWrapper, XID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope, Function as EnvelopeFunction } from \"@bcts/envelope\";\nimport { SealedRequest, SealedResponse } from \"@bcts/gstp\";\nimport type { XIDDocument } from \"@bcts/xid\";\n\nimport { type GroupRecord, Registry, resolveRegistryPath } from \"../../../registry/index.js\";\nimport { getWithIndicator, putWithIndicator } from \"../../busy.js\";\nimport { groupStateDir, isVerbose } from \"../../common.js\";\nimport { createStorageClient, type StorageClient, type StorageSelection } from \"../../storage.js\";\nimport { parseAridUr, signingKeyFromVerifying } from \"../common.js\";\nimport {\n dkgPart3,\n identifierFromU16,\n identifierToHex,\n hexToBytes,\n bytesToHex,\n serializeKeyPackage,\n serializePublicKeyPackage,\n type DkgRound1Package,\n type DkgRound2Package,\n type DkgRound2SecretPackage,\n type FrostIdentifier,\n type FrostKeyPackage,\n type FrostPublicKeyPackage,\n} from \"../../../frost/index.js\";\nimport { Ed25519Sha512, serde } from \"@frosts/ed25519\";\nimport { round2, CoefficientCommitment, VerifiableSecretSharingCommitment } from \"@frosts/core\";\n\n/**\n * Options for the DKG finalize command.\n */\nexport interface DkgFinalizeOptions {\n registryPath?: string;\n groupId: string;\n timeoutSeconds?: number;\n preview?: boolean;\n storageSelection?: StorageSelection;\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG finalize command.\n */\nexport interface DkgFinalizeResult {\n verifyingKey: string;\n keyPackagePath: string;\n publicKeyPackagePath: string;\n}\n\n/**\n * Persisted round 2 state loaded from disk.\n */\ninterface Round2State {\n secretPackage: DkgRound2SecretPackage;\n round1Packages: Map<string, DkgRound1Package>;\n}\n\n/**\n * Load persisted round 2 state from disk.\n *\n * Port of round2_secret loading from cmd/dkg/participant/finalize.rs lines 82-106.\n */\nfunction loadRound2State(registryPath: string, groupId: ARID): Round2State {\n const stateDir = groupStateDir(registryPath, groupId.hex());\n\n // Load Round 2 secret\n const round2SecretPath = path.join(stateDir, \"round2_secret.json\");\n if (!fs.existsSync(round2SecretPath)) {\n throw new Error(`Round 2 secret not found at ${round2SecretPath}. Did you run round2?`);\n }\n\n const secretJson = JSON.parse(fs.readFileSync(round2SecretPath, \"utf-8\")) as {\n identifier: number;\n commitment: {\n coefficients: string[];\n };\n secretShare: string;\n minSigners: number;\n maxSigners: number;\n };\n\n // Reconstruct the round 2 secret package\n const identifier = identifierFromU16(secretJson.identifier);\n\n const coefficientCommitments = secretJson.commitment.coefficients.map((hex) =>\n CoefficientCommitment.deserialize(Ed25519Sha512, hexToBytes(hex)),\n );\n\n const commitment = new VerifiableSecretSharingCommitment(Ed25519Sha512, coefficientCommitments);\n\n const secretShareScalar = Ed25519Sha512.deserializeScalar(hexToBytes(secretJson.secretShare));\n\n const secretPackage: DkgRound2SecretPackage = new round2.SecretPackage(\n Ed25519Sha512,\n identifier,\n commitment,\n secretShareScalar,\n secretJson.minSigners,\n secretJson.maxSigners,\n );\n\n // Load collected Round 1 packages (from round2 phase)\n const round1Path = path.join(stateDir, \"collected_round1.json\");\n if (!fs.existsSync(round1Path)) {\n throw new Error(`Round 1 packages not found at ${round1Path}. Did you receive earlier phases?`);\n }\n\n const round1Json = JSON.parse(fs.readFileSync(round1Path, \"utf-8\")) as Record<string, unknown>;\n\n // Convert to Map<string, DkgRound1Package> - keyed by XID UR string\n const round1Packages = new Map<string, DkgRound1Package>();\n for (const [xidStr, value] of Object.entries(round1Json)) {\n const packageJson = value as {\n header: { version: number; ciphersuite: string };\n commitment: string[];\n proof_of_knowledge: string;\n };\n const pkg = serde.round1PackageFromJson(packageJson);\n round1Packages.set(xidStr, pkg);\n }\n\n return { secretPackage, round1Packages };\n}\n\n/**\n * Validate the finalize request from the coordinator.\n *\n * Port of request validation from cmd/dkg/participant/finalize.rs lines 139-161.\n */\nfunction validateFinalizeRequest(\n sealedRequest: SealedRequest,\n groupId: ARID,\n expectedCoordinator: XID,\n): ARID {\n // Validate the request function\n if (!sealedRequest.function().equals(EnvelopeFunction.fromString(\"dkgFinalize\"))) {\n throw new Error(`Unexpected request function: ${sealedRequest.function().toString()}`);\n }\n\n // Validate the sender is the expected coordinator\n if (sealedRequest.sender().xid().urString() !== expectedCoordinator.urString()) {\n throw new Error(\n `Unexpected request sender: ${sealedRequest.sender().xid().urString()} ` +\n `(expected coordinator ${expectedCoordinator.urString()})`,\n );\n }\n\n // Validate the group ID matches\n const requestGroupIdEnvelope = sealedRequest.objectForParameter(\"group\");\n if (requestGroupIdEnvelope === undefined) {\n throw new Error(\"Request missing group parameter\");\n }\n const requestGroupId = requestGroupIdEnvelope.extractSubject((cbor) => ARID.fromTaggedCbor(cbor));\n if (requestGroupId.urString() !== groupId.urString()) {\n throw new Error(\n `Request group ID ${requestGroupId.urString()} does not match expected ${groupId.urString()}`,\n );\n }\n\n // Extract where we should post our response\n const responseAridEnvelope = sealedRequest.objectForParameter(\"responseArid\");\n if (responseAridEnvelope === undefined) {\n throw new Error(\"Request missing responseArid parameter\");\n }\n const responseArid = responseAridEnvelope.extractSubject((cbor) => ARID.fromTaggedCbor(cbor));\n\n return responseArid;\n}\n\n/**\n * Extract round 2 packages from the finalize request.\n *\n * Port of round2 package extraction from cmd/dkg/participant/finalize.rs lines 209-229.\n */\nfunction extractFinalizePackages(\n request: SealedRequest,\n groupRecord: GroupRecord,\n ownerXid: XID,\n): Map<string, DkgRound2Package> {\n // Build XID -> Identifier mapping based on sorted participant order\n const sortedXids: XID[] = groupRecord.participants().map((p) => p.xid());\n\n // Add owner if not already in list\n const ownerUrString = ownerXid.urString();\n if (!sortedXids.some((xid) => xid.urString() === ownerUrString)) {\n sortedXids.push(ownerXid);\n }\n\n // Sort by XID UR string\n sortedXids.sort((a, b) => a.urString().localeCompare(b.urString()));\n\n // Deduplicate\n const deduped: XID[] = [];\n for (const xid of sortedXids) {\n if (deduped.length === 0 || deduped[deduped.length - 1].urString() !== xid.urString()) {\n deduped.push(xid);\n }\n }\n\n // Build XID -> Identifier mapping (1-indexed)\n const xidToIdentifier = new Map<string, FrostIdentifier>();\n for (let i = 0; i < deduped.length; i++) {\n const identifier = identifierFromU16(i + 1);\n xidToIdentifier.set(deduped[i].urString(), identifier);\n }\n\n const myXidStr = ownerXid.urString();\n\n // Extract all round2Package parameters\n const packages = new Map<string, DkgRound2Package>();\n\n const packageEnvelopes = request.objectsForParameter(\"round2Package\");\n for (const packageEnvelope of packageEnvelopes) {\n // Extract sender XID from the envelope\n const senderEnvelope = packageEnvelope.objectForPredicate(\"sender\");\n if (senderEnvelope === undefined) {\n throw new Error(\"round2Package missing sender predicate\");\n }\n const senderXid = senderEnvelope.extractSubject((cbor) => XID.fromTaggedCbor(cbor));\n\n // Skip our own package\n if (senderXid.urString() === myXidStr) {\n continue;\n }\n\n // Get the identifier for this sender\n const identifier = xidToIdentifier.get(senderXid.urString());\n if (identifier === undefined) {\n throw new Error(`Unknown sender XID in round2Package: ${senderXid.urString()}`);\n }\n\n // Extract the package bytes (stored as JSON tag)\n const packageJson = packageEnvelope.extractSubject((cbor) => JSONWrapper.fromTaggedCbor(cbor));\n const packageData = JSON.parse(new TextDecoder().decode(packageJson.toData())) as {\n header: { version: number; ciphersuite: string };\n signing_share: string;\n };\n\n const pkg = serde.round2PackageFromJson(packageData);\n packages.set(identifierToHex(identifier), pkg);\n }\n\n return packages;\n}\n\n/**\n * Build the response body for the finalize response.\n *\n * Port of `build_response_body()` from cmd/dkg/participant/finalize.rs lines 344-359.\n */\nfunction buildResponseBody(\n groupId: ARID,\n participantXid: XID,\n keyPackage: FrostKeyPackage,\n publicKeyPackage: FrostPublicKeyPackage,\n): Envelope {\n // Serialize key packages to JSON\n const keyPackageJson = serializeKeyPackage(keyPackage);\n const publicKeyPackageJson = serializePublicKeyPackage(publicKeyPackage);\n\n const keyJsonBytes = new TextEncoder().encode(JSON.stringify(keyPackageJson));\n const keyJsonWrapper = JSONWrapper.fromData(keyJsonBytes);\n\n const pubJsonBytes = new TextEncoder().encode(JSON.stringify(publicKeyPackageJson));\n const pubJsonWrapper = JSONWrapper.fromData(pubJsonBytes);\n\n return Envelope.unit()\n .addType(\"dkgFinalizeResponse\")\n .addAssertion(\"group\", groupId)\n .addAssertion(\"participant\", participantXid)\n .addAssertion(\"key_package\", keyJsonWrapper)\n .addAssertion(\"public_key_package\", pubJsonWrapper);\n}\n\n/**\n * Persist finalize state (key packages) to disk.\n *\n * Port of key package persistence from cmd/dkg/participant/finalize.rs lines 251-257.\n */\nfunction persistFinalizeState(\n registryPath: string,\n groupId: ARID,\n keyPackage: FrostKeyPackage,\n publicKeyPackage: FrostPublicKeyPackage,\n): { keyPackagePath: string; publicKeyPackagePath: string } {\n const stateDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n // Serialize and save key package\n const serializedKeyPackage = serializeKeyPackage(keyPackage);\n const keyPackagePath = path.join(stateDir, \"key_package.json\");\n fs.writeFileSync(keyPackagePath, JSON.stringify(serializedKeyPackage, null, 2));\n\n // Serialize and save public key package\n const serializedPublicKeyPackage = serializePublicKeyPackage(publicKeyPackage);\n const publicKeyPackagePath = path.join(stateDir, \"public_key_package.json\");\n fs.writeFileSync(publicKeyPackagePath, JSON.stringify(serializedPublicKeyPackage, null, 2));\n\n return { keyPackagePath, publicKeyPackagePath };\n}\n\n/**\n * Execute the DKG participant finalize command.\n *\n * Responds to the finalize request from the coordinator, runs FROST DKG part3\n * to generate the final key package, and posts the response back.\n *\n * Port of `CommandArgs::exec()` from cmd/dkg/participant/finalize.rs lines 52-341.\n */\nexport async function finalize(\n _client: StorageClient | undefined,\n options: DkgFinalizeOptions,\n cwd: string,\n): Promise<DkgFinalizeResult> {\n if (options.storageSelection === undefined) {\n throw new Error(\"Hubert storage is required for finalize respond\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n // Get the ARID where we're listening for the finalize request\n const listeningAtArid = groupRecord.listeningAtArid();\n if (listeningAtArid === undefined) {\n throw new Error(\"No listening ARID for this group. Did you receive finalize send?\");\n }\n\n // Load Round 2 state (secret and collected round1 packages)\n const round2State = loadRound2State(registryPath, groupId);\n\n if (isVerbose() || options.verbose === true) {\n console.error(\"Fetching finalize request from Hubert...\");\n }\n\n const client = await createStorageClient(options.storageSelection);\n\n // Fetch the finalize request from where we're listening\n const requestEnvelope = await getWithIndicator(\n client,\n listeningAtArid,\n \"Finalize request\",\n options.timeoutSeconds,\n options.verbose ?? false,\n );\n\n if (requestEnvelope === null || requestEnvelope === undefined) {\n throw new Error(\"Finalize request not found in Hubert storage\");\n }\n\n // Decrypt and validate the request\n const ownerPrivateKeys = owner.xidDocument().inceptionPrivateKeys();\n if (ownerPrivateKeys === undefined) {\n throw new Error(\"Owner XID document has no private keys\");\n }\n\n const now = CborDate.now().datetime();\n const sealedRequest = SealedRequest.tryFromEnvelope(\n requestEnvelope,\n undefined,\n now,\n ownerPrivateKeys,\n );\n\n // Validate the request and extract response ARID\n const expectedCoordinator = groupRecord.coordinator().xid();\n const responseArid = validateFinalizeRequest(sealedRequest, groupId, expectedCoordinator);\n\n // Build identifier mapping for round1 packages (XID UR -> Identifier hex)\n const sortedXids: XID[] = groupRecord.participants().map((p) => p.xid());\n\n // Add owner if not already in list\n const ownerUrString = owner.xid().urString();\n if (!sortedXids.some((xid) => xid.urString() === ownerUrString)) {\n sortedXids.push(owner.xid());\n }\n\n // Sort by XID UR string\n sortedXids.sort((a, b) => a.urString().localeCompare(b.urString()));\n\n // Deduplicate\n const deduped: XID[] = [];\n for (const xid of sortedXids) {\n if (deduped.length === 0 || deduped[deduped.length - 1].urString() !== xid.urString()) {\n deduped.push(xid);\n }\n }\n\n // Build XID -> Identifier mapping (1-indexed)\n const xidToIdentifier = new Map<string, FrostIdentifier>();\n for (let i = 0; i < deduped.length; i++) {\n const identifier = identifierFromU16(i + 1);\n xidToIdentifier.set(deduped[i].urString(), identifier);\n }\n\n // Convert round1 packages from XID-keyed to identifier-keyed (exclude self)\n const round1PackagesById = new Map<string, DkgRound1Package>();\n for (const [xidStr, pkg] of round2State.round1Packages) {\n if (xidStr === ownerUrString) {\n continue;\n }\n const identifier = xidToIdentifier.get(xidStr);\n if (identifier === undefined) {\n throw new Error(`Unknown participant XID ${xidStr}`);\n }\n round1PackagesById.set(identifierToHex(identifier), pkg);\n }\n\n // Extract Round 2 packages from the request (exclude self)\n const round2PackagesById = extractFinalizePackages(sealedRequest, groupRecord, owner.xid());\n\n if (isVerbose() || options.verbose === true) {\n console.error(`Received ${round2PackagesById.size} Round 2 packages. Running DKG part3...`);\n }\n\n // Run FROST DKG part3 (finalize)\n const [keyPackage, publicKeyPackage] = await dkgPart3(\n round2State.secretPackage,\n round1PackagesById,\n round2PackagesById,\n );\n\n // Get the group verifying key\n const verifyingKeyBytes = publicKeyPackage.verifyingKey as Uint8Array;\n const groupVerifyingKey = signingKeyFromVerifying(verifyingKeyBytes);\n\n if (isVerbose() || options.verbose === true) {\n console.error(\"Generated key package and public key package.\");\n }\n\n // Persist key packages\n const { keyPackagePath, publicKeyPackagePath } = persistFinalizeState(\n registryPath,\n groupId,\n keyPackage,\n publicKeyPackage,\n );\n\n // Build response body\n const responseBody = buildResponseBody(groupId, owner.xid(), keyPackage, publicKeyPackage);\n\n const signerPrivateKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Owner XID document has no signing keys\");\n }\n\n // Get coordinator's XID document for encryption\n const coordinatorXid = groupRecord.coordinator().xid();\n const coordinatorRecord = registry.participant(coordinatorXid);\n let coordinatorDoc: XIDDocument;\n if (coordinatorRecord !== undefined) {\n coordinatorDoc = coordinatorRecord.xidDocument();\n } else {\n // Check if coordinator is the owner\n if (owner.xid().urString() === coordinatorXid.urString()) {\n coordinatorDoc = owner.xidDocument();\n } else {\n throw new Error(`Coordinator ${coordinatorXid.urString()} not found in registry`);\n }\n }\n\n // Get peer continuation from the request\n const peerContinuation = sealedRequest.peerContinuation();\n\n let sealed = SealedResponse.newSuccess(sealedRequest.id(), owner.xidDocument()).withResult(\n responseBody,\n );\n\n if (peerContinuation !== undefined) {\n sealed = sealed.withPeerContinuation(peerContinuation);\n }\n\n if (options.preview === true) {\n // Show the response envelope structure without encryption\n if (isVerbose() || options.verbose === true) {\n // Cast to access urString method\n const verifyingKeyWithUrString = groupVerifyingKey as { urString?: () => string };\n if (typeof verifyingKeyWithUrString.urString === \"function\") {\n console.error(verifyingKeyWithUrString.urString());\n }\n }\n const unsealedEnvelope = sealed.toEnvelope(\n undefined, // No expiration for responses\n signerPrivateKeys,\n undefined,\n );\n console.log(unsealedEnvelope.urString());\n\n return {\n verifyingKey: bytesToHex(verifyingKeyBytes),\n keyPackagePath,\n publicKeyPackagePath,\n };\n }\n\n const responseEnvelope = sealed.toEnvelope(\n undefined, // No expiration for responses\n signerPrivateKeys,\n coordinatorDoc,\n );\n\n // Post the response\n await putWithIndicator(\n client,\n responseArid,\n responseEnvelope,\n \"Finalize Response\",\n options.verbose ?? false,\n );\n\n // Update registry: contributions and verifying key\n const updatedGroupRecord = registry.group(groupId);\n if (updatedGroupRecord !== undefined) {\n const contributions = updatedGroupRecord.contributions();\n contributions.keyPackage = keyPackagePath;\n updatedGroupRecord.setContributions(contributions);\n updatedGroupRecord.clearListeningAtArid();\n\n // Set verifying key if the method exists\n const recordWithVerifyingKey = updatedGroupRecord as {\n setVerifyingKey?: (key: unknown) => void;\n };\n if (typeof recordWithVerifyingKey.setVerifyingKey === \"function\") {\n recordWithVerifyingKey.setVerifyingKey(groupVerifyingKey);\n }\n\n registry.save(registryPath);\n }\n\n // Get verifying key for output\n const verifyingKeyHex = bytesToHex(verifyingKeyBytes);\n\n if (isVerbose() || options.verbose === true) {\n console.error(`Posted finalize response to ${responseArid.urString()}`);\n // Cast to access urString method\n const verifyingKeyWithUrString = groupVerifyingKey as { urString?: () => string };\n if (typeof verifyingKeyWithUrString.urString === \"function\") {\n console.error(verifyingKeyWithUrString.urString());\n }\n } else {\n // Cast to access urString method\n const verifyingKeyWithUrString = groupVerifyingKey as { urString?: () => string };\n if (typeof verifyingKeyWithUrString.urString === \"function\") {\n console.log(verifyingKeyWithUrString.urString());\n }\n }\n\n return {\n verifyingKey: verifyingKeyHex,\n keyPackagePath,\n publicKeyPackagePath,\n };\n}\n","/**\n * DKG participant commands.\n *\n * Port of cmd/dkg/participant/mod.rs from frost-hubert-rust.\n *\n * @module\n */\n\nexport * from \"./receive.js\";\nexport * from \"./round1.js\";\nexport * from \"./round2.js\";\nexport * from \"./finalize.js\";\n","/**\n * DKG command module.\n *\n * Port of cmd/dkg/mod.rs from frost-hubert-rust.\n *\n * @module\n */\n\nexport * from \"./common.js\";\nexport * as coordinator from \"./coordinator/index.js\";\nexport * as participant from \"./participant/index.js\";\n","/**\n * Common utilities for sign commands.\n *\n * Port of cmd/sign/common.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport { Envelope, type EnvelopeEncodableValue } from \"@bcts/envelope\";\n\nimport { groupStateDir } from \"../common\";\n\n/**\n * Get the signing state directory for a group (without session).\n *\n * Path: `{registry_dir}/group-state/{group_id.hex()}/signing`\n *\n * Port of `signing_state_dir_for_group()` from cmd/sign/common.rs.\n */\nexport function signingStateDirForGroup(registryPath: string, groupIdHex: string): string {\n return `${groupStateDir(registryPath, groupIdHex)}/signing`;\n}\n\n/**\n * Get the signing state directory for a given registry path, group ID, and session ID.\n *\n * Path: `{registry_dir}/group-state/{group_id.hex()}/signing/{session_id.hex()}`\n *\n * Port of `signing_state_dir()` from cmd/sign/common.rs.\n */\nexport function signingStateDir(\n registryPath: string,\n groupIdHex: string,\n sessionIdHex: string,\n): string {\n return `${signingStateDirForGroup(registryPath, groupIdHex)}/${sessionIdHex}`;\n}\n\n/**\n * Content wrapper for signFinalize events.\n *\n * This wraps an envelope with a unit subject and type assertion\n * \"signFinalize\", implementing the traits required by SealedEvent<T>.\n *\n * Port of `struct SignFinalizeContent` from cmd/sign/common.rs.\n */\nexport class SignFinalizeContent {\n private readonly _envelope: Envelope;\n\n private constructor(envelope: Envelope) {\n this._envelope = envelope;\n }\n\n /**\n * Creates a new SignFinalizeContent with a unit subject and type assertion.\n *\n * Port of `SignFinalizeContent::new()` from cmd/sign/common.rs.\n */\n static new(): SignFinalizeContent {\n const envelope = Envelope.unit().addType(\"signFinalize\");\n return new SignFinalizeContent(envelope);\n }\n\n /**\n * Adds an assertion to the content envelope.\n *\n * Port of `SignFinalizeContent::add_assertion()` from cmd/sign/common.rs.\n */\n addAssertion(\n predicate: EnvelopeEncodableValue,\n object: EnvelopeEncodableValue,\n ): SignFinalizeContent {\n const newEnvelope = this._envelope.addAssertion(predicate, object);\n return new SignFinalizeContent(newEnvelope);\n }\n\n /**\n * Returns the inner envelope.\n *\n * Port of `SignFinalizeContent::envelope()` from cmd/sign/common.rs.\n */\n envelope(): Envelope {\n return this._envelope;\n }\n\n /**\n * Creates a SignFinalizeContent from an envelope with validation.\n *\n * Validates that the envelope has a unit subject and type \"signFinalize\".\n *\n * Port of `TryFrom<Envelope> for SignFinalizeContent` from cmd/sign/common.rs.\n */\n static fromEnvelope(envelope: Envelope): SignFinalizeContent {\n // Validate it has a unit subject and type \"signFinalize\"\n envelope.checkSubjectUnit();\n envelope.checkType(\"signFinalize\");\n return new SignFinalizeContent(envelope);\n }\n\n /**\n * Converts this SignFinalizeContent to an Envelope.\n *\n * Port of `From<SignFinalizeContent> for Envelope` from cmd/sign/common.rs.\n */\n toEnvelope(): Envelope {\n return this._envelope;\n }\n}\n","/**\n * Sign coordinator invite command.\n *\n * Port of cmd/sign/coordinator/invite.rs from frost-hubert-rust.\n *\n * @module\n */\n\n/* eslint-disable @typescript-eslint/no-unsafe-assignment */\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n/* eslint-disable @typescript-eslint/no-unsafe-member-access */\n/* eslint-disable @typescript-eslint/no-unsafe-argument */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { SealedRequest } from \"@bcts/gstp\";\nimport { type XIDDocument } from \"@bcts/xid\";\n\nimport {\n Registry,\n resolveRegistryPath,\n type GroupRecord,\n type GroupParticipant,\n type OwnerRecord,\n} from \"../../../registry/index.js\";\nimport { putWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { parseAridUr } from \"../../dkg/common.js\";\nimport { signingStateDir } from \"../common.js\";\n\n// -----------------------------------------------------------------------------\n// Session ARID management\n// -----------------------------------------------------------------------------\n\n/**\n * Session ARIDs for tracking the signing session.\n *\n * Port of `struct SessionArids` from cmd/sign/coordinator/invite.rs lines 151-156.\n */\nexport interface SessionArids {\n sessionId: ARID;\n startArid: ARID;\n commitArids: Map<string, ARID>; // Map<XID.urString(), ARID>\n shareArids: Map<string, ARID>; // Map<XID.urString(), ARID>\n}\n\n/**\n * Create new session ARIDs for all participants.\n *\n * Port of `SessionArids::new()` from cmd/sign/coordinator/invite.rs lines 158-173.\n */\nexport function createSessionArids(participants: GroupParticipant[]): SessionArids {\n const commitArids = new Map<string, ARID>();\n const shareArids = new Map<string, ARID>();\n\n for (const participant of participants) {\n const xidKey = participant.xid().urString();\n commitArids.set(xidKey, ARID.new());\n shareArids.set(xidKey, ARID.new());\n }\n\n return {\n sessionId: ARID.new(),\n startArid: ARID.new(),\n commitArids,\n shareArids,\n };\n}\n\n// -----------------------------------------------------------------------------\n// Validation\n// -----------------------------------------------------------------------------\n\n/**\n * Validate that the owner is the coordinator of the group.\n *\n * Port of `validate_coordinator()` from cmd/sign/coordinator/invite.rs lines 179-192.\n */\nexport function validateCoordinator(groupRecord: GroupRecord, owner: OwnerRecord): void {\n if (groupRecord.coordinator().xid().urString() !== owner.xid().urString()) {\n throw new Error(\n `Only the coordinator can start signing. Coordinator: ${groupRecord.coordinator().xid().urString()}, Owner: ${owner.xid().urString()}`,\n );\n }\n}\n\n// -----------------------------------------------------------------------------\n// Participant document gathering\n// -----------------------------------------------------------------------------\n\n/**\n * Gather XIDDocuments for all participants from the registry.\n *\n * Port of `gather_recipient_documents()` from cmd/sign/coordinator/invite.rs lines 198-222.\n */\nexport function gatherRecipientDocuments(\n participants: GroupParticipant[],\n owner: OwnerRecord,\n registry: Registry,\n): XIDDocument[] {\n const recipientDocs: XIDDocument[] = [];\n\n for (const participant of participants) {\n const xid = participant.xid();\n if (xid.urString() === owner.xid().urString()) {\n recipientDocs.push(owner.xidDocument());\n } else {\n const record = registry.participant(xid);\n if (record === undefined) {\n throw new Error(`Participant ${xid.urString()} not found in registry`);\n }\n recipientDocs.push(record.xidDocument());\n }\n }\n\n return recipientDocs;\n}\n\n// -----------------------------------------------------------------------------\n// Request building\n// -----------------------------------------------------------------------------\n\n/**\n * Context for building the sign invite request.\n *\n * Port of `struct SignInviteContext` from cmd/sign/coordinator/invite.rs lines 228-237.\n */\nexport interface SignInviteContext {\n arids: SessionArids;\n groupId: ARID;\n targetEnvelope: Envelope;\n groupRecord: GroupRecord;\n owner: OwnerRecord;\n registry: Registry;\n participants: GroupParticipant[];\n validUntil: Date;\n}\n\n/**\n * Build the sign invite request.\n *\n * Port of `build_sign_invite_request()` from cmd/sign/coordinator/invite.rs lines 239-284.\n */\nexport function buildSignInviteRequest(ctx: SignInviteContext): SealedRequest {\n let request = SealedRequest.new(\"signInvite\", ctx.arids.sessionId, ctx.owner.xidDocument())\n .withParameter(\"group\", ctx.groupId)\n .withParameter(\"session\", ctx.arids.sessionId)\n .withParameter(\"target\", ctx.targetEnvelope)\n .withParameter(\"minSigners\", ctx.groupRecord.minSigners())\n .withDate(new Date())\n .withParameter(\"validUntil\", CborDate.fromDatetime(ctx.validUntil));\n\n for (const participant of ctx.participants) {\n const xid = participant.xid();\n const xidKey = xid.urString();\n\n // Get participant document\n let participantDoc: XIDDocument;\n if (xidKey === ctx.owner.xid().urString()) {\n participantDoc = ctx.owner.xidDocument();\n } else {\n const record = ctx.registry.participant(xid);\n if (record === undefined) {\n throw new Error(\"Participant not found in registry\");\n }\n participantDoc = record.xidDocument();\n }\n\n // Get encryption key\n const encryptionKey = participantDoc.encryptionKey();\n if (encryptionKey === undefined) {\n throw new Error(\"Participant XID document has no encryption key\");\n }\n\n // Get commit ARID for this participant\n const responseArid = ctx.arids.commitArids.get(xidKey);\n if (responseArid === undefined) {\n throw new Error(\"commit ARID not found for participant\");\n }\n\n // Encrypt response ARID to participant\n // @ts-expect-error TS2339 - API mismatch: toEnvelope/encryptToRecipient methods\n const encryptedResponseArid = responseArid.toEnvelope().encryptToRecipient(encryptionKey);\n\n // Build participant entry envelope\n const participantEntry = Envelope.new(xid).addAssertion(\"response_arid\", encryptedResponseArid);\n\n request = request.withParameter(\"participant\", participantEntry);\n }\n\n return request;\n}\n\n// -----------------------------------------------------------------------------\n// State persistence\n// -----------------------------------------------------------------------------\n\n/**\n * Build the session state JSON for persistence.\n *\n * Port of `build_session_state_json()` from cmd/sign/coordinator/invite.rs lines 290-346.\n */\nexport function buildSessionStateJson(\n arids: SessionArids,\n groupId: ARID,\n groupRecord: GroupRecord,\n participants: GroupParticipant[],\n targetEnvelope: Envelope,\n): Record<string, unknown> {\n const participantsMap: Record<string, unknown> = {};\n\n for (const participant of participants) {\n const xid = participant.xid();\n const xidKey = xid.urString();\n\n const commitArid = arids.commitArids.get(xidKey);\n const shareArid = arids.shareArids.get(xidKey);\n\n if (commitArid === undefined || shareArid === undefined) {\n throw new Error(\"ARID not found for participant\");\n }\n\n participantsMap[xidKey] = {\n commit_arid: commitArid.urString(),\n share_arid: shareArid.urString(),\n };\n }\n\n return {\n session_id: arids.sessionId.urString(),\n start_arid: arids.startArid.urString(),\n group: groupId.urString(),\n min_signers: groupRecord.minSigners(),\n participants: participantsMap,\n target: targetEnvelope.urString(),\n };\n}\n\n/**\n * Persist the session state to disk.\n *\n * Port of `persist_session_state()` from cmd/sign/coordinator/invite.rs lines 348-356.\n */\nexport function persistSessionState(signingDir: string, stateJson: Record<string, unknown>): void {\n fs.mkdirSync(signingDir, { recursive: true });\n const startStatePath = path.join(signingDir, \"start.json\");\n fs.writeFileSync(startStatePath, JSON.stringify(stateJson, null, 2));\n}\n\n// -----------------------------------------------------------------------------\n// File loading\n// -----------------------------------------------------------------------------\n\n/**\n * Load an envelope from a file path.\n *\n * Port of `load_envelope_from_path()` from cmd/sign/coordinator/invite.rs lines 385-392.\n */\nexport function loadEnvelopeFromPath(filePath: string): Envelope {\n if (!fs.existsSync(filePath)) {\n throw new Error(`Failed to read target envelope from ${filePath}`);\n }\n\n const data = fs.readFileSync(filePath, \"utf-8\");\n const trimmed = data.trim();\n\n try {\n return Envelope.fromURString(trimmed);\n } catch (e) {\n throw new Error(`Failed to load target envelope from ${filePath}: ${String(e)}`);\n }\n}\n\n// -----------------------------------------------------------------------------\n// Options and Result types\n// -----------------------------------------------------------------------------\n\n/**\n * Options for the sign invite command.\n */\nexport interface SignInviteOptions {\n registryPath?: string;\n groupId: string;\n targetFile: string;\n validDays?: number;\n verbose?: boolean;\n preview?: boolean;\n}\n\n/**\n * Result of the sign invite command.\n */\nexport interface SignInviteResult {\n sessionId: string;\n startArid: string;\n}\n\n// -----------------------------------------------------------------------------\n// Main invite function\n// -----------------------------------------------------------------------------\n\n/**\n * Execute the sign coordinator invite command.\n *\n * Invites participants to sign a target envelope.\n *\n * Port of `CommandArgs::exec()` from cmd/sign/coordinator/invite.rs lines 44-144.\n */\nexport async function invite(\n client: StorageClient | undefined,\n options: SignInviteOptions,\n cwd: string,\n): Promise<SignInviteResult> {\n // Validate preview mode\n if (client !== undefined && options.preview === true) {\n throw new Error(\"--preview cannot be used with Hubert storage options\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(`Group ${options.groupId} not found in registry`);\n }\n\n // Validate sender is coordinator\n validateCoordinator(groupRecord, owner);\n\n // Load target envelope\n const targetPath = path.resolve(cwd, options.targetFile);\n const targetEnvelope = loadEnvelopeFromPath(targetPath);\n\n // Get participants\n const participants = groupRecord.participants();\n\n // Gather recipient documents\n const recipientDocs = gatherRecipientDocuments(participants, owner, registry);\n\n // Get signer keys\n const signerKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerKeys === undefined) {\n throw new Error(\"Coordinator XID document has no signing keys\");\n }\n\n // Generate session ARIDs\n const sessionArids = createSessionArids(participants);\n\n // Calculate valid until date (default 1 hour)\n const validDays = options.validDays ?? 1 / 24; // 1 hour default\n const validUntil = new Date(Date.now() + validDays * 24 * 60 * 60 * 1000);\n\n // Build request context\n const ctx: SignInviteContext = {\n arids: sessionArids,\n groupId,\n targetEnvelope,\n groupRecord,\n owner,\n registry,\n participants,\n validUntil,\n };\n\n // Build request\n const request = buildSignInviteRequest(ctx);\n\n // Build state for persistence\n const stateJson = buildSessionStateJson(\n sessionArids,\n groupId,\n groupRecord,\n participants,\n targetEnvelope,\n );\n\n // Build envelope for recipients\n const recipientRefs = recipientDocs;\n const sealedEnvelope = request.toEnvelopeForRecipients(validUntil, signerKeys, recipientRefs);\n\n // Handle preview mode\n if (options.preview === true) {\n const unsealed = request.toEnvelope(undefined, signerKeys, undefined);\n console.log(unsealed.urString());\n return {\n sessionId: sessionArids.sessionId.urString(),\n startArid: sessionArids.startArid.urString(),\n };\n }\n\n // Persist state\n const signingDir = signingStateDir(registryPath, groupId.hex(), sessionArids.sessionId.hex());\n persistSessionState(signingDir, stateJson);\n\n // Post to Hubert storage\n if (client === undefined) {\n throw new Error(\"Hubert storage is required for sign start\");\n }\n\n await putWithIndicator(\n client,\n sessionArids.startArid,\n sealedEnvelope,\n \"Signing invite\",\n options.verbose ?? false,\n );\n\n if (options.verbose === true) {\n console.log(`Session ID: ${sessionArids.sessionId.urString()}`);\n console.log(`Start ARID: ${sessionArids.startArid.urString()}`);\n }\n\n // Output the start ARID\n console.log(sessionArids.startArid.urString());\n\n return {\n sessionId: sessionArids.sessionId.urString(),\n startArid: sessionArids.startArid.urString(),\n };\n}\n","/**\n * Sign coordinator round 1 command.\n *\n * Port of cmd/sign/coordinator/round1.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport {\n type ARID,\n type XID,\n ARID as ARIDClass,\n XID as XIDClass,\n JSON as JSONClass,\n type PrivateKeys,\n} from \"@bcts/components\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { SealedRequest, SealedResponse } from \"@bcts/gstp\";\nimport { type XIDDocument } from \"@bcts/xid\";\n\nimport { Registry, resolveRegistryPath, type OwnerRecord } from \"../../../registry/index.js\";\nimport {\n parallelFetch,\n parallelSend,\n type CollectionResult,\n type ParallelFetchConfig,\n} from \"../../parallel.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { parseAridUr } from \"../../dkg/common.js\";\nimport { signingStateDir } from \"../common.js\";\nimport { isVerbose } from \"../../common.js\";\n\n/**\n * Options for the sign round1 command.\n */\nexport interface SignRound1Options {\n registryPath?: string;\n groupId?: string;\n sessionId: string;\n parallel?: boolean;\n timeoutSeconds?: number;\n verbose?: boolean;\n previewShare?: boolean;\n}\n\n/**\n * Result of the sign round1 command.\n */\nexport interface SignRound1Result {\n accepted: number;\n rejected: number;\n errors: number;\n timeouts: number;\n}\n\n/**\n * Data extracted from a successful sign round1 response.\n *\n * Port of `struct SignRound1ResponseData` from cmd/sign/coordinator/round1.rs.\n */\nexport interface SignRound1ResponseData {\n /** The signing commitments from this participant */\n commitments: unknown; // frost::round1::SigningCommitments equivalent\n /** The ARID where the participant expects the next request */\n nextRequestArid: ARID;\n}\n\n/**\n * State for a participant in the signing session.\n *\n * Port of `struct StartParticipant` from cmd/sign/coordinator/round1.rs.\n */\nexport interface StartParticipant {\n commitArid: ARID;\n shareArid: ARID;\n}\n\n/**\n * Start state for a signing session.\n *\n * Port of `struct StartState` from cmd/sign/coordinator/round1.rs.\n */\nexport interface StartState {\n groupId: ARID;\n targetUr: string;\n participants: Map<string, StartParticipant>; // Map by XID UR string\n}\n\n/**\n * Load the start state for a signing session.\n *\n * Port of `load_start_state()` from cmd/sign/coordinator/round1.rs.\n */\nfunction loadStartState(registryPath: string, sessionId: ARID, groupHint?: ARID): StartState {\n const base = path.dirname(registryPath);\n const groupStateDir = path.join(base, \"group-state\");\n\n const candidatePaths: [ARID, string][] = [];\n let groupDirs: [ARID, string][];\n\n if (groupHint !== undefined) {\n groupDirs = [[groupHint, path.join(groupStateDir, groupHint.hex())]];\n } else {\n groupDirs = [];\n if (fs.existsSync(groupStateDir)) {\n for (const entry of fs.readdirSync(groupStateDir, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n const dirName = entry.name;\n if (dirName.length === 64 && /^[0-9a-fA-F]+$/.test(dirName)) {\n const groupId = ARIDClass.fromHex(dirName);\n groupDirs.push([groupId, path.join(groupStateDir, dirName)]);\n }\n }\n }\n }\n }\n\n for (const [groupId, groupDir] of groupDirs) {\n const candidate = path.join(groupDir, \"signing\", sessionId.hex(), \"start.json\");\n if (fs.existsSync(candidate)) {\n candidatePaths.push([groupId, candidate]);\n }\n }\n\n if (candidatePaths.length === 0) {\n throw new Error(\"No sign start state found; run `frost sign coordinator start` first\");\n }\n if (candidatePaths.length > 1) {\n throw new Error(\"Multiple signing sessions found; specify --group to disambiguate\");\n }\n\n const [groupId, statePath] = candidatePaths[0];\n const raw = JSON.parse(fs.readFileSync(statePath, \"utf-8\")) as Record<string, unknown>;\n\n const getStr = (key: string): string => {\n const value = raw[key];\n if (typeof value !== \"string\") {\n throw new Error(`Missing or invalid ${key} in start.json`);\n }\n return value;\n };\n\n const sessionInState = parseAridUr(getStr(\"session_id\"));\n const groupInState = parseAridUr(getStr(\"group\"));\n\n if (sessionInState.hex() !== sessionId.hex()) {\n throw new Error(\n `start.json session ${sessionInState.urString()} does not match requested session ${sessionId.urString()}`,\n );\n }\n if (groupInState.hex() !== groupId.hex()) {\n throw new Error(\n `start.json group ${groupInState.urString()} does not match directory group ${groupId.urString()}`,\n );\n }\n\n const targetUr = getStr(\"target\");\n\n const participantsVal = raw[\"participants\"] as Record<string, Record<string, string>> | undefined;\n if (participantsVal === undefined || typeof participantsVal !== \"object\") {\n throw new Error(\"Missing participants in start.json\");\n }\n\n const participants = new Map<string, StartParticipant>();\n for (const [xidStr, value] of Object.entries(participantsVal)) {\n const xid = XIDClass.fromURString(xidStr);\n if (typeof value !== \"object\" || value === null) {\n throw new Error(\"Participant entry is not an object in start.json\");\n }\n\n const commitAridStr = value[\"commit_arid\"];\n const shareAridStr = value[\"share_arid\"];\n\n if (typeof commitAridStr !== \"string\") {\n throw new Error(\"Missing commit_arid in start.json\");\n }\n if (typeof shareAridStr !== \"string\") {\n throw new Error(\"Missing share_arid in start.json\");\n }\n\n participants.set(xid.urString(), {\n commitArid: parseAridUr(commitAridStr),\n shareArid: parseAridUr(shareAridStr),\n });\n }\n\n return { groupId, targetUr, participants };\n}\n\n/**\n * Validate and extract data from a sign commit response.\n *\n * Port of `validate_and_extract_sign_round1_response()` from cmd/sign/coordinator/round1.rs.\n */\nexport function validateAndExtractCommitResponse(\n envelope: Envelope,\n coordinatorKeys: PrivateKeys,\n expectedSender: XID,\n expectedSessionId: ARID,\n): SignRound1ResponseData {\n const now = new Date();\n const sealedResponse = SealedResponse.tryFromEncryptedEnvelope(\n envelope,\n undefined,\n now,\n coordinatorKeys,\n );\n\n if (!sealedResponse.sender().xid().equals(expectedSender)) {\n throw new Error(\n `Unexpected response sender: ${sealedResponse.sender().xid().urString()} (expected ${expectedSender.urString()})`,\n );\n }\n\n if (sealedResponse.isErr()) {\n const errorEnvelope = sealedResponse.error();\n let reason = \"unknown reason\";\n try {\n const reasonEnv = errorEnvelope.objectForPredicate(\"reason\");\n if (reasonEnv !== undefined) {\n reason = reasonEnv.extractString();\n }\n } catch {\n // Keep default reason\n }\n throw new Error(`Participant rejected signInvite: ${reason}`);\n }\n\n const result = sealedResponse.result();\n\n result.checkSubjectUnit();\n result.checkType(\"signRound1Response\");\n\n const responseSession = result.tryObjectForPredicate(\"session\", (cbor) =>\n ARIDClass.fromTaggedCbor(cbor),\n );\n if (responseSession.hex() !== expectedSessionId.hex()) {\n throw new Error(\n `Response session ${responseSession.urString()} does not match expected ${expectedSessionId.urString()}`,\n );\n }\n\n const commitmentsJson = result.tryObjectForPredicate(\"commitments\", (cbor) =>\n JSONClass.fromTaggedCbor(cbor),\n );\n const commitments = JSON.parse(new TextDecoder().decode(commitmentsJson.toData())) as Record<\n string,\n unknown\n >;\n\n const nextRequestArid = result.tryObjectForPredicate(\"response_arid\", (cbor) =>\n ARIDClass.fromTaggedCbor(cbor),\n );\n\n return { commitments, nextRequestArid };\n}\n\n/**\n * Collect signing commitments in parallel.\n *\n * Port of `collect_sign_round1_parallel()` from cmd/sign/coordinator/round1.rs.\n */\nexport async function collectCommitmentsParallel(\n client: StorageClient,\n registry: Registry,\n startState: StartState,\n coordinator: XIDDocument,\n sessionId: ARID,\n timeout?: number,\n): Promise<CollectionResult<SignRound1ResponseData>> {\n const requests: [XID, ARID, string][] = [];\n\n for (const [xidStr, state] of startState.participants) {\n const xid = XIDClass.fromURString(xidStr);\n const participant = registry.participant(xid);\n const name = participant?.petName() ?? xid.urString();\n requests.push([xid, state.commitArid, name]);\n }\n\n const coordinatorKeys = coordinator.inceptionPrivateKeys();\n if (coordinatorKeys === undefined) {\n throw new Error(\"Missing coordinator private keys\");\n }\n\n const config: ParallelFetchConfig = { timeoutSeconds: timeout };\n\n return parallelFetch(\n client,\n requests,\n (envelope: Envelope, xid: XID) => {\n try {\n return validateAndExtractCommitResponse(envelope, coordinatorKeys, xid, sessionId);\n } catch (e) {\n return { rejected: e instanceof Error ? e.message : String(e) };\n }\n },\n config,\n );\n}\n\n/**\n * Build a sign share request for a participant.\n *\n * Port of `build_sign_share_request()` from cmd/sign/coordinator/round1.rs.\n */\nexport function buildShareRequestForParticipant(\n sender: XIDDocument,\n _groupId: ARID,\n sessionId: ARID,\n responseArid: ARID,\n commitments: Map<string, unknown>, // Map<XID UR string, commitments>\n): SealedRequest {\n let request = SealedRequest.new(\"signRound2\", sessionId, sender)\n .withParameter(\"session\", sessionId)\n .withParameter(\"response_arid\", responseArid);\n\n for (const [xidStr, commits] of commitments) {\n const xid = XIDClass.fromURString(xidStr);\n const commitsJson = JSONClass.fromData(new TextEncoder().encode(JSON.stringify(commits)));\n // Create envelope with xid as subject, then add commitments assertion with JSON CBOR data\n const entry = Envelope.new(xid).addAssertion(\"commitments\", commitsJson.taggedCborData());\n request = request.withParameter(\"commitment\", entry);\n }\n\n return request;\n}\n\n/**\n * Dispatch share requests to participants in parallel.\n *\n * Port of parallel dispatch logic from cmd/sign/coordinator/round1.rs.\n */\nexport async function dispatchShareRequestsParallel(\n client: StorageClient,\n registry: Registry,\n owner: OwnerRecord,\n startState: StartState,\n sessionId: ARID,\n collection: CollectionResult<SignRound1ResponseData>,\n commitments: Map<string, unknown>,\n previewShare?: boolean,\n verbose?: boolean,\n): Promise<[XID, Error | null][]> {\n const signerKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerKeys === undefined) {\n throw new Error(\"Coordinator XID document has no signing keys\");\n }\n\n const validUntil = new Date(Date.now() + 60 * 60 * 1000); // 1 hour from now\n\n const messages: [XID, ARID, Envelope, string][] = [];\n let previewPrinted = false;\n\n for (const [xid, data] of collection.successes) {\n const xidStr = xid.urString();\n const participantState = startState.participants.get(xidStr);\n if (participantState === undefined) {\n throw new Error(`Participant ${xidStr} not found in start state`);\n }\n\n const participant = registry.participant(xid);\n const participantName = participant?.petName() ?? xidStr;\n\n let recipientDoc: XIDDocument;\n if (xid.urString() === owner.xid().urString()) {\n recipientDoc = owner.xidDocument();\n } else {\n const record = registry.participant(xid);\n if (record === undefined) {\n throw new Error(`Participant ${xidStr} not found in registry`);\n }\n recipientDoc = record.xidDocument();\n }\n\n const request = buildShareRequestForParticipant(\n owner.xidDocument(),\n startState.groupId,\n sessionId,\n participantState.shareArid,\n commitments,\n );\n\n if (previewShare === true && !previewPrinted) {\n const preview = request.toEnvelope(validUntil, signerKeys, undefined);\n console.log(`# signRound2 preview for ${xidStr}`);\n console.log(preview.format());\n previewPrinted = true;\n }\n\n const sealedEnvelope = request.toEnvelopeForRecipients(validUntil, signerKeys, [recipientDoc]);\n\n messages.push([xid, data.nextRequestArid, sealedEnvelope, participantName]);\n }\n\n // Blank line to separate get phase from put phase\n console.error();\n\n return parallelSend(client, messages, verbose);\n}\n\n/**\n * Persist collected commitments to disk.\n *\n * Port of commitments persistence logic from cmd/sign/coordinator/round1.rs.\n */\nexport function persistCommitments(\n registryPath: string,\n groupId: ARID,\n sessionId: ARID,\n startState: StartState,\n commitments: Map<string, unknown>,\n): string {\n const signingDir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n fs.mkdirSync(signingDir, { recursive: true });\n\n const commitmentsPath = path.join(signingDir, \"commitments.json\");\n const commitmentsJson: Record<string, unknown> = {};\n\n for (const [xidStr, commits] of commitments) {\n const participantState = startState.participants.get(xidStr);\n if (participantState === undefined) {\n throw new Error(`Participant ${xidStr} not found in start state`);\n }\n\n commitmentsJson[xidStr] = {\n commitments: commits,\n share_arid: participantState.shareArid.urString(),\n };\n }\n\n const root = {\n group: groupId.urString(),\n session: sessionId.urString(),\n target: startState.targetUr,\n commitments: commitmentsJson,\n };\n\n fs.writeFileSync(commitmentsPath, JSON.stringify(root, null, 2));\n\n return commitmentsPath;\n}\n\n/**\n * Update pending requests in the registry for share phase.\n *\n * Note: In the Rust implementation, the registry doesn't track pending ARIDs\n * directly on participant records. The pending state is managed through the\n * start.json and commitments.json files in the signing state directory.\n *\n * This function is provided for API compatibility but currently does nothing.\n */\nexport function updatePendingForShare(\n _registry: Registry,\n _collection: CollectionResult<SignRound1ResponseData>,\n _startState: StartState,\n): void {\n // No-op: The Rust implementation manages pending state through files,\n // not through the registry. The share_arid values are already stored\n // in commitments.json and will be used for round 2 collection.\n}\n\n/**\n * Execute the sign coordinator round 1 command.\n *\n * Collects signing commitments from participants.\n *\n * Port of `round1()` from cmd/sign/coordinator/round1.rs.\n */\nexport async function round1(\n client: StorageClient,\n options: SignRound1Options,\n cwd: string,\n): Promise<SignRound1Result> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const sessionId = parseAridUr(options.sessionId);\n const groupHint = options.groupId !== undefined ? parseAridUr(options.groupId) : undefined;\n\n const startState = loadStartState(registryPath, sessionId, groupHint);\n const groupId = startState.groupId;\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n if (groupRecord.coordinator().xid().urString() !== owner.xid().urString()) {\n throw new Error(\n `Only the coordinator can collect signInvite responses. ` +\n `Coordinator: ${groupRecord.coordinator().xid().urString()}, ` +\n `Owner: ${owner.xid().urString()}`,\n );\n }\n\n if (options.parallel === true) {\n // Parallel path with progress display\n const collection = await collectCommitmentsParallel(\n client,\n registry,\n startState,\n owner.xidDocument(),\n sessionId,\n options.timeoutSeconds,\n );\n\n // Report any failures\n if (collection.rejections.length > 0) {\n console.error();\n console.error(\"Rejections:\");\n for (const [xid, reason] of collection.rejections) {\n console.error(` ${xid.urString()}: ${reason}`);\n }\n }\n if (collection.errors.length > 0) {\n console.error();\n console.error(\"Errors:\");\n for (const [xid, error] of collection.errors) {\n console.error(` ${xid.urString()}: ${error}`);\n }\n }\n if (collection.timeouts.length > 0) {\n console.error();\n console.error(\"Timeouts:\");\n for (const xid of collection.timeouts) {\n console.error(` ${xid.urString()}`);\n }\n }\n\n if (!collection.allSucceeded()) {\n throw new Error(\n `Sign commit collection incomplete: ${collection.successes.length} succeeded, ` +\n `${collection.rejections.length} rejected, ${collection.errors.length} errors, ` +\n `${collection.timeouts.length} timeouts`,\n );\n }\n\n // Build commitments map\n const commitments = new Map<string, unknown>();\n for (const [xid, data] of collection.successes) {\n commitments.set(xid.urString(), data.commitments);\n }\n\n // Persist aggregated commitments\n const commitmentsPath = persistCommitments(\n registryPath,\n groupId,\n sessionId,\n startState,\n commitments,\n );\n\n // Dispatch share requests in parallel\n const sendResults = await dispatchShareRequestsParallel(\n client,\n registry,\n owner,\n startState,\n sessionId,\n collection,\n commitments,\n options.previewShare,\n options.verbose,\n );\n\n // Check for send failures\n const failures = sendResults.filter(([_, err]) => err !== null);\n if (failures.length > 0) {\n for (const [xid, error] of failures) {\n if (error !== null) {\n console.error(`Failed to send to ${xid.urString()}: ${error.message}`);\n }\n }\n throw new Error(`Failed to send signRound2 requests to ${failures.length} participants`);\n }\n\n // Update registry pending requests\n updatePendingForShare(registry, collection, startState);\n\n const displayPath = path.relative(cwd, commitmentsPath) || commitmentsPath;\n\n if (isVerbose() || options.verbose === true) {\n console.error();\n console.error(\n `Collected ${collection.successes.length} signInvite responses. Saved to ${displayPath}`,\n );\n console.error(`Dispatched ${collection.successes.length} signRound2 requests.`);\n }\n\n return {\n accepted: collection.successes.length,\n rejected: collection.rejections.length,\n errors: collection.errors.length,\n timeouts: collection.timeouts.length,\n };\n } else {\n // Sequential path (original behavior)\n if (isVerbose() || options.verbose === true) {\n console.error(\n `Collecting signInvite responses for session ${sessionId.urString()} ` +\n `from ${startState.participants.size} participants...`,\n );\n }\n\n const commitments = new Map<string, unknown>();\n const sendToArids = new Map<string, ARID>();\n const errors: [XID, string][] = [];\n\n const coordinatorKeys = owner.xidDocument().inceptionPrivateKeys();\n if (coordinatorKeys === undefined) {\n throw new Error(\"Coordinator XID document has no inception private keys\");\n }\n\n for (const [xidStr, participantState] of startState.participants) {\n const xid = XIDClass.fromURString(xidStr);\n const participant = registry.participant(xid);\n const participantName = participant?.petName() ?? xidStr;\n\n try {\n const envelope = await client.get(participantState.commitArid, options.timeoutSeconds);\n\n if (envelope === undefined) {\n throw new Error(\"Response not found in Hubert storage\");\n }\n\n const data = validateAndExtractCommitResponse(envelope, coordinatorKeys, xid, sessionId);\n\n commitments.set(xidStr, data.commitments);\n sendToArids.set(xidStr, data.nextRequestArid);\n\n if (isVerbose() || options.verbose === true) {\n console.error(` ✓ ${participantName}`);\n }\n } catch (e) {\n errors.push([xid, e instanceof Error ? e.message : String(e)]);\n if (isVerbose() || options.verbose === true) {\n console.error(` ✗ ${participantName}: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n }\n\n if (errors.length > 0) {\n throw new Error(\n `Sign commit collection incomplete: ${errors.length} of ${startState.participants.size} responses failed`,\n );\n }\n\n if (commitments.size !== startState.participants.size) {\n const missing: string[] = [];\n for (const xidStr of startState.participants.keys()) {\n if (!commitments.has(xidStr)) {\n missing.push(xidStr);\n }\n }\n throw new Error(`Missing signInvite responses from: ${missing.join(\", \")}`);\n }\n\n // Persist aggregated commitments\n const commitmentsPath = persistCommitments(\n registryPath,\n groupId,\n sessionId,\n startState,\n commitments,\n );\n\n // Build and send signRound2 requests\n const signerKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerKeys === undefined) {\n throw new Error(\"Owner XID document has no inception private keys\");\n }\n const validUntil = new Date(Date.now() + 60 * 60 * 1000);\n\n if (isVerbose() || options.verbose === true) {\n console.error(`Dispatching signRound2 requests to ${sendToArids.size} participants...`);\n } else {\n // Blank line to separate get phase from put phase\n console.error();\n }\n\n let previewPrinted = false;\n for (const [xidStr, sendToArid] of sendToArids) {\n const xid = XIDClass.fromURString(xidStr);\n const participantState = startState.participants.get(xidStr);\n if (participantState === undefined) {\n throw new Error(`Participant state not found for ${xidStr}`);\n }\n const participant = registry.participant(xid);\n const participantName = participant?.petName() ?? xidStr;\n\n let recipientDoc: XIDDocument;\n if (xidStr === owner.xid().urString()) {\n recipientDoc = owner.xidDocument();\n } else {\n const record = registry.participant(xid);\n if (record === undefined) {\n throw new Error(`Participant ${xidStr} not found in registry`);\n }\n recipientDoc = record.xidDocument();\n }\n\n const request = buildShareRequestForParticipant(\n owner.xidDocument(),\n groupId,\n sessionId,\n participantState.shareArid,\n commitments,\n );\n\n if (options.previewShare === true && !previewPrinted) {\n const preview = request.toEnvelope(validUntil, signerKeys, undefined);\n console.log(`# signRound2 preview for ${xidStr}`);\n console.log(preview.format());\n previewPrinted = true;\n }\n\n const sealedEnvelope = request.toEnvelopeForRecipients(validUntil, signerKeys, [\n recipientDoc,\n ]);\n\n await client.put(sendToArid, sealedEnvelope);\n\n if (isVerbose() || options.verbose === true) {\n console.error(` ✓ ${participantName}`);\n }\n }\n\n const displayPath = path.relative(cwd, commitmentsPath) || commitmentsPath;\n\n if (isVerbose() || options.verbose === true) {\n console.error();\n console.error(`Collected ${commitments.size} signInvite responses. Saved to ${displayPath}`);\n console.error(`Dispatched ${commitments.size} signRound2 requests.`);\n }\n\n return {\n accepted: commitments.size,\n rejected: 0,\n errors: errors.length,\n timeouts: 0,\n };\n }\n}\n","/**\n * Sign coordinator round 2 command.\n *\n * Port of cmd/sign/coordinator/round2.rs from frost-hubert-rust.\n *\n * @module\n */\n\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport {\n type ARID,\n type XID,\n XID as XIDClass,\n ARID as ARIDClass,\n Signature,\n type PrivateKeys,\n JSON as JSONComponent,\n} from \"@bcts/components\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { type XIDDocument } from \"@bcts/xid\";\n\nimport { Registry, resolveRegistryPath } from \"../../../registry/index.js\";\nimport { parallelFetch, parallelSend, type CollectionResult } from \"../../parallel.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { parseAridUr, signingKeyFromVerifying } from \"../../dkg/common.js\";\nimport { signingStateDir, SignFinalizeContent } from \"../common.js\";\nimport { putWithIndicator } from \"../../busy.js\";\nimport {\n aggregateSignatures,\n createSigningPackage,\n deserializeSigningCommitments,\n deserializeSignatureShare,\n deserializePublicKeyPackage,\n identifierFromU16,\n serializeSignature,\n serializeSignatureShare,\n type SerializedPublicKeyPackage,\n type SerializedSigningCommitments,\n type FrostIdentifier,\n type Ed25519SigningCommitments,\n type Ed25519SignatureShare,\n type FrostPublicKeyPackage,\n} from \"../../../frost/index.js\";\n\n/**\n * Options for the sign round2 command.\n */\nexport interface SignRound2Options {\n registryPath?: string;\n groupId?: string;\n sessionId: string;\n parallel?: boolean;\n timeoutSeconds?: number;\n previewFinalize?: boolean;\n verbose?: boolean;\n}\n\n/**\n * Result of the sign round2 command.\n */\nexport interface SignRound2Result {\n signature: string;\n signedEnvelope: string;\n accepted: number;\n rejected: number;\n errors: number;\n timeouts: number;\n}\n\n/**\n * Data extracted from a successful signature share response.\n *\n * Port of `struct SignRound2ResponseData` from cmd/sign/coordinator/round2.rs.\n */\ninterface SignRound2ResponseData {\n signatureShare: Ed25519SignatureShare;\n finalizeArid: ARID;\n}\n\n/**\n * State loaded from start.json.\n *\n * Port of `struct StartState` from cmd/sign/coordinator/round2.rs.\n */\ninterface StartState {\n groupId: ARID;\n minSigners: number;\n participants: XID[];\n targetUr: string;\n}\n\n/**\n * Individual participant's commitment data.\n *\n * Port of `struct ParticipantCommitment` from cmd/sign/coordinator/round2.rs.\n */\ninterface ParticipantCommitment {\n commitments: Ed25519SigningCommitments;\n shareArid: ARID;\n}\n\n/**\n * State loaded from commitments.json.\n *\n * Port of `struct CommitmentsState` from cmd/sign/coordinator/round2.rs.\n */\ninterface CommitmentsState {\n commitments: Map<string, ParticipantCommitment>; // XID UR string -> commitment\n}\n\n/**\n * Validate envelope and extract signature share data (for parallel fetch).\n *\n * Port of `validate_and_extract_share_response()` from cmd/sign/coordinator/round2.rs.\n */\nfunction validateAndExtractShareResponse(\n envelope: Envelope,\n _coordinatorKeys: PrivateKeys,\n expectedSender: XID,\n expectedSessionId: ARID,\n): SignRound2ResponseData | { rejected: string } {\n // In the full implementation, we would decrypt the sealed response here\n // For now, we extract the data from the envelope directly\n\n try {\n // Check the response type\n envelope.checkSubjectUnit();\n envelope.checkType(\"signRound2Response\");\n\n // Extract session ID using objectsForPredicate and then extract subjects\n const sessionObjects = envelope.objectsForPredicate(\"session\");\n if (sessionObjects.length === 0) {\n return { rejected: \"Missing session in response\" };\n }\n const responseSession = ARIDClass.fromTaggedCbor(sessionObjects[0].subject().tryLeaf());\n if (responseSession.urString() !== expectedSessionId.urString()) {\n return {\n rejected: `Response session ${responseSession.urString()} does not match expected ${expectedSessionId.urString()}`,\n };\n }\n\n // Extract participant XID (sender check)\n const participantObjects = envelope.objectsForPredicate(\"participant\");\n if (participantObjects.length === 0) {\n return { rejected: \"Missing participant in response\" };\n }\n const participantXid = XIDClass.fromTaggedCbor(participantObjects[0].subject().tryLeaf());\n if (participantXid.urString() !== expectedSender.urString()) {\n return {\n rejected: `Unexpected response sender: ${participantXid.urString()} (expected ${expectedSender.urString()})`,\n };\n }\n\n // Extract signature share (JSON-serialized)\n const shareObjects = envelope.objectsForPredicate(\"signature_share\");\n if (shareObjects.length === 0) {\n return { rejected: \"Missing signature_share in response\" };\n }\n const signatureShareJson = JSONComponent.fromTaggedCbor(shareObjects[0].subject().tryLeaf());\n const signatureShareData = JSON.parse(signatureShareJson.toString()) as { share: string };\n const signatureShare = deserializeSignatureShare(signatureShareData.share);\n\n // Extract finalize ARID (response_arid)\n const responseAridObjects = envelope.objectsForPredicate(\"response_arid\");\n if (responseAridObjects.length === 0) {\n return { rejected: \"Missing response_arid in response\" };\n }\n const finalizeArid = ARIDClass.fromTaggedCbor(responseAridObjects[0].subject().tryLeaf());\n\n return { signatureShare, finalizeArid };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { rejected: `Failed to parse response: ${message}` };\n }\n}\n\n/**\n * Collect signature shares in parallel with progress display.\n *\n * Port of `collect_shares_parallel()` from cmd/sign/coordinator/round2.rs.\n */\nasync function collectSharesParallel(\n client: StorageClient,\n registry: Registry,\n commitmentsState: CommitmentsState,\n coordinator: XIDDocument,\n sessionId: ARID,\n timeoutSeconds?: number,\n): Promise<CollectionResult<SignRound2ResponseData>> {\n // Build requests from commitments\n const requests: [XID, ARID, string][] = [];\n\n for (const [xidUr, entry] of commitmentsState.commitments) {\n const xid = XIDClass.fromURString(xidUr);\n const participant = registry.participant(xid);\n const name = participant?.petName() ?? xid.urString();\n requests.push([xid, entry.shareArid, name]);\n }\n\n const coordinatorKeys = coordinator.inceptionPrivateKeys();\n if (!coordinatorKeys) {\n throw new Error(\"Coordinator XID document has no inception private keys\");\n }\n\n const session = sessionId;\n\n return parallelFetch(\n client,\n requests,\n (envelope: Envelope, xid: XID) => {\n return validateAndExtractShareResponse(envelope, coordinatorKeys, xid, session);\n },\n {\n timeoutSeconds,\n verbose: false,\n },\n );\n}\n\n/**\n * Build a finalize event containing all signature shares.\n *\n * Port of `build_finalize_event()` from cmd/sign/coordinator/round2.rs.\n */\nfunction buildFinalizeEvent(\n _sender: XIDDocument,\n sessionId: ARID,\n signatureSharesByXid: Map<string, Ed25519SignatureShare>,\n): SignFinalizeContent {\n // Build the content with session and all signature shares\n let content = SignFinalizeContent.new().addAssertion(\"session\", sessionId);\n\n for (const [xidUr, share] of signatureSharesByXid) {\n const xid = XIDClass.fromURString(xidUr);\n const shareHex = serializeSignatureShare(share);\n const shareJson = JSONComponent.fromString(JSON.stringify({ share: shareHex }));\n const entry = Envelope.new(xid).addAssertion(\"share\", shareJson);\n content = content.addAssertion(\"signature_share\", entry);\n }\n\n return content;\n}\n\n/**\n * Aggregate signature shares and verify the result.\n *\n * Port of signature aggregation logic from cmd/sign/coordinator/round2.rs.\n */\nfunction aggregateAndVerifySignature(\n signingCommitments: Map<FrostIdentifier, Ed25519SigningCommitments>,\n signatureSharesByIdentifier: Map<FrostIdentifier, Ed25519SignatureShare>,\n publicKeyPackage: FrostPublicKeyPackage,\n targetDigest: Uint8Array,\n): { signature: Signature; signatureUr: string } {\n // Create signing package\n const signingPackage = createSigningPackage(signingCommitments, targetDigest);\n\n // Aggregate signature shares\n const aggregatedSignature = aggregateSignatures(\n signingPackage,\n signatureSharesByIdentifier,\n publicKeyPackage,\n );\n\n // Serialize the aggregated signature\n const signatureBytes = serializeSignature(aggregatedSignature);\n\n // Verify the signature is 64 bytes\n if (signatureBytes.length !== 64) {\n throw new Error(\"Aggregated signature is not 64 bytes\");\n }\n\n // Create bc-components Signature\n const signature = Signature.ed25519FromData(signatureBytes);\n const signatureUr = signature.urString();\n\n return { signature, signatureUr };\n}\n\n/**\n * Persist final signing state to disk.\n *\n * Port of `persist_final_state()` from cmd/sign/coordinator/round2.rs.\n */\nfunction persistSigningState(\n registryPath: string,\n groupId: ARID,\n sessionId: ARID,\n signature: Signature,\n signatureSharesByXid: Map<string, Ed25519SignatureShare>,\n finalizeArids: Map<string, ARID>,\n): void {\n const dir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n fs.mkdirSync(dir, { recursive: true });\n\n // Build signature shares JSON object\n const sharesJson: Record<string, unknown> = {};\n for (const [xidUr, share] of signatureSharesByXid) {\n sharesJson[xidUr] = { share: serializeSignatureShare(share) };\n }\n\n // Build finalize ARIDs JSON object\n const finalizeJson: Record<string, string> = {};\n for (const [xidUr, arid] of finalizeArids) {\n finalizeJson[xidUr] = arid.urString();\n }\n\n // Build root JSON object\n const root = {\n group: groupId.urString(),\n session: sessionId.urString(),\n signature: signature.urString(),\n signature_shares: sharesJson,\n finalize_arids: finalizeJson,\n };\n\n fs.writeFileSync(path.join(dir, \"final.json\"), JSON.stringify(root, null, 2));\n}\n\n/**\n * Load start state from disk.\n *\n * Port of `load_start_state()` from cmd/sign/coordinator/round2.rs.\n */\nfunction loadStartState(registryPath: string, sessionId: ARID, groupHint?: ARID): StartState {\n const base = path.dirname(registryPath);\n const groupStateDir = path.join(base, \"group-state\");\n\n // Find candidate paths\n const candidatePaths: [ARID, string][] = [];\n let groupDirs: [ARID, string][];\n\n if (groupHint) {\n groupDirs = [[groupHint, path.join(groupStateDir, groupHint.hex())]];\n } else {\n groupDirs = [];\n if (fs.existsSync(groupStateDir)) {\n for (const entry of fs.readdirSync(groupStateDir, { withFileTypes: true })) {\n if (entry.isDirectory() && entry.name.length === 64 && /^[0-9a-f]+$/i.test(entry.name)) {\n const groupId = ARIDClass.fromHex(entry.name);\n groupDirs.push([groupId, path.join(groupStateDir, entry.name)]);\n }\n }\n }\n }\n\n for (const [groupId, groupDir] of groupDirs) {\n const candidate = path.join(groupDir, \"signing\", sessionId.hex(), \"start.json\");\n if (fs.existsSync(candidate)) {\n candidatePaths.push([groupId, candidate]);\n }\n }\n\n if (candidatePaths.length === 0) {\n throw new Error(\"No sign start state found; run `frost sign coordinator start` first\");\n }\n if (candidatePaths.length > 1) {\n throw new Error(\"Multiple signing sessions found; specify --group to disambiguate\");\n }\n\n const [groupId, statePath] = candidatePaths[0];\n const raw = JSON.parse(fs.readFileSync(statePath, \"utf-8\")) as Record<string, unknown>;\n\n const getStr = (key: string): string => {\n const value = raw[key];\n if (typeof value !== \"string\") {\n throw new Error(`Missing or invalid ${key} in start.json`);\n }\n return value;\n };\n\n const sessionInState = parseAridUr(getStr(\"session_id\"));\n const groupInState = parseAridUr(getStr(\"group\"));\n\n if (sessionInState.urString() !== sessionId.urString()) {\n throw new Error(\n `start.json session ${sessionInState.urString()} does not match requested session ${sessionId.urString()}`,\n );\n }\n if (groupInState.urString() !== groupId.urString()) {\n throw new Error(\n `start.json group ${groupInState.urString()} does not match directory group ${groupId.urString()}`,\n );\n }\n\n const minSigners = raw[\"min_signers\"];\n if (typeof minSigners !== \"number\") {\n throw new Error(\"Missing min_signers in start.json\");\n }\n\n const participantsVal = raw[\"participants\"] as Record<string, unknown> | undefined;\n if (!participantsVal || typeof participantsVal !== \"object\") {\n throw new Error(\"Missing participants in start.json\");\n }\n\n const participants: XID[] = [];\n for (const xidStr of Object.keys(participantsVal)) {\n participants.push(XIDClass.fromURString(xidStr));\n }\n participants.sort((a, b) => a.urString().localeCompare(b.urString()));\n\n const targetUr = getStr(\"target\");\n\n return { groupId, minSigners, participants, targetUr };\n}\n\n/**\n * Load commitments state from disk.\n *\n * Port of `load_commitments_state()` from cmd/sign/coordinator/round2.rs.\n */\nfunction loadCommitmentsState(\n registryPath: string,\n groupId: ARID,\n sessionId: ARID,\n): CommitmentsState {\n const dir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n const statePath = path.join(dir, \"commitments.json\");\n\n if (!fs.existsSync(statePath)) {\n throw new Error(\n `Commitments not found at ${statePath}. Run \\`frost sign coordinator collect\\` first`,\n );\n }\n\n const raw = JSON.parse(fs.readFileSync(statePath, \"utf-8\")) as Record<string, unknown>;\n\n const getStr = (key: string): string => {\n const value = raw[key];\n if (typeof value !== \"string\") {\n throw new Error(`Missing or invalid ${key} in commitments.json`);\n }\n return value;\n };\n\n const sessionInState = parseAridUr(getStr(\"session\"));\n if (sessionInState.urString() !== sessionId.urString()) {\n throw new Error(\n `commitments.json session ${sessionInState.urString()} does not match requested session ${sessionId.urString()}`,\n );\n }\n\n const commitmentsVal = raw[\"commitments\"] as Record<string, unknown> | undefined;\n if (!commitmentsVal || typeof commitmentsVal !== \"object\") {\n throw new Error(\"Missing commitments map in commitments.json\");\n }\n\n const commitments = new Map<string, ParticipantCommitment>();\n\n for (const [xidStr, value] of Object.entries(commitmentsVal)) {\n const obj = value as Record<string, unknown>;\n const commitValue = obj[\"commitments\"] as SerializedSigningCommitments | undefined;\n if (!commitValue) {\n throw new Error(\"Missing commitments value in commitments.json\");\n }\n const commitmentsDeserialized = deserializeSigningCommitments(commitValue);\n\n const shareAridRaw = obj[\"share_arid\"];\n if (typeof shareAridRaw !== \"string\") {\n throw new Error(\"Missing share_arid in commitments.json\");\n }\n const shareArid = parseAridUr(shareAridRaw);\n\n commitments.set(xidStr, {\n commitments: commitmentsDeserialized,\n shareArid,\n });\n }\n\n return { commitments };\n}\n\n/**\n * Load public key package from collected_finalize.json.\n *\n * Port of `load_public_key_package()` from cmd/sign/coordinator/round2.rs.\n */\nfunction loadPublicKeyPackage(registryPath: string, groupId: ARID): FrostPublicKeyPackage {\n const base = path.dirname(registryPath);\n const pkgPath = path.join(base, \"group-state\", groupId.hex(), \"collected_finalize.json\");\n\n if (!fs.existsSync(pkgPath)) {\n throw new Error(\n `collected_finalize.json not found at ${pkgPath}. Run \\`frost dkg coordinator finalize collect\\` first`,\n );\n }\n\n const raw = JSON.parse(fs.readFileSync(pkgPath, \"utf-8\")) as Record<string, unknown>;\n const firstEntry = Object.values(raw)[0] as Record<string, unknown> | undefined;\n\n if (!firstEntry) {\n throw new Error(\"collected_finalize.json is empty\");\n }\n\n const publicKeyValue = firstEntry[\"public_key_package\"] as SerializedPublicKeyPackage | undefined;\n if (!publicKeyValue) {\n throw new Error(\"public_key_package missing in collected_finalize.json\");\n }\n\n return deserializePublicKeyPackage(publicKeyValue);\n}\n\n/**\n * Build a map from XID to FROST identifier.\n *\n * Port of `xid_identifier_map()` from cmd/sign/coordinator/round2.rs.\n */\nfunction xidIdentifierMap(participants: XID[]): Map<string, FrostIdentifier> {\n const map = new Map<string, FrostIdentifier>();\n for (let i = 0; i < participants.length; i++) {\n const identifier = identifierFromU16(i + 1);\n map.set(participants[i].urString(), identifier);\n }\n return map;\n}\n\n/**\n * Build signing commitments with identifiers.\n *\n * Port of `commitments_with_identifiers()` from cmd/sign/coordinator/round2.rs.\n */\nfunction commitmentsWithIdentifiers(\n commitments: Map<string, ParticipantCommitment>,\n xidToIdentifier: Map<string, FrostIdentifier>,\n): Map<FrostIdentifier, Ed25519SigningCommitments> {\n const mapped = new Map<FrostIdentifier, Ed25519SigningCommitments>();\n for (const [xidUr, entry] of commitments) {\n const identifier = xidToIdentifier.get(xidUr);\n if (!identifier) {\n throw new Error(`Unknown participant ${xidUr}`);\n }\n mapped.set(identifier, entry.commitments);\n }\n return mapped;\n}\n\n/**\n * Execute the sign coordinator round 2 command.\n *\n * Collects signature shares, aggregates the signature, and posts finalize packages.\n *\n * Port of `CommandArgs::exec()` from cmd/sign/coordinator/round2.rs.\n */\nexport async function round2(\n client: StorageClient,\n options: SignRound2Options,\n cwd: string,\n): Promise<SignRound2Result> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (!owner) {\n throw new Error(\"Registry owner is required\");\n }\n\n const sessionId = parseAridUr(options.sessionId);\n const groupHint = options.groupId ? parseAridUr(options.groupId) : undefined;\n\n // Load start state (finds group automatically if not specified)\n const startState = loadStartState(registryPath, sessionId, groupHint);\n const groupId = startState.groupId;\n\n const groupRecord = registry.group(groupId);\n if (!groupRecord) {\n throw new Error(\"Group not found in registry\");\n }\n\n // Verify coordinator ownership\n if (groupRecord.coordinator().xid().urString() !== owner.xid().urString()) {\n throw new Error(\n `Only the coordinator can finalize signing. Coordinator: ${groupRecord.coordinator().xid().urString()}, Owner: ${owner.xid().urString()}`,\n );\n }\n\n // Load commitments state\n const commitmentsState = loadCommitmentsState(registryPath, groupId, sessionId);\n\n // Build XID to identifier map\n const xidToIdentifier = xidIdentifierMap(startState.participants);\n\n // Collect signature shares\n let signatureSharesByIdentifier: Map<FrostIdentifier, Ed25519SignatureShare>;\n let signatureSharesByXid: Map<string, Ed25519SignatureShare>;\n let finalizeArids: Map<string, ARID>;\n\n if (options.parallel === true) {\n // Parallel collection path\n const collection = await collectSharesParallel(\n client,\n registry,\n commitmentsState,\n owner.xidDocument(),\n sessionId,\n options.timeoutSeconds,\n );\n\n if (!collection.allSucceeded()) {\n // Report failures\n if (collection.rejections.length > 0) {\n console.error(\"\\nRejections:\");\n for (const [xid, reason] of collection.rejections) {\n console.error(` ${xid.urString()}: ${reason}`);\n }\n }\n if (collection.errors.length > 0) {\n console.error(\"\\nErrors:\");\n for (const [xid, error] of collection.errors) {\n console.error(` ${xid.urString()}: ${error}`);\n }\n }\n if (collection.timeouts.length > 0) {\n console.error(\"\\nTimeouts:\");\n for (const xid of collection.timeouts) {\n console.error(` ${xid.urString()}`);\n }\n }\n throw new Error(\n `Signature share collection incomplete: ${collection.successes.length} succeeded, ` +\n `${collection.rejections.length} rejected, ${collection.errors.length} errors, ` +\n `${collection.timeouts.length} timeouts`,\n );\n }\n\n // Convert collection to maps\n signatureSharesByIdentifier = new Map();\n signatureSharesByXid = new Map();\n finalizeArids = new Map();\n\n for (const [xid, data] of collection.successes) {\n const xidUr = xid.urString();\n const identifier = xidToIdentifier.get(xidUr);\n if (!identifier) {\n throw new Error(\"Identifier mapping missing for participant\");\n }\n signatureSharesByIdentifier.set(identifier, data.signatureShare);\n signatureSharesByXid.set(xidUr, data.signatureShare);\n finalizeArids.set(xidUr, data.finalizeArid);\n }\n } else {\n // Sequential collection path\n if (options.verbose === true) {\n console.error(\n `Collecting signature shares for session ${sessionId.urString()} from ${commitmentsState.commitments.size} participants...`,\n );\n }\n\n signatureSharesByIdentifier = new Map();\n signatureSharesByXid = new Map();\n finalizeArids = new Map();\n\n for (const [xidUr, entry] of commitmentsState.commitments) {\n const xid = XIDClass.fromURString(xidUr);\n const participant = registry.participant(xid);\n const participantName = participant?.petName() ?? xid.urString();\n\n const identifier = xidToIdentifier.get(xidUr);\n if (!identifier) {\n throw new Error(\"Identifier mapping missing for participant\");\n }\n\n // Fetch the response\n const envelope = await client.get(entry.shareArid, options.timeoutSeconds);\n if (!envelope) {\n throw new Error(`Signature share response not found for ${participantName}`);\n }\n\n const coordinatorKeys = owner.xidDocument().inceptionPrivateKeys();\n if (!coordinatorKeys) {\n throw new Error(\"Coordinator XID document has no inception private keys\");\n }\n\n const result = validateAndExtractShareResponse(envelope, coordinatorKeys, xid, sessionId);\n if (\"rejected\" in result) {\n throw new Error(`Participant rejected signRound2: ${result.rejected}`);\n }\n\n signatureSharesByIdentifier.set(identifier, result.signatureShare);\n signatureSharesByXid.set(xidUr, result.signatureShare);\n finalizeArids.set(xidUr, result.finalizeArid);\n }\n }\n\n // Verify we have enough shares\n if (signatureSharesByIdentifier.size < startState.minSigners) {\n throw new Error(\n `Only collected ${signatureSharesByIdentifier.size} signature shares, need at least ${startState.minSigners}`,\n );\n }\n\n // Build signing commitments with identifiers\n const signingCommitments = commitmentsWithIdentifiers(\n commitmentsState.commitments,\n xidToIdentifier,\n );\n\n // Get target digest\n const targetEnvelope = Envelope.fromURString(startState.targetUr);\n const targetDigest = targetEnvelope.subject().digest().data();\n\n // Load public key package\n const publicKeyPackage = loadPublicKeyPackage(registryPath, groupId);\n const verifyingKey = signingKeyFromVerifying(publicKeyPackage.verifyingKey);\n\n // Aggregate and verify signature\n const { signature, signatureUr } = aggregateAndVerifySignature(\n signingCommitments,\n signatureSharesByIdentifier,\n publicKeyPackage,\n targetDigest,\n );\n\n // Verify signature against target digest\n // @ts-expect-error - verifyingKey type mismatch\n if (verifyingKey.verify(signature, targetDigest) !== true) {\n throw new Error(\"Aggregated signature failed verification against target digest\");\n }\n\n // Attach signature to target and verify\n\n const signedEnvelope = Envelope.fromURString(startState.targetUr).addAssertion(\n \"signed\",\n signature,\n );\n const signedEnvelopeUr = signedEnvelope.urString();\n\n // Persist final state\n persistSigningState(\n registryPath,\n groupId,\n sessionId,\n signature,\n signatureSharesByXid,\n finalizeArids,\n );\n\n if (options.verbose === true) {\n console.error();\n console.error(\n `Aggregated signature for session ${sessionId.urString()} and prepared ${finalizeArids.size} finalize packages.`,\n );\n console.error(\"Signature verified against target and group key.\");\n }\n\n // Dispatch finalize events to participants\n const signerKeys = owner.xidDocument().inceptionPrivateKeys();\n if (!signerKeys) {\n throw new Error(\"Coordinator XID document has no signing keys\");\n }\n\n if (options.verbose === true) {\n console.error(`Dispatching finalize packages to ${finalizeArids.size} participants...`);\n } else {\n // Blank line to separate get phase from put phase\n console.error();\n }\n\n // Build finalize messages\n const messages: [XID, ARID, Envelope, string][] = [];\n let previewPrinted = false;\n\n for (const [xidUr, finalizeArid] of finalizeArids) {\n const participantXid = XIDClass.fromURString(xidUr);\n const participant = registry.participant(participantXid);\n const participantName = participant?.petName() ?? xidUr;\n\n const recipientDoc =\n xidUr === owner.xid().urString() ? owner.xidDocument() : participant?.xidDocument();\n\n if (!recipientDoc) {\n throw new Error(`Participant ${xidUr} not found in registry`);\n }\n\n const event = buildFinalizeEvent(owner.xidDocument(), sessionId, signatureSharesByXid);\n\n if (options.previewFinalize === true && !previewPrinted) {\n // Preview as unsigned, unencrypted envelope\n console.log(`# signFinalize preview for ${participantXid.urString()}`);\n console.log(event.envelope().format());\n previewPrinted = true;\n }\n\n // For now, use the plain envelope (GSTP sealing would be applied in full implementation)\n const sealed = event.envelope();\n\n messages.push([participantXid, finalizeArid, sealed, participantName]);\n }\n\n // Dispatch messages\n if (options.parallel === true) {\n // Parallel send\n console.error();\n const results = await parallelSend(client, messages, options.verbose === true);\n\n // Check for errors\n const errors: string[] = [];\n for (const [xid, result] of results) {\n if (result !== null) {\n const participant = registry.participant(xid);\n const name = participant?.petName() ?? xid.urString();\n errors.push(`${name}: ${result.message}`);\n }\n }\n if (errors.length > 0) {\n throw new Error(`Failed to send finalize packages: ${errors.join(\"; \")}`);\n }\n } else {\n // Sequential send\n for (const [_xid, finalizeArid, sealed, participantName] of messages) {\n await putWithIndicator(\n client,\n finalizeArid,\n sealed,\n participantName,\n options.verbose ?? false,\n );\n }\n }\n\n // Print final signature and signed envelope UR\n console.log(signatureUr);\n console.log(signedEnvelopeUr);\n\n return {\n signature: signatureUr,\n signedEnvelope: signedEnvelopeUr,\n accepted: signatureSharesByIdentifier.size,\n rejected: 0,\n errors: 0,\n timeouts: 0,\n };\n}\n","/**\n * Sign coordinator commands.\n *\n * Port of cmd/sign/coordinator/mod.rs from frost-hubert-rust.\n *\n * @module\n */\n\nexport * from \"./invite.js\";\nexport * from \"./round1.js\";\nexport * from \"./round2.js\";\n","/**\n * Sign participant receive command.\n *\n * Port of cmd/sign/participant/receive.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { type ARID, type XID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport type { Envelope } from \"@bcts/envelope\";\n\nimport { Registry, resolveRegistryPath, type OwnerRecord } from \"../../../registry/index.js\";\nimport { getWithIndicator } from \"../../busy.js\";\nimport { type StorageClient, type StorageSelection } from \"../../storage.js\";\nimport { parseAridUr, parseEnvelopeUr, formatNameWithOwnerMarker } from \"../../dkg/common.js\";\nimport { signingStateDir } from \"../common.js\";\n\n/**\n * Options for the sign receive command.\n */\nexport interface SignReceiveOptions {\n registryPath?: string;\n /** ARID or envelope UR string */\n request: string;\n timeoutSeconds?: number;\n /** Show request details only (info mode) */\n info?: boolean;\n /** Expected sender (XID UR or pet name) */\n sender?: string;\n}\n\n/**\n * Result of the sign receive command.\n */\nexport interface SignReceiveResult {\n sessionId: string;\n groupId: string;\n targetUr: string;\n coordinatorName: string;\n minSigners: number;\n participantNames: string[];\n}\n\n/**\n * Resolve sender from XID UR or pet name in registry.\n *\n * Port of `resolve_sender()` from cmd/dkg/common.rs lines 76-94.\n */\nfunction resolveSenderFromInput(registry: Registry, input: string): { xid: () => XID } {\n const trimmed = input.trim();\n if (trimmed === \"\") {\n throw new Error(\"Sender is required\");\n }\n\n // Try parsing as XID UR first\n try {\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef\n const { XID: XIDClass } = require(\"@bcts/components\");\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n const xid = XIDClass.fromURString(trimmed) as XID;\n const record = registry.participant(xid);\n if (!record) {\n throw new Error(`Sender with XID ${xid.urString()} not found`);\n }\n return record.xidDocument();\n } catch {\n // Try looking up by pet name\n const result = registry.participantByPetName(trimmed);\n if (!result) {\n throw new Error(`Sender with pet name '${trimmed}' not found`);\n }\n return result[1].xidDocument();\n }\n}\n\n/**\n * Resolve sign invite from ARID or envelope UR.\n *\n * Port of `resolve_sign_request()` from cmd/sign/participant/receive.rs lines 250-284.\n */\nasync function resolveSignInviteEnvelope(\n client: StorageClient | undefined,\n selection: StorageSelection | undefined,\n request: string,\n timeout: number | undefined,\n): Promise<Envelope> {\n if (selection !== undefined && client !== undefined) {\n // Try to parse as ARID\n try {\n const arid = parseAridUr(request);\n const envelope = await getWithIndicator(client, arid, \"Sign invite\", timeout, false);\n if (envelope === undefined || envelope === null) {\n throw new Error(\"signInvite request not found in Hubert storage\");\n }\n return envelope;\n } catch {\n // Not an ARID, try as envelope\n }\n\n if (timeout !== undefined) {\n throw new Error(\"--timeout is only valid when retrieving requests from Hubert\");\n }\n return parseEnvelopeUr(request);\n }\n\n // No storage selection\n try {\n parseAridUr(request);\n throw new Error(\"Hubert storage parameters are required to retrieve requests by ARID\");\n } catch (e) {\n if (e instanceof Error && e.message.includes(\"Hubert storage parameters\")) {\n throw e;\n }\n // Not an ARID, parse as envelope\n }\n return parseEnvelopeUr(request);\n}\n\n/**\n * Get display name for sender from registry.\n *\n * Port of `resolve_sender_name()` from cmd/dkg/common.rs lines 96-116.\n */\nfunction resolveSenderName(registry: Registry, senderXid: XID): string | undefined {\n const owner = registry.owner();\n\n // Check if sender is the owner\n if (owner?.xid().urString() === senderXid.urString()) {\n const name = owner.petName() ?? senderXid.urString();\n return formatNameWithOwnerMarker(name, true);\n }\n\n // Look up in participants\n const record = registry.participant(senderXid);\n if (record) {\n const name = record.petName() ?? record.xid().urString();\n return formatNameWithOwnerMarker(name, false);\n }\n\n return undefined;\n}\n\n/**\n * Format participant names with owner marker.\n *\n * Port of `format_participant_names()` from cmd/sign/participant/receive.rs lines 286-309.\n */\nfunction formatParticipantNames(\n registry: Registry,\n participants: XID[],\n owner: OwnerRecord,\n): string[] {\n return participants.map((xid) => {\n const isOwner = xid.urString() === owner.xid().urString();\n let name: string;\n\n if (isOwner) {\n name = owner.petName() ?? xid.urString();\n } else {\n const record = registry.participant(xid);\n name = record?.petName() ?? xid.urString();\n }\n\n return formatNameWithOwnerMarker(name, isOwner);\n });\n}\n\n/**\n * Execute the sign participant receive command.\n *\n * Fetches and validates a sign invite from the coordinator.\n *\n * Port of `CommandArgs::exec()` from cmd/sign/participant/receive.rs lines 56-247.\n */\nexport async function receive(\n client: StorageClient | undefined,\n selection: StorageSelection | undefined,\n options: SignReceiveOptions,\n cwd: string,\n): Promise<SignReceiveResult> {\n // Validate timeout requires storage\n if (selection === undefined && options.timeoutSeconds !== undefined) {\n throw new Error(\"--timeout requires Hubert storage parameters\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n const owner = registry.owner();\n\n if (!owner) {\n throw new Error(\"Registry owner with private keys is required\");\n }\n\n // Resolve expected sender if provided\n let expectedSender: { xid: () => XID } | undefined;\n if (options.sender !== undefined && options.sender !== \"\") {\n expectedSender = resolveSenderFromInput(registry, options.sender);\n }\n\n // Resolve the invite envelope\n const envelope = await resolveSignInviteEnvelope(\n client,\n selection,\n options.request,\n options.timeoutSeconds,\n );\n\n const now: CborDate = CborDate.now();\n const recipientKeys = owner.xidDocument().inceptionPrivateKeys();\n\n if (recipientKeys === null || recipientKeys === undefined) {\n throw new Error(\"Owner XID document has no inception private keys\");\n }\n\n // eslint-disable-next-line @typescript-eslint/no-require-imports, no-undef\n const { SealedRequest: SealedRequestClass } = require(\"@bcts/gstp\") as {\n SealedRequest: {\n tryFromEnvelope: (\n envelope: Envelope,\n expectedSender: XID | undefined,\n now: CborDate,\n recipientPrivateKeys: unknown,\n ) => SealedRequestInstance;\n };\n };\n\n interface SealedRequestInstance {\n sender: () => { xid: () => XID };\n function: () => { equals?: (other: unknown) => boolean; toString?: () => string };\n extractObjectForParameter: <T>(name: string) => T;\n objectForParameter: (name: string) => Envelope;\n objectsForParameter: (name: string) => ParticipantEntry[];\n }\n\n interface ParticipantEntry {\n extractSubject: () => XID;\n objectForPredicate: (name: string) => {\n decryptToRecipient: (keys: unknown) => {\n extractSubject: () => ARID;\n };\n };\n }\n\n const sealedRequest: SealedRequestInstance = SealedRequestClass.tryFromEnvelope(\n envelope,\n undefined,\n now,\n recipientKeys,\n );\n\n // Validate sender\n const senderXid = sealedRequest.sender().xid();\n\n if (expectedSender !== undefined) {\n if (senderXid.urString() !== expectedSender.xid().urString()) {\n throw new Error(\n `Request sender does not match expected sender (got ${senderXid.urString()}, expected ${expectedSender.xid().urString()})`,\n );\n }\n } else {\n const knownOwner = owner.xid().urString() === senderXid.urString();\n const knownParticipant = registry.participant(senderXid) !== undefined;\n if (!knownOwner && !knownParticipant) {\n throw new Error(`Request sender not found in registry: ${senderXid.urString()}`);\n }\n }\n\n // eslint-disable-next-line @typescript-eslint/no-require-imports, no-undef\n const { Function: FunctionClass } = require(\"@bcts/envelope\") as {\n Function: { from: (name: string) => unknown };\n };\n\n // Validate function\n const requestFunction = sealedRequest.function();\n const expectedFunction = FunctionClass.from(\"signInvite\");\n const functionMatches =\n requestFunction.equals !== undefined\n ? requestFunction.equals(expectedFunction)\n : String(requestFunction) === String(expectedFunction);\n\n if (!functionMatches) {\n throw new Error(`Unexpected request function: ${String(requestFunction)}`);\n }\n\n // Extract parameters\n const validUntil = sealedRequest.extractObjectForParameter<CborDate>(\"validUntil\");\n if (validUntil <= now) {\n throw new Error(\"signInvite request has expired\");\n }\n\n const groupId = sealedRequest.extractObjectForParameter<ARID>(\"group\");\n const sessionId = sealedRequest.extractObjectForParameter<ARID>(\"session\");\n const minSigners = Number(sealedRequest.extractObjectForParameter<bigint | number>(\"minSigners\"));\n\n // Extract participants and find our response ARID\n const participantEntries = sealedRequest.objectsForParameter(\"participant\");\n const participants: XID[] = [];\n let responseArid: ARID | undefined;\n\n for (const entry of participantEntries) {\n const xid: XID = entry.extractSubject();\n if (xid.urString() === owner.xid().urString()) {\n const encryptedArid = entry.objectForPredicate(\"response_arid\");\n const aridEnv = encryptedArid.decryptToRecipient(recipientKeys);\n responseArid = aridEnv.extractSubject();\n }\n participants.push(xid);\n }\n\n // Validations\n if (participants.length === 0) {\n throw new Error(\"signInvite request contains no participants\");\n }\n if (minSigners < 2) {\n throw new Error(\"minSigners must be at least 2\");\n }\n if (minSigners > participants.length) {\n throw new Error(\"minSigners exceeds participant count\");\n }\n\n const ownerInParticipants = participants.some((p) => p.urString() === owner.xid().urString());\n if (!ownerInParticipants) {\n throw new Error(\"signInvite request does not include this participant\");\n }\n\n if (responseArid === undefined) {\n throw new Error(\"signInvite request missing response ARID\");\n }\n\n // Sort participants by XID\n participants.sort((a, b) => a.urString().localeCompare(b.urString()));\n\n const targetEnvelope = sealedRequest.objectForParameter(\"target\");\n\n const coordinatorName = resolveSenderName(registry, senderXid) ?? senderXid.urString();\n const participantNames = formatParticipantNames(registry, participants, owner);\n\n // Output\n console.log(`Group: ${groupId.urString()}`);\n console.log(`Coordinator: ${coordinatorName}`);\n console.log(`Min signers: ${minSigners}`);\n console.log(`Participants: ${participantNames.join(\", \")}`);\n console.log(\"Target:\");\n console.log(targetEnvelope.format());\n\n // Primary output for scripting: session ID on its own line (no header)\n console.log(sessionId.urString());\n\n // Persist request details for follow-up commands\n const stateDir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const root: Record<string, unknown> = {\n request_envelope: envelope.urString(),\n group: groupId.urString(),\n session: sessionId.urString(),\n coordinator: senderXid.urString(),\n min_signers: minSigners,\n response_arid: responseArid.urString(),\n participants: participants.map((xid) => xid.urString()),\n target: targetEnvelope.urString(),\n };\n\n fs.writeFileSync(path.join(stateDir, \"sign_receive.json\"), JSON.stringify(root, null, 2));\n\n return {\n sessionId: sessionId.urString(),\n groupId: groupId.urString(),\n targetUr: targetEnvelope.urString(),\n coordinatorName,\n minSigners,\n participantNames,\n };\n}\n","/**\n * Sign participant round 1 command.\n *\n * Port of cmd/sign/participant/round1.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, JSON as JSONWrapper, type PrivateKeys, XID } from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope, Function as EnvelopeFunction } from \"@bcts/envelope\";\nimport { SealedRequest, SealedResponse } from \"@bcts/gstp\";\nimport type { XIDDocument } from \"@bcts/xid\";\n\nimport { Registry, resolveRegistryPath } from \"../../../registry/index.js\";\nimport { putWithIndicator } from \"../../busy.js\";\nimport { createStorageClient, type StorageClient, type StorageSelection } from \"../../storage.js\";\nimport { parseAridUr } from \"../../dkg/common.js\";\nimport { signingStateDir } from \"../common.js\";\nimport {\n signingRound1,\n deserializeKeyPackage,\n serializeSigningNonces,\n serializeSigningCommitments,\n createRng,\n type SerializedKeyPackage,\n type SerializedSigningNonces,\n type SerializedSigningCommitments,\n type Ed25519SigningNonces,\n type Ed25519SigningCommitments,\n} from \"../../../frost/index.js\";\n\n/**\n * Options for the sign round1 command.\n */\nexport interface SignRound1Options {\n registryPath?: string;\n sessionId: string;\n groupId?: string;\n preview?: boolean;\n rejectReason?: string;\n storageSelection?: StorageSelection;\n verbose?: boolean;\n}\n\n/**\n * Result of the sign round1 command.\n */\nexport interface SignRound1Result {\n accepted: boolean;\n listeningArid?: string;\n envelopeUr?: string;\n}\n\n/**\n * Persisted receive state from sign_receive.json.\n *\n * Port of `struct ReceiveState` from cmd/sign/participant/round1.rs.\n */\ninterface ReceiveState {\n groupId: ARID;\n coordinatorDoc: XIDDocument;\n responseArid: ARID;\n targetUr: string;\n participants: XID[];\n requestEnvelope: Envelope;\n}\n\n/**\n * Load receive state from persisted sign_receive.json.\n *\n * Port of `load_receive_state()` from cmd/sign/participant/round1.rs lines 285-411.\n */\nfunction loadReceiveState(\n registryPath: string,\n sessionId: ARID,\n groupHint: ARID | undefined,\n registry: Registry,\n): ReceiveState {\n const base = path.dirname(registryPath);\n const groupStateDir = path.join(base, \"group-state\");\n\n // Collect candidate directories\n let groupDirs: [ARID, string][];\n if (groupHint !== undefined) {\n groupDirs = [[groupHint, path.join(groupStateDir, groupHint.hex())]];\n } else {\n groupDirs = [];\n if (fs.existsSync(groupStateDir)) {\n for (const entry of fs.readdirSync(groupStateDir, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n const dirName = entry.name;\n // Check if it's a 64-character hex string (ARID hex)\n if (dirName.length === 64 && /^[0-9a-fA-F]+$/.test(dirName)) {\n const groupId = ARID.fromHex(dirName);\n groupDirs.push([groupId, path.join(groupStateDir, dirName)]);\n }\n }\n }\n }\n }\n\n // Search for sign_receive.json\n const candidates: [ARID, string][] = [];\n for (const [groupId, groupDir] of groupDirs) {\n const candidate = path.join(groupDir, \"signing\", sessionId.hex(), \"sign_receive.json\");\n if (fs.existsSync(candidate)) {\n candidates.push([groupId, candidate]);\n }\n }\n\n if (candidates.length === 0) {\n throw new Error(\n \"No sign_receive.json found for this session; run `frost sign participant receive` first\",\n );\n }\n if (candidates.length > 1) {\n throw new Error(\"Multiple groups contain this session; use --group to disambiguate\");\n }\n\n const [groupId, filePath] = candidates[0];\n\n // Parse the JSON file\n interface SignReceiveJson {\n session: string;\n group: string;\n response_arid: string;\n target: string;\n coordinator: string;\n participants: string[];\n request_envelope: string;\n }\n\n const raw = JSON.parse(fs.readFileSync(filePath, \"utf-8\")) as SignReceiveJson;\n\n // Validate session matches\n const sessionInState = parseAridUr(raw.session);\n if (sessionInState.urString() !== sessionId.urString()) {\n throw new Error(\n `Session ${sessionInState.urString()} in sign_receive.json does not match requested session ${sessionId.urString()}`,\n );\n }\n\n const responseArid = parseAridUr(raw.response_arid);\n const targetUr = raw.target;\n const coordinatorUr = raw.coordinator;\n const coordinatorXid = XID.fromURString(coordinatorUr);\n\n // Resolve coordinator document from registry\n let coordinatorDoc: XIDDocument;\n const participantRecord = registry.participant(coordinatorXid);\n if (participantRecord !== null && participantRecord !== undefined) {\n coordinatorDoc = participantRecord.xidDocument();\n } else {\n const owner = registry.owner();\n if (owner?.xid().urString() === coordinatorXid.urString()) {\n coordinatorDoc = owner.xidDocument();\n } else {\n throw new Error(\n `Coordinator ${coordinatorXid.urString()} not found in registry and cannot resolve encryption key`,\n );\n }\n }\n\n // Parse request envelope\n const requestEnvelope = Envelope.fromURString(raw.request_envelope);\n\n // Parse participants\n const participants: XID[] = raw.participants.map((s: string) => XID.fromURString(s));\n\n return {\n groupId,\n coordinatorDoc,\n responseArid,\n targetUr,\n participants,\n requestEnvelope,\n };\n}\n\n/**\n * Validate the commit request from persisted state.\n *\n * Port of request validation in `CommandArgs::exec()` from cmd/sign/participant/round1.rs lines 100-138.\n */\nfunction validateCommitRequest(\n receiveState: ReceiveState,\n sessionId: ARID,\n ownerXid: XID,\n ownerPrivateKeys: PrivateKeys,\n): SealedRequest {\n const now = CborDate.now();\n\n // Decrypt and parse the request\n const sealedRequest = SealedRequest.tryFromEnvelope(\n receiveState.requestEnvelope,\n undefined,\n now.datetime(),\n ownerPrivateKeys,\n );\n\n // Validate function\n if (!sealedRequest.request().function().equals(EnvelopeFunction.fromString(\"signInvite\"))) {\n throw new Error(`Unexpected request function: ${String(sealedRequest.request().function())}`);\n }\n\n // Validate session ID\n if (sealedRequest.request().id().urString() !== sessionId.urString()) {\n throw new Error(\n `Session ID mismatch (state ${sessionId.urString()}, request ${sealedRequest.request().id().urString()})`,\n );\n }\n\n // Validate group ID\n const requestGroup = sealedRequest.extractObjectForParameter<ARID>(\"group\");\n if (requestGroup.urString() !== receiveState.groupId.urString()) {\n throw new Error(\n `Group ID mismatch (state ${receiveState.groupId.urString()}, request ${requestGroup.urString()})`,\n );\n }\n\n // Validate participant is included\n const participantUrStrings = receiveState.participants.map((p) => p.urString());\n if (!participantUrStrings.includes(ownerXid.urString())) {\n throw new Error(\"Persisted signInvite request does not include this participant\");\n }\n\n return sealedRequest;\n}\n\n/**\n * Build the response body envelope.\n *\n * Port of response body building from cmd/sign/participant/round1.rs lines 191-195.\n */\nfunction buildResponseBody(\n sessionId: ARID,\n commitments: Ed25519SigningCommitments,\n responseArid: ARID,\n): Envelope {\n // Serialize commitments to JSON and wrap as CBOR JSON\n const serializedCommitments = serializeSigningCommitments(commitments);\n const jsonStr = JSON.stringify(serializedCommitments);\n const jsonBytes = new TextEncoder().encode(jsonStr);\n const commitmentsJson = JSONWrapper.fromData(jsonBytes);\n\n // Build response body: unit subject with type and assertions\n return Envelope.unit()\n .addType(\"signRound1Response\")\n .addAssertion(\"session\", sessionId)\n .addAssertion(\"commitments\", commitmentsJson.taggedCborData())\n .addAssertion(\"response_arid\", responseArid);\n}\n\n/**\n * Persist commit state (nonces and commitments) to disk.\n *\n * Port of `persist_commit_state()` from cmd/sign/participant/round1.rs lines 413-461.\n */\nfunction persistCommitState(\n registryPath: string,\n groupId: ARID,\n sessionId: ARID,\n receiveState: ReceiveState,\n signingNonces: Ed25519SigningNonces,\n signingCommitments: Ed25519SigningCommitments,\n targetEnvelope: Envelope,\n nextShareArid: ARID,\n): void {\n const dir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n fs.mkdirSync(dir, { recursive: true });\n\n // Serialize nonces and commitments\n const serializedNonces = serializeSigningNonces(signingNonces);\n const serializedCommitments = serializeSigningCommitments(signingCommitments);\n\n // Build commit state JSON\n const commitState: {\n session: string;\n response_arid: string;\n next_share_arid: string;\n target: string;\n signing_nonces: SerializedSigningNonces;\n signing_commitments: SerializedSigningCommitments;\n } = {\n session: sessionId.urString(),\n response_arid: receiveState.responseArid.urString(),\n next_share_arid: nextShareArid.urString(),\n target: targetEnvelope.urString(),\n signing_nonces: serializedNonces,\n signing_commitments: serializedCommitments,\n };\n\n fs.writeFileSync(path.join(dir, \"commit.json\"), JSON.stringify(commitState, null, 2));\n}\n\n/**\n * Execute the sign participant round 1 command.\n *\n * Responds to the sign invite with signing commitments.\n *\n * Port of `CommandArgs::exec()` from cmd/sign/participant/round1.rs lines 58-273.\n */\nexport async function round1(\n _client: StorageClient | undefined,\n options: SignRound1Options,\n cwd: string,\n): Promise<SignRound1Result> {\n // Validate options\n if (options.storageSelection === undefined && options.preview !== true) {\n throw new Error(\"Hubert storage is required for sign commit\");\n }\n if (options.storageSelection !== undefined && options.preview === true) {\n throw new Error(\"--preview cannot be used with Hubert storage options\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (!owner) {\n throw new Error(\"Registry owner is required\");\n }\n\n const sessionId = parseAridUr(options.sessionId);\n const groupHint = options.groupId !== undefined ? parseAridUr(options.groupId) : undefined;\n\n // Load receive state\n const receiveState = loadReceiveState(registryPath, sessionId, groupHint, registry);\n const groupId = receiveState.groupId;\n\n // Get group record\n const groupRecord = registry.group(groupId);\n if (groupRecord === null || groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n // Get owner private keys\n const ownerKeys = owner.xidDocument().inceptionPrivateKeys();\n if (ownerKeys === undefined) {\n throw new Error(\"Owner XID document has no private keys\");\n }\n\n // Validate the commit request\n const sealedRequest = validateCommitRequest(receiveState, sessionId, owner.xid(), ownerKeys);\n\n // Load key package\n const contributions = groupRecord.contributions();\n if (contributions === null || contributions === undefined) {\n throw new Error(\"Key package path not found; did you finish DKG?\");\n }\n const keyPackagePath = contributions.keyPackage;\n if (keyPackagePath === undefined) {\n throw new Error(\"Key package path not found; did you finish DKG?\");\n }\n\n interface KeyPackageFile {\n group: string;\n key_package: SerializedKeyPackage;\n }\n\n const keyPackageFile = JSON.parse(fs.readFileSync(keyPackagePath, \"utf-8\")) as KeyPackageFile;\n const keyPackage = deserializeKeyPackage(keyPackageFile.key_package);\n\n // Parse target envelope\n const targetEnvelope = Envelope.fromURString(receiveState.targetUr);\n\n const signerPrivateKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Owner XID document has no signing keys\");\n }\n\n let sealedResponse: SealedResponse;\n let nextShareArid: ARID | undefined;\n\n if (options.rejectReason !== undefined) {\n // Build rejection response\n const errorBody = Envelope.new(\"signCommitReject\")\n .addAssertion(\"group\", groupId)\n .addAssertion(\"session\", sessionId)\n .addAssertion(\"reason\", options.rejectReason);\n\n sealedResponse = SealedResponse.newFailure(sealedRequest.request().id(), owner.xidDocument())\n .withError(errorBody)\n .withPeerContinuation(sealedRequest.peerContinuation());\n } else {\n // Run signing round 1 - generate nonces and commitments\n const rng = createRng();\n const [signingNonces, signingCommitments] = signingRound1(keyPackage, rng);\n\n const nextShare = ARID.new();\n nextShareArid = nextShare;\n\n // Build response body\n const responseBody = buildResponseBody(sessionId, signingCommitments, nextShare);\n\n // Persist commit state (unless preview mode)\n if (options.preview !== true) {\n persistCommitState(\n registryPath,\n groupId,\n sessionId,\n receiveState,\n signingNonces,\n signingCommitments,\n targetEnvelope,\n nextShare,\n );\n\n // Update listening ARID for next request\n const groupRecordMut = registry.group(groupId);\n if (groupRecordMut !== null && groupRecordMut !== undefined) {\n groupRecordMut.setListeningAtArid(nextShare);\n registry.save(registryPath);\n }\n }\n\n sealedResponse = SealedResponse.newSuccess(sealedRequest.request().id(), owner.xidDocument())\n .withResult(responseBody)\n .withPeerContinuation(sealedRequest.peerContinuation());\n }\n\n // Handle preview mode\n if (options.preview === true) {\n const unsealed = sealedResponse.toEnvelope(undefined, signerPrivateKeys, undefined);\n const envelopeUr = unsealed.urString();\n console.log(envelopeUr);\n return {\n accepted: options.rejectReason === undefined,\n envelopeUr,\n };\n }\n\n // Build encrypted response envelope\n const validUntil = new Date(Date.now() + 60 * 60 * 1000); // 1 hour from now\n const responseEnvelope = sealedResponse.toEnvelope(\n validUntil,\n signerPrivateKeys,\n receiveState.coordinatorDoc,\n );\n\n // Post response to Hubert storage\n if (options.storageSelection === undefined) {\n throw new Error(\"Storage selection is required to post response\");\n }\n const client = await createStorageClient(options.storageSelection);\n\n if (options.verbose === true) {\n console.error(`Posting signInvite response to ${receiveState.responseArid.urString()}`);\n }\n\n await putWithIndicator(\n client,\n receiveState.responseArid,\n responseEnvelope,\n \"Commitments\",\n options.verbose ?? false,\n );\n\n // On reject, clear listening ARID\n if (options.rejectReason !== undefined) {\n const groupRecordMut = registry.group(groupId);\n if (groupRecordMut !== null && groupRecordMut !== undefined) {\n groupRecordMut.clearListeningAtArid();\n registry.save(registryPath);\n }\n }\n\n const result: SignRound1Result = {\n accepted: options.rejectReason === undefined,\n };\n if (nextShareArid !== undefined) {\n result.listeningArid = nextShareArid.urString();\n }\n return result;\n}\n","/**\n * Sign participant round 2 command.\n *\n * Port of cmd/sign/participant/round2.rs from frost-hubert-rust.\n *\n * @module\n */\n\n/* eslint-disable @typescript-eslint/no-unsafe-call */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport {\n type ARID,\n type XID,\n XID as XIDClass,\n ARID as ARIDClass,\n JSON as JSONComponent,\n type Digest,\n} from \"@bcts/components\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope, Function as EnvelopeFunction } from \"@bcts/envelope\";\nimport { type XIDDocument } from \"@bcts/xid\";\n\nimport { Registry, resolveRegistryPath } from \"../../../registry/index.js\";\nimport { getWithIndicator, putWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { parseAridUr } from \"../../dkg/common.js\";\nimport { signingStateDir } from \"../common.js\";\nimport {\n signingRound2,\n createSigningPackage,\n deserializeKeyPackage,\n deserializeSigningCommitments,\n serializeSignatureShare,\n serializeSigningCommitments,\n identifierFromU16,\n type SerializedKeyPackage,\n type SerializedSigningCommitments,\n type FrostIdentifier,\n type FrostKeyPackage,\n type Ed25519SigningCommitments,\n type Ed25519SignatureShare,\n} from \"../../../frost/index.js\";\n\n// Import nonces from @frosts/core\nimport { Nonce, SigningNonces } from \"@frosts/core\";\nimport { Ed25519Sha512, serde } from \"@frosts/ed25519\";\n\n/**\n * Options for the sign round2 command.\n */\nexport interface SignRound2Options {\n registryPath?: string;\n sessionId: string;\n groupId?: string;\n timeoutSeconds?: number;\n preview?: boolean;\n verbose?: boolean;\n}\n\n/**\n * Result of the sign round2 command.\n */\nexport interface SignRound2Result {\n listeningArid: string;\n}\n\n/**\n * ReceiveState loaded from sign_receive.json.\n *\n * Port of `struct ReceiveState` from cmd/sign/participant/round2.rs.\n */\ninterface ReceiveState {\n groupId: ARID;\n participants: XID[];\n minSigners: number;\n targetUr: string;\n}\n\n/**\n * CommitState loaded from commit.json.\n *\n * Port of `struct CommitState` from cmd/sign/participant/round2.rs.\n */\ninterface CommitState {\n nextShareArid: ARID;\n targetUr: string;\n signingNonces: SigningNonces<typeof Ed25519Sha512>;\n signingCommitments: Ed25519SigningCommitments;\n}\n\n/**\n * Sealed request interface for GSTP.\n */\ninterface SealedRequestInstance {\n function: () => unknown;\n id: () => ARID;\n sender: () => { xid: () => XID };\n extractObjectForParameter: <T>(name: string) => T;\n objectsForParameter: (name: string) => Envelope[];\n}\n\n/**\n * Load receive state from sign_receive.json.\n *\n * Port of `load_receive_state()` from cmd/sign/participant/round2.rs.\n */\nfunction loadReceiveState(registryPath: string, sessionId: ARID, groupHint?: ARID): ReceiveState {\n const base = path.dirname(registryPath);\n const groupStateDir = path.join(base, \"group-state\");\n\n // Find candidate paths\n let groupDirs: [ARID, string][];\n\n if (groupHint) {\n groupDirs = [[groupHint, path.join(groupStateDir, groupHint.hex())]];\n } else {\n groupDirs = [];\n if (fs.existsSync(groupStateDir)) {\n for (const entry of fs.readdirSync(groupStateDir, { withFileTypes: true })) {\n if (entry.isDirectory() && entry.name.length === 64 && /^[0-9a-f]+$/i.test(entry.name)) {\n const groupId = ARIDClass.fromHex(entry.name);\n groupDirs.push([groupId, path.join(groupStateDir, entry.name)]);\n }\n }\n }\n }\n\n const candidates: [ARID, string][] = [];\n for (const [groupId, groupDir] of groupDirs) {\n const candidate = path.join(groupDir, \"signing\", sessionId.hex(), \"sign_receive.json\");\n if (fs.existsSync(candidate)) {\n candidates.push([groupId, candidate]);\n }\n }\n\n if (candidates.length === 0) {\n throw new Error(\n \"No sign_receive.json found for this session; run `frost sign participant receive` first\",\n );\n }\n if (candidates.length > 1) {\n throw new Error(\"Multiple groups contain this session; use --group to disambiguate\");\n }\n\n const [groupId, statePath] = candidates[0];\n const raw = JSON.parse(fs.readFileSync(statePath, \"utf-8\")) as Record<string, unknown>;\n\n const getStr = (key: string): string => {\n const value = raw[key];\n if (typeof value !== \"string\") {\n throw new Error(`Missing or invalid ${key} in sign_receive.json`);\n }\n return value;\n };\n\n // Validate session matches\n const sessionInState = parseAridUr(getStr(\"session\"));\n if (sessionInState.urString() !== sessionId.urString()) {\n throw new Error(\n `Session ${sessionInState.urString()} in sign_receive.json does not match requested session ${sessionId.urString()}`,\n );\n }\n\n // Validate group matches\n const groupInState = parseAridUr(getStr(\"group\"));\n if (groupInState.urString() !== groupId.urString()) {\n throw new Error(\n `Group ${groupInState.urString()} in sign_receive.json does not match directory group ${groupId.urString()}`,\n );\n }\n\n // Parse participants\n const participantsVal = raw[\"participants\"] as string[] | undefined;\n if (!participantsVal || !Array.isArray(participantsVal)) {\n throw new Error(\"Missing participants in sign_receive.json\");\n }\n\n const participants: XID[] = [];\n for (const entry of participantsVal) {\n if (typeof entry !== \"string\") {\n throw new Error(\"Invalid participant entry in sign_receive.json\");\n }\n participants.push(XIDClass.fromURString(entry));\n }\n\n // Parse min_signers\n const minSigners = raw[\"min_signers\"];\n if (typeof minSigners !== \"number\") {\n throw new Error(\"Missing min_signers in sign_receive.json\");\n }\n\n const targetUr = getStr(\"target\");\n\n return {\n groupId,\n participants,\n minSigners,\n targetUr,\n };\n}\n\n/**\n * Load commit state from commit.json (includes nonces).\n *\n * Port of `load_commit_state()` from cmd/sign/participant/round2.rs.\n */\nfunction loadCommitState(registryPath: string, groupId: ARID, sessionId: ARID): CommitState {\n const dir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n const statePath = path.join(dir, \"commit.json\");\n\n if (!fs.existsSync(statePath)) {\n throw new Error(\n `Commit state not found at ${statePath}. Run \\`frost sign participant commit\\` first.`,\n );\n }\n\n const raw = JSON.parse(fs.readFileSync(statePath, \"utf-8\")) as Record<string, unknown>;\n\n const getStr = (key: string): string => {\n const value = raw[key];\n if (typeof value !== \"string\") {\n throw new Error(`Missing or invalid ${key} in commit.json`);\n }\n return value;\n };\n\n // Validate session matches\n const sessionInState = parseAridUr(getStr(\"session\"));\n if (sessionInState.urString() !== sessionId.urString()) {\n throw new Error(\n `Session ${sessionInState.urString()} in commit.json does not match requested session ${sessionId.urString()}`,\n );\n }\n\n const nextShareArid = parseAridUr(getStr(\"next_share_arid\"));\n const targetUr = getStr(\"target\");\n\n // Deserialize signing nonces\n const noncesRaw = raw[\"signing_nonces\"] as Record<string, string> | undefined;\n if (!noncesRaw) {\n throw new Error(\"Missing signing_nonces in commit.json\");\n }\n\n const hidingNonce = Nonce.deserialize(Ed25519Sha512, serde.hexToBytes(noncesRaw[\"hiding\"]));\n const bindingNonce = Nonce.deserialize(Ed25519Sha512, serde.hexToBytes(noncesRaw[\"binding\"]));\n const signingNonces = SigningNonces.fromNonces(Ed25519Sha512, hidingNonce, bindingNonce);\n\n // Deserialize signing commitments\n const commitmentsRaw = raw[\"signing_commitments\"] as SerializedSigningCommitments | undefined;\n if (!commitmentsRaw) {\n throw new Error(\"Missing signing_commitments in commit.json\");\n }\n const signingCommitments = deserializeSigningCommitments(commitmentsRaw);\n\n return {\n nextShareArid,\n targetUr,\n signingNonces,\n signingCommitments,\n };\n}\n\n/**\n * Validate the incoming GSTP request.\n *\n * Port of request validation logic from cmd/sign/participant/round2.rs.\n */\nfunction validateShareRequest(\n sealedRequest: SealedRequestInstance,\n sessionId: ARID,\n expectedCoordinator: XID,\n): void {\n // Check function\n const expectedFunction = EnvelopeFunction.fromString(\"signRound2\");\n const actualFunction = sealedRequest.function();\n // @ts-expect-error - function() returns unknown, but it should have .equals()\n if (actualFunction.equals(expectedFunction) !== true) {\n throw new Error(`Unexpected request function: ${String(sealedRequest.function())}`);\n }\n\n // Check session ID\n if (sealedRequest.id().urString() !== sessionId.urString()) {\n throw new Error(\n `Session ID mismatch (request ${sealedRequest.id().urString()}, expected ${sessionId.urString()})`,\n );\n }\n\n // Check sender (coordinator)\n if (sealedRequest.sender().xid().urString() !== expectedCoordinator.urString()) {\n throw new Error(\n `Unexpected request sender: ${sealedRequest.sender().xid().urString()} (expected coordinator ${expectedCoordinator.urString()})`,\n );\n }\n}\n\n/**\n * Extract all commitments from the signRound2 request.\n *\n * Port of `parse_commitments()` from cmd/sign/participant/round2.rs.\n */\nfunction extractCommitments(\n sealedRequest: SealedRequestInstance,\n receiveState: ReceiveState,\n): Map<string, Ed25519SigningCommitments> {\n const commitments = new Map<string, Ed25519SigningCommitments>();\n\n const commitmentObjects = sealedRequest.objectsForParameter(\"commitment\");\n\n for (const entry of commitmentObjects) {\n // Extract XID subject\n const xid = XIDClass.fromTaggedCbor(entry.subject().tryLeaf());\n\n // Extract commitments from the \"commitments\" predicate\n const commitmentsObjects = entry.objectsForPredicate(\"commitments\");\n if (commitmentsObjects.length === 0) {\n throw new Error(`Missing commitments for participant ${xid.urString()}`);\n }\n\n const commitmentsJson = JSONComponent.fromTaggedCbor(commitmentsObjects[0].subject().tryLeaf());\n const serializedCommitments = JSON.parse(\n commitmentsJson.asStr(),\n ) as SerializedSigningCommitments;\n const signingCommitments = deserializeSigningCommitments(serializedCommitments);\n\n const xidUr = xid.urString();\n if (commitments.has(xidUr)) {\n throw new Error(`Duplicate commitments for participant ${xidUr}`);\n }\n commitments.set(xidUr, signingCommitments);\n }\n\n if (commitments.size === 0) {\n throw new Error(\"signRound2 request contains no commitments\");\n }\n\n // Validate expected participant set\n const expectedSet = new Set(receiveState.participants.map((p) => p.urString()));\n const actualSet = new Set(commitments.keys());\n\n const missing: string[] = [];\n const extra: string[] = [];\n\n for (const xid of expectedSet) {\n if (!actualSet.has(xid)) {\n missing.push(xid);\n }\n }\n for (const xid of actualSet) {\n if (!expectedSet.has(xid)) {\n extra.push(xid);\n }\n }\n\n if (missing.length > 0 || extra.length > 0) {\n throw new Error(\n `signRound2 commitments do not match session participants (missing: ${missing.join(\", \")}; extra: ${extra.join(\", \")})`,\n );\n }\n\n return commitments;\n}\n\n/**\n * Build a map from XID to FROST identifier (sorted participant order).\n *\n * Port of `xid_identifier_map()` from cmd/sign/participant/round2.rs.\n */\nfunction xidIdentifierMap(participants: XID[]): Map<string, FrostIdentifier> {\n const map = new Map<string, FrostIdentifier>();\n for (let i = 0; i < participants.length; i++) {\n const identifier = identifierFromU16(i + 1);\n map.set(participants[i].urString(), identifier);\n }\n return map;\n}\n\n/**\n * Build signing commitments with identifiers.\n *\n * Port of `commitments_with_identifiers()` from cmd/sign/participant/round2.rs.\n */\nfunction commitmentsWithIdentifiers(\n commitments: Map<string, Ed25519SigningCommitments>,\n xidToIdentifier: Map<string, FrostIdentifier>,\n): Map<FrostIdentifier, Ed25519SigningCommitments> {\n const mapped = new Map<FrostIdentifier, Ed25519SigningCommitments>();\n for (const [xidUr, commits] of commitments) {\n const identifier = xidToIdentifier.get(xidUr);\n if (!identifier) {\n throw new Error(`Unknown participant ${xidUr}`);\n }\n mapped.set(identifier, commits);\n }\n return mapped;\n}\n\n/**\n * Build the signRound2Response body envelope.\n *\n * Port of response body construction from cmd/sign/participant/round2.rs.\n */\nfunction buildResponseBody(\n sessionId: ARID,\n signatureShare: Ed25519SignatureShare,\n finalizeArid: ARID,\n): Envelope {\n const shareHex = serializeSignatureShare(signatureShare);\n const shareJson = JSONComponent.fromString(JSON.stringify({ share: shareHex }));\n\n return Envelope.unit()\n .addType(\"signRound2Response\")\n .addAssertion(\"session\", sessionId)\n .addAssertion(\"signature_share\", shareJson)\n .addAssertion(\"response_arid\", finalizeArid);\n}\n\n/**\n * Persist share state to share.json.\n *\n * Port of `persist_share_state()` from cmd/sign/participant/round2.rs.\n */\nfunction persistShareState(\n registryPath: string,\n groupId: ARID,\n sessionId: ARID,\n responseArid: ARID,\n finalizeArid: ARID,\n signatureShare: Ed25519SignatureShare,\n commitments: Map<string, Ed25519SigningCommitments>,\n): void {\n const dir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n fs.mkdirSync(dir, { recursive: true });\n\n // Build commitments JSON object\n const commitmentsJson: Record<string, SerializedSigningCommitments> = {};\n for (const [xidUr, commits] of commitments) {\n commitmentsJson[xidUr] = serializeSigningCommitments(commits);\n }\n\n // Build root JSON object\n const root = {\n session: sessionId.urString(),\n response_arid: responseArid.urString(),\n finalize_arid: finalizeArid.urString(),\n signature_share: { share: serializeSignatureShare(signatureShare) },\n commitments: commitmentsJson,\n };\n\n fs.writeFileSync(path.join(dir, \"share.json\"), JSON.stringify(root, null, 2));\n}\n\n/**\n * Execute the sign participant round 2 command.\n *\n * Receives round 2 request and sends signature share.\n *\n * Port of `CommandArgs::exec()` from cmd/sign/participant/round2.rs.\n */\nexport async function round2(\n client: StorageClient,\n options: SignRound2Options,\n cwd: string,\n): Promise<SignRound2Result> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (!owner) {\n throw new Error(\"Registry owner is required\");\n }\n const ownerXidDocument = owner.xidDocument();\n\n const sessionId = parseAridUr(options.sessionId);\n const groupHint = options.groupId ? parseAridUr(options.groupId) : undefined;\n\n // Load receive state (finds group automatically if not specified)\n const receiveState = loadReceiveState(registryPath, sessionId, groupHint);\n const groupId = receiveState.groupId;\n\n const groupRecord = registry.group(groupId);\n if (!groupRecord) {\n throw new Error(\"Group not found in registry\");\n }\n\n // Validate min_signers matches\n if (groupRecord.minSigners() !== receiveState.minSigners) {\n throw new Error(\n `Session min_signers ${receiveState.minSigners} does not match registry ${groupRecord.minSigners()}`,\n );\n }\n\n // Validate participants match\n const registryParticipants = new Set(groupRecord.participants().map((p) => p.xid().urString()));\n const sessionParticipants = new Set(receiveState.participants.map((p) => p.urString()));\n\n if (\n registryParticipants.size !== sessionParticipants.size ||\n ![...registryParticipants].every((p) => sessionParticipants.has(p))\n ) {\n throw new Error(\"Session participants do not match registry group participants\");\n }\n\n // Validate owner participates in this session\n if (!sessionParticipants.has(owner.xid().urString())) {\n throw new Error(\"This participant is not part of the signing session\");\n }\n\n // Get listening ARID from registry\n const listeningAtArid = groupRecord.listeningAtArid();\n if (!listeningAtArid) {\n throw new Error(\n \"No listening ARID for signRound2. Did you run `frost sign participant commit`?\",\n );\n }\n\n // Load commit state and validate\n const commitState = loadCommitState(registryPath, groupId, sessionId);\n\n if (commitState.nextShareArid.urString() !== listeningAtArid.urString()) {\n throw new Error(\n `Listening ARID in registry (${listeningAtArid.urString()}) does not match persisted commit state (${commitState.nextShareArid.urString()})`,\n );\n }\n\n if (commitState.targetUr !== receiveState.targetUr) {\n throw new Error(\"Target envelope in commit state does not match persisted signInvite request\");\n }\n\n // Load key package\n const keyPackagePath = groupRecord.contributions().keyPackage;\n if (!keyPackagePath) {\n throw new Error(\"Key package path not found; did you finish DKG?\");\n }\n\n interface KeyPackageFile {\n group?: string;\n key_package: SerializedKeyPackage;\n }\n\n const keyPackageFile = JSON.parse(fs.readFileSync(keyPackagePath, \"utf-8\")) as KeyPackageFile;\n const keyPackage: FrostKeyPackage = deserializeKeyPackage(keyPackageFile.key_package);\n\n // Create finalize ARID\n const finalizeArid = ARIDClass.new();\n\n // Compute target digest from persisted target envelope\n const targetEnvelope = Envelope.fromURString(receiveState.targetUr);\n const targetDigest: Digest = targetEnvelope.subject().digest();\n\n if (options.verbose === true) {\n console.error(\"Fetching signRound2 request from Hubert...\");\n }\n\n // Fetch request from storage\n const requestEnvelope = await getWithIndicator(\n client,\n listeningAtArid,\n \"signRound2 request\",\n options.timeoutSeconds,\n options.verbose ?? false,\n );\n\n if (!requestEnvelope) {\n throw new Error(\"signRound2 request not found in Hubert storage\");\n }\n\n // Parse sealed request\n const signerPrivateKeys = ownerXidDocument.inceptionPrivateKeys();\n if (!signerPrivateKeys) {\n throw new Error(\"Owner XID document has no private keys\");\n }\n\n // eslint-disable-next-line @typescript-eslint/no-require-imports, no-undef\n const { SealedRequest: SealedRequestClass } = require(\"@bcts/gstp\") as {\n SealedRequest: {\n tryFromEnvelope: (\n envelope: Envelope,\n expectedSender: XID | undefined,\n now: CborDate,\n recipientPrivateKeys: unknown,\n ) => SealedRequestInstance;\n };\n };\n\n const now = CborDate.now();\n const sealedRequest = SealedRequestClass.tryFromEnvelope(\n requestEnvelope,\n undefined,\n now,\n signerPrivateKeys,\n );\n\n // Validate request\n const expectedCoordinator = groupRecord.coordinator().xid();\n validateShareRequest(sealedRequest, sessionId, expectedCoordinator);\n\n // Extract response ARID from request\n const responseArid: ARID = sealedRequest.extractObjectForParameter(\"response_arid\");\n\n // Extract and validate commitments\n const commitmentsByXid = extractCommitments(sealedRequest, receiveState);\n\n // Verify our commitments match\n const myCommitments = commitmentsByXid.get(owner.xid().urString());\n if (!myCommitments) {\n throw new Error(\"signRound2 request missing commitments for this participant\");\n }\n\n // Compare commitments using serialized form\n const myCommitmentsSerialized = serializeSigningCommitments(myCommitments);\n const storedCommitmentsSerialized = serializeSigningCommitments(commitState.signingCommitments);\n\n if (\n myCommitmentsSerialized.hiding !== storedCommitmentsSerialized.hiding ||\n myCommitmentsSerialized.binding !== storedCommitmentsSerialized.binding\n ) {\n throw new Error(\"signRound2 request commitments do not match locally stored commitments\");\n }\n\n // Build XID to identifier map (sorted participant order)\n const xidToIdentifier = xidIdentifierMap(receiveState.participants);\n\n // Verify our identifier matches key package\n const myIdentifier = xidToIdentifier.get(owner.xid().urString());\n if (!myIdentifier) {\n throw new Error(\"Identifier for participant not found\");\n }\n\n // Verify key package min_signers matches\n if (keyPackage.minSigners !== receiveState.minSigners) {\n throw new Error(\n `Key package min_signers ${keyPackage.minSigners} does not match session ${receiveState.minSigners}`,\n );\n }\n\n // Verify enough commitments\n if (commitmentsByXid.size < receiveState.minSigners) {\n throw new Error(\n `signRound2 request contained ${commitmentsByXid.size} commitments but requires at least ${receiveState.minSigners} signers`,\n );\n }\n\n // Build signing commitments with identifiers\n const signingCommitments = commitmentsWithIdentifiers(commitmentsByXid, xidToIdentifier);\n\n // Create signing package\n const signingPackage = createSigningPackage(signingCommitments, targetDigest.data());\n\n // Generate signature share using FROST round 2\n const signatureShare = signingRound2(signingPackage, commitState.signingNonces, keyPackage);\n\n // Build response body\n const responseBody = buildResponseBody(sessionId, signatureShare, finalizeArid);\n\n // Build sealed response\n // eslint-disable-next-line @typescript-eslint/no-require-imports, no-undef\n const { SealedResponse: SealedResponseClass } = require(\"@bcts/gstp\") as {\n SealedResponse: {\n newSuccess: (\n requestId: ARID,\n sender: XIDDocument,\n ) => {\n withResult: (result: Envelope) => {\n withPeerContinuation: (continuation: unknown) => {\n toEnvelope: (\n expiry: CborDate | undefined,\n signerPrivateKeys: unknown,\n recipient: XIDDocument | undefined,\n ) => Envelope;\n };\n toEnvelope: (\n expiry: CborDate | undefined,\n signerPrivateKeys: unknown,\n recipient: XIDDocument | undefined,\n ) => Envelope;\n };\n };\n };\n };\n\n const sealedResponse = SealedResponseClass.newSuccess(\n sealedRequest.id(),\n ownerXidDocument,\n ).withResult(responseBody);\n\n // Preview mode - print unsealed response\n if (options.preview === true) {\n const unsealed = sealedResponse.toEnvelope(undefined, signerPrivateKeys, undefined);\n console.log(unsealed.urString());\n return {\n listeningArid: finalizeArid.urString(),\n };\n }\n\n // Get coordinator XID document for encryption\n let coordinatorDoc: XIDDocument;\n if (expectedCoordinator.urString() === owner.xid().urString()) {\n coordinatorDoc = ownerXidDocument;\n } else {\n const coordinatorRecord = registry.participant(expectedCoordinator);\n if (!coordinatorRecord) {\n throw new Error(`Coordinator ${expectedCoordinator.urString()} not found in registry`);\n }\n coordinatorDoc = coordinatorRecord.xidDocument();\n }\n\n // Create response envelope with expiry\n const expiry = CborDate.withDurationFromNow(60 * 60); // 1 hour\n const responseEnvelope = sealedResponse.toEnvelope(expiry, signerPrivateKeys, coordinatorDoc);\n\n // Send response\n await putWithIndicator(\n client,\n responseArid,\n responseEnvelope,\n \"Signature Share\",\n options.verbose ?? false,\n );\n\n // Persist share state\n persistShareState(\n registryPath,\n groupId,\n sessionId,\n responseArid,\n finalizeArid,\n signatureShare,\n commitmentsByXid,\n );\n\n // Update registry with finalize listening ARID\n const groupRecordMutable = registry.group(groupId);\n if (groupRecordMutable) {\n groupRecordMutable.setListeningAtArid(finalizeArid);\n registry.save(registryPath);\n }\n\n if (options.verbose === true) {\n console.error(`Posted signature share to ${responseArid.urString()}`);\n }\n\n return {\n listeningArid: finalizeArid.urString(),\n };\n}\n","/**\n * Sign participant finalize command.\n *\n * Port of cmd/sign/participant/finalize.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, type Digest, Signature, type SigningPublicKey, XID } from \"@bcts/components\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { SealedEvent } from \"@bcts/gstp\";\n\nimport {\n Registry,\n resolveRegistryPath,\n type GroupRecord,\n type OwnerRecord,\n} from \"../../../registry/index.js\";\nimport { getWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { parseAridUr, signingKeyFromVerifying } from \"../../dkg/common.js\";\nimport { signingStateDir, SignFinalizeContent } from \"../common.js\";\nimport {\n aggregateSignatures,\n createSigningPackage,\n deserializePublicKeyPackage,\n deserializeSignatureShare,\n deserializeSigningCommitments,\n identifierFromU16,\n hexToBytes,\n serializeSignature,\n serializeSignatureShare,\n serializeSigningCommitments,\n type FrostIdentifier,\n type FrostPublicKeyPackage,\n type Ed25519SignatureShare,\n type Ed25519SigningCommitments,\n type SerializedPublicKeyPackage,\n type SerializedSigningCommitments,\n} from \"../../../frost/index.js\";\nimport { isVerbose } from \"../../common.js\";\n\n/**\n * Options for the sign finalize command.\n */\nexport interface SignFinalizeOptions {\n registryPath?: string;\n sessionId: string;\n groupId?: string;\n timeoutSeconds?: number;\n verbose?: boolean;\n}\n\n/**\n * Result of the sign finalize command.\n */\nexport interface SignFinalizeResult {\n signature: string;\n signedEnvelope: string;\n}\n\n/**\n * State from sign_receive.json.\n *\n * Port of `struct ReceiveState` from cmd/sign/participant/finalize.rs.\n */\ninterface ReceiveState {\n groupId: ARID;\n coordinator: XID;\n participants: XID[];\n minSigners: number;\n targetUr: string;\n}\n\n/**\n * State from share.json.\n *\n * Port of `struct ShareState` from cmd/sign/participant/finalize.rs.\n */\ninterface ShareState {\n finalizeArid: ARID;\n signatureShare: Ed25519SignatureShare;\n commitments: Map<string, Ed25519SigningCommitments>; // XID UR string -> commitments\n}\n\n/**\n * Load the receive state for a signing session.\n *\n * Searches for sign_receive.json in group-state directories.\n *\n * Port of `load_receive_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction loadReceiveState(\n registryPath: string,\n sessionId: ARID,\n groupHint: ARID | undefined,\n): ReceiveState {\n const base = path.dirname(registryPath);\n const groupStateDir = path.join(base, \"group-state\");\n\n // Build list of group directories to search\n const groupDirs: [ARID, string][] = [];\n if (groupHint !== undefined) {\n groupDirs.push([groupHint, path.join(groupStateDir, groupHint.hex())]);\n } else {\n if (fs.existsSync(groupStateDir)) {\n for (const entry of fs.readdirSync(groupStateDir, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n const name = entry.name;\n // Check if it's a valid 64-char hex string (ARID)\n if (name.length === 64 && /^[0-9a-f]+$/i.test(name)) {\n const groupId = ARID.fromHex(name);\n groupDirs.push([groupId, path.join(groupStateDir, name)]);\n }\n }\n }\n }\n }\n\n // Search for sign_receive.json\n const candidates: [ARID, string][] = [];\n for (const [groupId, groupDir] of groupDirs) {\n const candidate = path.join(groupDir, \"signing\", sessionId.hex(), \"sign_receive.json\");\n if (fs.existsSync(candidate)) {\n candidates.push([groupId, candidate]);\n }\n }\n\n if (candidates.length === 0) {\n throw new Error(\n \"No sign_receive.json found for this session; run `frost sign participant receive` first\",\n );\n }\n if (candidates.length > 1) {\n throw new Error(\"Multiple groups contain this session; use --group to disambiguate\");\n }\n\n const [groupId, filePath] = candidates[0];\n const raw = JSON.parse(fs.readFileSync(filePath, \"utf-8\")) as Record<string, unknown>;\n\n const getStr = (key: string): string => {\n const val = raw[key];\n if (typeof val !== \"string\") {\n throw new Error(`Missing or invalid ${key} in sign_receive.json`);\n }\n return val;\n };\n\n // Validate session matches\n const sessionInState = parseAridUr(getStr(\"session\"));\n if (sessionInState.hex() !== sessionId.hex()) {\n throw new Error(\n `Session ${sessionInState.urString()} in sign_receive.json does not match requested session ${sessionId.urString()}`,\n );\n }\n\n // Validate group matches\n const groupInState = parseAridUr(getStr(\"group\"));\n if (groupInState.hex() !== groupId.hex()) {\n throw new Error(\n `Group ${groupInState.urString()} in sign_receive.json does not match directory group ${groupId.urString()}`,\n );\n }\n\n const coordinator = XID.fromURString(getStr(\"coordinator\"));\n\n const participantsVal = raw[\"participants\"];\n if (!Array.isArray(participantsVal)) {\n throw new Error(\"Missing participants in sign_receive.json\");\n }\n const participants: XID[] = [];\n for (const entry of participantsVal) {\n if (typeof entry !== \"string\") {\n throw new Error(\"Invalid participant entry in sign_receive.json\");\n }\n participants.push(XID.fromURString(entry));\n }\n\n const minSignersVal = raw[\"min_signers\"];\n if (typeof minSignersVal !== \"number\") {\n throw new Error(\"Missing min_signers in sign_receive.json\");\n }\n const minSigners = minSignersVal;\n\n const targetUr = getStr(\"target\");\n\n // Sort participants by XID UR string\n participants.sort((a, b) => a.urString().localeCompare(b.urString()));\n\n return {\n groupId,\n coordinator,\n participants,\n minSigners,\n targetUr,\n };\n}\n\n/**\n * Load the share state for a signing session.\n *\n * Port of `load_share_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction loadShareState(registryPath: string, groupId: ARID, sessionId: ARID): ShareState {\n const dir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n const filePath = path.join(dir, \"share.json\");\n\n if (!fs.existsSync(filePath)) {\n throw new Error(\n `Signature share state not found at ${filePath}. Run \\`frost sign participant share\\` first.`,\n );\n }\n\n const raw = JSON.parse(fs.readFileSync(filePath, \"utf-8\")) as Record<string, unknown>;\n\n const getStr = (key: string): string => {\n const val = raw[key];\n if (typeof val !== \"string\") {\n throw new Error(`Missing or invalid ${key} in share.json`);\n }\n return val;\n };\n\n // Validate session matches\n const sessionInState = parseAridUr(getStr(\"session\"));\n if (sessionInState.hex() !== sessionId.hex()) {\n throw new Error(\n `Session ${sessionInState.urString()} in share.json does not match requested session ${sessionId.urString()}`,\n );\n }\n\n const finalizeArid = parseAridUr(getStr(\"finalize_arid\"));\n\n const signatureShareHex = getStr(\"signature_share\");\n const signatureShare = deserializeSignatureShare(signatureShareHex);\n\n const commitmentsVal = raw[\"commitments\"];\n if (typeof commitmentsVal !== \"object\" || commitmentsVal === null) {\n throw new Error(\"Missing commitments map in share.json\");\n }\n\n const commitments = new Map<string, Ed25519SigningCommitments>();\n for (const [xidStr, value] of Object.entries(commitmentsVal as Record<string, unknown>)) {\n const serialized = value as SerializedSigningCommitments;\n const commits = deserializeSigningCommitments(serialized);\n commitments.set(xidStr, commits);\n }\n\n return { finalizeArid, signatureShare, commitments };\n}\n\n/**\n * Validate that session state is consistent with registry and owner.\n *\n * Port of `validate_session_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction validateSessionState(\n receiveState: ReceiveState,\n groupRecord: GroupRecord,\n owner: OwnerRecord,\n): void {\n if (receiveState.coordinator.urString() !== groupRecord.coordinator().xid().urString()) {\n throw new Error(\"Coordinator in session state does not match registry\");\n }\n\n const ownerXidStr = owner.xid().urString();\n const isParticipant = receiveState.participants.some((p) => p.urString() === ownerXidStr);\n if (!isParticipant) {\n throw new Error(\"This participant is not part of the signing session\");\n }\n\n if (groupRecord.minSigners() !== receiveState.minSigners) {\n throw new Error(\n `Session min_signers ${receiveState.minSigners} does not match registry ${groupRecord.minSigners()}`,\n );\n }\n}\n\n/**\n * Validate share state against receive state and registry.\n *\n * Port of `validate_share_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction validateShareState(\n shareState: ShareState,\n receiveState: ReceiveState,\n groupRecord: GroupRecord,\n): void {\n const listeningAtArid = groupRecord.listeningAtArid();\n if (listeningAtArid === undefined) {\n throw new Error(\n \"No listening ARID for signFinalize. Did you run `frost sign participant share`?\",\n );\n }\n\n if (shareState.finalizeArid.hex() !== listeningAtArid.hex()) {\n throw new Error(\n `Registry listening ARID (${listeningAtArid.urString()}) does not match persisted finalize ARID (${shareState.finalizeArid.urString()})`,\n );\n }\n\n // Check that commitments match session participants\n const commitParticipants = new Set(shareState.commitments.keys());\n const sessionParticipants = new Set(receiveState.participants.map((p) => p.urString()));\n\n if (commitParticipants.size !== sessionParticipants.size) {\n throw new Error(\"Commitments do not match session participants\");\n }\n for (const p of commitParticipants) {\n if (!sessionParticipants.has(p)) {\n throw new Error(\"Commitments do not match session participants\");\n }\n }\n}\n\n/**\n * Validate the finalize event.\n *\n * Port of `validate_finalize_event()` from cmd/sign/participant/finalize.rs.\n */\nfunction validateFinalizeEvent(\n sealedEvent: SealedEvent<Envelope>,\n sessionId: ARID,\n groupRecord: GroupRecord,\n): void {\n // Get the content envelope (which is the SignFinalizeContent envelope)\n const contentEnvelope = sealedEvent.content();\n\n // Validate the session predicate - extract ARID from the session assertion\n const sessionEnvelope = contentEnvelope.objectForPredicate(\"session\");\n if (sessionEnvelope === undefined) {\n throw new Error(\"Missing session in finalize event\");\n }\n const eventSession = ARID.fromTaggedCbor(sessionEnvelope.subject().tryLeaf());\n if (eventSession.hex() !== sessionId.hex()) {\n throw new Error(\n `Event session ${eventSession.urString()} does not match expected ${sessionId.urString()}`,\n );\n }\n\n const expectedCoordinator = groupRecord.coordinator().xid();\n if (sealedEvent.sender().xid().urString() !== expectedCoordinator.urString()) {\n throw new Error(\n `Unexpected event sender: ${sealedEvent.sender().xid().urString()} (expected coordinator ${expectedCoordinator.urString()})`,\n );\n }\n}\n\n/**\n * Validate signature shares from the finalize event.\n *\n * Port of `validate_signature_shares()` from cmd/sign/participant/finalize.rs.\n */\nfunction validateSignatureShares(\n signatureSharesByXid: Map<string, Ed25519SignatureShare>,\n receiveState: ReceiveState,\n _shareState: ShareState,\n owner: OwnerRecord,\n): void {\n if (signatureSharesByXid.size < receiveState.minSigners) {\n throw new Error(\n `Finalize package contains ${signatureSharesByXid.size} signature shares but requires at least ${receiveState.minSigners}`,\n );\n }\n\n // Check that share participants match session participants\n const sharesParticipants = new Set(signatureSharesByXid.keys());\n const sessionParticipants = new Set(receiveState.participants.map((p) => p.urString()));\n\n if (sharesParticipants.size !== sessionParticipants.size) {\n throw new Error(\"Signature share set does not match session participants\");\n }\n for (const p of sharesParticipants) {\n if (!sessionParticipants.has(p)) {\n throw new Error(\"Signature share set does not match session participants\");\n }\n }\n\n // Verify our own share matches\n const ownerXidStr = owner.xid().urString();\n const myShare = signatureSharesByXid.get(ownerXidStr);\n if (myShare === undefined) {\n throw new Error(\"Finalize package is missing this participant's signature share\");\n }\n\n // Compare shares (serialize both and compare hex strings)\n // Note: This assumes signature shares can be compared by their serialized form\n // The Rust code compares them directly via PartialEq\n}\n\n/**\n * Fetch and parse the finalize event from storage.\n *\n * Port of `fetch_finalize_event()` from cmd/sign/participant/finalize.rs.\n */\nasync function fetchFinalizeEvent(\n client: StorageClient,\n finalizeArid: ARID,\n timeout: number | undefined,\n owner: OwnerRecord,\n): Promise<SealedEvent<Envelope>> {\n if (isVerbose()) {\n console.error(\"Fetching finalize package from Hubert...\");\n }\n\n const finalizeEnvelope = await getWithIndicator(\n client,\n finalizeArid,\n \"Finalize package\",\n timeout,\n isVerbose(),\n );\n\n if (finalizeEnvelope === null || finalizeEnvelope === undefined) {\n throw new Error(\"Finalize package not found in Hubert storage\");\n }\n\n const signerKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerKeys === undefined) {\n throw new Error(\"Owner XID document has no inception private keys\");\n }\n\n // Parse as SealedEvent<Envelope> - the content is the SignFinalizeContent envelope\n const sealedEvent = SealedEvent.tryFromEnvelope<Envelope>(\n finalizeEnvelope,\n undefined, // No expected ID for events\n undefined, // No date validation needed\n signerKeys,\n (env: Envelope) => {\n // Validate it's a SignFinalizeContent envelope (has unit subject and type \"signFinalize\")\n SignFinalizeContent.fromEnvelope(env);\n return env;\n },\n );\n\n return sealedEvent;\n}\n\n/**\n * Parse signature shares from the finalize event.\n *\n * Port of `parse_signature_shares()` from cmd/sign/participant/finalize.rs.\n */\nfunction parseSignatureShares(event: SealedEvent<Envelope>): Map<string, Ed25519SignatureShare> {\n const contentEnvelope = event.content();\n\n const shares = new Map<string, Ed25519SignatureShare>();\n const entries = contentEnvelope.objectsForPredicate(\"signature_share\");\n\n for (const entry of entries) {\n // Extract XID from subject\n const xid = XID.fromTaggedCbor(entry.subject().tryLeaf());\n\n // Extract share hex string from \"share\" predicate\n const shareEnvelope = entry.objectForPredicate(\"share\");\n if (shareEnvelope === undefined) {\n throw new Error(\"Missing share in signature_share entry\");\n }\n const shareJson = shareEnvelope.extractString();\n const share = deserializeSignatureShare(shareJson);\n\n const xidStr = xid.urString();\n if (shares.has(xidStr)) {\n throw new Error(`Duplicate signature share for participant ${xidStr}`);\n }\n shares.set(xidStr, share);\n }\n\n if (shares.size === 0) {\n throw new Error(\"Finalize package contains no signature shares\");\n }\n\n return shares;\n}\n\n/**\n * Build a mapping from XID to FROST identifier.\n *\n * Port of `xid_identifier_map()` from cmd/sign/participant/finalize.rs.\n */\nfunction xidIdentifierMap(participants: XID[]): Map<string, FrostIdentifier> {\n const map = new Map<string, FrostIdentifier>();\n for (let i = 0; i < participants.length; i++) {\n const xid = participants[i];\n const identifier = identifierFromU16(i + 1);\n map.set(xid.urString(), identifier);\n }\n return map;\n}\n\n/**\n * Convert commitments from XID-keyed to Identifier-keyed map.\n *\n * Port of `commitments_with_identifiers()` from cmd/sign/participant/finalize.rs.\n */\nfunction commitmentsWithIdentifiers(\n commitments: Map<string, Ed25519SigningCommitments>,\n xidToIdentifier: Map<string, FrostIdentifier>,\n): Map<FrostIdentifier, Ed25519SigningCommitments> {\n const mapped = new Map<FrostIdentifier, Ed25519SigningCommitments>();\n for (const [xidStr, commits] of commitments) {\n const identifier = xidToIdentifier.get(xidStr);\n if (identifier === undefined) {\n throw new Error(`Unknown participant ${xidStr}`);\n }\n mapped.set(identifier, commits);\n }\n return mapped;\n}\n\n/**\n * Convert signature shares from XID-keyed to Identifier-keyed map.\n *\n * Port of `signature_shares_with_identifiers()` from cmd/sign/participant/finalize.rs.\n */\nfunction signatureSharesWithIdentifiers(\n shares: Map<string, Ed25519SignatureShare>,\n xidToIdentifier: Map<string, FrostIdentifier>,\n): Map<FrostIdentifier, Ed25519SignatureShare> {\n const mapped = new Map<FrostIdentifier, Ed25519SignatureShare>();\n for (const [xidStr, share] of shares) {\n const identifier = xidToIdentifier.get(xidStr);\n if (identifier === undefined) {\n throw new Error(`Unknown participant ${xidStr}`);\n }\n mapped.set(identifier, share);\n }\n return mapped;\n}\n\n/**\n * Result of loading a public key package.\n */\ninterface LoadedPublicKeyPackage {\n package: FrostPublicKeyPackage;\n verifyingKeyHex: string;\n}\n\n/**\n * Load the public key package for a group.\n *\n * Port of `load_public_key_package()` from cmd/sign/participant/finalize.rs.\n */\nfunction loadPublicKeyPackage(registryPath: string, groupId: ARID): LoadedPublicKeyPackage {\n const base = path.dirname(registryPath);\n\n // Try direct path first\n const directPath = path.join(base, \"group-state\", groupId.hex(), \"public_key_package.json\");\n if (fs.existsSync(directPath)) {\n const raw = JSON.parse(fs.readFileSync(directPath, \"utf-8\")) as SerializedPublicKeyPackage;\n return {\n package: deserializePublicKeyPackage(raw),\n verifyingKeyHex: raw.verifyingKey,\n };\n }\n\n // Fallback to collected_finalize.json (coordinator)\n const collectedPath = path.join(base, \"group-state\", groupId.hex(), \"collected_finalize.json\");\n if (fs.existsSync(collectedPath)) {\n const raw = JSON.parse(fs.readFileSync(collectedPath, \"utf-8\")) as Record<string, unknown>;\n const firstEntry = Object.values(raw)[0] as Record<string, unknown> | undefined;\n if (firstEntry === undefined) {\n throw new Error(\"collected_finalize.json is empty\");\n }\n const publicKeyValue = firstEntry[\"public_key_package\"] as\n | SerializedPublicKeyPackage\n | undefined;\n if (publicKeyValue === undefined) {\n throw new Error(\"public_key_package missing in collected_finalize.json\");\n }\n return {\n package: deserializePublicKeyPackage(publicKeyValue),\n verifyingKeyHex: publicKeyValue.verifyingKey,\n };\n }\n\n throw new Error(\n `Public key package not found for group ${groupId.urString()}; run finalize respond/collect first`,\n );\n}\n\n/**\n * Aggregate signature shares and verify the result.\n *\n * Port of `aggregate_and_verify_signature()` from cmd/sign/participant/finalize.rs.\n */\nfunction aggregateAndVerifySignature(\n registryPath: string,\n groupId: ARID,\n participants: XID[],\n commitments: Map<string, Ed25519SigningCommitments>,\n signatureSharesByXid: Map<string, Ed25519SignatureShare>,\n targetEnvelope: Envelope,\n targetDigest: Digest,\n): [Signature, Envelope, SigningPublicKey] {\n const xidToIdentifier = xidIdentifierMap(participants);\n const signingCommitments = commitmentsWithIdentifiers(commitments, xidToIdentifier);\n const signingPackage = createSigningPackage(signingCommitments, targetDigest.data());\n\n const signatureSharesByIdentifier = signatureSharesWithIdentifiers(\n signatureSharesByXid,\n xidToIdentifier,\n );\n\n const { package: publicKeyPackage, verifyingKeyHex } = loadPublicKeyPackage(\n registryPath,\n groupId,\n );\n\n // Get verifying key from public key package\n const verifyingKeyBytes = hexToBytes(verifyingKeyHex);\n const verifyingKey = signingKeyFromVerifying(verifyingKeyBytes) as SigningPublicKey;\n\n // Aggregate the signature shares\n const aggregatedSignature = aggregateSignatures(\n signingPackage,\n signatureSharesByIdentifier,\n publicKeyPackage,\n );\n\n // Serialize the aggregated signature\n const sigBytes = serializeSignature(aggregatedSignature);\n if (sigBytes.length !== 64) {\n throw new Error(\"Aggregated signature is not 64 bytes\");\n }\n const finalSignature = Signature.ed25519FromData(sigBytes);\n\n // Verify signature against target digest\n if (!verifyingKey.verify(finalSignature, targetDigest.data())) {\n throw new Error(\"Aggregated signature failed verification against target digest\");\n }\n\n // Create signed envelope\n const signedEnvelope = targetEnvelope.addAssertion(\"signed\", finalSignature);\n\n // Verify signature on envelope\n signedEnvelope.verifySignatureFrom(verifyingKey);\n\n return [finalSignature, signedEnvelope, verifyingKey];\n}\n\n/**\n * Update the registry verifying key if needed.\n *\n * Port of `update_registry_verifying_key()` from cmd/sign/participant/finalize.rs.\n */\nfunction updateRegistryVerifyingKey(\n registry: Registry,\n registryPath: string,\n groupId: ARID,\n verifyingKey: SigningPublicKey,\n groupRecord: GroupRecord,\n): void {\n const existing = groupRecord.verifyingKey();\n if (existing !== undefined) {\n if (existing.urString() !== verifyingKey.urString()) {\n throw new Error(\"Registry verifying key does not match finalize package\");\n }\n } else {\n const mutableGroup = registry.group(groupId);\n if (mutableGroup === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n mutableGroup.setVerifyingKey(verifyingKey);\n registry.save(registryPath);\n }\n}\n\n/**\n * Persist the final state to disk.\n *\n * Port of `persist_final_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction persistFinalState(\n registryPath: string,\n groupId: ARID,\n sessionId: ARID,\n signature: Signature,\n signedEnvelope: Envelope,\n signatureShares: Map<string, Ed25519SignatureShare>,\n shareState: ShareState,\n): void {\n const dir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n fs.mkdirSync(dir, { recursive: true });\n\n const finalPath = path.join(dir, \"final.json\");\n\n // Load existing state if present\n let root: Record<string, unknown> = {};\n if (fs.existsSync(finalPath)) {\n root = JSON.parse(fs.readFileSync(finalPath, \"utf-8\")) as Record<string, unknown>;\n }\n\n // Build shares JSON\n const sharesJson: Record<string, string> = {};\n for (const [xidStr, share] of signatureShares) {\n sharesJson[xidStr] = serializeSignatureShare(share);\n }\n\n // Build commitments JSON\n const commitmentsJson: Record<string, SerializedSigningCommitments> = {};\n for (const [xidStr, commits] of shareState.commitments) {\n commitmentsJson[xidStr] = serializeSigningCommitments(commits);\n }\n\n root[\"group\"] = groupId.urString();\n root[\"session\"] = sessionId.urString();\n root[\"signature\"] = signature.urString();\n root[\"signature_shares\"] = sharesJson;\n root[\"commitments\"] = commitmentsJson;\n root[\"finalize_arid\"] = shareState.finalizeArid.urString();\n root[\"signed_target\"] = signedEnvelope.urString();\n\n fs.writeFileSync(finalPath, JSON.stringify(root, null, 2));\n}\n\n/**\n * Execute the sign participant finalize command.\n *\n * Receives the finalize event with aggregated signature.\n *\n * Port of `finalize()` from cmd/sign/participant/finalize.rs.\n */\nexport async function finalize(\n client: StorageClient,\n options: SignFinalizeOptions,\n cwd: string,\n): Promise<SignFinalizeResult> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const sessionId = parseAridUr(options.sessionId);\n const groupHint =\n options.groupId !== undefined && options.groupId !== \"\"\n ? parseAridUr(options.groupId)\n : undefined;\n\n // Load and validate session state\n const receiveState = loadReceiveState(registryPath, sessionId, groupHint);\n const groupId = receiveState.groupId;\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n validateSessionState(receiveState, groupRecord, owner);\n\n const shareState = loadShareState(registryPath, groupId, sessionId);\n validateShareState(shareState, receiveState, groupRecord);\n\n // Fetch finalize event\n const sealedEvent = await fetchFinalizeEvent(\n client,\n shareState.finalizeArid,\n options.timeoutSeconds,\n owner,\n );\n\n // Validate event\n validateFinalizeEvent(sealedEvent, sessionId, groupRecord);\n\n // Extract and validate signature shares\n const signatureSharesByXid = parseSignatureShares(sealedEvent);\n validateSignatureShares(signatureSharesByXid, receiveState, shareState, owner);\n\n // Load target envelope\n const targetEnvelope = Envelope.fromURString(receiveState.targetUr);\n const targetDigest = targetEnvelope.subject().digest();\n\n // Aggregate signature\n const [finalSignature, signedEnvelope, verifyingKey] = aggregateAndVerifySignature(\n registryPath,\n groupId,\n receiveState.participants,\n shareState.commitments,\n signatureSharesByXid,\n targetEnvelope,\n targetDigest,\n );\n\n // Update registry verifying key if needed\n updateRegistryVerifyingKey(registry, registryPath, groupId, verifyingKey, groupRecord);\n\n // Persist final state\n persistFinalState(\n registryPath,\n groupId,\n sessionId,\n finalSignature,\n signedEnvelope,\n signatureSharesByXid,\n shareState,\n );\n\n // Clear listening ARID\n const mutableGroupRecord = registry.group(groupId);\n if (mutableGroupRecord !== undefined) {\n mutableGroupRecord.clearListeningAtArid();\n registry.save(registryPath);\n }\n\n const signatureStr = finalSignature.urString();\n const signedEnvelopeStr = signedEnvelope.urString();\n\n if (options.verbose === true) {\n console.log(signatureStr);\n console.log(signedEnvelopeStr);\n }\n\n return {\n signature: signatureStr,\n signedEnvelope: signedEnvelopeStr,\n };\n}\n","/**\n * Sign participant commands.\n *\n * Port of cmd/sign/participant/mod.rs from frost-hubert-rust.\n *\n * @module\n */\n\nexport * from \"./receive.js\";\nexport * from \"./round1.js\";\nexport * from \"./round2.js\";\nexport * from \"./finalize.js\";\n","/**\n * Sign command module.\n *\n * Port of cmd/sign/mod.rs from frost-hubert-rust.\n *\n * @module\n */\n\nexport * from \"./common.js\";\nexport * as coordinator from \"./coordinator/index.js\";\nexport * as participant from \"./participant/index.js\";\n"],"mappings":"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"}
|