@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.
Files changed (114) hide show
  1. package/LICENSE +48 -0
  2. package/README.md +35 -0
  3. package/dist/bin/frost.cjs +109 -0
  4. package/dist/bin/frost.cjs.map +1 -0
  5. package/dist/bin/frost.d.cts +1 -0
  6. package/dist/bin/frost.d.mts +1 -0
  7. package/dist/bin/frost.mjs +109 -0
  8. package/dist/bin/frost.mjs.map +1 -0
  9. package/dist/chunk-CQwRTUmo.cjs +53 -0
  10. package/dist/chunk-D3JzZLW2.mjs +21 -0
  11. package/dist/cmd/index.cjs +45 -0
  12. package/dist/cmd/index.d.cts +4 -0
  13. package/dist/cmd/index.d.mts +4 -0
  14. package/dist/cmd/index.mjs +7 -0
  15. package/dist/cmd-C8pmNd28.mjs +4664 -0
  16. package/dist/cmd-C8pmNd28.mjs.map +1 -0
  17. package/dist/cmd-CxUgryx_.cjs +4803 -0
  18. package/dist/cmd-CxUgryx_.cjs.map +1 -0
  19. package/dist/dkg/index.cjs +7 -0
  20. package/dist/dkg/index.d.cts +2 -0
  21. package/dist/dkg/index.d.mts +2 -0
  22. package/dist/dkg/index.mjs +3 -0
  23. package/dist/dkg-D4RcblWl.cjs +364 -0
  24. package/dist/dkg-D4RcblWl.cjs.map +1 -0
  25. package/dist/dkg-DqGrAV81.mjs +334 -0
  26. package/dist/dkg-DqGrAV81.mjs.map +1 -0
  27. package/dist/frost/index.cjs +37 -0
  28. package/dist/frost/index.d.cts +207 -0
  29. package/dist/frost/index.d.cts.map +1 -0
  30. package/dist/frost/index.d.mts +207 -0
  31. package/dist/frost/index.d.mts.map +1 -0
  32. package/dist/frost/index.mjs +3 -0
  33. package/dist/frost-CMH1K0Cw.cjs +511 -0
  34. package/dist/frost-CMH1K0Cw.cjs.map +1 -0
  35. package/dist/frost-Csp0IOrd.mjs +326 -0
  36. package/dist/frost-Csp0IOrd.mjs.map +1 -0
  37. package/dist/index-BGVoWW5P.d.cts +172 -0
  38. package/dist/index-BGVoWW5P.d.cts.map +1 -0
  39. package/dist/index-BJeUYrdE.d.mts +396 -0
  40. package/dist/index-BJeUYrdE.d.mts.map +1 -0
  41. package/dist/index-ByMDUYKw.d.mts +1098 -0
  42. package/dist/index-ByMDUYKw.d.mts.map +1 -0
  43. package/dist/index-DejLkr_F.d.mts +172 -0
  44. package/dist/index-DejLkr_F.d.mts.map +1 -0
  45. package/dist/index-Dib1OE-e.d.cts +1098 -0
  46. package/dist/index-Dib1OE-e.d.cts.map +1 -0
  47. package/dist/index-DnvBKgec.d.cts +396 -0
  48. package/dist/index-DnvBKgec.d.cts.map +1 -0
  49. package/dist/index.cjs +85 -0
  50. package/dist/index.cjs.map +1 -0
  51. package/dist/index.d.cts +15 -0
  52. package/dist/index.d.cts.map +1 -0
  53. package/dist/index.d.mts +15 -0
  54. package/dist/index.d.mts.map +1 -0
  55. package/dist/index.mjs +24 -0
  56. package/dist/index.mjs.map +1 -0
  57. package/dist/registry/index.cjs +13 -0
  58. package/dist/registry/index.d.cts +2 -0
  59. package/dist/registry/index.d.mts +2 -0
  60. package/dist/registry/index.mjs +3 -0
  61. package/dist/registry-CBjRRqNv.mjs +144 -0
  62. package/dist/registry-CBjRRqNv.mjs.map +1 -0
  63. package/dist/registry-CWp2amuo.mjs +789 -0
  64. package/dist/registry-CWp2amuo.mjs.map +1 -0
  65. package/dist/registry-D5yh293y.cjs +857 -0
  66. package/dist/registry-D5yh293y.cjs.map +1 -0
  67. package/dist/registry-DNUNW6SH.cjs +163 -0
  68. package/dist/registry-DNUNW6SH.cjs.map +1 -0
  69. package/package.json +119 -0
  70. package/src/bin/frost.ts +218 -0
  71. package/src/cmd/busy.ts +64 -0
  72. package/src/cmd/check.ts +20 -0
  73. package/src/cmd/common.ts +40 -0
  74. package/src/cmd/dkg/common.ts +275 -0
  75. package/src/cmd/dkg/coordinator/finalize.ts +592 -0
  76. package/src/cmd/dkg/coordinator/index.ts +12 -0
  77. package/src/cmd/dkg/coordinator/invite.ts +217 -0
  78. package/src/cmd/dkg/coordinator/round1.ts +889 -0
  79. package/src/cmd/dkg/coordinator/round2.ts +959 -0
  80. package/src/cmd/dkg/index.ts +11 -0
  81. package/src/cmd/dkg/participant/finalize.ts +575 -0
  82. package/src/cmd/dkg/participant/index.ts +12 -0
  83. package/src/cmd/dkg/participant/receive.ts +348 -0
  84. package/src/cmd/dkg/participant/round1.ts +464 -0
  85. package/src/cmd/dkg/participant/round2.ts +627 -0
  86. package/src/cmd/index.ts +18 -0
  87. package/src/cmd/parallel.ts +334 -0
  88. package/src/cmd/registry/index.ts +88 -0
  89. package/src/cmd/registry/owner/index.ts +9 -0
  90. package/src/cmd/registry/owner/set.ts +70 -0
  91. package/src/cmd/registry/participant/add.ts +70 -0
  92. package/src/cmd/registry/participant/index.ts +9 -0
  93. package/src/cmd/sign/common.ts +108 -0
  94. package/src/cmd/sign/coordinator/index.ts +11 -0
  95. package/src/cmd/sign/coordinator/invite.ts +431 -0
  96. package/src/cmd/sign/coordinator/round1.ts +751 -0
  97. package/src/cmd/sign/coordinator/round2.ts +836 -0
  98. package/src/cmd/sign/index.ts +11 -0
  99. package/src/cmd/sign/participant/finalize.ts +823 -0
  100. package/src/cmd/sign/participant/index.ts +12 -0
  101. package/src/cmd/sign/participant/receive.ts +378 -0
  102. package/src/cmd/sign/participant/round1.ts +479 -0
  103. package/src/cmd/sign/participant/round2.ts +748 -0
  104. package/src/cmd/storage.ts +116 -0
  105. package/src/dkg/group-invite.ts +414 -0
  106. package/src/dkg/index.ts +10 -0
  107. package/src/dkg/proposed-participant.ts +132 -0
  108. package/src/frost/index.ts +456 -0
  109. package/src/index.ts +45 -0
  110. package/src/registry/group-record.ts +392 -0
  111. package/src/registry/index.ts +12 -0
  112. package/src/registry/owner-record.ts +146 -0
  113. package/src/registry/participant-record.ts +186 -0
  114. package/src/registry/registry-impl.ts +364 -0
@@ -0,0 +1,217 @@
1
+ /**
2
+ * DKG coordinator invite command.
3
+ *
4
+ * Port of cmd/dkg/coordinator/invite.rs from frost-hubert-rust.
5
+ *
6
+ * @module
7
+ */
8
+
9
+ import * as fs from "node:fs";
10
+ import * as path from "node:path";
11
+
12
+ import { ARID, type XID } from "@bcts/components";
13
+
14
+ import { DkgInvite } from "../../../dkg/index.js";
15
+ import {
16
+ GroupParticipant,
17
+ GroupRecord,
18
+ PendingRequests,
19
+ Registry,
20
+ resolveRegistryPath,
21
+ } from "../../../registry/index.js";
22
+ import { putWithIndicator } from "../../busy.js";
23
+ import { type StorageClient } from "../../storage.js";
24
+ import { dkgStateDir, resolveParticipants, resolveSender } from "../common.js";
25
+
26
+ /**
27
+ * Options for the DKG invite command.
28
+ */
29
+ export interface DkgInviteOptions {
30
+ registryPath?: string;
31
+ minSigners?: number;
32
+ charter: string;
33
+ validDays: number;
34
+ participantNames: string[];
35
+ verbose?: boolean;
36
+ }
37
+
38
+ /**
39
+ * Result of the DKG invite command.
40
+ */
41
+ export interface DkgInviteResult {
42
+ groupId: ARID;
43
+ requestId: ARID;
44
+ envelopeUr: string;
45
+ }
46
+
47
+ /**
48
+ * Internal data structure for building an invite.
49
+ *
50
+ * Port of `InviteData` struct from cmd/dkg/coordinator/invite.rs lines 122-126.
51
+ */
52
+ interface InviteData {
53
+ invite: DkgInvite;
54
+ participantXids: XID[];
55
+ pendingRequests: PendingRequests;
56
+ }
57
+
58
+ /**
59
+ * Build the DKG invite with validation.
60
+ *
61
+ * Port of `build_invite()` from cmd/dkg/coordinator/invite.rs lines 128-181.
62
+ */
63
+ function buildInvite(
64
+ registry: Registry,
65
+ minSignersArg: number | undefined,
66
+ charter: string,
67
+ participantNames: string[],
68
+ validDays: number,
69
+ ): InviteData {
70
+ // Resolve participants using the common utility
71
+ const resolved = resolveParticipants(registry, participantNames);
72
+ const participantDocs: string[] = resolved.map(([, record]) => record.xidDocumentUr());
73
+ const participantXids: XID[] = resolved.map(([xid]) => xid);
74
+
75
+ // These are the ARIDs where participants will post their invite responses
76
+ const collectFromArids: ARID[] = participantDocs.map(() => ARID.new());
77
+
78
+ // Build pending_requests: coordinator will collect invite responses from these ARIDs
79
+ const pendingRequests = new PendingRequests();
80
+ for (let i = 0; i < participantXids.length; i++) {
81
+ pendingRequests.addCollectOnly(participantXids[i], collectFromArids[i]);
82
+ }
83
+
84
+ // Validate participant count
85
+ const participantCount = participantDocs.length;
86
+ if (participantCount < 2) {
87
+ throw new Error("At least two participants are required for a DKG invite");
88
+ }
89
+
90
+ // Validate and default minSigners
91
+ const minSigners = minSignersArg ?? participantCount;
92
+ if (minSigners < 2) {
93
+ throw new Error("--min-signers must be at least 2");
94
+ }
95
+ if (minSigners > participantCount) {
96
+ throw new Error("--min-signers cannot exceed participant count");
97
+ }
98
+
99
+ // Get sender (registry owner)
100
+ const sender = resolveSender(registry);
101
+
102
+ // Calculate dates
103
+ const now = new Date();
104
+ const validUntil = new Date(Date.now() + validDays * 24 * 60 * 60 * 1000);
105
+
106
+ // Create the invite
107
+ const invite = DkgInvite.create(
108
+ ARID.new(), // requestId
109
+ sender,
110
+ ARID.new(), // groupId
111
+ now,
112
+ validUntil,
113
+ minSigners,
114
+ charter,
115
+ participantDocs,
116
+ collectFromArids,
117
+ );
118
+
119
+ return { invite, participantXids, pendingRequests };
120
+ }
121
+
122
+ /**
123
+ * Execute the DKG invite command.
124
+ *
125
+ * Port of `invite()` from cmd/dkg/coordinator/invite.rs.
126
+ */
127
+ export async function invite(
128
+ client: StorageClient,
129
+ options: DkgInviteOptions,
130
+ cwd: string,
131
+ ): Promise<DkgInviteResult> {
132
+ const registryPath = resolveRegistryPath(options.registryPath, cwd);
133
+ const registry = Registry.load(registryPath);
134
+
135
+ // Build the invite with validation
136
+ const inviteData = buildInvite(
137
+ registry,
138
+ options.minSigners,
139
+ options.charter,
140
+ options.participantNames,
141
+ options.validDays,
142
+ );
143
+
144
+ const { invite: dkgInvite, participantXids, pendingRequests } = inviteData;
145
+ const groupId = dkgInvite.groupId();
146
+ const requestId = dkgInvite.requestId();
147
+
148
+ // Create sealed envelope
149
+ const envelope = dkgInvite.toEnvelope();
150
+
151
+ // Send to storage
152
+ const startArid = ARID.new();
153
+ await putWithIndicator(
154
+ client,
155
+ startArid,
156
+ envelope,
157
+ "Sending DKG invite",
158
+ options.verbose ?? false,
159
+ );
160
+
161
+ // Save group record to registry
162
+ const owner = registry.owner();
163
+ if (!owner) {
164
+ throw new Error("Registry owner is required to issue invites");
165
+ }
166
+
167
+ const coordinator = new GroupParticipant(owner.xid());
168
+ const groupParticipants = participantXids.map((xid) => new GroupParticipant(xid));
169
+
170
+ const groupRecord = new GroupRecord(
171
+ options.charter,
172
+ dkgInvite.minSigners(),
173
+ coordinator,
174
+ groupParticipants,
175
+ );
176
+
177
+ // Track pending requests
178
+ groupRecord.setPendingRequests(pendingRequests);
179
+
180
+ // Use recordGroup() for proper merge behavior
181
+ registry.recordGroup(groupId, groupRecord);
182
+ registry.save(registryPath);
183
+
184
+ // Save invite state
185
+ const stateDir = dkgStateDir(registryPath, groupId.hex());
186
+ fs.mkdirSync(stateDir, { recursive: true });
187
+
188
+ const inviteState: {
189
+ group: string;
190
+ request_id: string;
191
+ start_arid: string;
192
+ valid_until: string;
193
+ participants: { xid: string; response_arid: string }[];
194
+ } = {
195
+ group: groupId.urString(),
196
+ request_id: requestId.urString(),
197
+ start_arid: startArid.urString(),
198
+ valid_until: dkgInvite.validUntil().toISOString(),
199
+ participants: dkgInvite.participants().map((p) => ({
200
+ xid: p.xid().urString(),
201
+ response_arid: p.responseArid().urString(),
202
+ })),
203
+ };
204
+
205
+ fs.writeFileSync(path.join(stateDir, "invite.json"), JSON.stringify(inviteState, null, 2));
206
+
207
+ if (options.verbose === true) {
208
+ console.log(`Group ID: ${groupId.urString()}`);
209
+ console.log(`Start ARID: ${startArid.urString()}`);
210
+ }
211
+
212
+ return {
213
+ groupId,
214
+ requestId,
215
+ envelopeUr: envelope.urString(),
216
+ };
217
+ }