@bcts/frost-hubert 1.0.0-alpha.22 → 1.0.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (174) hide show
  1. package/dist/bin/frost.cjs +347 -75
  2. package/dist/bin/frost.cjs.map +1 -1
  3. package/dist/bin/frost.mjs +347 -75
  4. package/dist/bin/frost.mjs.map +1 -1
  5. package/dist/busy-DkM2jAIZ.mjs +27 -0
  6. package/dist/busy-DkM2jAIZ.mjs.map +1 -0
  7. package/dist/busy-EZU7EKr6.cjs +38 -0
  8. package/dist/busy-EZU7EKr6.cjs.map +1 -0
  9. package/dist/{chunk-uaV2rQ02.cjs → chunk-CZWwpsFl.cjs} +22 -32
  10. package/dist/{chunk-ClPoSABd.mjs → chunk-CjcI7cDX.mjs} +6 -12
  11. package/dist/cmd/index.cjs +46 -43
  12. package/dist/cmd/index.d.cts +2 -4
  13. package/dist/cmd/index.d.mts +2 -4
  14. package/dist/cmd/index.mjs +7 -6
  15. package/dist/cmd-Bw9_i2_f.cjs +130 -0
  16. package/dist/cmd-Bw9_i2_f.cjs.map +1 -0
  17. package/dist/cmd-CS1uJtuD.mjs +113 -0
  18. package/dist/cmd-CS1uJtuD.mjs.map +1 -0
  19. package/dist/common-CvH6dFvQ.mjs +282 -0
  20. package/dist/common-CvH6dFvQ.mjs.map +1 -0
  21. package/dist/common-DUWvtc08.mjs +96 -0
  22. package/dist/common-DUWvtc08.mjs.map +1 -0
  23. package/dist/common-lKP5EzHy.cjs +372 -0
  24. package/dist/common-lKP5EzHy.cjs.map +1 -0
  25. package/dist/common-lThIvJmZ.cjs +114 -0
  26. package/dist/common-lThIvJmZ.cjs.map +1 -0
  27. package/dist/dkg/index.cjs +245 -7
  28. package/dist/dkg/index.cjs.map +1 -0
  29. package/dist/dkg/index.d.cts +2 -2
  30. package/dist/dkg/index.d.mts +2 -2
  31. package/dist/dkg/index.mjs +238 -2
  32. package/dist/dkg/index.mjs.map +1 -0
  33. package/dist/finalize-BRgJK-Xv.cjs +402 -0
  34. package/dist/finalize-BRgJK-Xv.cjs.map +1 -0
  35. package/dist/finalize-BfLgzn8f.cjs +303 -0
  36. package/dist/finalize-BfLgzn8f.cjs.map +1 -0
  37. package/dist/finalize-CNTDj6aS.mjs +389 -0
  38. package/dist/finalize-CNTDj6aS.mjs.map +1 -0
  39. package/dist/finalize-EC3ikHQq.mjs +252 -0
  40. package/dist/finalize-EC3ikHQq.mjs.map +1 -0
  41. package/dist/finalize-IA01t_Qq.mjs +290 -0
  42. package/dist/finalize-IA01t_Qq.mjs.map +1 -0
  43. package/dist/finalize-UPyI1yb1.cjs +265 -0
  44. package/dist/finalize-UPyI1yb1.cjs.map +1 -0
  45. package/dist/frost/index.cjs +8 -9
  46. package/dist/frost/index.cjs.map +1 -1
  47. package/dist/frost/index.mjs +2 -3
  48. package/dist/frost/index.mjs.map +1 -1
  49. package/dist/{group-invite-Dz1Jmiky.d.cts → index-B3c-80VS.d.cts} +25 -2
  50. package/dist/index-B3c-80VS.d.cts.map +1 -0
  51. package/dist/{index-CcvTi5EA.d.cts → index-BgbSGpxn.d.mts} +102 -80
  52. package/dist/index-BgbSGpxn.d.mts.map +1 -0
  53. package/dist/{registry-impl-CE76sTXQ.d.cts → index-C8QeHNwa.d.cts} +46 -2
  54. package/dist/index-C8QeHNwa.d.cts.map +1 -0
  55. package/dist/{group-invite-Wk9CIbHL.d.mts → index-D3QTWkEm.d.mts} +25 -2
  56. package/dist/index-D3QTWkEm.d.mts.map +1 -0
  57. package/dist/{registry-impl-BETn_lEO.d.mts → index-DVbWyOs7.d.mts} +46 -2
  58. package/dist/index-DVbWyOs7.d.mts.map +1 -0
  59. package/dist/{index-DNCPeLNM.d.mts → index-F1iNEAJR.d.cts} +102 -80
  60. package/dist/index-F1iNEAJR.d.cts.map +1 -0
  61. package/dist/index.cjs +72 -68
  62. package/dist/index.cjs.map +1 -1
  63. package/dist/index.d.cts +4 -7
  64. package/dist/index.d.cts.map +1 -1
  65. package/dist/index.d.mts +4 -7
  66. package/dist/index.d.mts.map +1 -1
  67. package/dist/index.mjs +11 -10
  68. package/dist/index.mjs.map +1 -1
  69. package/dist/invite-5277FQVT.cjs +274 -0
  70. package/dist/invite-5277FQVT.cjs.map +1 -0
  71. package/dist/invite-DUTcfTgX.cjs +109 -0
  72. package/dist/invite-DUTcfTgX.cjs.map +1 -0
  73. package/dist/invite-IU4n0dq2.mjs +96 -0
  74. package/dist/invite-IU4n0dq2.mjs.map +1 -0
  75. package/dist/invite-RU-OXTNS.mjs +219 -0
  76. package/dist/invite-RU-OXTNS.mjs.map +1 -0
  77. package/dist/parallel-D1R6ZGlY.cjs +318 -0
  78. package/dist/parallel-D1R6ZGlY.cjs.map +1 -0
  79. package/dist/parallel-D6zc6VW4.mjs +235 -0
  80. package/dist/parallel-D6zc6VW4.mjs.map +1 -0
  81. package/dist/proposed-participant-Dm1Eq6mX.cjs +141 -0
  82. package/dist/proposed-participant-Dm1Eq6mX.cjs.map +1 -0
  83. package/dist/proposed-participant-cWM7iUrO.mjs +129 -0
  84. package/dist/proposed-participant-cWM7iUrO.mjs.map +1 -0
  85. package/dist/receive-CAI-x4II.cjs +213 -0
  86. package/dist/receive-CAI-x4II.cjs.map +1 -0
  87. package/dist/receive-D2Nn68L7.mjs +188 -0
  88. package/dist/receive-D2Nn68L7.mjs.map +1 -0
  89. package/dist/receive-DA_KQEgk.mjs +177 -0
  90. package/dist/receive-DA_KQEgk.mjs.map +1 -0
  91. package/dist/receive-kZMsXhbK.cjs +190 -0
  92. package/dist/receive-kZMsXhbK.cjs.map +1 -0
  93. package/dist/registry/index.cjs +881 -13
  94. package/dist/registry/index.cjs.map +1 -0
  95. package/dist/registry/index.d.cts +1 -1
  96. package/dist/registry/index.d.mts +1 -1
  97. package/dist/registry/index.mjs +867 -2
  98. package/dist/registry/index.mjs.map +1 -0
  99. package/dist/{registry-FMU-ec5K.cjs → registry-9puTaRrD.cjs} +28 -31
  100. package/dist/registry-9puTaRrD.cjs.map +1 -0
  101. package/dist/{registry-BDnNV1Rk.mjs → registry-BpCwtrRt.mjs} +7 -10
  102. package/dist/{registry-BDnNV1Rk.mjs.map → registry-BpCwtrRt.mjs.map} +1 -1
  103. package/dist/round1-4Hyx8w0x.cjs +422 -0
  104. package/dist/round1-4Hyx8w0x.cjs.map +1 -0
  105. package/dist/round1-7v9LlE11.mjs +373 -0
  106. package/dist/round1-7v9LlE11.mjs.map +1 -0
  107. package/dist/round1-BHBjru1m.cjs +465 -0
  108. package/dist/round1-BHBjru1m.cjs.map +1 -0
  109. package/dist/round1-CMLKN2RR.mjs +195 -0
  110. package/dist/round1-CMLKN2RR.mjs.map +1 -0
  111. package/dist/round1-CWSXZx5R.cjs +208 -0
  112. package/dist/round1-CWSXZx5R.cjs.map +1 -0
  113. package/dist/round1-CcQCGlIT.mjs +208 -0
  114. package/dist/round1-CcQCGlIT.mjs.map +1 -0
  115. package/dist/round1-Cgm7j1kI.mjs +452 -0
  116. package/dist/round1-Cgm7j1kI.mjs.map +1 -0
  117. package/dist/round1-DQ0fnc1H.cjs +221 -0
  118. package/dist/round1-DQ0fnc1H.cjs.map +1 -0
  119. package/dist/round2-BWz9SQIi.cjs +305 -0
  120. package/dist/round2-BWz9SQIi.cjs.map +1 -0
  121. package/dist/round2-BkNRCXgS.mjs +292 -0
  122. package/dist/round2-BkNRCXgS.mjs.map +1 -0
  123. package/dist/round2-Bl2uK93U.mjs +450 -0
  124. package/dist/round2-Bl2uK93U.mjs.map +1 -0
  125. package/dist/round2-CdUT-AhH.cjs +499 -0
  126. package/dist/round2-CdUT-AhH.cjs.map +1 -0
  127. package/dist/round2-DOA3rnV-.mjs +280 -0
  128. package/dist/round2-DOA3rnV-.mjs.map +1 -0
  129. package/dist/round2-Dg24w-TU.mjs +397 -0
  130. package/dist/round2-Dg24w-TU.mjs.map +1 -0
  131. package/dist/round2-LylCa84n.cjs +293 -0
  132. package/dist/round2-LylCa84n.cjs.map +1 -0
  133. package/dist/round2-o2Q-GMbX.cjs +410 -0
  134. package/dist/round2-o2Q-GMbX.cjs.map +1 -0
  135. package/dist/storage-B-Gu68-O.cjs +79 -0
  136. package/dist/storage-B-Gu68-O.cjs.map +1 -0
  137. package/dist/storage-Bkkliz0K.mjs +74 -0
  138. package/dist/storage-Bkkliz0K.mjs.map +1 -0
  139. package/package.json +17 -17
  140. package/src/bin/frost.ts +849 -128
  141. package/src/cmd/common.ts +19 -1
  142. package/src/cmd/dkg/common.ts +97 -10
  143. package/src/cmd/dkg/coordinator/invite.ts +5 -2
  144. package/src/cmd/dkg/participant/finalize.ts +52 -18
  145. package/src/cmd/dkg/participant/round1.ts +39 -38
  146. package/src/cmd/dkg/participant/round2.ts +60 -26
  147. package/src/cmd/sign/coordinator/round2.ts +5 -1
  148. package/src/cmd/sign/participant/finalize.ts +6 -2
  149. package/src/cmd/sign/participant/receive.ts +5 -2
  150. package/src/dkg/group-invite.ts +12 -2
  151. package/src/dkg/proposed-participant.ts +33 -5
  152. package/src/frost/index.ts +1 -1
  153. package/src/registry/owner-record.ts +13 -2
  154. package/src/registry/participant-record.ts +36 -4
  155. package/src/registry/registry-impl.ts +74 -18
  156. package/dist/group-invite-CrbOabFL.cjs +0 -368
  157. package/dist/group-invite-CrbOabFL.cjs.map +0 -1
  158. package/dist/group-invite-Dz1Jmiky.d.cts.map +0 -1
  159. package/dist/group-invite-RPElq-fm.mjs +0 -338
  160. package/dist/group-invite-RPElq-fm.mjs.map +0 -1
  161. package/dist/group-invite-Wk9CIbHL.d.mts.map +0 -1
  162. package/dist/index-CcvTi5EA.d.cts.map +0 -1
  163. package/dist/index-DNCPeLNM.d.mts.map +0 -1
  164. package/dist/registry-FMU-ec5K.cjs.map +0 -1
  165. package/dist/registry-impl-BETn_lEO.d.mts.map +0 -1
  166. package/dist/registry-impl-C7w4awTv.cjs +0 -865
  167. package/dist/registry-impl-C7w4awTv.cjs.map +0 -1
  168. package/dist/registry-impl-CE76sTXQ.d.cts.map +0 -1
  169. package/dist/registry-impl-eYXVSPwM.mjs +0 -797
  170. package/dist/registry-impl-eYXVSPwM.mjs.map +0 -1
  171. package/dist/sign-2bOp18Fs.cjs +0 -4875
  172. package/dist/sign-2bOp18Fs.cjs.map +0 -1
  173. package/dist/sign-D8C3HJ4B.mjs +0 -4736
  174. package/dist/sign-D8C3HJ4B.mjs.map +0 -1
@@ -0,0 +1,499 @@
1
+ const require_chunk = require("./chunk-CZWwpsFl.cjs");
2
+ const require_registry_index = require("./registry/index.cjs");
3
+ const require_common = require("./common-lKP5EzHy.cjs");
4
+ const require_busy = require("./busy-EZU7EKr6.cjs");
5
+ const require_parallel = require("./parallel-D1R6ZGlY.cjs");
6
+ let _bcts_components = require("@bcts/components");
7
+ let _bcts_envelope = require("@bcts/envelope");
8
+ let _bcts_gstp = require("@bcts/gstp");
9
+ let node_fs = require("node:fs");
10
+ node_fs = require_chunk.__toESM(node_fs, 1);
11
+ let node_path = require("node:path");
12
+ node_path = require_chunk.__toESM(node_path, 1);
13
+ //#region src/cmd/dkg/coordinator/round2.ts
14
+ /**
15
+ * Copyright © 2023-2026 Blockchain Commons, LLC
16
+ * Copyright © 2025-2026 Parity Technologies
17
+ *
18
+ *
19
+ * DKG coordinator round 2 command.
20
+ *
21
+ * Port of cmd/dkg/coordinator/round2.rs from frost-hubert-rust.
22
+ *
23
+ * @module
24
+ */
25
+ var round2_exports = /* @__PURE__ */ require_chunk.__exportAll({
26
+ buildFinalizeRequestForParticipant: () => buildFinalizeRequestForParticipant,
27
+ collectRound2Parallel: () => collectRound2Parallel,
28
+ dispatchFinalizeRequestsParallel: () => dispatchFinalizeRequestsParallel,
29
+ persistRound2Packages: () => persistRound2Packages,
30
+ round2: () => round2,
31
+ updatePendingForFinalizeFromCollection: () => updatePendingForFinalizeFromCollection,
32
+ validateAndExtractRound2Response: () => validateAndExtractRound2Response
33
+ });
34
+ /**
35
+ * Validate that the owner is the coordinator of the group.
36
+ *
37
+ * Port of coordinator check from round2.rs lines 86-94.
38
+ */
39
+ function validateCoordinator(groupRecord, ownerXid) {
40
+ if (groupRecord.coordinator().xid().urString() !== ownerXid.urString()) throw new Error(`Only the coordinator can collect Round 2 responses and send finalize packages. Coordinator: ${groupRecord.coordinator().xid().urString()}, Owner: ${ownerXid.urString()}`);
41
+ }
42
+ /**
43
+ * Validate envelope and extract Round 2 data (for parallel fetch).
44
+ *
45
+ * Port of `validate_and_extract_round2_response()` from round2.rs lines 646-708.
46
+ */
47
+ function validateAndExtractRound2Response(envelope, coordinatorKeys, expectedGroupId, expectedSender) {
48
+ const now = /* @__PURE__ */ new Date();
49
+ let sealed;
50
+ try {
51
+ sealed = _bcts_gstp.SealedResponse.tryFromEncryptedEnvelope(envelope, void 0, now, coordinatorKeys);
52
+ } catch (err) {
53
+ return { rejected: `Failed to decrypt/parse response: ${err instanceof Error ? err.message : String(err)}` };
54
+ }
55
+ if (!sealed.isOk()) try {
56
+ return { rejected: `Participant reported error: ${sealed.error().optionalObjectForPredicate("reason")?.extractString() ?? "unknown reason"}` };
57
+ } catch {
58
+ return { rejected: "Participant reported error: unknown reason" };
59
+ }
60
+ let result;
61
+ try {
62
+ result = sealed.result();
63
+ } catch {
64
+ return { rejected: "Response has no result envelope" };
65
+ }
66
+ try {
67
+ result.checkSubjectUnit();
68
+ result.checkType("dkgRound2Response");
69
+ } catch (err) {
70
+ return { rejected: `Invalid response type: ${err instanceof Error ? err.message : String(err)}` };
71
+ }
72
+ try {
73
+ const groupId = result.objectForPredicate("group").extractSubject((cbor) => _bcts_components.ARID.fromTaggedCbor(cbor));
74
+ if (groupId.urString() !== expectedGroupId.urString()) return { rejected: `Response group ID ${groupId.urString()} does not match expected ${expectedGroupId.urString()}` };
75
+ } catch (err) {
76
+ return { rejected: `Failed to extract group: ${err instanceof Error ? err.message : String(err)}` };
77
+ }
78
+ try {
79
+ const senderXid = result.objectForPredicate("participant").extractSubject((cbor) => _bcts_components.XID.fromTaggedCbor(cbor));
80
+ if (senderXid.urString() !== expectedSender.urString()) return { rejected: `Response participant ${senderXid.urString()} does not match expected ${expectedSender.urString()}` };
81
+ } catch (err) {
82
+ return { rejected: `Failed to extract participant: ${err instanceof Error ? err.message : String(err)}` };
83
+ }
84
+ let nextResponseArid;
85
+ try {
86
+ nextResponseArid = result.objectForPredicate("response_arid").extractSubject((cbor) => _bcts_components.ARID.fromTaggedCbor(cbor));
87
+ } catch (err) {
88
+ return { rejected: `Failed to extract response_arid: ${err instanceof Error ? err.message : String(err)}` };
89
+ }
90
+ const packages = [];
91
+ try {
92
+ const pkgEnvelopes = result.objectsForPredicate("round2Package");
93
+ for (const pkgEnv of pkgEnvelopes) {
94
+ const recipient = pkgEnv.objectForPredicate("recipient").extractSubject((cbor) => _bcts_components.XID.fromTaggedCbor(cbor));
95
+ const pkgJsonStr = pkgEnv.extractString();
96
+ const pkg = JSON.parse(pkgJsonStr);
97
+ packages.push([recipient, pkg]);
98
+ }
99
+ } catch (err) {
100
+ return { rejected: `Failed to extract round2 packages: ${err instanceof Error ? err.message : String(err)}` };
101
+ }
102
+ return {
103
+ packages,
104
+ nextResponseArid
105
+ };
106
+ }
107
+ /**
108
+ * Fetch a Round 2 response sequentially.
109
+ *
110
+ * Port of `fetch_round2_response()` from round2.rs lines 364-442.
111
+ */
112
+ async function fetchRound2Response(client, arid, timeout, coordinatorKeys, expectedGroup, expectedSender) {
113
+ const envelope = await require_busy.getWithIndicator(client, arid, expectedSender.urString(), timeout, require_common.isVerbose());
114
+ if (envelope === null || envelope === void 0) throw new Error("Response not found in Hubert storage");
115
+ const result = validateAndExtractRound2Response(envelope, coordinatorKeys, expectedGroup, expectedSender);
116
+ if ("rejected" in result) throw new Error(result.rejected);
117
+ return {
118
+ packages: result.packages,
119
+ nextResponseArid: result.nextResponseArid
120
+ };
121
+ }
122
+ /**
123
+ * Collect Round 2 responses sequentially.
124
+ *
125
+ * Port of `collect_round2()` from round2.rs lines 216-357.
126
+ */
127
+ async function collectRound2(client, registryPath, registry, coordinatorKeys, groupId, pendingRequests, timeout) {
128
+ if (require_common.isVerbose()) console.error(`Collecting Round 2 responses from ${pendingRequests.len()} participants...`);
129
+ const allPackages = /* @__PURE__ */ new Map();
130
+ const nextResponseArids = [];
131
+ const errors = [];
132
+ for (const [participantXid, collectFromArid] of pendingRequests.iterCollect()) {
133
+ const participantName = registry.participant(participantXid)?.petName() ?? participantXid.urString();
134
+ if (require_common.isVerbose()) console.error(`${participantName}...`);
135
+ try {
136
+ const collected = await fetchRound2Response(client, collectFromArid, timeout, coordinatorKeys, groupId, participantXid);
137
+ allPackages.set(participantXid.urString(), collected.packages);
138
+ nextResponseArids.push([participantXid, collected.nextResponseArid]);
139
+ } catch (err) {
140
+ if (require_common.isVerbose()) console.error(`error: ${err instanceof Error ? err.message : String(err)}`);
141
+ errors.push([participantXid, err instanceof Error ? err.message : String(err)]);
142
+ }
143
+ }
144
+ if (errors.length > 0) {
145
+ if (require_common.isVerbose()) {
146
+ console.error();
147
+ console.error(`Failed to collect from ${errors.length} participants:`);
148
+ }
149
+ for (const [xid, error] of errors) console.error(` ${xid.urString()}: ${error}`);
150
+ throw new Error(`Round 2 collection incomplete: ${errors.length} of ${pendingRequests.len()} responses failed`);
151
+ }
152
+ const displayPath = persistRound2PackagesFromMap(registryPath, groupId, allPackages, nextResponseArids);
153
+ const newPending = new require_registry_index.PendingRequests();
154
+ for (const [xid, sendToArid] of nextResponseArids) newPending.addSendOnly(xid, sendToArid);
155
+ const groupRecord = registry.group(groupId);
156
+ if (groupRecord === void 0) throw new Error("Group not found in registry");
157
+ groupRecord.setPendingRequests(newPending);
158
+ registry.save(registryPath);
159
+ return {
160
+ packages: allPackages,
161
+ nextResponseArids,
162
+ displayPath
163
+ };
164
+ }
165
+ /**
166
+ * Persist Round 2 packages from a Map (sequential collection).
167
+ */
168
+ function persistRound2PackagesFromMap(registryPath, groupId, allPackages, nextResponseArids) {
169
+ const stateDir = require_common.groupStateDir(registryPath, groupId.hex());
170
+ node_fs.mkdirSync(stateDir, { recursive: true });
171
+ const collectedPath = node_path.join(stateDir, "collected_round2.json");
172
+ const root = {};
173
+ for (const [senderUrString, packages] of allPackages) {
174
+ const senderMap = {};
175
+ const responseArid = nextResponseArids.find(([xid]) => xid.urString() === senderUrString)?.[1];
176
+ if (responseArid !== void 0) senderMap["response_arid"] = responseArid.urString();
177
+ const packagesJson = {};
178
+ for (const [recipient, pkg] of packages) packagesJson[recipient.urString()] = pkg;
179
+ senderMap["packages"] = packagesJson;
180
+ root[senderUrString] = senderMap;
181
+ }
182
+ node_fs.writeFileSync(collectedPath, JSON.stringify(root, null, 2));
183
+ const cwd = process.cwd();
184
+ if (collectedPath.startsWith(cwd)) return collectedPath.slice(cwd.length + 1);
185
+ return collectedPath;
186
+ }
187
+ /**
188
+ * Collect Round 2 responses in parallel with progress display.
189
+ *
190
+ * Port of `collect_round2_parallel()` from round2.rs lines 607-643.
191
+ */
192
+ async function collectRound2Parallel(client, registry, pendingRequests, coordinatorKeys, expectedGroupId, timeout) {
193
+ const requests = [];
194
+ for (const [xid, arid] of pendingRequests.iterCollect()) {
195
+ const name = registry.participant(xid)?.petName() ?? xid.urString();
196
+ requests.push([
197
+ xid,
198
+ arid,
199
+ name
200
+ ]);
201
+ }
202
+ return require_parallel.parallelFetch(client, requests, (envelope, xid) => validateAndExtractRound2Response(envelope, coordinatorKeys, expectedGroupId, xid), require_parallel.parallelFetchConfigWithTimeout(timeout));
203
+ }
204
+ /**
205
+ * Persist Round 2 packages from parallel collection results.
206
+ *
207
+ * Port of `persist_round2_packages()` from round2.rs lines 712-758.
208
+ */
209
+ function persistRound2Packages(registryPath, groupId, successes) {
210
+ const stateDir = require_common.groupStateDir(registryPath, groupId.hex());
211
+ node_fs.mkdirSync(stateDir, { recursive: true });
212
+ const collectedPath = node_path.join(stateDir, "collected_round2.json");
213
+ const root = {};
214
+ for (const [sender, data] of successes) {
215
+ const senderMap = {};
216
+ senderMap["response_arid"] = data.nextResponseArid.urString();
217
+ const packagesJson = {};
218
+ for (const [recipient, pkg] of data.packages) packagesJson[recipient.urString()] = pkg;
219
+ senderMap["packages"] = packagesJson;
220
+ root[sender.urString()] = senderMap;
221
+ }
222
+ node_fs.writeFileSync(collectedPath, JSON.stringify(root, null, 2));
223
+ const cwd = process.cwd();
224
+ if (collectedPath.startsWith(cwd)) return collectedPath.slice(cwd.length + 1);
225
+ return collectedPath;
226
+ }
227
+ /**
228
+ * Update pending requests from parallel collection results.
229
+ *
230
+ * Port of `update_pending_for_finalize_from_collection()` from round2.rs lines 761-777.
231
+ */
232
+ function updatePendingForFinalizeFromCollection(registry, registryPath, groupId, successes) {
233
+ const newPending = new require_registry_index.PendingRequests();
234
+ for (const [xid, data] of successes) newPending.addSendOnly(xid, data.nextResponseArid);
235
+ const groupRecord = registry.group(groupId);
236
+ if (groupRecord === void 0) throw new Error("Group not found in registry");
237
+ groupRecord.setPendingRequests(newPending);
238
+ registry.save(registryPath);
239
+ }
240
+ /**
241
+ * Gather packages FOR a specific recipient (from all other senders).
242
+ *
243
+ * Port of `gather_packages_for_recipient()` from round2.rs lines 552-571.
244
+ */
245
+ function gatherPackagesForRecipient(recipient, allPackages) {
246
+ const result = [];
247
+ for (const [senderUrString, packages] of allPackages) for (const [rcpt, pkg] of packages) if (rcpt.urString() === recipient.urString()) {
248
+ const { XID: XIDClass } = require("@bcts/components");
249
+ const sender = XIDClass.fromURString(senderUrString);
250
+ result.push([sender, pkg]);
251
+ }
252
+ if (result.length === 0) throw new Error(`No round2 packages found for recipient ${recipient.urString()}`);
253
+ return result;
254
+ }
255
+ /**
256
+ * Build a finalize request for a participant.
257
+ *
258
+ * Port of `build_finalize_request_for_participant()` from round2.rs lines 575-594.
259
+ */
260
+ function buildFinalizeRequestForParticipant(sender, groupId, responseArid, packages) {
261
+ let request = _bcts_gstp.SealedRequest.new("dkgFinalize", _bcts_components.ARID.new(), sender).withParameter("group", groupId).withParameter("responseArid", responseArid);
262
+ for (const [pkgSender, pkg] of packages) {
263
+ const encoded = JSON.stringify(pkg);
264
+ const pkgEnvelope = _bcts_envelope.Envelope.new(encoded).addAssertion("sender", pkgSender);
265
+ request = request.withParameter("round2Package", pkgEnvelope);
266
+ }
267
+ return request;
268
+ }
269
+ /**
270
+ * Send finalize requests sequentially.
271
+ *
272
+ * Port of `send_finalize_requests()` from round2.rs lines 444-550.
273
+ */
274
+ async function sendFinalizeRequests(client, registryPath, registry, coordinator, groupId, collection, preview) {
275
+ const signerPrivateKeys = coordinator.inceptionPrivateKeys();
276
+ if (signerPrivateKeys === void 0) throw new Error("Coordinator XID document has no signing keys");
277
+ const validUntil = new Date(Date.now() + 3600 * 1e3);
278
+ const participantInfo = [];
279
+ for (const [xid, sendToArid] of collection.nextResponseArids) {
280
+ const record = registry.participant(xid);
281
+ if (record === void 0) throw new Error(`Participant ${xid.urString()} not found in registry`);
282
+ const collectFromArid = _bcts_components.ARID.new();
283
+ participantInfo.push([
284
+ xid,
285
+ record.xidDocument(),
286
+ sendToArid,
287
+ collectFromArid
288
+ ]);
289
+ }
290
+ if (require_common.isVerbose()) console.error(`Sending finalize packages to ${participantInfo.length} participants...`);
291
+ else console.error();
292
+ let previewOutput;
293
+ for (const [xid, recipientDoc, sendToArid, collectFromArid] of participantInfo) {
294
+ const participantName = registry.participant(xid)?.petName() ?? xid.urString();
295
+ if (require_common.isVerbose()) console.error(`${participantName}...`);
296
+ const request = buildFinalizeRequestForParticipant(coordinator, groupId, collectFromArid, gatherPackagesForRecipient(xid, collection.packages));
297
+ if (preview && previewOutput === void 0) previewOutput = [participantName, request.toEnvelope(validUntil, signerPrivateKeys, void 0).urString()];
298
+ await require_busy.putWithIndicator(client, sendToArid, request.toEnvelopeForRecipients(validUntil, signerPrivateKeys, [recipientDoc]), participantName, require_common.isVerbose());
299
+ }
300
+ const newPendingRequests = new require_registry_index.PendingRequests();
301
+ for (const [xid, , , collectFromArid] of participantInfo) newPendingRequests.addCollectOnly(xid, collectFromArid);
302
+ const groupRecord = registry.group(groupId);
303
+ if (groupRecord === void 0) throw new Error("Group not found in registry");
304
+ groupRecord.setPendingRequests(newPendingRequests);
305
+ registry.save(registryPath);
306
+ return previewOutput;
307
+ }
308
+ /**
309
+ * Dispatch finalize requests in parallel.
310
+ *
311
+ * Port of `dispatch_finalize_requests_parallel()` from round2.rs lines 780-900.
312
+ */
313
+ async function dispatchFinalizeRequestsParallel(client, registry, registryPath, coordinator, groupId, successes, preview) {
314
+ const signerPrivateKeys = coordinator.inceptionPrivateKeys();
315
+ if (signerPrivateKeys === void 0) throw new Error("Coordinator XID document has no signing keys");
316
+ const validUntil = new Date(Date.now() + 3600 * 1e3);
317
+ const allPackages = /* @__PURE__ */ new Map();
318
+ for (const [xid, data] of successes) allPackages.set(xid.urString(), data.packages);
319
+ const messages = [];
320
+ const collectArids = [];
321
+ let previewOutput;
322
+ for (const [xid, data] of successes) {
323
+ const record = registry.participant(xid);
324
+ if (record === void 0) throw new Error(`Participant ${xid.urString()} not found in registry`);
325
+ const recipientDoc = record.xidDocument();
326
+ const participantName = record.petName() ?? xid.urString();
327
+ const collectFromArid = _bcts_components.ARID.new();
328
+ collectArids.push([xid, collectFromArid]);
329
+ const request = buildFinalizeRequestForParticipant(coordinator, groupId, collectFromArid, gatherPackagesForRecipient(xid, allPackages));
330
+ if (preview && previewOutput === void 0) previewOutput = [participantName, request.toEnvelope(validUntil, signerPrivateKeys, void 0).urString()];
331
+ const sealedEnvelope = request.toEnvelopeForRecipients(validUntil, signerPrivateKeys, [recipientDoc]);
332
+ messages.push([
333
+ xid,
334
+ data.nextResponseArid,
335
+ sealedEnvelope,
336
+ participantName
337
+ ]);
338
+ }
339
+ console.error();
340
+ const failures = (await require_parallel.parallelSend(client, messages, require_common.isVerbose())).filter(([, err]) => err !== null);
341
+ if (failures.length > 0) {
342
+ for (const [xid, error] of failures) if (error !== null) console.error(`Failed to send to ${xid.urString()}: ${error.message}`);
343
+ throw new Error(`Failed to send finalize requests to ${failures.length} participants`);
344
+ }
345
+ const newPendingRequests = new require_registry_index.PendingRequests();
346
+ for (const [xid, collectFromArid] of collectArids) newPendingRequests.addCollectOnly(xid, collectFromArid);
347
+ const groupRecord = registry.group(groupId);
348
+ if (groupRecord === void 0) throw new Error("Group not found in registry");
349
+ groupRecord.setPendingRequests(newPendingRequests);
350
+ registry.save(registryPath);
351
+ return previewOutput;
352
+ }
353
+ /**
354
+ * Print summary for parallel collection.
355
+ *
356
+ * Port of `print_summary_parallel()` from round2.rs lines 903-964.
357
+ */
358
+ function printSummaryParallel(collection, displayPath, preview) {
359
+ if (collection.rejections.length > 0) {
360
+ console.error();
361
+ console.error("Rejections:");
362
+ for (const [xid, reason] of collection.rejections) console.error(` ${xid.urString()}: ${reason}`);
363
+ }
364
+ if (collection.errors.length > 0) {
365
+ console.error();
366
+ console.error("Errors:");
367
+ for (const [xid, error] of collection.errors) console.error(` ${xid.urString()}: ${error}`);
368
+ }
369
+ if (collection.timeouts.length > 0) {
370
+ console.error();
371
+ console.error("Timeouts:");
372
+ for (const xid of collection.timeouts) console.error(` ${xid.urString()}`);
373
+ }
374
+ if (!collection.allSucceeded()) {
375
+ console.error();
376
+ console.error(`Round 2 collection incomplete: ${collection.successes.length} succeeded, ${collection.rejections.length} rejected, ${collection.errors.length} errors, ${collection.timeouts.length} timeouts`);
377
+ return;
378
+ }
379
+ if (preview !== void 0) {
380
+ const [participantName, ur] = preview;
381
+ if (require_common.isVerbose()) {
382
+ console.error(`# Finalize preview for ${participantName}`);
383
+ console.error();
384
+ }
385
+ console.error(`Collected ${collection.successes.length} Round 2 responses to ${displayPath} and sent ${collection.successes.length} finalize requests.`);
386
+ console.log(ur);
387
+ } else if (require_common.isVerbose()) {
388
+ console.error();
389
+ console.error(`Collected ${collection.successes.length} Round 2 responses to ${displayPath} and sent ${collection.successes.length} finalize requests.`);
390
+ }
391
+ }
392
+ /**
393
+ * Execute the DKG coordinator round 2 command.
394
+ *
395
+ * Collects Round 2 responses and sends finalize packages.
396
+ *
397
+ * Port of `CommandArgs::exec()` from cmd/dkg/coordinator/round2.rs lines 59-203.
398
+ */
399
+ async function round2(client, options, cwd) {
400
+ const registryPath = require_registry_index.resolveRegistryPath(options.registryPath, cwd);
401
+ const registry = require_registry_index.Registry.load(registryPath);
402
+ const owner = registry.owner();
403
+ if (owner === void 0) throw new Error("Registry owner is required");
404
+ const ownerDoc = owner.xidDocument();
405
+ const groupId = require_common.parseAridUr(options.groupId);
406
+ const groupRecord = registry.group(groupId);
407
+ if (groupRecord === void 0) throw new Error(`Group ${options.groupId} not found in registry`);
408
+ validateCoordinator(groupRecord, owner.xid());
409
+ const pendingRequests = groupRecord.pendingRequests();
410
+ if (pendingRequests.isEmpty()) throw new Error("No pending requests for this group. Did you run 'frost dkg coordinator round1'?");
411
+ const coordinatorKeys = ownerDoc.inceptionPrivateKeys();
412
+ if (coordinatorKeys === void 0) throw new Error("Coordinator XID document has no private keys");
413
+ if (options.parallel === true) {
414
+ const collection = await collectRound2Parallel(client, registry, pendingRequests, coordinatorKeys, groupId, options.timeoutSeconds);
415
+ const displayPath = persistRound2Packages(registryPath, groupId, collection.successes);
416
+ updatePendingForFinalizeFromCollection(registry, registryPath, groupId, collection.successes);
417
+ printSummaryParallel(collection, displayPath, await dispatchFinalizeRequestsParallel(client, registry, registryPath, ownerDoc, groupId, collection.successes, options.preview ?? false));
418
+ return {
419
+ accepted: collection.successes.length,
420
+ rejected: collection.rejections.length,
421
+ errors: collection.errors.length,
422
+ timeouts: collection.timeouts.length,
423
+ displayPath
424
+ };
425
+ } else {
426
+ const collection = await collectRound2(client, registryPath, registry, coordinatorKeys, groupId, pendingRequests, options.timeoutSeconds);
427
+ const preview = await sendFinalizeRequests(client, registryPath, registry, ownerDoc, groupId, collection, options.preview ?? false);
428
+ if (preview !== void 0) {
429
+ const [participantName, ur] = preview;
430
+ if (require_common.isVerbose()) {
431
+ console.error(`# Finalize preview for ${participantName}`);
432
+ console.error();
433
+ }
434
+ console.error(`Collected ${collection.packages.size} Round 2 responses to ${collection.displayPath} and sent ${collection.nextResponseArids.length} finalize requests.`);
435
+ console.log(ur);
436
+ } else if (require_common.isVerbose()) {
437
+ console.error();
438
+ console.error(`Collected ${collection.packages.size} Round 2 responses to ${collection.displayPath} and sent ${collection.nextResponseArids.length} finalize requests.`);
439
+ }
440
+ return {
441
+ accepted: collection.packages.size,
442
+ rejected: 0,
443
+ errors: 0,
444
+ timeouts: 0,
445
+ displayPath: collection.displayPath
446
+ };
447
+ }
448
+ }
449
+ //#endregion
450
+ Object.defineProperty(exports, "buildFinalizeRequestForParticipant", {
451
+ enumerable: true,
452
+ get: function() {
453
+ return buildFinalizeRequestForParticipant;
454
+ }
455
+ });
456
+ Object.defineProperty(exports, "collectRound2Parallel", {
457
+ enumerable: true,
458
+ get: function() {
459
+ return collectRound2Parallel;
460
+ }
461
+ });
462
+ Object.defineProperty(exports, "dispatchFinalizeRequestsParallel", {
463
+ enumerable: true,
464
+ get: function() {
465
+ return dispatchFinalizeRequestsParallel;
466
+ }
467
+ });
468
+ Object.defineProperty(exports, "persistRound2Packages", {
469
+ enumerable: true,
470
+ get: function() {
471
+ return persistRound2Packages;
472
+ }
473
+ });
474
+ Object.defineProperty(exports, "round2", {
475
+ enumerable: true,
476
+ get: function() {
477
+ return round2;
478
+ }
479
+ });
480
+ Object.defineProperty(exports, "round2_exports", {
481
+ enumerable: true,
482
+ get: function() {
483
+ return round2_exports;
484
+ }
485
+ });
486
+ Object.defineProperty(exports, "updatePendingForFinalizeFromCollection", {
487
+ enumerable: true,
488
+ get: function() {
489
+ return updatePendingForFinalizeFromCollection;
490
+ }
491
+ });
492
+ Object.defineProperty(exports, "validateAndExtractRound2Response", {
493
+ enumerable: true,
494
+ get: function() {
495
+ return validateAndExtractRound2Response;
496
+ }
497
+ });
498
+
499
+ //# sourceMappingURL=round2-CdUT-AhH.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"round2-CdUT-AhH.cjs","names":["SealedResponse","ARID","XID","getWithIndicator","isVerbose","PendingRequests","groupStateDir","path","parallelFetch","parallelFetchConfigWithTimeout","SealedRequest","Envelope","putWithIndicator","parallelSend","resolveRegistryPath","Registry","parseAridUr"],"sources":["../src/cmd/dkg/coordinator/round2.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\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"],"mappings":"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"}