@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,64 @@
1
+ /**
2
+ * Progress indicator utilities.
3
+ *
4
+ * Port of cmd/busy.rs from frost-hubert-rust.
5
+ *
6
+ * @module
7
+ */
8
+
9
+ import { type ARID } from "@bcts/components";
10
+ import { type Envelope } from "@bcts/envelope";
11
+
12
+ import { type StorageClient } from "./storage.js";
13
+
14
+ /**
15
+ * Put an envelope to storage with a progress indicator.
16
+ *
17
+ * Port of `put_with_indicator()` from cmd/busy.rs.
18
+ */
19
+ export async function putWithIndicator(
20
+ client: StorageClient,
21
+ arid: ARID,
22
+ envelope: Envelope,
23
+ message: string,
24
+ verbose: boolean,
25
+ ): Promise<void> {
26
+ if (verbose) {
27
+ console.log(`${message}...`);
28
+ }
29
+
30
+ await client.put(arid, envelope);
31
+
32
+ if (verbose) {
33
+ console.log(`${message}... done`);
34
+ }
35
+ }
36
+
37
+ /**
38
+ * Get an envelope from storage with a progress indicator.
39
+ *
40
+ * Port of `get_with_indicator()` from cmd/busy.rs.
41
+ */
42
+ export async function getWithIndicator(
43
+ client: StorageClient,
44
+ arid: ARID,
45
+ message: string,
46
+ timeoutSeconds: number | undefined,
47
+ verbose: boolean,
48
+ ): Promise<Envelope | undefined> {
49
+ if (verbose) {
50
+ console.log(`${message}...`);
51
+ }
52
+
53
+ const envelope = await client.get(arid, timeoutSeconds);
54
+
55
+ if (verbose) {
56
+ if (envelope) {
57
+ console.log(`${message}... found`);
58
+ } else {
59
+ console.log(`${message}... not found`);
60
+ }
61
+ }
62
+
63
+ return envelope;
64
+ }
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Check command utilities.
3
+ *
4
+ * Port of cmd/check.rs from frost-hubert-rust.
5
+ *
6
+ * @module
7
+ */
8
+
9
+ import { type ARID } from "@bcts/components";
10
+
11
+ import { type StorageClient } from "./storage.js";
12
+
13
+ /**
14
+ * Check if an ARID exists in storage.
15
+ *
16
+ * Port of check functionality from cmd/check.rs.
17
+ */
18
+ export async function checkAridExists(client: StorageClient, arid: ARID): Promise<boolean> {
19
+ return client.exists(arid);
20
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Common utilities for commands.
3
+ *
4
+ * Port of cmd/common.rs from frost-hubert-rust.
5
+ *
6
+ * @module
7
+ */
8
+
9
+ import * as path from "node:path";
10
+
11
+ /**
12
+ * Get the group state directory for a given registry path and group ID.
13
+ *
14
+ * Port of `group_state_dir()` from cmd/common.rs.
15
+ */
16
+ export function groupStateDir(registryPath: string, groupIdHex: string): string {
17
+ const base = path.dirname(registryPath);
18
+ return path.join(base, "group-state", groupIdHex);
19
+ }
20
+
21
+ /**
22
+ * Global verbose flag.
23
+ */
24
+ let verboseFlag = false;
25
+
26
+ /**
27
+ * Set the verbose flag.
28
+ */
29
+ export function setVerbose(value: boolean): void {
30
+ verboseFlag = value;
31
+ }
32
+
33
+ /**
34
+ * Check if verbose mode is enabled.
35
+ *
36
+ * Port of `is_verbose()` from cmd/common.rs.
37
+ */
38
+ export function isVerbose(): boolean {
39
+ return verboseFlag;
40
+ }
@@ -0,0 +1,275 @@
1
+ /**
2
+ * Common utilities for DKG commands.
3
+ *
4
+ * Port of cmd/dkg/common.rs from frost-hubert-rust.
5
+ *
6
+ * @module
7
+ */
8
+
9
+ import * as path from "node:path";
10
+
11
+ import { type ARID, type XID } from "@bcts/components";
12
+ import { type Envelope } from "@bcts/envelope";
13
+ import { UR } from "@bcts/uniform-resources";
14
+ import { type XIDDocument } from "@bcts/xid";
15
+
16
+ import {
17
+ GroupParticipant,
18
+ type OwnerRecord,
19
+ type ParticipantRecord,
20
+ type Registry,
21
+ } from "../../registry/index.js";
22
+
23
+ // Re-export cross-cutting utilities for convenience
24
+ export { groupStateDir } from "../common.js";
25
+
26
+ /**
27
+ * Parse an ARID from a UR string.
28
+ *
29
+ * Port of `parse_arid_ur()` from cmd/dkg/common.rs.
30
+ */
31
+ export function parseAridUr(urString: string): ARID {
32
+ const ur = UR.fromURString(urString.trim());
33
+
34
+ if (ur.urTypeStr() !== "arid") {
35
+ throw new Error(`Expected ur:arid, found ur:${ur.urTypeStr()}`);
36
+ }
37
+
38
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef
39
+ const { ARID: ARIDClass } = require("@bcts/components");
40
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
41
+ return ARIDClass.fromCbor(ur.cbor());
42
+ }
43
+
44
+ /**
45
+ * Parse an envelope from a UR string.
46
+ *
47
+ * Port of `parse_envelope_ur()` from cmd/dkg/common.rs.
48
+ */
49
+ export function parseEnvelopeUr(urString: string): Envelope {
50
+ const ur = UR.fromURString(urString.trim());
51
+
52
+ if (ur.urTypeStr() !== "envelope") {
53
+ throw new Error(`Expected ur:envelope, found ur:${ur.urTypeStr()}`);
54
+ }
55
+
56
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef
57
+ const { Envelope: EnvelopeClass } = require("@bcts/envelope");
58
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-return, @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
59
+ return EnvelopeClass.fromCbor(ur.cbor());
60
+ }
61
+
62
+ /**
63
+ * Resolve the sender XID document from the registry.
64
+ *
65
+ * Port of `resolve_sender()` from cmd/dkg/common.rs.
66
+ */
67
+ export function resolveSender(registry: Registry): XIDDocument {
68
+ const owner = registry.owner();
69
+
70
+ if (!owner) {
71
+ throw new Error("No owner set in registry. Run 'registry owner set' first.");
72
+ }
73
+
74
+ return owner.xidDocument();
75
+ }
76
+
77
+ // -----------------------------------------------------------------------------
78
+ // Participant resolution
79
+ // -----------------------------------------------------------------------------
80
+
81
+ /**
82
+ * Resolve participant identifiers (XID URs or pet names) to records.
83
+ *
84
+ * Port of `resolve_participants()` from cmd/dkg/common.rs lines 29-74.
85
+ */
86
+ export function resolveParticipants(
87
+ registry: Registry,
88
+ inputs: string[],
89
+ ): [XID, ParticipantRecord][] {
90
+ const seenArgs = new Set<string>();
91
+ const seenXids = new Set<string>();
92
+ const resolved: [XID, ParticipantRecord][] = [];
93
+
94
+ for (const raw of inputs) {
95
+ const trimmed = raw.trim();
96
+ if (trimmed === "") {
97
+ throw new Error("Participant identifier cannot be empty");
98
+ }
99
+ if (seenArgs.has(trimmed)) {
100
+ throw new Error(`Duplicate participant argument: ${trimmed}`);
101
+ }
102
+ seenArgs.add(trimmed);
103
+
104
+ let xid: XID;
105
+ let record: ParticipantRecord;
106
+
107
+ // Try parsing as XID UR first
108
+ try {
109
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef
110
+ const { XID: XIDClass } = require("@bcts/components");
111
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
112
+ xid = XIDClass.fromURString(trimmed) as XID;
113
+
114
+ const foundRecord = registry.participant(xid);
115
+ if (!foundRecord) {
116
+ throw new Error(`Participant with XID ${xid.urString()} not found in registry`);
117
+ }
118
+ record = foundRecord;
119
+ } catch {
120
+ // Try looking up by pet name
121
+ const result = registry.participantByPetName(trimmed);
122
+ if (!result) {
123
+ throw new Error(`Participant with pet name '${trimmed}' not found`);
124
+ }
125
+ [xid, record] = result;
126
+ }
127
+
128
+ const xidUr = xid.urString();
129
+ if (seenXids.has(xidUr)) {
130
+ throw new Error(`Duplicate participant specified; multiple inputs resolve to ${xidUr}`);
131
+ }
132
+ seenXids.add(xidUr);
133
+
134
+ resolved.push([xid, record]);
135
+ }
136
+
137
+ return resolved;
138
+ }
139
+
140
+ /**
141
+ * Get display name for sender from registry.
142
+ *
143
+ * Port of `resolve_sender_name()` from cmd/dkg/common.rs lines 96-116.
144
+ */
145
+ export function resolveSenderName(registry: Registry, sender: XIDDocument): string | undefined {
146
+ const owner = registry.owner();
147
+ const senderXid = sender.xid();
148
+
149
+ // Check if sender is the owner
150
+ if (owner?.xidDocument().xid().urString() === senderXid.urString()) {
151
+ const name = owner.petName() ?? senderXid.urString();
152
+ return formatNameWithOwnerMarker(name, true);
153
+ }
154
+
155
+ // Look up in participants
156
+ const record = registry.participant(senderXid);
157
+ if (record) {
158
+ const name = record.petName() ?? record.xid().urString();
159
+ return formatNameWithOwnerMarker(name, false);
160
+ }
161
+
162
+ return undefined;
163
+ }
164
+
165
+ // -----------------------------------------------------------------------------
166
+ // Group participant building
167
+ // -----------------------------------------------------------------------------
168
+
169
+ /**
170
+ * Build GroupParticipant[] from XIDDocuments using registry lookups.
171
+ *
172
+ * Port of `build_group_participants()` from cmd/dkg/common.rs lines 122-131.
173
+ */
174
+ export function buildGroupParticipants(
175
+ registry: Registry,
176
+ owner: OwnerRecord,
177
+ participants: XIDDocument[],
178
+ ): GroupParticipant[] {
179
+ return participants.map((doc) => groupParticipantFromRegistry(registry, owner, doc));
180
+ }
181
+
182
+ /**
183
+ * Create a GroupParticipant from a XIDDocument, validating against the registry.
184
+ *
185
+ * Port of `group_participant_from_registry()` from cmd/dkg/common.rs lines 133-149.
186
+ */
187
+ export function groupParticipantFromRegistry(
188
+ registry: Registry,
189
+ owner: OwnerRecord,
190
+ document: XIDDocument,
191
+ ): GroupParticipant {
192
+ const xid = document.xid();
193
+
194
+ // If the document is the owner, allow it
195
+ if (xid.urString() === owner.xid().urString()) {
196
+ return new GroupParticipant(xid);
197
+ }
198
+
199
+ // Otherwise, verify the participant is in the registry
200
+ if (!registry.participant(xid)) {
201
+ throw new Error(`Invite participant not found in registry: ${xid.urString()}`);
202
+ }
203
+
204
+ return new GroupParticipant(xid);
205
+ }
206
+
207
+ // -----------------------------------------------------------------------------
208
+ // Name formatting
209
+ // -----------------------------------------------------------------------------
210
+
211
+ /**
212
+ * Format a participant name with owner marker if applicable.
213
+ *
214
+ * Port of `format_name_with_owner_marker()` from cmd/dkg/common.rs lines 155-157.
215
+ */
216
+ export function formatNameWithOwnerMarker(name: string, isOwner: boolean): string {
217
+ return isOwner ? `* ${name}` : name;
218
+ }
219
+
220
+ /**
221
+ * Get display names for participants, sorted by XID, with owner marked.
222
+ *
223
+ * Port of `participant_names_from_registry()` from cmd/dkg/common.rs lines 159-191.
224
+ */
225
+ export function participantNamesFromRegistry(
226
+ registry: Registry,
227
+ participants: XIDDocument[],
228
+ ownerXid: XID,
229
+ ownerPetName: string | undefined,
230
+ ): string[] {
231
+ // Sort by XID UR string
232
+ const sorted = [...participants].sort((a, b) =>
233
+ a.xid().urString().localeCompare(b.xid().urString()),
234
+ );
235
+
236
+ return sorted.map((document) => {
237
+ const xid = document.xid();
238
+ const isOwner = xid.urString() === ownerXid.urString();
239
+
240
+ let name: string;
241
+ if (isOwner) {
242
+ name = ownerPetName ?? xid.urString();
243
+ } else {
244
+ const record = registry.participant(xid);
245
+ if (!record) {
246
+ throw new Error(`Invite participant not found in registry: ${xid.urString()}`);
247
+ }
248
+ name = record.petName() ?? xid.urString();
249
+ }
250
+
251
+ return formatNameWithOwnerMarker(name, isOwner);
252
+ });
253
+ }
254
+
255
+ /**
256
+ * Get the DKG state directory for a given registry path and group ID.
257
+ *
258
+ * Port of `dkg_state_dir()` from cmd/dkg/common.rs.
259
+ */
260
+ export function dkgStateDir(registryPath: string, groupIdHex: string): string {
261
+ const base = path.dirname(registryPath);
262
+ return path.join(base, "group-state", groupIdHex, "dkg");
263
+ }
264
+
265
+ /**
266
+ * Convert a verifying key bytes to a SigningPublicKey.
267
+ *
268
+ * Port of `signing_key_from_verifying()` from cmd/dkg/common.rs.
269
+ */
270
+ export function signingKeyFromVerifying(verifyingKeyBytes: Uint8Array): unknown {
271
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef
272
+ const { SigningPublicKey: SigningPublicKeyClass } = require("@bcts/components");
273
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
274
+ return SigningPublicKeyClass.fromBytes(verifyingKeyBytes);
275
+ }