@bcts/frost-hubert 1.0.0-beta.0 → 1.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/bin/frost.cjs +17 -19
- package/dist/bin/frost.cjs.map +1 -1
- package/dist/bin/frost.mjs +16 -17
- package/dist/bin/frost.mjs.map +1 -1
- package/dist/{busy-EZU7EKr6.cjs → busy-B_h0bNAJ.cjs} +1 -1
- package/dist/{busy-DkM2jAIZ.mjs.map → busy-B_h0bNAJ.cjs.map} +1 -1
- package/dist/{busy-DkM2jAIZ.mjs → busy-BlU8_pS2.mjs} +1 -1
- package/dist/{busy-EZU7EKr6.cjs.map → busy-BlU8_pS2.mjs.map} +1 -1
- package/dist/cmd/index.cjs +6 -7
- package/dist/cmd/index.d.cts +1 -1
- package/dist/cmd/index.d.mts +1 -1
- package/dist/cmd/index.mjs +5 -6
- package/dist/{cmd-Bw9_i2_f.cjs → cmd-CCVhHzG7.cjs} +20 -21
- package/dist/{cmd-Bw9_i2_f.cjs.map → cmd-CCVhHzG7.cjs.map} +1 -1
- package/dist/{cmd-CS1uJtuD.mjs → cmd-DNsHd19v.mjs} +20 -21
- package/dist/{cmd-CS1uJtuD.mjs.map → cmd-DNsHd19v.mjs.map} +1 -1
- package/dist/{common-lThIvJmZ.cjs → common-7-BOgaTt.cjs} +2 -3
- package/dist/{common-lThIvJmZ.cjs.map → common-7-BOgaTt.cjs.map} +1 -1
- package/dist/{common-CvH6dFvQ.mjs → common-Cf1UvJaP.mjs} +3 -3
- package/dist/{common-CvH6dFvQ.mjs.map → common-Cf1UvJaP.mjs.map} +1 -1
- package/dist/{common-lKP5EzHy.cjs → common-CnvAUC2b.cjs} +3 -3
- package/dist/{common-lKP5EzHy.cjs.map → common-CnvAUC2b.cjs.map} +1 -1
- package/dist/{common-DUWvtc08.mjs → common-DNrD_-EI.mjs} +2 -2
- package/dist/{common-DUWvtc08.mjs.map → common-DNrD_-EI.mjs.map} +1 -1
- package/dist/dkg/index.cjs +1 -2
- package/dist/dkg/index.cjs.map +1 -1
- package/dist/dkg/index.d.cts +1 -1
- package/dist/dkg/index.d.mts +1 -1
- package/dist/dkg/index.mjs +1 -1
- package/dist/dkg/index.mjs.map +1 -1
- package/dist/{finalize-CNTDj6aS.mjs → finalize-BpC0rz93.mjs} +6 -6
- package/dist/{finalize-CNTDj6aS.mjs.map → finalize-BpC0rz93.mjs.map} +1 -1
- package/dist/{finalize-BRgJK-Xv.cjs → finalize-Cb0obTSo.cjs} +6 -6
- package/dist/{finalize-BRgJK-Xv.cjs.map → finalize-Cb0obTSo.cjs.map} +1 -1
- package/dist/{finalize-BfLgzn8f.cjs → finalize-DHEnKobp.cjs} +5 -5
- package/dist/{finalize-BfLgzn8f.cjs.map → finalize-DHEnKobp.cjs.map} +1 -1
- package/dist/{finalize-UPyI1yb1.cjs → finalize-DQ0VGUHO.cjs} +7 -7
- package/dist/{finalize-UPyI1yb1.cjs.map → finalize-DQ0VGUHO.cjs.map} +1 -1
- package/dist/{finalize-IA01t_Qq.mjs → finalize-DtRxHZ7H.mjs} +5 -5
- package/dist/{finalize-IA01t_Qq.mjs.map → finalize-DtRxHZ7H.mjs.map} +1 -1
- package/dist/{finalize-EC3ikHQq.mjs → finalize-T83Ko8nG.mjs} +6 -6
- package/dist/{finalize-EC3ikHQq.mjs.map → finalize-T83Ko8nG.mjs.map} +1 -1
- package/dist/frost/index.cjs +1 -1
- package/dist/frost/index.cjs.map +1 -1
- package/dist/frost/index.d.cts.map +1 -1
- package/dist/frost/index.d.mts.map +1 -1
- package/dist/frost/index.mjs +1 -1
- package/dist/frost/index.mjs.map +1 -1
- package/dist/{index-F1iNEAJR.d.cts → index-BErX9AZF.d.cts} +3 -3
- package/dist/index-BErX9AZF.d.cts.map +1 -0
- package/dist/{index-B3c-80VS.d.cts → index-BaUVw4b1.d.mts} +2 -2
- package/dist/index-BaUVw4b1.d.mts.map +1 -0
- package/dist/{index-C8QeHNwa.d.cts → index-CD50Qtgw.d.cts} +1 -1
- package/dist/index-CD50Qtgw.d.cts.map +1 -0
- package/dist/{index-DVbWyOs7.d.mts → index-CD50Qtgw.d.mts} +1 -1
- package/dist/index-CD50Qtgw.d.mts.map +1 -0
- package/dist/{index-BgbSGpxn.d.mts → index-Drklne-Y.d.mts} +3 -3
- package/dist/index-Drklne-Y.d.mts.map +1 -0
- package/dist/{index-D3QTWkEm.d.mts → index-gkmZzEuD.d.cts} +2 -2
- package/dist/index-gkmZzEuD.d.cts.map +1 -0
- package/dist/index.cjs +7 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +3 -3
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +6 -7
- package/dist/index.mjs.map +1 -1
- package/dist/{invite-5277FQVT.cjs → invite-1tzg0B0P.cjs} +5 -5
- package/dist/{invite-5277FQVT.cjs.map → invite-1tzg0B0P.cjs.map} +1 -1
- package/dist/{invite-DUTcfTgX.cjs → invite-BLwtexAu.cjs} +4 -4
- package/dist/{invite-DUTcfTgX.cjs.map → invite-BLwtexAu.cjs.map} +1 -1
- package/dist/{invite-IU4n0dq2.mjs → invite-Be2v2SVc.mjs} +4 -4
- package/dist/{invite-IU4n0dq2.mjs.map → invite-Be2v2SVc.mjs.map} +1 -1
- package/dist/{invite-RU-OXTNS.mjs → invite-D8mQSnFz.mjs} +5 -5
- package/dist/{invite-RU-OXTNS.mjs.map → invite-D8mQSnFz.mjs.map} +1 -1
- package/dist/{parallel-D6zc6VW4.mjs → parallel-PZiwHZT8.mjs} +1 -1
- package/dist/{parallel-D1R6ZGlY.cjs.map → parallel-PZiwHZT8.mjs.map} +1 -1
- package/dist/{parallel-D1R6ZGlY.cjs → parallel-szwYx-bi.cjs} +1 -1
- package/dist/{parallel-D6zc6VW4.mjs.map → parallel-szwYx-bi.cjs.map} +1 -1
- package/dist/{proposed-participant-Dm1Eq6mX.cjs → proposed-participant-BvHNnpcZ.cjs} +1 -2
- package/dist/{proposed-participant-Dm1Eq6mX.cjs.map → proposed-participant-BvHNnpcZ.cjs.map} +1 -1
- package/dist/{proposed-participant-cWM7iUrO.mjs → proposed-participant-Detb823_.mjs} +1 -1
- package/dist/{proposed-participant-cWM7iUrO.mjs.map → proposed-participant-Detb823_.mjs.map} +1 -1
- package/dist/{receive-CAI-x4II.cjs → receive-BR-knnGv.cjs} +6 -6
- package/dist/{receive-CAI-x4II.cjs.map → receive-BR-knnGv.cjs.map} +1 -1
- package/dist/{receive-kZMsXhbK.cjs → receive-D_r4Mryr.cjs} +6 -6
- package/dist/{receive-kZMsXhbK.cjs.map → receive-D_r4Mryr.cjs.map} +1 -1
- package/dist/{receive-D2Nn68L7.mjs → receive-dkSCSGpl.mjs} +5 -5
- package/dist/{receive-D2Nn68L7.mjs.map → receive-dkSCSGpl.mjs.map} +1 -1
- package/dist/{receive-DA_KQEgk.mjs → receive-g8EhZF2Y.mjs} +6 -6
- package/dist/{receive-DA_KQEgk.mjs.map → receive-g8EhZF2Y.mjs.map} +1 -1
- package/dist/registry/index.cjs +1 -1
- package/dist/registry/index.cjs.map +1 -1
- package/dist/registry/index.d.cts +1 -1
- package/dist/registry/index.d.mts +1 -1
- package/dist/registry/index.mjs.map +1 -1
- package/dist/{registry-9puTaRrD.cjs → registry-CkIbA7nt.cjs} +79 -2
- package/dist/registry-CkIbA7nt.cjs.map +1 -0
- package/dist/{registry-BpCwtrRt.mjs → registry-DGjs4qDK.mjs} +74 -3
- package/dist/registry-DGjs4qDK.mjs.map +1 -0
- package/dist/{round1-BHBjru1m.cjs → round1-9FAqFvL5.cjs} +5 -5
- package/dist/{round1-BHBjru1m.cjs.map → round1-9FAqFvL5.cjs.map} +1 -1
- package/dist/{round1-CcQCGlIT.mjs → round1-B8haiMM8.mjs} +6 -6
- package/dist/{round1-CcQCGlIT.mjs.map → round1-B8haiMM8.mjs.map} +1 -1
- package/dist/{round1-Cgm7j1kI.mjs → round1-BOIE1E4O.mjs} +5 -5
- package/dist/{round1-Cgm7j1kI.mjs.map → round1-BOIE1E4O.mjs.map} +1 -1
- package/dist/{round1-4Hyx8w0x.cjs → round1-Bq0vweyQ.cjs} +5 -5
- package/dist/{round1-4Hyx8w0x.cjs.map → round1-Bq0vweyQ.cjs.map} +1 -1
- package/dist/{round1-CWSXZx5R.cjs → round1-CXkXoVQU.cjs} +9 -9
- package/dist/{round1-CWSXZx5R.cjs.map → round1-CXkXoVQU.cjs.map} +1 -1
- package/dist/{round1-7v9LlE11.mjs → round1-D8t7EzIo.mjs} +5 -5
- package/dist/{round1-7v9LlE11.mjs.map → round1-D8t7EzIo.mjs.map} +1 -1
- package/dist/{round1-DQ0fnc1H.cjs → round1-DriPu15x.cjs} +7 -7
- package/dist/{round1-DQ0fnc1H.cjs.map → round1-DriPu15x.cjs.map} +1 -1
- package/dist/{round1-CMLKN2RR.mjs → round1-Y2kcVwnR.mjs} +7 -7
- package/dist/{round1-CMLKN2RR.mjs.map → round1-Y2kcVwnR.mjs.map} +1 -1
- package/dist/{round2-BWz9SQIi.cjs → round2-AMDYMUIg.cjs} +5 -5
- package/dist/{round2-BWz9SQIi.cjs.map → round2-AMDYMUIg.cjs.map} +1 -1
- package/dist/{round2-o2Q-GMbX.cjs → round2-BHQKVJFo.cjs} +7 -7
- package/dist/{round2-o2Q-GMbX.cjs.map → round2-BHQKVJFo.cjs.map} +1 -1
- package/dist/{round2-Bl2uK93U.mjs → round2-BfetYacV.mjs} +5 -5
- package/dist/{round2-Bl2uK93U.mjs.map → round2-BfetYacV.mjs.map} +1 -1
- package/dist/{round2-Dg24w-TU.mjs → round2-Cf5CJc_8.mjs} +7 -7
- package/dist/{round2-Dg24w-TU.mjs.map → round2-Cf5CJc_8.mjs.map} +1 -1
- package/dist/{round2-LylCa84n.cjs → round2-CvrmylN1.cjs} +7 -7
- package/dist/{round2-LylCa84n.cjs.map → round2-CvrmylN1.cjs.map} +1 -1
- package/dist/{round2-CdUT-AhH.cjs → round2-Dk_w97nl.cjs} +5 -5
- package/dist/{round2-CdUT-AhH.cjs.map → round2-Dk_w97nl.cjs.map} +1 -1
- package/dist/{round2-BkNRCXgS.mjs → round2-Z2JhMwxc.mjs} +5 -5
- package/dist/{round2-BkNRCXgS.mjs.map → round2-Z2JhMwxc.mjs.map} +1 -1
- package/dist/{round2-DOA3rnV-.mjs → round2-mF6UlkT-.mjs} +6 -6
- package/dist/{round2-DOA3rnV-.mjs.map → round2-mF6UlkT-.mjs.map} +1 -1
- package/package.json +14 -14
- package/dist/index-B3c-80VS.d.cts.map +0 -1
- package/dist/index-BgbSGpxn.d.mts.map +0 -1
- package/dist/index-C8QeHNwa.d.cts.map +0 -1
- package/dist/index-D3QTWkEm.d.mts.map +0 -1
- package/dist/index-DVbWyOs7.d.mts.map +0 -1
- package/dist/index-F1iNEAJR.d.cts.map +0 -1
- package/dist/registry-9puTaRrD.cjs.map +0 -1
- package/dist/registry-BpCwtrRt.mjs.map +0 -1
- package/dist/storage-B-Gu68-O.cjs +0 -79
- package/dist/storage-B-Gu68-O.cjs.map +0 -1
- package/dist/storage-Bkkliz0K.mjs +0 -74
- package/dist/storage-Bkkliz0K.mjs.map +0 -1
- /package/dist/{chunk-CZWwpsFl.cjs → chunk-DakpK96I.cjs} +0 -0
- /package/dist/{chunk-CjcI7cDX.mjs → chunk-z9aeyW2b.mjs} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finalize-BRgJK-Xv.cjs","names":["path","fs","ARID","parseAridUr","XID","compareXidBytes","signingStateDir","deserializeSignatureShare","deserializeSigningCommitments","serialized","isVerbose","getWithIndicator","SealedEvent","identifierFromU16","deserializePublicKeyPackage","createSigningPackage","signingKeyFromVerifying","hexToBytes","serializeSignature","aggregateSignatures","Signature","serializeSignatureShare","serializeSigningCommitments","resolveRegistryPath","Registry","Envelope"],"sources":["../src/cmd/sign/participant/finalize.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * Sign participant finalize command.\n *\n * Port of cmd/sign/participant/finalize.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, type Digest, Signature, type SigningPublicKey, XID } from \"@bcts/components\";\nimport { compareXidBytes } from \"../../../dkg/proposed-participant.js\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { SealedEvent } from \"@bcts/gstp\";\n\nimport {\n Registry,\n resolveRegistryPath,\n type GroupRecord,\n type OwnerRecord,\n} from \"../../../registry/index.js\";\nimport { getWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { parseAridUr, signingKeyFromVerifying } from \"../../dkg/common.js\";\nimport { signingStateDir, SignFinalizeContent } from \"../common.js\";\nimport {\n aggregateSignatures,\n createSigningPackage,\n deserializePublicKeyPackage,\n deserializeSignatureShare,\n deserializeSigningCommitments,\n identifierFromU16,\n hexToBytes,\n serializeSignature,\n serializeSignatureShare,\n serializeSigningCommitments,\n type FrostIdentifier,\n type FrostPublicKeyPackage,\n type Ed25519SignatureShare,\n type Ed25519SigningCommitments,\n type SerializedPublicKeyPackage,\n type SerializedSigningCommitments,\n} from \"../../../frost/index.js\";\nimport { isVerbose } from \"../../common.js\";\n\n/**\n * Options for the sign finalize command.\n */\nexport interface SignFinalizeOptions {\n registryPath?: string;\n sessionId: string;\n groupId?: string;\n timeoutSeconds?: number;\n verbose?: boolean;\n}\n\n/**\n * Result of the sign finalize command.\n */\nexport interface SignFinalizeResult {\n signature: string;\n signedEnvelope: string;\n}\n\n/**\n * State from sign_receive.json.\n *\n * Port of `struct ReceiveState` from cmd/sign/participant/finalize.rs.\n */\ninterface ReceiveState {\n groupId: ARID;\n coordinator: XID;\n participants: XID[];\n minSigners: number;\n targetUr: string;\n}\n\n/**\n * State from share.json.\n *\n * Port of `struct ShareState` from cmd/sign/participant/finalize.rs.\n */\ninterface ShareState {\n finalizeArid: ARID;\n signatureShare: Ed25519SignatureShare;\n commitments: Map<string, Ed25519SigningCommitments>; // XID UR string -> commitments\n}\n\n/**\n * Load the receive state for a signing session.\n *\n * Searches for sign_receive.json in group-state directories.\n *\n * Port of `load_receive_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction loadReceiveState(\n registryPath: string,\n sessionId: ARID,\n groupHint: ARID | undefined,\n): ReceiveState {\n const base = path.dirname(registryPath);\n const groupStateDir = path.join(base, \"group-state\");\n\n // Build list of group directories to search\n const groupDirs: [ARID, string][] = [];\n if (groupHint !== undefined) {\n groupDirs.push([groupHint, path.join(groupStateDir, groupHint.hex())]);\n } else {\n if (fs.existsSync(groupStateDir)) {\n for (const entry of fs.readdirSync(groupStateDir, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n const name = entry.name;\n // Check if it's a valid 64-char hex string (ARID)\n if (name.length === 64 && /^[0-9a-f]+$/i.test(name)) {\n const groupId = ARID.fromHex(name);\n groupDirs.push([groupId, path.join(groupStateDir, name)]);\n }\n }\n }\n }\n }\n\n // Search for sign_receive.json\n const candidates: [ARID, string][] = [];\n for (const [groupId, groupDir] of groupDirs) {\n const candidate = path.join(groupDir, \"signing\", sessionId.hex(), \"sign_receive.json\");\n if (fs.existsSync(candidate)) {\n candidates.push([groupId, candidate]);\n }\n }\n\n if (candidates.length === 0) {\n throw new Error(\n \"No sign_receive.json found for this session; run `frost sign participant receive` first\",\n );\n }\n if (candidates.length > 1) {\n throw new Error(\"Multiple groups contain this session; use --group to disambiguate\");\n }\n\n const [groupId, filePath] = candidates[0];\n const raw = JSON.parse(fs.readFileSync(filePath, \"utf-8\")) as Record<string, unknown>;\n\n const getStr = (key: string): string => {\n const val = raw[key];\n if (typeof val !== \"string\") {\n throw new Error(`Missing or invalid ${key} in sign_receive.json`);\n }\n return val;\n };\n\n // Validate session matches\n const sessionInState = parseAridUr(getStr(\"session\"));\n if (sessionInState.hex() !== sessionId.hex()) {\n throw new Error(\n `Session ${sessionInState.urString()} in sign_receive.json does not match requested session ${sessionId.urString()}`,\n );\n }\n\n // Validate group matches\n const groupInState = parseAridUr(getStr(\"group\"));\n if (groupInState.hex() !== groupId.hex()) {\n throw new Error(\n `Group ${groupInState.urString()} in sign_receive.json does not match directory group ${groupId.urString()}`,\n );\n }\n\n const coordinator = XID.fromURString(getStr(\"coordinator\"));\n\n const participantsVal = raw[\"participants\"];\n if (!Array.isArray(participantsVal)) {\n throw new Error(\"Missing participants in sign_receive.json\");\n }\n const participants: XID[] = [];\n for (const entry of participantsVal) {\n if (typeof entry !== \"string\") {\n throw new Error(\"Invalid participant entry in sign_receive.json\");\n }\n participants.push(XID.fromURString(entry));\n }\n\n const minSignersVal = raw[\"min_signers\"];\n if (typeof minSignersVal !== \"number\") {\n throw new Error(\"Missing min_signers in sign_receive.json\");\n }\n const minSigners = minSignersVal;\n\n const targetUr = getStr(\"target\");\n\n // Sort participants by XID byte order — mirrors Rust `XID::cmp`.\n // The earlier port used `urString().localeCompare(...)`, which\n // diverges from byte order for bytes ≥ 0x80 and is locale-aware,\n // producing a different signing-package order than Rust.\n participants.sort((a, b) => compareXidBytes(a.toData(), b.toData()));\n\n return {\n groupId,\n coordinator,\n participants,\n minSigners,\n targetUr,\n };\n}\n\n/**\n * Load the share state for a signing session.\n *\n * Port of `load_share_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction loadShareState(registryPath: string, groupId: ARID, sessionId: ARID): ShareState {\n const dir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n const filePath = path.join(dir, \"share.json\");\n\n if (!fs.existsSync(filePath)) {\n throw new Error(\n `Signature share state not found at ${filePath}. Run \\`frost sign participant share\\` first.`,\n );\n }\n\n const raw = JSON.parse(fs.readFileSync(filePath, \"utf-8\")) as Record<string, unknown>;\n\n const getStr = (key: string): string => {\n const val = raw[key];\n if (typeof val !== \"string\") {\n throw new Error(`Missing or invalid ${key} in share.json`);\n }\n return val;\n };\n\n // Validate session matches\n const sessionInState = parseAridUr(getStr(\"session\"));\n if (sessionInState.hex() !== sessionId.hex()) {\n throw new Error(\n `Session ${sessionInState.urString()} in share.json does not match requested session ${sessionId.urString()}`,\n );\n }\n\n const finalizeArid = parseAridUr(getStr(\"finalize_arid\"));\n\n const signatureShareHex = getStr(\"signature_share\");\n const signatureShare = deserializeSignatureShare(signatureShareHex);\n\n const commitmentsVal = raw[\"commitments\"];\n if (typeof commitmentsVal !== \"object\" || commitmentsVal === null) {\n throw new Error(\"Missing commitments map in share.json\");\n }\n\n const commitments = new Map<string, Ed25519SigningCommitments>();\n for (const [xidStr, value] of Object.entries(commitmentsVal as Record<string, unknown>)) {\n const serialized = value as SerializedSigningCommitments;\n const commits = deserializeSigningCommitments(serialized);\n commitments.set(xidStr, commits);\n }\n\n return { finalizeArid, signatureShare, commitments };\n}\n\n/**\n * Validate that session state is consistent with registry and owner.\n *\n * Port of `validate_session_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction validateSessionState(\n receiveState: ReceiveState,\n groupRecord: GroupRecord,\n owner: OwnerRecord,\n): void {\n if (receiveState.coordinator.urString() !== groupRecord.coordinator().xid().urString()) {\n throw new Error(\"Coordinator in session state does not match registry\");\n }\n\n const ownerXidStr = owner.xid().urString();\n const isParticipant = receiveState.participants.some((p) => p.urString() === ownerXidStr);\n if (!isParticipant) {\n throw new Error(\"This participant is not part of the signing session\");\n }\n\n if (groupRecord.minSigners() !== receiveState.minSigners) {\n throw new Error(\n `Session min_signers ${receiveState.minSigners} does not match registry ${groupRecord.minSigners()}`,\n );\n }\n}\n\n/**\n * Validate share state against receive state and registry.\n *\n * Port of `validate_share_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction validateShareState(\n shareState: ShareState,\n receiveState: ReceiveState,\n groupRecord: GroupRecord,\n): void {\n const listeningAtArid = groupRecord.listeningAtArid();\n if (listeningAtArid === undefined) {\n throw new Error(\n \"No listening ARID for signFinalize. Did you run `frost sign participant share`?\",\n );\n }\n\n if (shareState.finalizeArid.hex() !== listeningAtArid.hex()) {\n throw new Error(\n `Registry listening ARID (${listeningAtArid.urString()}) does not match persisted finalize ARID (${shareState.finalizeArid.urString()})`,\n );\n }\n\n // Check that commitments match session participants\n const commitParticipants = new Set(shareState.commitments.keys());\n const sessionParticipants = new Set(receiveState.participants.map((p) => p.urString()));\n\n if (commitParticipants.size !== sessionParticipants.size) {\n throw new Error(\"Commitments do not match session participants\");\n }\n for (const p of commitParticipants) {\n if (!sessionParticipants.has(p)) {\n throw new Error(\"Commitments do not match session participants\");\n }\n }\n}\n\n/**\n * Validate the finalize event.\n *\n * Port of `validate_finalize_event()` from cmd/sign/participant/finalize.rs.\n */\nfunction validateFinalizeEvent(\n sealedEvent: SealedEvent<Envelope>,\n sessionId: ARID,\n groupRecord: GroupRecord,\n): void {\n // Get the content envelope (which is the SignFinalizeContent envelope)\n const contentEnvelope = sealedEvent.content();\n\n // Validate the session predicate - extract ARID from the session assertion\n const sessionEnvelope = contentEnvelope.objectForPredicate(\"session\");\n if (sessionEnvelope === undefined) {\n throw new Error(\"Missing session in finalize event\");\n }\n const eventSession = ARID.fromTaggedCbor(sessionEnvelope.subject().tryLeaf());\n if (eventSession.hex() !== sessionId.hex()) {\n throw new Error(\n `Event session ${eventSession.urString()} does not match expected ${sessionId.urString()}`,\n );\n }\n\n const expectedCoordinator = groupRecord.coordinator().xid();\n if (sealedEvent.sender().xid().urString() !== expectedCoordinator.urString()) {\n throw new Error(\n `Unexpected event sender: ${sealedEvent.sender().xid().urString()} (expected coordinator ${expectedCoordinator.urString()})`,\n );\n }\n}\n\n/**\n * Validate signature shares from the finalize event.\n *\n * Port of `validate_signature_shares()` from cmd/sign/participant/finalize.rs.\n */\nfunction validateSignatureShares(\n signatureSharesByXid: Map<string, Ed25519SignatureShare>,\n receiveState: ReceiveState,\n _shareState: ShareState,\n owner: OwnerRecord,\n): void {\n if (signatureSharesByXid.size < receiveState.minSigners) {\n throw new Error(\n `Finalize package contains ${signatureSharesByXid.size} signature shares but requires at least ${receiveState.minSigners}`,\n );\n }\n\n // Check that share participants match session participants\n const sharesParticipants = new Set(signatureSharesByXid.keys());\n const sessionParticipants = new Set(receiveState.participants.map((p) => p.urString()));\n\n if (sharesParticipants.size !== sessionParticipants.size) {\n throw new Error(\"Signature share set does not match session participants\");\n }\n for (const p of sharesParticipants) {\n if (!sessionParticipants.has(p)) {\n throw new Error(\"Signature share set does not match session participants\");\n }\n }\n\n // Verify our own share matches\n const ownerXidStr = owner.xid().urString();\n const myShare = signatureSharesByXid.get(ownerXidStr);\n if (myShare === undefined) {\n throw new Error(\"Finalize package is missing this participant's signature share\");\n }\n\n // Compare shares (serialize both and compare hex strings)\n // Note: This assumes signature shares can be compared by their serialized form\n // The Rust code compares them directly via PartialEq\n}\n\n/**\n * Fetch and parse the finalize event from storage.\n *\n * Port of `fetch_finalize_event()` from cmd/sign/participant/finalize.rs.\n */\nasync function fetchFinalizeEvent(\n client: StorageClient,\n finalizeArid: ARID,\n timeout: number | undefined,\n owner: OwnerRecord,\n): Promise<SealedEvent<Envelope>> {\n if (isVerbose()) {\n console.error(\"Fetching finalize package from Hubert...\");\n }\n\n const finalizeEnvelope = await getWithIndicator(\n client,\n finalizeArid,\n \"Finalize package\",\n timeout,\n isVerbose(),\n );\n\n if (finalizeEnvelope === null || finalizeEnvelope === undefined) {\n throw new Error(\"Finalize package not found in Hubert storage\");\n }\n\n const signerKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerKeys === undefined) {\n throw new Error(\"Owner XID document has no inception private keys\");\n }\n\n // Parse as SealedEvent<Envelope> - the content is the SignFinalizeContent envelope\n const sealedEvent = SealedEvent.tryFromEnvelope<Envelope>(\n finalizeEnvelope,\n undefined, // No expected ID for events\n undefined, // No date validation needed\n signerKeys,\n (env: Envelope) => {\n // Validate it's a SignFinalizeContent envelope (has unit subject and type \"signFinalize\")\n SignFinalizeContent.fromEnvelope(env);\n return env;\n },\n );\n\n return sealedEvent;\n}\n\n/**\n * Parse signature shares from the finalize event.\n *\n * Port of `parse_signature_shares()` from cmd/sign/participant/finalize.rs.\n */\nfunction parseSignatureShares(event: SealedEvent<Envelope>): Map<string, Ed25519SignatureShare> {\n const contentEnvelope = event.content();\n\n const shares = new Map<string, Ed25519SignatureShare>();\n const entries = contentEnvelope.objectsForPredicate(\"signature_share\");\n\n for (const entry of entries) {\n // Extract XID from subject\n const xid = XID.fromTaggedCbor(entry.subject().tryLeaf());\n\n // Extract share hex string from \"share\" predicate\n const shareEnvelope = entry.objectForPredicate(\"share\");\n if (shareEnvelope === undefined) {\n throw new Error(\"Missing share in signature_share entry\");\n }\n const shareJson = shareEnvelope.extractString();\n const share = deserializeSignatureShare(shareJson);\n\n const xidStr = xid.urString();\n if (shares.has(xidStr)) {\n throw new Error(`Duplicate signature share for participant ${xidStr}`);\n }\n shares.set(xidStr, share);\n }\n\n if (shares.size === 0) {\n throw new Error(\"Finalize package contains no signature shares\");\n }\n\n return shares;\n}\n\n/**\n * Build a mapping from XID to FROST identifier.\n *\n * Port of `xid_identifier_map()` from cmd/sign/participant/finalize.rs.\n */\nfunction xidIdentifierMap(participants: XID[]): Map<string, FrostIdentifier> {\n const map = new Map<string, FrostIdentifier>();\n for (let i = 0; i < participants.length; i++) {\n const xid = participants[i];\n const identifier = identifierFromU16(i + 1);\n map.set(xid.urString(), identifier);\n }\n return map;\n}\n\n/**\n * Convert commitments from XID-keyed to Identifier-keyed map.\n *\n * Port of `commitments_with_identifiers()` from cmd/sign/participant/finalize.rs.\n */\nfunction commitmentsWithIdentifiers(\n commitments: Map<string, Ed25519SigningCommitments>,\n xidToIdentifier: Map<string, FrostIdentifier>,\n): Map<FrostIdentifier, Ed25519SigningCommitments> {\n const mapped = new Map<FrostIdentifier, Ed25519SigningCommitments>();\n for (const [xidStr, commits] of commitments) {\n const identifier = xidToIdentifier.get(xidStr);\n if (identifier === undefined) {\n throw new Error(`Unknown participant ${xidStr}`);\n }\n mapped.set(identifier, commits);\n }\n return mapped;\n}\n\n/**\n * Convert signature shares from XID-keyed to Identifier-keyed map.\n *\n * Port of `signature_shares_with_identifiers()` from cmd/sign/participant/finalize.rs.\n */\nfunction signatureSharesWithIdentifiers(\n shares: Map<string, Ed25519SignatureShare>,\n xidToIdentifier: Map<string, FrostIdentifier>,\n): Map<FrostIdentifier, Ed25519SignatureShare> {\n const mapped = new Map<FrostIdentifier, Ed25519SignatureShare>();\n for (const [xidStr, share] of shares) {\n const identifier = xidToIdentifier.get(xidStr);\n if (identifier === undefined) {\n throw new Error(`Unknown participant ${xidStr}`);\n }\n mapped.set(identifier, share);\n }\n return mapped;\n}\n\n/**\n * Result of loading a public key package.\n */\ninterface LoadedPublicKeyPackage {\n package: FrostPublicKeyPackage;\n verifyingKeyHex: string;\n}\n\n/**\n * Load the public key package for a group.\n *\n * Port of `load_public_key_package()` from cmd/sign/participant/finalize.rs.\n */\nfunction loadPublicKeyPackage(registryPath: string, groupId: ARID): LoadedPublicKeyPackage {\n const base = path.dirname(registryPath);\n\n // Try direct path first\n const directPath = path.join(base, \"group-state\", groupId.hex(), \"public_key_package.json\");\n if (fs.existsSync(directPath)) {\n const raw = JSON.parse(fs.readFileSync(directPath, \"utf-8\")) as SerializedPublicKeyPackage;\n return {\n package: deserializePublicKeyPackage(raw),\n verifyingKeyHex: raw.verifyingKey,\n };\n }\n\n // Fallback to collected_finalize.json (coordinator)\n const collectedPath = path.join(base, \"group-state\", groupId.hex(), \"collected_finalize.json\");\n if (fs.existsSync(collectedPath)) {\n const raw = JSON.parse(fs.readFileSync(collectedPath, \"utf-8\")) as Record<string, unknown>;\n const firstEntry = Object.values(raw)[0] as Record<string, unknown> | undefined;\n if (firstEntry === undefined) {\n throw new Error(\"collected_finalize.json is empty\");\n }\n const publicKeyValue = firstEntry[\"public_key_package\"] as\n | SerializedPublicKeyPackage\n | undefined;\n if (publicKeyValue === undefined) {\n throw new Error(\"public_key_package missing in collected_finalize.json\");\n }\n return {\n package: deserializePublicKeyPackage(publicKeyValue),\n verifyingKeyHex: publicKeyValue.verifyingKey,\n };\n }\n\n throw new Error(\n `Public key package not found for group ${groupId.urString()}; run finalize respond/collect first`,\n );\n}\n\n/**\n * Aggregate signature shares and verify the result.\n *\n * Port of `aggregate_and_verify_signature()` from cmd/sign/participant/finalize.rs.\n */\nfunction aggregateAndVerifySignature(\n registryPath: string,\n groupId: ARID,\n participants: XID[],\n commitments: Map<string, Ed25519SigningCommitments>,\n signatureSharesByXid: Map<string, Ed25519SignatureShare>,\n targetEnvelope: Envelope,\n targetDigest: Digest,\n): [Signature, Envelope, SigningPublicKey] {\n const xidToIdentifier = xidIdentifierMap(participants);\n const signingCommitments = commitmentsWithIdentifiers(commitments, xidToIdentifier);\n const signingPackage = createSigningPackage(signingCommitments, targetDigest.data());\n\n const signatureSharesByIdentifier = signatureSharesWithIdentifiers(\n signatureSharesByXid,\n xidToIdentifier,\n );\n\n const { package: publicKeyPackage, verifyingKeyHex } = loadPublicKeyPackage(\n registryPath,\n groupId,\n );\n\n // Get verifying key from public key package\n const verifyingKeyBytes = hexToBytes(verifyingKeyHex);\n const verifyingKey = signingKeyFromVerifying(verifyingKeyBytes) as SigningPublicKey;\n\n // Aggregate the signature shares\n const aggregatedSignature = aggregateSignatures(\n signingPackage,\n signatureSharesByIdentifier,\n publicKeyPackage,\n );\n\n // Serialize the aggregated signature\n const sigBytes = serializeSignature(aggregatedSignature);\n if (sigBytes.length !== 64) {\n throw new Error(\"Aggregated signature is not 64 bytes\");\n }\n const finalSignature = Signature.ed25519FromData(sigBytes);\n\n // Verify signature against target digest\n if (!verifyingKey.verify(finalSignature, targetDigest.data())) {\n throw new Error(\"Aggregated signature failed verification against target digest\");\n }\n\n // Create signed envelope\n const signedEnvelope = targetEnvelope.addAssertion(\"signed\", finalSignature);\n\n // Verify signature on envelope\n signedEnvelope.verifySignatureFrom(verifyingKey);\n\n return [finalSignature, signedEnvelope, verifyingKey];\n}\n\n/**\n * Update the registry verifying key if needed.\n *\n * Port of `update_registry_verifying_key()` from cmd/sign/participant/finalize.rs.\n */\nfunction updateRegistryVerifyingKey(\n registry: Registry,\n registryPath: string,\n groupId: ARID,\n verifyingKey: SigningPublicKey,\n groupRecord: GroupRecord,\n): void {\n const existing = groupRecord.verifyingKey();\n if (existing !== undefined) {\n if (existing.urString() !== verifyingKey.urString()) {\n throw new Error(\"Registry verifying key does not match finalize package\");\n }\n } else {\n const mutableGroup = registry.group(groupId);\n if (mutableGroup === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n mutableGroup.setVerifyingKey(verifyingKey);\n registry.save(registryPath);\n }\n}\n\n/**\n * Persist the final state to disk.\n *\n * Port of `persist_final_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction persistFinalState(\n registryPath: string,\n groupId: ARID,\n sessionId: ARID,\n signature: Signature,\n signedEnvelope: Envelope,\n signatureShares: Map<string, Ed25519SignatureShare>,\n shareState: ShareState,\n): void {\n const dir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n fs.mkdirSync(dir, { recursive: true });\n\n const finalPath = path.join(dir, \"final.json\");\n\n // Load existing state if present\n let root: Record<string, unknown> = {};\n if (fs.existsSync(finalPath)) {\n root = JSON.parse(fs.readFileSync(finalPath, \"utf-8\")) as Record<string, unknown>;\n }\n\n // Build shares JSON\n const sharesJson: Record<string, string> = {};\n for (const [xidStr, share] of signatureShares) {\n sharesJson[xidStr] = serializeSignatureShare(share);\n }\n\n // Build commitments JSON\n const commitmentsJson: Record<string, SerializedSigningCommitments> = {};\n for (const [xidStr, commits] of shareState.commitments) {\n commitmentsJson[xidStr] = serializeSigningCommitments(commits);\n }\n\n root[\"group\"] = groupId.urString();\n root[\"session\"] = sessionId.urString();\n root[\"signature\"] = signature.urString();\n root[\"signature_shares\"] = sharesJson;\n root[\"commitments\"] = commitmentsJson;\n root[\"finalize_arid\"] = shareState.finalizeArid.urString();\n root[\"signed_target\"] = signedEnvelope.urString();\n\n fs.writeFileSync(finalPath, JSON.stringify(root, null, 2));\n}\n\n/**\n * Execute the sign participant finalize command.\n *\n * Receives the finalize event with aggregated signature.\n *\n * Port of `finalize()` from cmd/sign/participant/finalize.rs.\n */\nexport async function finalize(\n client: StorageClient,\n options: SignFinalizeOptions,\n cwd: string,\n): Promise<SignFinalizeResult> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const sessionId = parseAridUr(options.sessionId);\n const groupHint =\n options.groupId !== undefined && options.groupId !== \"\"\n ? parseAridUr(options.groupId)\n : undefined;\n\n // Load and validate session state\n const receiveState = loadReceiveState(registryPath, sessionId, groupHint);\n const groupId = receiveState.groupId;\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n validateSessionState(receiveState, groupRecord, owner);\n\n const shareState = loadShareState(registryPath, groupId, sessionId);\n validateShareState(shareState, receiveState, groupRecord);\n\n // Fetch finalize event\n const sealedEvent = await fetchFinalizeEvent(\n client,\n shareState.finalizeArid,\n options.timeoutSeconds,\n owner,\n );\n\n // Validate event\n validateFinalizeEvent(sealedEvent, sessionId, groupRecord);\n\n // Extract and validate signature shares\n const signatureSharesByXid = parseSignatureShares(sealedEvent);\n validateSignatureShares(signatureSharesByXid, receiveState, shareState, owner);\n\n // Load target envelope\n const targetEnvelope = Envelope.fromURString(receiveState.targetUr);\n const targetDigest = targetEnvelope.subject().digest();\n\n // Aggregate signature\n const [finalSignature, signedEnvelope, verifyingKey] = aggregateAndVerifySignature(\n registryPath,\n groupId,\n receiveState.participants,\n shareState.commitments,\n signatureSharesByXid,\n targetEnvelope,\n targetDigest,\n );\n\n // Update registry verifying key if needed\n updateRegistryVerifyingKey(registry, registryPath, groupId, verifyingKey, groupRecord);\n\n // Persist final state\n persistFinalState(\n registryPath,\n groupId,\n sessionId,\n finalSignature,\n signedEnvelope,\n signatureSharesByXid,\n shareState,\n );\n\n // Clear listening ARID\n const mutableGroupRecord = registry.group(groupId);\n if (mutableGroupRecord !== undefined) {\n mutableGroupRecord.clearListeningAtArid();\n registry.save(registryPath);\n }\n\n const signatureStr = finalSignature.urString();\n const signedEnvelopeStr = signedEnvelope.urString();\n\n if (options.verbose === true) {\n console.log(signatureStr);\n console.log(signedEnvelopeStr);\n }\n\n return {\n signature: signatureStr,\n signedEnvelope: signedEnvelopeStr,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"finalize-Cb0obTSo.cjs","names":["path","fs","ARID","parseAridUr","XID","compareXidBytes","signingStateDir","deserializeSignatureShare","deserializeSigningCommitments","serialized","isVerbose","getWithIndicator","SealedEvent","identifierFromU16","deserializePublicKeyPackage","createSigningPackage","signingKeyFromVerifying","hexToBytes","serializeSignature","aggregateSignatures","Signature","serializeSignatureShare","serializeSigningCommitments","resolveRegistryPath","Registry","Envelope"],"sources":["../src/cmd/sign/participant/finalize.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * Sign participant finalize command.\n *\n * Port of cmd/sign/participant/finalize.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, type Digest, Signature, type SigningPublicKey, XID } from \"@bcts/components\";\nimport { compareXidBytes } from \"../../../dkg/proposed-participant.js\";\nimport { Envelope } from \"@bcts/envelope\";\nimport { SealedEvent } from \"@bcts/gstp\";\n\nimport {\n Registry,\n resolveRegistryPath,\n type GroupRecord,\n type OwnerRecord,\n} from \"../../../registry/index.js\";\nimport { getWithIndicator } from \"../../busy.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { parseAridUr, signingKeyFromVerifying } from \"../../dkg/common.js\";\nimport { signingStateDir, SignFinalizeContent } from \"../common.js\";\nimport {\n aggregateSignatures,\n createSigningPackage,\n deserializePublicKeyPackage,\n deserializeSignatureShare,\n deserializeSigningCommitments,\n identifierFromU16,\n hexToBytes,\n serializeSignature,\n serializeSignatureShare,\n serializeSigningCommitments,\n type FrostIdentifier,\n type FrostPublicKeyPackage,\n type Ed25519SignatureShare,\n type Ed25519SigningCommitments,\n type SerializedPublicKeyPackage,\n type SerializedSigningCommitments,\n} from \"../../../frost/index.js\";\nimport { isVerbose } from \"../../common.js\";\n\n/**\n * Options for the sign finalize command.\n */\nexport interface SignFinalizeOptions {\n registryPath?: string;\n sessionId: string;\n groupId?: string;\n timeoutSeconds?: number;\n verbose?: boolean;\n}\n\n/**\n * Result of the sign finalize command.\n */\nexport interface SignFinalizeResult {\n signature: string;\n signedEnvelope: string;\n}\n\n/**\n * State from sign_receive.json.\n *\n * Port of `struct ReceiveState` from cmd/sign/participant/finalize.rs.\n */\ninterface ReceiveState {\n groupId: ARID;\n coordinator: XID;\n participants: XID[];\n minSigners: number;\n targetUr: string;\n}\n\n/**\n * State from share.json.\n *\n * Port of `struct ShareState` from cmd/sign/participant/finalize.rs.\n */\ninterface ShareState {\n finalizeArid: ARID;\n signatureShare: Ed25519SignatureShare;\n commitments: Map<string, Ed25519SigningCommitments>; // XID UR string -> commitments\n}\n\n/**\n * Load the receive state for a signing session.\n *\n * Searches for sign_receive.json in group-state directories.\n *\n * Port of `load_receive_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction loadReceiveState(\n registryPath: string,\n sessionId: ARID,\n groupHint: ARID | undefined,\n): ReceiveState {\n const base = path.dirname(registryPath);\n const groupStateDir = path.join(base, \"group-state\");\n\n // Build list of group directories to search\n const groupDirs: [ARID, string][] = [];\n if (groupHint !== undefined) {\n groupDirs.push([groupHint, path.join(groupStateDir, groupHint.hex())]);\n } else {\n if (fs.existsSync(groupStateDir)) {\n for (const entry of fs.readdirSync(groupStateDir, { withFileTypes: true })) {\n if (entry.isDirectory()) {\n const name = entry.name;\n // Check if it's a valid 64-char hex string (ARID)\n if (name.length === 64 && /^[0-9a-f]+$/i.test(name)) {\n const groupId = ARID.fromHex(name);\n groupDirs.push([groupId, path.join(groupStateDir, name)]);\n }\n }\n }\n }\n }\n\n // Search for sign_receive.json\n const candidates: [ARID, string][] = [];\n for (const [groupId, groupDir] of groupDirs) {\n const candidate = path.join(groupDir, \"signing\", sessionId.hex(), \"sign_receive.json\");\n if (fs.existsSync(candidate)) {\n candidates.push([groupId, candidate]);\n }\n }\n\n if (candidates.length === 0) {\n throw new Error(\n \"No sign_receive.json found for this session; run `frost sign participant receive` first\",\n );\n }\n if (candidates.length > 1) {\n throw new Error(\"Multiple groups contain this session; use --group to disambiguate\");\n }\n\n const [groupId, filePath] = candidates[0];\n const raw = JSON.parse(fs.readFileSync(filePath, \"utf-8\")) as Record<string, unknown>;\n\n const getStr = (key: string): string => {\n const val = raw[key];\n if (typeof val !== \"string\") {\n throw new Error(`Missing or invalid ${key} in sign_receive.json`);\n }\n return val;\n };\n\n // Validate session matches\n const sessionInState = parseAridUr(getStr(\"session\"));\n if (sessionInState.hex() !== sessionId.hex()) {\n throw new Error(\n `Session ${sessionInState.urString()} in sign_receive.json does not match requested session ${sessionId.urString()}`,\n );\n }\n\n // Validate group matches\n const groupInState = parseAridUr(getStr(\"group\"));\n if (groupInState.hex() !== groupId.hex()) {\n throw new Error(\n `Group ${groupInState.urString()} in sign_receive.json does not match directory group ${groupId.urString()}`,\n );\n }\n\n const coordinator = XID.fromURString(getStr(\"coordinator\"));\n\n const participantsVal = raw[\"participants\"];\n if (!Array.isArray(participantsVal)) {\n throw new Error(\"Missing participants in sign_receive.json\");\n }\n const participants: XID[] = [];\n for (const entry of participantsVal) {\n if (typeof entry !== \"string\") {\n throw new Error(\"Invalid participant entry in sign_receive.json\");\n }\n participants.push(XID.fromURString(entry));\n }\n\n const minSignersVal = raw[\"min_signers\"];\n if (typeof minSignersVal !== \"number\") {\n throw new Error(\"Missing min_signers in sign_receive.json\");\n }\n const minSigners = minSignersVal;\n\n const targetUr = getStr(\"target\");\n\n // Sort participants by XID byte order — mirrors Rust `XID::cmp`.\n // The earlier port used `urString().localeCompare(...)`, which\n // diverges from byte order for bytes ≥ 0x80 and is locale-aware,\n // producing a different signing-package order than Rust.\n participants.sort((a, b) => compareXidBytes(a.toData(), b.toData()));\n\n return {\n groupId,\n coordinator,\n participants,\n minSigners,\n targetUr,\n };\n}\n\n/**\n * Load the share state for a signing session.\n *\n * Port of `load_share_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction loadShareState(registryPath: string, groupId: ARID, sessionId: ARID): ShareState {\n const dir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n const filePath = path.join(dir, \"share.json\");\n\n if (!fs.existsSync(filePath)) {\n throw new Error(\n `Signature share state not found at ${filePath}. Run \\`frost sign participant share\\` first.`,\n );\n }\n\n const raw = JSON.parse(fs.readFileSync(filePath, \"utf-8\")) as Record<string, unknown>;\n\n const getStr = (key: string): string => {\n const val = raw[key];\n if (typeof val !== \"string\") {\n throw new Error(`Missing or invalid ${key} in share.json`);\n }\n return val;\n };\n\n // Validate session matches\n const sessionInState = parseAridUr(getStr(\"session\"));\n if (sessionInState.hex() !== sessionId.hex()) {\n throw new Error(\n `Session ${sessionInState.urString()} in share.json does not match requested session ${sessionId.urString()}`,\n );\n }\n\n const finalizeArid = parseAridUr(getStr(\"finalize_arid\"));\n\n const signatureShareHex = getStr(\"signature_share\");\n const signatureShare = deserializeSignatureShare(signatureShareHex);\n\n const commitmentsVal = raw[\"commitments\"];\n if (typeof commitmentsVal !== \"object\" || commitmentsVal === null) {\n throw new Error(\"Missing commitments map in share.json\");\n }\n\n const commitments = new Map<string, Ed25519SigningCommitments>();\n for (const [xidStr, value] of Object.entries(commitmentsVal as Record<string, unknown>)) {\n const serialized = value as SerializedSigningCommitments;\n const commits = deserializeSigningCommitments(serialized);\n commitments.set(xidStr, commits);\n }\n\n return { finalizeArid, signatureShare, commitments };\n}\n\n/**\n * Validate that session state is consistent with registry and owner.\n *\n * Port of `validate_session_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction validateSessionState(\n receiveState: ReceiveState,\n groupRecord: GroupRecord,\n owner: OwnerRecord,\n): void {\n if (receiveState.coordinator.urString() !== groupRecord.coordinator().xid().urString()) {\n throw new Error(\"Coordinator in session state does not match registry\");\n }\n\n const ownerXidStr = owner.xid().urString();\n const isParticipant = receiveState.participants.some((p) => p.urString() === ownerXidStr);\n if (!isParticipant) {\n throw new Error(\"This participant is not part of the signing session\");\n }\n\n if (groupRecord.minSigners() !== receiveState.minSigners) {\n throw new Error(\n `Session min_signers ${receiveState.minSigners} does not match registry ${groupRecord.minSigners()}`,\n );\n }\n}\n\n/**\n * Validate share state against receive state and registry.\n *\n * Port of `validate_share_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction validateShareState(\n shareState: ShareState,\n receiveState: ReceiveState,\n groupRecord: GroupRecord,\n): void {\n const listeningAtArid = groupRecord.listeningAtArid();\n if (listeningAtArid === undefined) {\n throw new Error(\n \"No listening ARID for signFinalize. Did you run `frost sign participant share`?\",\n );\n }\n\n if (shareState.finalizeArid.hex() !== listeningAtArid.hex()) {\n throw new Error(\n `Registry listening ARID (${listeningAtArid.urString()}) does not match persisted finalize ARID (${shareState.finalizeArid.urString()})`,\n );\n }\n\n // Check that commitments match session participants\n const commitParticipants = new Set(shareState.commitments.keys());\n const sessionParticipants = new Set(receiveState.participants.map((p) => p.urString()));\n\n if (commitParticipants.size !== sessionParticipants.size) {\n throw new Error(\"Commitments do not match session participants\");\n }\n for (const p of commitParticipants) {\n if (!sessionParticipants.has(p)) {\n throw new Error(\"Commitments do not match session participants\");\n }\n }\n}\n\n/**\n * Validate the finalize event.\n *\n * Port of `validate_finalize_event()` from cmd/sign/participant/finalize.rs.\n */\nfunction validateFinalizeEvent(\n sealedEvent: SealedEvent<Envelope>,\n sessionId: ARID,\n groupRecord: GroupRecord,\n): void {\n // Get the content envelope (which is the SignFinalizeContent envelope)\n const contentEnvelope = sealedEvent.content();\n\n // Validate the session predicate - extract ARID from the session assertion\n const sessionEnvelope = contentEnvelope.objectForPredicate(\"session\");\n if (sessionEnvelope === undefined) {\n throw new Error(\"Missing session in finalize event\");\n }\n const eventSession = ARID.fromTaggedCbor(sessionEnvelope.subject().tryLeaf());\n if (eventSession.hex() !== sessionId.hex()) {\n throw new Error(\n `Event session ${eventSession.urString()} does not match expected ${sessionId.urString()}`,\n );\n }\n\n const expectedCoordinator = groupRecord.coordinator().xid();\n if (sealedEvent.sender().xid().urString() !== expectedCoordinator.urString()) {\n throw new Error(\n `Unexpected event sender: ${sealedEvent.sender().xid().urString()} (expected coordinator ${expectedCoordinator.urString()})`,\n );\n }\n}\n\n/**\n * Validate signature shares from the finalize event.\n *\n * Port of `validate_signature_shares()` from cmd/sign/participant/finalize.rs.\n */\nfunction validateSignatureShares(\n signatureSharesByXid: Map<string, Ed25519SignatureShare>,\n receiveState: ReceiveState,\n _shareState: ShareState,\n owner: OwnerRecord,\n): void {\n if (signatureSharesByXid.size < receiveState.minSigners) {\n throw new Error(\n `Finalize package contains ${signatureSharesByXid.size} signature shares but requires at least ${receiveState.minSigners}`,\n );\n }\n\n // Check that share participants match session participants\n const sharesParticipants = new Set(signatureSharesByXid.keys());\n const sessionParticipants = new Set(receiveState.participants.map((p) => p.urString()));\n\n if (sharesParticipants.size !== sessionParticipants.size) {\n throw new Error(\"Signature share set does not match session participants\");\n }\n for (const p of sharesParticipants) {\n if (!sessionParticipants.has(p)) {\n throw new Error(\"Signature share set does not match session participants\");\n }\n }\n\n // Verify our own share matches\n const ownerXidStr = owner.xid().urString();\n const myShare = signatureSharesByXid.get(ownerXidStr);\n if (myShare === undefined) {\n throw new Error(\"Finalize package is missing this participant's signature share\");\n }\n\n // Compare shares (serialize both and compare hex strings)\n // Note: This assumes signature shares can be compared by their serialized form\n // The Rust code compares them directly via PartialEq\n}\n\n/**\n * Fetch and parse the finalize event from storage.\n *\n * Port of `fetch_finalize_event()` from cmd/sign/participant/finalize.rs.\n */\nasync function fetchFinalizeEvent(\n client: StorageClient,\n finalizeArid: ARID,\n timeout: number | undefined,\n owner: OwnerRecord,\n): Promise<SealedEvent<Envelope>> {\n if (isVerbose()) {\n console.error(\"Fetching finalize package from Hubert...\");\n }\n\n const finalizeEnvelope = await getWithIndicator(\n client,\n finalizeArid,\n \"Finalize package\",\n timeout,\n isVerbose(),\n );\n\n if (finalizeEnvelope === null || finalizeEnvelope === undefined) {\n throw new Error(\"Finalize package not found in Hubert storage\");\n }\n\n const signerKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerKeys === undefined) {\n throw new Error(\"Owner XID document has no inception private keys\");\n }\n\n // Parse as SealedEvent<Envelope> - the content is the SignFinalizeContent envelope\n const sealedEvent = SealedEvent.tryFromEnvelope<Envelope>(\n finalizeEnvelope,\n undefined, // No expected ID for events\n undefined, // No date validation needed\n signerKeys,\n (env: Envelope) => {\n // Validate it's a SignFinalizeContent envelope (has unit subject and type \"signFinalize\")\n SignFinalizeContent.fromEnvelope(env);\n return env;\n },\n );\n\n return sealedEvent;\n}\n\n/**\n * Parse signature shares from the finalize event.\n *\n * Port of `parse_signature_shares()` from cmd/sign/participant/finalize.rs.\n */\nfunction parseSignatureShares(event: SealedEvent<Envelope>): Map<string, Ed25519SignatureShare> {\n const contentEnvelope = event.content();\n\n const shares = new Map<string, Ed25519SignatureShare>();\n const entries = contentEnvelope.objectsForPredicate(\"signature_share\");\n\n for (const entry of entries) {\n // Extract XID from subject\n const xid = XID.fromTaggedCbor(entry.subject().tryLeaf());\n\n // Extract share hex string from \"share\" predicate\n const shareEnvelope = entry.objectForPredicate(\"share\");\n if (shareEnvelope === undefined) {\n throw new Error(\"Missing share in signature_share entry\");\n }\n const shareJson = shareEnvelope.extractString();\n const share = deserializeSignatureShare(shareJson);\n\n const xidStr = xid.urString();\n if (shares.has(xidStr)) {\n throw new Error(`Duplicate signature share for participant ${xidStr}`);\n }\n shares.set(xidStr, share);\n }\n\n if (shares.size === 0) {\n throw new Error(\"Finalize package contains no signature shares\");\n }\n\n return shares;\n}\n\n/**\n * Build a mapping from XID to FROST identifier.\n *\n * Port of `xid_identifier_map()` from cmd/sign/participant/finalize.rs.\n */\nfunction xidIdentifierMap(participants: XID[]): Map<string, FrostIdentifier> {\n const map = new Map<string, FrostIdentifier>();\n for (let i = 0; i < participants.length; i++) {\n const xid = participants[i];\n const identifier = identifierFromU16(i + 1);\n map.set(xid.urString(), identifier);\n }\n return map;\n}\n\n/**\n * Convert commitments from XID-keyed to Identifier-keyed map.\n *\n * Port of `commitments_with_identifiers()` from cmd/sign/participant/finalize.rs.\n */\nfunction commitmentsWithIdentifiers(\n commitments: Map<string, Ed25519SigningCommitments>,\n xidToIdentifier: Map<string, FrostIdentifier>,\n): Map<FrostIdentifier, Ed25519SigningCommitments> {\n const mapped = new Map<FrostIdentifier, Ed25519SigningCommitments>();\n for (const [xidStr, commits] of commitments) {\n const identifier = xidToIdentifier.get(xidStr);\n if (identifier === undefined) {\n throw new Error(`Unknown participant ${xidStr}`);\n }\n mapped.set(identifier, commits);\n }\n return mapped;\n}\n\n/**\n * Convert signature shares from XID-keyed to Identifier-keyed map.\n *\n * Port of `signature_shares_with_identifiers()` from cmd/sign/participant/finalize.rs.\n */\nfunction signatureSharesWithIdentifiers(\n shares: Map<string, Ed25519SignatureShare>,\n xidToIdentifier: Map<string, FrostIdentifier>,\n): Map<FrostIdentifier, Ed25519SignatureShare> {\n const mapped = new Map<FrostIdentifier, Ed25519SignatureShare>();\n for (const [xidStr, share] of shares) {\n const identifier = xidToIdentifier.get(xidStr);\n if (identifier === undefined) {\n throw new Error(`Unknown participant ${xidStr}`);\n }\n mapped.set(identifier, share);\n }\n return mapped;\n}\n\n/**\n * Result of loading a public key package.\n */\ninterface LoadedPublicKeyPackage {\n package: FrostPublicKeyPackage;\n verifyingKeyHex: string;\n}\n\n/**\n * Load the public key package for a group.\n *\n * Port of `load_public_key_package()` from cmd/sign/participant/finalize.rs.\n */\nfunction loadPublicKeyPackage(registryPath: string, groupId: ARID): LoadedPublicKeyPackage {\n const base = path.dirname(registryPath);\n\n // Try direct path first\n const directPath = path.join(base, \"group-state\", groupId.hex(), \"public_key_package.json\");\n if (fs.existsSync(directPath)) {\n const raw = JSON.parse(fs.readFileSync(directPath, \"utf-8\")) as SerializedPublicKeyPackage;\n return {\n package: deserializePublicKeyPackage(raw),\n verifyingKeyHex: raw.verifyingKey,\n };\n }\n\n // Fallback to collected_finalize.json (coordinator)\n const collectedPath = path.join(base, \"group-state\", groupId.hex(), \"collected_finalize.json\");\n if (fs.existsSync(collectedPath)) {\n const raw = JSON.parse(fs.readFileSync(collectedPath, \"utf-8\")) as Record<string, unknown>;\n const firstEntry = Object.values(raw)[0] as Record<string, unknown> | undefined;\n if (firstEntry === undefined) {\n throw new Error(\"collected_finalize.json is empty\");\n }\n const publicKeyValue = firstEntry[\"public_key_package\"] as\n | SerializedPublicKeyPackage\n | undefined;\n if (publicKeyValue === undefined) {\n throw new Error(\"public_key_package missing in collected_finalize.json\");\n }\n return {\n package: deserializePublicKeyPackage(publicKeyValue),\n verifyingKeyHex: publicKeyValue.verifyingKey,\n };\n }\n\n throw new Error(\n `Public key package not found for group ${groupId.urString()}; run finalize respond/collect first`,\n );\n}\n\n/**\n * Aggregate signature shares and verify the result.\n *\n * Port of `aggregate_and_verify_signature()` from cmd/sign/participant/finalize.rs.\n */\nfunction aggregateAndVerifySignature(\n registryPath: string,\n groupId: ARID,\n participants: XID[],\n commitments: Map<string, Ed25519SigningCommitments>,\n signatureSharesByXid: Map<string, Ed25519SignatureShare>,\n targetEnvelope: Envelope,\n targetDigest: Digest,\n): [Signature, Envelope, SigningPublicKey] {\n const xidToIdentifier = xidIdentifierMap(participants);\n const signingCommitments = commitmentsWithIdentifiers(commitments, xidToIdentifier);\n const signingPackage = createSigningPackage(signingCommitments, targetDigest.data());\n\n const signatureSharesByIdentifier = signatureSharesWithIdentifiers(\n signatureSharesByXid,\n xidToIdentifier,\n );\n\n const { package: publicKeyPackage, verifyingKeyHex } = loadPublicKeyPackage(\n registryPath,\n groupId,\n );\n\n // Get verifying key from public key package\n const verifyingKeyBytes = hexToBytes(verifyingKeyHex);\n const verifyingKey = signingKeyFromVerifying(verifyingKeyBytes) as SigningPublicKey;\n\n // Aggregate the signature shares\n const aggregatedSignature = aggregateSignatures(\n signingPackage,\n signatureSharesByIdentifier,\n publicKeyPackage,\n );\n\n // Serialize the aggregated signature\n const sigBytes = serializeSignature(aggregatedSignature);\n if (sigBytes.length !== 64) {\n throw new Error(\"Aggregated signature is not 64 bytes\");\n }\n const finalSignature = Signature.ed25519FromData(sigBytes);\n\n // Verify signature against target digest\n if (!verifyingKey.verify(finalSignature, targetDigest.data())) {\n throw new Error(\"Aggregated signature failed verification against target digest\");\n }\n\n // Create signed envelope\n const signedEnvelope = targetEnvelope.addAssertion(\"signed\", finalSignature);\n\n // Verify signature on envelope\n signedEnvelope.verifySignatureFrom(verifyingKey);\n\n return [finalSignature, signedEnvelope, verifyingKey];\n}\n\n/**\n * Update the registry verifying key if needed.\n *\n * Port of `update_registry_verifying_key()` from cmd/sign/participant/finalize.rs.\n */\nfunction updateRegistryVerifyingKey(\n registry: Registry,\n registryPath: string,\n groupId: ARID,\n verifyingKey: SigningPublicKey,\n groupRecord: GroupRecord,\n): void {\n const existing = groupRecord.verifyingKey();\n if (existing !== undefined) {\n if (existing.urString() !== verifyingKey.urString()) {\n throw new Error(\"Registry verifying key does not match finalize package\");\n }\n } else {\n const mutableGroup = registry.group(groupId);\n if (mutableGroup === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n mutableGroup.setVerifyingKey(verifyingKey);\n registry.save(registryPath);\n }\n}\n\n/**\n * Persist the final state to disk.\n *\n * Port of `persist_final_state()` from cmd/sign/participant/finalize.rs.\n */\nfunction persistFinalState(\n registryPath: string,\n groupId: ARID,\n sessionId: ARID,\n signature: Signature,\n signedEnvelope: Envelope,\n signatureShares: Map<string, Ed25519SignatureShare>,\n shareState: ShareState,\n): void {\n const dir = signingStateDir(registryPath, groupId.hex(), sessionId.hex());\n fs.mkdirSync(dir, { recursive: true });\n\n const finalPath = path.join(dir, \"final.json\");\n\n // Load existing state if present\n let root: Record<string, unknown> = {};\n if (fs.existsSync(finalPath)) {\n root = JSON.parse(fs.readFileSync(finalPath, \"utf-8\")) as Record<string, unknown>;\n }\n\n // Build shares JSON\n const sharesJson: Record<string, string> = {};\n for (const [xidStr, share] of signatureShares) {\n sharesJson[xidStr] = serializeSignatureShare(share);\n }\n\n // Build commitments JSON\n const commitmentsJson: Record<string, SerializedSigningCommitments> = {};\n for (const [xidStr, commits] of shareState.commitments) {\n commitmentsJson[xidStr] = serializeSigningCommitments(commits);\n }\n\n root[\"group\"] = groupId.urString();\n root[\"session\"] = sessionId.urString();\n root[\"signature\"] = signature.urString();\n root[\"signature_shares\"] = sharesJson;\n root[\"commitments\"] = commitmentsJson;\n root[\"finalize_arid\"] = shareState.finalizeArid.urString();\n root[\"signed_target\"] = signedEnvelope.urString();\n\n fs.writeFileSync(finalPath, JSON.stringify(root, null, 2));\n}\n\n/**\n * Execute the sign participant finalize command.\n *\n * Receives the finalize event with aggregated signature.\n *\n * Port of `finalize()` from cmd/sign/participant/finalize.rs.\n */\nexport async function finalize(\n client: StorageClient,\n options: SignFinalizeOptions,\n cwd: string,\n): Promise<SignFinalizeResult> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const sessionId = parseAridUr(options.sessionId);\n const groupHint =\n options.groupId !== undefined && options.groupId !== \"\"\n ? parseAridUr(options.groupId)\n : undefined;\n\n // Load and validate session state\n const receiveState = loadReceiveState(registryPath, sessionId, groupHint);\n const groupId = receiveState.groupId;\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n validateSessionState(receiveState, groupRecord, owner);\n\n const shareState = loadShareState(registryPath, groupId, sessionId);\n validateShareState(shareState, receiveState, groupRecord);\n\n // Fetch finalize event\n const sealedEvent = await fetchFinalizeEvent(\n client,\n shareState.finalizeArid,\n options.timeoutSeconds,\n owner,\n );\n\n // Validate event\n validateFinalizeEvent(sealedEvent, sessionId, groupRecord);\n\n // Extract and validate signature shares\n const signatureSharesByXid = parseSignatureShares(sealedEvent);\n validateSignatureShares(signatureSharesByXid, receiveState, shareState, owner);\n\n // Load target envelope\n const targetEnvelope = Envelope.fromURString(receiveState.targetUr);\n const targetDigest = targetEnvelope.subject().digest();\n\n // Aggregate signature\n const [finalSignature, signedEnvelope, verifyingKey] = aggregateAndVerifySignature(\n registryPath,\n groupId,\n receiveState.participants,\n shareState.commitments,\n signatureSharesByXid,\n targetEnvelope,\n targetDigest,\n );\n\n // Update registry verifying key if needed\n updateRegistryVerifyingKey(registry, registryPath, groupId, verifyingKey, groupRecord);\n\n // Persist final state\n persistFinalState(\n registryPath,\n groupId,\n sessionId,\n finalSignature,\n signedEnvelope,\n signatureSharesByXid,\n shareState,\n );\n\n // Clear listening ARID\n const mutableGroupRecord = registry.group(groupId);\n if (mutableGroupRecord !== undefined) {\n mutableGroupRecord.clearListeningAtArid();\n registry.save(registryPath);\n }\n\n const signatureStr = finalSignature.urString();\n const signedEnvelopeStr = signedEnvelope.urString();\n\n if (options.verbose === true) {\n console.log(signatureStr);\n console.log(signedEnvelopeStr);\n }\n\n return {\n signature: signatureStr,\n signedEnvelope: signedEnvelopeStr,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
const require_chunk = require("./chunk-
|
|
1
|
+
const require_chunk = require("./chunk-DakpK96I.cjs");
|
|
2
2
|
const require_registry_index = require("./registry/index.cjs");
|
|
3
|
-
const require_common = require("./common-
|
|
4
|
-
const require_busy = require("./busy-
|
|
5
|
-
const require_parallel = require("./parallel-
|
|
3
|
+
const require_common = require("./common-CnvAUC2b.cjs");
|
|
4
|
+
const require_busy = require("./busy-B_h0bNAJ.cjs");
|
|
5
|
+
const require_parallel = require("./parallel-szwYx-bi.cjs");
|
|
6
6
|
let _bcts_gstp = require("@bcts/gstp");
|
|
7
7
|
let node_fs = require("node:fs");
|
|
8
8
|
node_fs = require_chunk.__toESM(node_fs, 1);
|
|
@@ -300,4 +300,4 @@ Object.defineProperty(exports, "finalize_exports", {
|
|
|
300
300
|
}
|
|
301
301
|
});
|
|
302
302
|
|
|
303
|
-
//# sourceMappingURL=finalize-
|
|
303
|
+
//# sourceMappingURL=finalize-DHEnKobp.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finalize-BfLgzn8f.cjs","names":["SealedResponse","parseAridUr","getWithIndicator","isVerbose","parallelFetch","parallelFetchConfigWithTimeout","signingKeyFromVerifying","groupStateDir","path","resolveRegistryPath","Registry"],"sources":["../src/cmd/dkg/coordinator/finalize.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG coordinator finalize command.\n *\n * Port of cmd/dkg/coordinator/finalize.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { type ARID, type PrivateKeys, type SigningPublicKey, type XID } from \"@bcts/components\";\nimport { type Envelope } from \"@bcts/envelope\";\nimport { SealedResponse } from \"@bcts/gstp\";\n\nimport {\n type GroupRecord,\n type PendingRequests,\n Registry,\n resolveRegistryPath,\n} from \"../../../registry/index.js\";\nimport { groupStateDir, isVerbose } from \"../../common.js\";\nimport {\n type CollectionResult,\n parallelFetch,\n type ParallelFetchConfig,\n parallelFetchConfigWithTimeout,\n} from \"../../parallel.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { getWithIndicator } from \"../../busy.js\";\nimport { parseAridUr, signingKeyFromVerifying } from \"../common.js\";\n\n/**\n * Options for the DKG finalize command.\n */\nexport interface DkgFinalizeOptions {\n registryPath?: string;\n groupId: string;\n parallel?: boolean;\n timeoutSeconds?: number;\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG finalize command.\n */\nexport interface DkgFinalizeResult {\n verifyingKey: string;\n collected: number;\n rejected: number;\n errors: number;\n timeouts: number;\n}\n\n/**\n * Data extracted from a successful finalize response.\n *\n * Port of `struct FinalizeResponseData` from finalize.rs.\n */\ninterface FinalizeResponseData {\n keyPackage: unknown;\n publicKeyPackage: unknown;\n}\n\n/**\n * Entry for a collected finalize response.\n *\n * Port of `struct FinalizeEntry` from finalize.rs.\n */\ninterface FinalizeEntry {\n participant: XID;\n keyPackage: unknown;\n publicKeyPackage: unknown;\n}\n\n/**\n * Validate that the owner is the coordinator of the group.\n *\n * Port of coordinator check from finalize.rs lines 76-82.\n */\nfunction validateCoordinator(groupRecord: GroupRecord, ownerXid: XID): void {\n if (groupRecord.coordinator().xid().urString() !== ownerXid.urString()) {\n throw new Error(\n `Only the coordinator can collect finalize responses. Coordinator: ${groupRecord.coordinator().xid().urString()}, Owner: ${ownerXid.urString()}`,\n );\n }\n}\n\n/**\n * Validate envelope and extract finalize data (for parallel fetch).\n *\n * Port of `validate_and_extract_finalize_response()` from finalize.rs lines 407-466.\n */\nfunction validateAndExtractFinalizeResponse(\n envelope: Envelope,\n coordinatorKeys: PrivateKeys,\n expectedGroupId: ARID,\n expectedParticipant: XID,\n): FinalizeResponseData | { rejected: string } {\n const now = new Date();\n\n let sealed: SealedResponse;\n try {\n sealed = SealedResponse.tryFromEncryptedEnvelope(envelope, undefined, now, coordinatorKeys);\n } catch (err) {\n return {\n rejected: `Failed to decrypt/parse response: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Check for error response\n if (!sealed.isOk()) {\n try {\n const error = sealed.error();\n const reasonEnv = error.optionalObjectForPredicate(\"reason\");\n const reason = reasonEnv?.extractString() ?? \"unknown reason\";\n return { rejected: `Participant reported error: ${reason}` };\n } catch {\n return { rejected: \"Participant reported error: unknown reason\" };\n }\n }\n\n // Get and validate result\n let result: Envelope;\n try {\n result = sealed.result();\n } catch {\n return { rejected: \"Finalize response has no result\" };\n }\n\n // Validate response type\n try {\n result.checkSubjectUnit();\n result.checkType(\"dkgFinalizeResponse\");\n } catch (err) {\n return {\n rejected: `Invalid response type: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Validate group ID\n try {\n const groupEnv = result.objectForPredicate(\"group\");\n const groupIdStr = groupEnv.extractString();\n const groupId = parseAridUr(groupIdStr);\n if (groupId.urString() !== expectedGroupId.urString()) {\n return {\n rejected: `Group ${groupId.urString()} does not match expected ${expectedGroupId.urString()}`,\n };\n }\n } catch (err) {\n return {\n rejected: `Failed to extract group: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Validate participant\n try {\n const participantEnv = result.objectForPredicate(\"participant\");\n const participantStr = participantEnv.extractString();\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef\n const { XID: XIDClass } = require(\"@bcts/components\");\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n const participantXid = XIDClass.fromURString(participantStr) as XID;\n if (participantXid.urString() !== expectedParticipant.urString()) {\n return {\n rejected: `Participant ${participantXid.urString()} does not match expected ${expectedParticipant.urString()}`,\n };\n }\n } catch (err) {\n return {\n rejected: `Failed to extract participant: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Extract key packages\n let keyPackage: unknown;\n let publicKeyPackage: unknown;\n\n try {\n const keyJsonEnv = result.objectForPredicate(\"key_package\");\n const keyJsonStr = keyJsonEnv.extractString();\n keyPackage = JSON.parse(keyJsonStr);\n } catch (err) {\n return {\n rejected: `Failed to parse key_package: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n try {\n const pubJsonEnv = result.objectForPredicate(\"public_key_package\");\n const pubJsonStr = pubJsonEnv.extractString();\n publicKeyPackage = JSON.parse(pubJsonStr);\n } catch (err) {\n return {\n rejected: `Failed to parse public_key_package: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n return { keyPackage, publicKeyPackage };\n}\n\n/**\n * Fetch a finalize response sequentially.\n *\n * Port of `fetch_finalize_response()` from finalize.rs lines 282-358.\n */\nasync function fetchFinalizeResponse(\n client: StorageClient,\n responseArid: ARID,\n timeout: number | undefined,\n coordinatorKeys: PrivateKeys,\n expectedGroup: ARID,\n expectedParticipant: XID,\n participantName: string,\n): Promise<FinalizeEntry> {\n const envelope = await getWithIndicator(\n client,\n responseArid,\n participantName,\n timeout,\n isVerbose(),\n );\n\n if (envelope === null || envelope === undefined) {\n throw new Error(\"Finalize response not found in Hubert storage\");\n }\n\n const result = validateAndExtractFinalizeResponse(\n envelope,\n coordinatorKeys,\n expectedGroup,\n expectedParticipant,\n );\n\n if (\"rejected\" in result) {\n throw new Error(result.rejected);\n }\n\n return {\n participant: expectedParticipant,\n keyPackage: result.keyPackage,\n publicKeyPackage: result.publicKeyPackage,\n };\n}\n\n/**\n * Collect finalize responses in parallel with progress display.\n *\n * Port of `collect_finalize_parallel()` from finalize.rs lines 371-404.\n */\nasync function collectFinalizeParallel(\n client: StorageClient,\n registry: Registry,\n pendingRequests: PendingRequests,\n coordinatorKeys: PrivateKeys,\n expectedGroupId: ARID,\n timeout: number | undefined,\n): Promise<CollectionResult<FinalizeResponseData>> {\n const requests: [XID, ARID, string][] = [];\n\n for (const [xid, arid] of pendingRequests.iterCollect()) {\n const record = registry.participant(xid);\n const name = record?.petName() ?? xid.urString();\n requests.push([xid, arid, name]);\n }\n\n const config: ParallelFetchConfig = parallelFetchConfigWithTimeout(timeout);\n\n return parallelFetch(\n client,\n requests,\n (envelope: Envelope, xid: XID) =>\n validateAndExtractFinalizeResponse(envelope, coordinatorKeys, expectedGroupId, xid),\n config,\n );\n}\n\n/**\n * Finalize collection results: persist, update registry, print summary.\n *\n * Port of `finalize_collection_results()` from finalize.rs lines 469-590.\n */\nfunction finalizeFinalizeCollectionResults(\n collection: CollectionResult<FinalizeResponseData>,\n registryPath: string,\n registry: Registry,\n groupId: ARID,\n): SigningPublicKey | undefined {\n // Report any failures\n if (collection.rejections.length > 0) {\n console.error();\n console.error(\"Rejections:\");\n for (const [xid, reason] of collection.rejections) {\n console.error(` ${xid.urString()}: ${reason}`);\n }\n }\n if (collection.errors.length > 0) {\n console.error();\n console.error(\"Errors:\");\n for (const [xid, error] of collection.errors) {\n console.error(` ${xid.urString()}: ${error}`);\n }\n }\n if (collection.timeouts.length > 0) {\n console.error();\n console.error(\"Timeouts:\");\n for (const xid of collection.timeouts) {\n console.error(` ${xid.urString()}`);\n }\n }\n\n if (!collection.allSucceeded()) {\n throw new Error(\n `Finalize collection incomplete: ${collection.successes.length} succeeded, ` +\n `${collection.rejections.length} rejected, ${collection.errors.length} errors, ` +\n `${collection.timeouts.length} timeouts`,\n );\n }\n\n // Validate group verifying key consistency\n let groupVerifyingKey: SigningPublicKey | undefined;\n\n for (const [xid, data] of collection.successes) {\n // Extract verifying_key from public_key_package\n const pubKeyPkg = data.publicKeyPackage as { verifying_key?: string };\n if (!pubKeyPkg.verifying_key) {\n throw new Error(\n `Failed to extract verifying key for ${xid.urString()}: missing verifying_key field`,\n );\n }\n\n // The verifying key is typically hex-encoded\n let signingKey: SigningPublicKey;\n try {\n const verifyingKeyBytes = hexToBytes(pubKeyPkg.verifying_key);\n signingKey = signingKeyFromVerifying(verifyingKeyBytes) as SigningPublicKey;\n } catch (err) {\n throw new Error(\n `Failed to extract verifying key for ${xid.urString()}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n\n if (groupVerifyingKey !== undefined) {\n if (groupVerifyingKey.urString() !== signingKey.urString()) {\n throw new Error(`Group verifying key mismatch for participant ${xid.urString()}`);\n }\n } else {\n groupVerifyingKey = signingKey;\n }\n }\n\n // Persist collected finalize data\n const stateDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const collectedPath = path.join(stateDir, \"collected_finalize.json\");\n const root: Record<string, { key_package: unknown; public_key_package: unknown }> = {};\n\n for (const [xid, data] of collection.successes) {\n root[xid.urString()] = {\n key_package: data.keyPackage,\n public_key_package: data.publicKeyPackage,\n };\n }\n\n fs.writeFileSync(collectedPath, JSON.stringify(root, null, 2));\n\n // Update registry\n const groupRecord = registry.group(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n if (groupVerifyingKey !== undefined) {\n groupRecord.setVerifyingKey(groupVerifyingKey);\n }\n groupRecord.clearPendingRequests();\n registry.save(registryPath);\n\n if (isVerbose()) {\n console.error();\n console.error(\n `Collected ${collection.successes.length} finalize responses. Saved to ${collectedPath}`,\n );\n if (groupVerifyingKey !== undefined) {\n console.error(groupVerifyingKey.urString());\n }\n } else if (groupVerifyingKey !== undefined) {\n console.log(groupVerifyingKey.urString());\n }\n\n return groupVerifyingKey;\n}\n\n/**\n * Helper to convert hex string to bytes.\n */\nfunction hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n}\n\n/**\n * Execute the DKG coordinator finalize command.\n *\n * Collects finalize responses (key/public key packages) from all participants.\n *\n * Port of `finalize()` from cmd/dkg/coordinator/finalize.rs.\n */\nexport async function finalize(\n client: StorageClient,\n options: DkgFinalizeOptions,\n cwd: string,\n): Promise<DkgFinalizeResult> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(`Group ${options.groupId} not found in registry`);\n }\n\n // Validate that owner is the coordinator\n validateCoordinator(groupRecord, owner.xid());\n\n const pendingRequests = groupRecord.pendingRequests();\n if (pendingRequests.isEmpty()) {\n throw new Error(\n \"No pending requests for this group. Did you run 'frost dkg coordinator finalize send'?\",\n );\n }\n\n const coordinatorKeys = owner.xidDocument().inceptionPrivateKeys();\n if (coordinatorKeys === undefined) {\n throw new Error(\"Coordinator XID document has no private keys\");\n }\n\n let verifyingKey: SigningPublicKey | undefined;\n let collected: number;\n let rejected = 0;\n let errors: number;\n let timeouts = 0;\n\n if (options.parallel === true) {\n // Parallel path with progress display\n const collection = await collectFinalizeParallel(\n client,\n registry,\n pendingRequests,\n coordinatorKeys,\n groupId,\n options.timeoutSeconds,\n );\n\n verifyingKey = finalizeFinalizeCollectionResults(collection, registryPath, registry, groupId);\n\n collected = collection.successes.length;\n rejected = collection.rejections.length;\n errors = collection.errors.length;\n timeouts = collection.timeouts.length;\n } else {\n // Sequential path (original behavior)\n const collectedEntries: FinalizeEntry[] = [];\n const errorEntries: [XID, string][] = [];\n let groupVerifyingKey: SigningPublicKey | undefined;\n\n if (isVerbose()) {\n console.error(`Collecting finalize responses from ${pendingRequests.len()} participants...`);\n }\n\n for (const [participantXid, collectFromArid] of pendingRequests.iterCollect()) {\n const record = registry.participant(participantXid);\n const name = record?.petName() ?? participantXid.urString();\n\n try {\n const entry = await fetchFinalizeResponse(\n client,\n collectFromArid,\n options.timeoutSeconds,\n coordinatorKeys,\n groupId,\n participantXid,\n name,\n );\n\n // Extract verifying key from public_key_package\n const pubKeyPkg = entry.publicKeyPackage as { verifying_key?: string };\n if (!pubKeyPkg.verifying_key) {\n throw new Error(\"missing verifying_key field\");\n }\n\n const verifyingKeyBytes = hexToBytes(pubKeyPkg.verifying_key);\n const signingKey = signingKeyFromVerifying(verifyingKeyBytes) as SigningPublicKey;\n\n if (groupVerifyingKey !== undefined) {\n if (groupVerifyingKey.urString() !== signingKey.urString()) {\n if (isVerbose()) {\n console.error(\"error: group verifying key mismatch\");\n }\n errorEntries.push([participantXid, \"Group verifying key mismatch across responses\"]);\n continue;\n }\n } else {\n groupVerifyingKey = signingKey;\n }\n\n collectedEntries.push(entry);\n } catch (err) {\n if (isVerbose()) {\n console.error(`error: ${err instanceof Error ? err.message : String(err)}`);\n }\n errorEntries.push([participantXid, err instanceof Error ? err.message : String(err)]);\n }\n }\n\n if (errorEntries.length > 0) {\n if (isVerbose()) {\n console.error();\n console.error(`Failed to collect from ${errorEntries.length} participants:`);\n for (const [xid, error] of errorEntries) {\n console.error(` ${xid.urString()}: ${error}`);\n }\n }\n throw new Error(\n `Finalize collection incomplete: ${errorEntries.length} of ${pendingRequests.len()} responses failed`,\n );\n }\n\n // Persist collected finalize data\n const stateDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const collectedPath = path.join(stateDir, \"collected_finalize.json\");\n const root: Record<string, { key_package: unknown; public_key_package: unknown }> = {};\n\n for (const entry of collectedEntries) {\n root[entry.participant.urString()] = {\n key_package: entry.keyPackage,\n public_key_package: entry.publicKeyPackage,\n };\n }\n\n fs.writeFileSync(collectedPath, JSON.stringify(root, null, 2));\n\n // Update registry pending requests cleared\n const groupRecordMut = registry.group(groupId);\n if (groupRecordMut === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n if (groupVerifyingKey !== undefined) {\n groupRecordMut.setVerifyingKey(groupVerifyingKey);\n }\n groupRecordMut.clearPendingRequests();\n registry.save(registryPath);\n\n if (isVerbose()) {\n console.error();\n console.error(\n `Collected ${collectedEntries.length} finalize responses. Saved to ${collectedPath}`,\n );\n if (groupVerifyingKey !== undefined) {\n console.error(groupVerifyingKey.urString());\n }\n } else if (groupVerifyingKey !== undefined) {\n console.log(groupVerifyingKey.urString());\n }\n\n verifyingKey = groupVerifyingKey;\n collected = collectedEntries.length;\n errors = errorEntries.length;\n }\n\n return {\n verifyingKey: verifyingKey?.urString() ?? \"\",\n collected,\n rejected,\n errors,\n timeouts,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"finalize-DHEnKobp.cjs","names":["SealedResponse","parseAridUr","getWithIndicator","isVerbose","parallelFetch","parallelFetchConfigWithTimeout","signingKeyFromVerifying","groupStateDir","path","resolveRegistryPath","Registry"],"sources":["../src/cmd/dkg/coordinator/finalize.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG coordinator finalize command.\n *\n * Port of cmd/dkg/coordinator/finalize.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { type ARID, type PrivateKeys, type SigningPublicKey, type XID } from \"@bcts/components\";\nimport { type Envelope } from \"@bcts/envelope\";\nimport { SealedResponse } from \"@bcts/gstp\";\n\nimport {\n type GroupRecord,\n type PendingRequests,\n Registry,\n resolveRegistryPath,\n} from \"../../../registry/index.js\";\nimport { groupStateDir, isVerbose } from \"../../common.js\";\nimport {\n type CollectionResult,\n parallelFetch,\n type ParallelFetchConfig,\n parallelFetchConfigWithTimeout,\n} from \"../../parallel.js\";\nimport { type StorageClient } from \"../../storage.js\";\nimport { getWithIndicator } from \"../../busy.js\";\nimport { parseAridUr, signingKeyFromVerifying } from \"../common.js\";\n\n/**\n * Options for the DKG finalize command.\n */\nexport interface DkgFinalizeOptions {\n registryPath?: string;\n groupId: string;\n parallel?: boolean;\n timeoutSeconds?: number;\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG finalize command.\n */\nexport interface DkgFinalizeResult {\n verifyingKey: string;\n collected: number;\n rejected: number;\n errors: number;\n timeouts: number;\n}\n\n/**\n * Data extracted from a successful finalize response.\n *\n * Port of `struct FinalizeResponseData` from finalize.rs.\n */\ninterface FinalizeResponseData {\n keyPackage: unknown;\n publicKeyPackage: unknown;\n}\n\n/**\n * Entry for a collected finalize response.\n *\n * Port of `struct FinalizeEntry` from finalize.rs.\n */\ninterface FinalizeEntry {\n participant: XID;\n keyPackage: unknown;\n publicKeyPackage: unknown;\n}\n\n/**\n * Validate that the owner is the coordinator of the group.\n *\n * Port of coordinator check from finalize.rs lines 76-82.\n */\nfunction validateCoordinator(groupRecord: GroupRecord, ownerXid: XID): void {\n if (groupRecord.coordinator().xid().urString() !== ownerXid.urString()) {\n throw new Error(\n `Only the coordinator can collect finalize responses. Coordinator: ${groupRecord.coordinator().xid().urString()}, Owner: ${ownerXid.urString()}`,\n );\n }\n}\n\n/**\n * Validate envelope and extract finalize data (for parallel fetch).\n *\n * Port of `validate_and_extract_finalize_response()` from finalize.rs lines 407-466.\n */\nfunction validateAndExtractFinalizeResponse(\n envelope: Envelope,\n coordinatorKeys: PrivateKeys,\n expectedGroupId: ARID,\n expectedParticipant: XID,\n): FinalizeResponseData | { rejected: string } {\n const now = new Date();\n\n let sealed: SealedResponse;\n try {\n sealed = SealedResponse.tryFromEncryptedEnvelope(envelope, undefined, now, coordinatorKeys);\n } catch (err) {\n return {\n rejected: `Failed to decrypt/parse response: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Check for error response\n if (!sealed.isOk()) {\n try {\n const error = sealed.error();\n const reasonEnv = error.optionalObjectForPredicate(\"reason\");\n const reason = reasonEnv?.extractString() ?? \"unknown reason\";\n return { rejected: `Participant reported error: ${reason}` };\n } catch {\n return { rejected: \"Participant reported error: unknown reason\" };\n }\n }\n\n // Get and validate result\n let result: Envelope;\n try {\n result = sealed.result();\n } catch {\n return { rejected: \"Finalize response has no result\" };\n }\n\n // Validate response type\n try {\n result.checkSubjectUnit();\n result.checkType(\"dkgFinalizeResponse\");\n } catch (err) {\n return {\n rejected: `Invalid response type: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Validate group ID\n try {\n const groupEnv = result.objectForPredicate(\"group\");\n const groupIdStr = groupEnv.extractString();\n const groupId = parseAridUr(groupIdStr);\n if (groupId.urString() !== expectedGroupId.urString()) {\n return {\n rejected: `Group ${groupId.urString()} does not match expected ${expectedGroupId.urString()}`,\n };\n }\n } catch (err) {\n return {\n rejected: `Failed to extract group: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Validate participant\n try {\n const participantEnv = result.objectForPredicate(\"participant\");\n const participantStr = participantEnv.extractString();\n // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-require-imports, no-undef\n const { XID: XIDClass } = require(\"@bcts/components\");\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access\n const participantXid = XIDClass.fromURString(participantStr) as XID;\n if (participantXid.urString() !== expectedParticipant.urString()) {\n return {\n rejected: `Participant ${participantXid.urString()} does not match expected ${expectedParticipant.urString()}`,\n };\n }\n } catch (err) {\n return {\n rejected: `Failed to extract participant: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n // Extract key packages\n let keyPackage: unknown;\n let publicKeyPackage: unknown;\n\n try {\n const keyJsonEnv = result.objectForPredicate(\"key_package\");\n const keyJsonStr = keyJsonEnv.extractString();\n keyPackage = JSON.parse(keyJsonStr);\n } catch (err) {\n return {\n rejected: `Failed to parse key_package: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n try {\n const pubJsonEnv = result.objectForPredicate(\"public_key_package\");\n const pubJsonStr = pubJsonEnv.extractString();\n publicKeyPackage = JSON.parse(pubJsonStr);\n } catch (err) {\n return {\n rejected: `Failed to parse public_key_package: ${err instanceof Error ? err.message : String(err)}`,\n };\n }\n\n return { keyPackage, publicKeyPackage };\n}\n\n/**\n * Fetch a finalize response sequentially.\n *\n * Port of `fetch_finalize_response()` from finalize.rs lines 282-358.\n */\nasync function fetchFinalizeResponse(\n client: StorageClient,\n responseArid: ARID,\n timeout: number | undefined,\n coordinatorKeys: PrivateKeys,\n expectedGroup: ARID,\n expectedParticipant: XID,\n participantName: string,\n): Promise<FinalizeEntry> {\n const envelope = await getWithIndicator(\n client,\n responseArid,\n participantName,\n timeout,\n isVerbose(),\n );\n\n if (envelope === null || envelope === undefined) {\n throw new Error(\"Finalize response not found in Hubert storage\");\n }\n\n const result = validateAndExtractFinalizeResponse(\n envelope,\n coordinatorKeys,\n expectedGroup,\n expectedParticipant,\n );\n\n if (\"rejected\" in result) {\n throw new Error(result.rejected);\n }\n\n return {\n participant: expectedParticipant,\n keyPackage: result.keyPackage,\n publicKeyPackage: result.publicKeyPackage,\n };\n}\n\n/**\n * Collect finalize responses in parallel with progress display.\n *\n * Port of `collect_finalize_parallel()` from finalize.rs lines 371-404.\n */\nasync function collectFinalizeParallel(\n client: StorageClient,\n registry: Registry,\n pendingRequests: PendingRequests,\n coordinatorKeys: PrivateKeys,\n expectedGroupId: ARID,\n timeout: number | undefined,\n): Promise<CollectionResult<FinalizeResponseData>> {\n const requests: [XID, ARID, string][] = [];\n\n for (const [xid, arid] of pendingRequests.iterCollect()) {\n const record = registry.participant(xid);\n const name = record?.petName() ?? xid.urString();\n requests.push([xid, arid, name]);\n }\n\n const config: ParallelFetchConfig = parallelFetchConfigWithTimeout(timeout);\n\n return parallelFetch(\n client,\n requests,\n (envelope: Envelope, xid: XID) =>\n validateAndExtractFinalizeResponse(envelope, coordinatorKeys, expectedGroupId, xid),\n config,\n );\n}\n\n/**\n * Finalize collection results: persist, update registry, print summary.\n *\n * Port of `finalize_collection_results()` from finalize.rs lines 469-590.\n */\nfunction finalizeFinalizeCollectionResults(\n collection: CollectionResult<FinalizeResponseData>,\n registryPath: string,\n registry: Registry,\n groupId: ARID,\n): SigningPublicKey | undefined {\n // Report any failures\n if (collection.rejections.length > 0) {\n console.error();\n console.error(\"Rejections:\");\n for (const [xid, reason] of collection.rejections) {\n console.error(` ${xid.urString()}: ${reason}`);\n }\n }\n if (collection.errors.length > 0) {\n console.error();\n console.error(\"Errors:\");\n for (const [xid, error] of collection.errors) {\n console.error(` ${xid.urString()}: ${error}`);\n }\n }\n if (collection.timeouts.length > 0) {\n console.error();\n console.error(\"Timeouts:\");\n for (const xid of collection.timeouts) {\n console.error(` ${xid.urString()}`);\n }\n }\n\n if (!collection.allSucceeded()) {\n throw new Error(\n `Finalize collection incomplete: ${collection.successes.length} succeeded, ` +\n `${collection.rejections.length} rejected, ${collection.errors.length} errors, ` +\n `${collection.timeouts.length} timeouts`,\n );\n }\n\n // Validate group verifying key consistency\n let groupVerifyingKey: SigningPublicKey | undefined;\n\n for (const [xid, data] of collection.successes) {\n // Extract verifying_key from public_key_package\n const pubKeyPkg = data.publicKeyPackage as { verifying_key?: string };\n if (!pubKeyPkg.verifying_key) {\n throw new Error(\n `Failed to extract verifying key for ${xid.urString()}: missing verifying_key field`,\n );\n }\n\n // The verifying key is typically hex-encoded\n let signingKey: SigningPublicKey;\n try {\n const verifyingKeyBytes = hexToBytes(pubKeyPkg.verifying_key);\n signingKey = signingKeyFromVerifying(verifyingKeyBytes) as SigningPublicKey;\n } catch (err) {\n throw new Error(\n `Failed to extract verifying key for ${xid.urString()}: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n );\n }\n\n if (groupVerifyingKey !== undefined) {\n if (groupVerifyingKey.urString() !== signingKey.urString()) {\n throw new Error(`Group verifying key mismatch for participant ${xid.urString()}`);\n }\n } else {\n groupVerifyingKey = signingKey;\n }\n }\n\n // Persist collected finalize data\n const stateDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const collectedPath = path.join(stateDir, \"collected_finalize.json\");\n const root: Record<string, { key_package: unknown; public_key_package: unknown }> = {};\n\n for (const [xid, data] of collection.successes) {\n root[xid.urString()] = {\n key_package: data.keyPackage,\n public_key_package: data.publicKeyPackage,\n };\n }\n\n fs.writeFileSync(collectedPath, JSON.stringify(root, null, 2));\n\n // Update registry\n const groupRecord = registry.group(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n if (groupVerifyingKey !== undefined) {\n groupRecord.setVerifyingKey(groupVerifyingKey);\n }\n groupRecord.clearPendingRequests();\n registry.save(registryPath);\n\n if (isVerbose()) {\n console.error();\n console.error(\n `Collected ${collection.successes.length} finalize responses. Saved to ${collectedPath}`,\n );\n if (groupVerifyingKey !== undefined) {\n console.error(groupVerifyingKey.urString());\n }\n } else if (groupVerifyingKey !== undefined) {\n console.log(groupVerifyingKey.urString());\n }\n\n return groupVerifyingKey;\n}\n\n/**\n * Helper to convert hex string to bytes.\n */\nfunction hexToBytes(hex: string): Uint8Array {\n const bytes = new Uint8Array(hex.length / 2);\n for (let i = 0; i < bytes.length; i++) {\n bytes[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16);\n }\n return bytes;\n}\n\n/**\n * Execute the DKG coordinator finalize command.\n *\n * Collects finalize responses (key/public key packages) from all participants.\n *\n * Port of `finalize()` from cmd/dkg/coordinator/finalize.rs.\n */\nexport async function finalize(\n client: StorageClient,\n options: DkgFinalizeOptions,\n cwd: string,\n): Promise<DkgFinalizeResult> {\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n\n if (groupRecord === undefined) {\n throw new Error(`Group ${options.groupId} not found in registry`);\n }\n\n // Validate that owner is the coordinator\n validateCoordinator(groupRecord, owner.xid());\n\n const pendingRequests = groupRecord.pendingRequests();\n if (pendingRequests.isEmpty()) {\n throw new Error(\n \"No pending requests for this group. Did you run 'frost dkg coordinator finalize send'?\",\n );\n }\n\n const coordinatorKeys = owner.xidDocument().inceptionPrivateKeys();\n if (coordinatorKeys === undefined) {\n throw new Error(\"Coordinator XID document has no private keys\");\n }\n\n let verifyingKey: SigningPublicKey | undefined;\n let collected: number;\n let rejected = 0;\n let errors: number;\n let timeouts = 0;\n\n if (options.parallel === true) {\n // Parallel path with progress display\n const collection = await collectFinalizeParallel(\n client,\n registry,\n pendingRequests,\n coordinatorKeys,\n groupId,\n options.timeoutSeconds,\n );\n\n verifyingKey = finalizeFinalizeCollectionResults(collection, registryPath, registry, groupId);\n\n collected = collection.successes.length;\n rejected = collection.rejections.length;\n errors = collection.errors.length;\n timeouts = collection.timeouts.length;\n } else {\n // Sequential path (original behavior)\n const collectedEntries: FinalizeEntry[] = [];\n const errorEntries: [XID, string][] = [];\n let groupVerifyingKey: SigningPublicKey | undefined;\n\n if (isVerbose()) {\n console.error(`Collecting finalize responses from ${pendingRequests.len()} participants...`);\n }\n\n for (const [participantXid, collectFromArid] of pendingRequests.iterCollect()) {\n const record = registry.participant(participantXid);\n const name = record?.petName() ?? participantXid.urString();\n\n try {\n const entry = await fetchFinalizeResponse(\n client,\n collectFromArid,\n options.timeoutSeconds,\n coordinatorKeys,\n groupId,\n participantXid,\n name,\n );\n\n // Extract verifying key from public_key_package\n const pubKeyPkg = entry.publicKeyPackage as { verifying_key?: string };\n if (!pubKeyPkg.verifying_key) {\n throw new Error(\"missing verifying_key field\");\n }\n\n const verifyingKeyBytes = hexToBytes(pubKeyPkg.verifying_key);\n const signingKey = signingKeyFromVerifying(verifyingKeyBytes) as SigningPublicKey;\n\n if (groupVerifyingKey !== undefined) {\n if (groupVerifyingKey.urString() !== signingKey.urString()) {\n if (isVerbose()) {\n console.error(\"error: group verifying key mismatch\");\n }\n errorEntries.push([participantXid, \"Group verifying key mismatch across responses\"]);\n continue;\n }\n } else {\n groupVerifyingKey = signingKey;\n }\n\n collectedEntries.push(entry);\n } catch (err) {\n if (isVerbose()) {\n console.error(`error: ${err instanceof Error ? err.message : String(err)}`);\n }\n errorEntries.push([participantXid, err instanceof Error ? err.message : String(err)]);\n }\n }\n\n if (errorEntries.length > 0) {\n if (isVerbose()) {\n console.error();\n console.error(`Failed to collect from ${errorEntries.length} participants:`);\n for (const [xid, error] of errorEntries) {\n console.error(` ${xid.urString()}: ${error}`);\n }\n }\n throw new Error(\n `Finalize collection incomplete: ${errorEntries.length} of ${pendingRequests.len()} responses failed`,\n );\n }\n\n // Persist collected finalize data\n const stateDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n const collectedPath = path.join(stateDir, \"collected_finalize.json\");\n const root: Record<string, { key_package: unknown; public_key_package: unknown }> = {};\n\n for (const entry of collectedEntries) {\n root[entry.participant.urString()] = {\n key_package: entry.keyPackage,\n public_key_package: entry.publicKeyPackage,\n };\n }\n\n fs.writeFileSync(collectedPath, JSON.stringify(root, null, 2));\n\n // Update registry pending requests cleared\n const groupRecordMut = registry.group(groupId);\n if (groupRecordMut === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n if (groupVerifyingKey !== undefined) {\n groupRecordMut.setVerifyingKey(groupVerifyingKey);\n }\n groupRecordMut.clearPendingRequests();\n registry.save(registryPath);\n\n if (isVerbose()) {\n console.error();\n console.error(\n `Collected ${collectedEntries.length} finalize responses. Saved to ${collectedPath}`,\n );\n if (groupVerifyingKey !== undefined) {\n console.error(groupVerifyingKey.urString());\n }\n } else if (groupVerifyingKey !== undefined) {\n console.log(groupVerifyingKey.urString());\n }\n\n verifyingKey = groupVerifyingKey;\n collected = collectedEntries.length;\n errors = errorEntries.length;\n }\n\n return {\n verifyingKey: verifyingKey?.urString() ?? \"\",\n collected,\n rejected,\n errors,\n timeouts,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
const require_chunk = require("./chunk-
|
|
2
|
-
const require_proposed_participant = require("./proposed-participant-
|
|
1
|
+
const require_chunk = require("./chunk-DakpK96I.cjs");
|
|
2
|
+
const require_proposed_participant = require("./proposed-participant-BvHNnpcZ.cjs");
|
|
3
3
|
const require_registry_index = require("./registry/index.cjs");
|
|
4
|
-
const require_common = require("./common-
|
|
5
|
-
const require_busy = require("./busy-
|
|
6
|
-
const
|
|
4
|
+
const require_common = require("./common-CnvAUC2b.cjs");
|
|
5
|
+
const require_busy = require("./busy-B_h0bNAJ.cjs");
|
|
6
|
+
const require_registry = require("./registry-CkIbA7nt.cjs");
|
|
7
7
|
const require_frost_index = require("./frost/index.cjs");
|
|
8
8
|
let _bcts_components = require("@bcts/components");
|
|
9
9
|
let _bcts_dcbor = require("@bcts/dcbor");
|
|
@@ -164,7 +164,7 @@ async function finalize(_client, options, cwd) {
|
|
|
164
164
|
if (listeningAtArid === void 0) throw new Error("No listening ARID for this group. Did you receive finalize send?");
|
|
165
165
|
const round2State = loadRound2State(registryPath, groupId);
|
|
166
166
|
if (require_common.isVerbose() || options.verbose === true) console.error("Fetching finalize request from Hubert...");
|
|
167
|
-
const client = await
|
|
167
|
+
const client = await require_registry.createStorageClient(options.storageSelection);
|
|
168
168
|
const requestEnvelope = await require_busy.getWithIndicator(client, listeningAtArid, "Finalize request", options.timeoutSeconds, options.verbose ?? false);
|
|
169
169
|
if (requestEnvelope === null || requestEnvelope === void 0) throw new Error("Finalize request not found in Hubert storage");
|
|
170
170
|
const ownerPrivateKeys = owner.xidDocument().inceptionPrivateKeys();
|
|
@@ -262,4 +262,4 @@ Object.defineProperty(exports, "finalize_exports", {
|
|
|
262
262
|
}
|
|
263
263
|
});
|
|
264
264
|
|
|
265
|
-
//# sourceMappingURL=finalize-
|
|
265
|
+
//# sourceMappingURL=finalize-DQ0VGUHO.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"finalize-UPyI1yb1.cjs","names":["groupStateDir","path","fs","hexToBytes","identifierFromU16","VerifiableSecretSharingCommitment","Ed25519Sha512","CoefficientCommitment","round2","serde","EnvelopeFunction","ARID","compareXidBytes","XID","JSONWrapper","identifierToHex","serializeKeyPackage","serializePublicKeyPackage","Envelope","resolveRegistryPath","Registry","parseAridUr","isVerbose","createStorageClient","getWithIndicator","CborDate","SealedRequest","dkgPart3","signingKeyFromVerifying","SealedResponse","bytesToHex","putWithIndicator"],"sources":["../src/cmd/dkg/participant/finalize.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG participant finalize command.\n *\n * Port of cmd/dkg/participant/finalize.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, JSON as JSONWrapper, XID } from \"@bcts/components\";\nimport { compareXidBytes } from \"../../../dkg/proposed-participant.js\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope, Function as EnvelopeFunction } from \"@bcts/envelope\";\nimport { SealedRequest, SealedResponse } from \"@bcts/gstp\";\nimport type { XIDDocument } from \"@bcts/xid\";\n\nimport { type GroupRecord, Registry, resolveRegistryPath } from \"../../../registry/index.js\";\nimport { getWithIndicator, putWithIndicator } from \"../../busy.js\";\nimport { groupStateDir, isVerbose } from \"../../common.js\";\nimport { createStorageClient, type StorageClient, type StorageSelection } from \"../../storage.js\";\nimport { parseAridUr, signingKeyFromVerifying } from \"../common.js\";\nimport {\n dkgPart3,\n identifierFromU16,\n identifierToHex,\n hexToBytes,\n bytesToHex,\n serializeKeyPackage,\n serializePublicKeyPackage,\n type DkgRound1Package,\n type DkgRound2Package,\n type DkgRound2SecretPackage,\n type FrostIdentifier,\n type FrostKeyPackage,\n type FrostPublicKeyPackage,\n} from \"../../../frost/index.js\";\nimport { Ed25519Sha512, serde } from \"@frosts/ed25519\";\nimport { round2, CoefficientCommitment, VerifiableSecretSharingCommitment } from \"@frosts/core\";\n\n/**\n * Options for the DKG finalize command.\n */\nexport interface DkgFinalizeOptions {\n registryPath?: string;\n groupId: string;\n timeoutSeconds?: number;\n preview?: boolean;\n storageSelection?: StorageSelection;\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG finalize command.\n */\nexport interface DkgFinalizeResult {\n verifyingKey: string;\n keyPackagePath: string;\n publicKeyPackagePath: string;\n}\n\n/**\n * Persisted round 2 state loaded from disk.\n */\ninterface Round2State {\n secretPackage: DkgRound2SecretPackage;\n round1Packages: Map<string, DkgRound1Package>;\n}\n\n/**\n * Load persisted round 2 state from disk.\n *\n * Port of round2_secret loading from cmd/dkg/participant/finalize.rs lines 82-106.\n */\nfunction loadRound2State(registryPath: string, groupId: ARID): Round2State {\n const stateDir = groupStateDir(registryPath, groupId.hex());\n\n // Load Round 2 secret\n const round2SecretPath = path.join(stateDir, \"round2_secret.json\");\n if (!fs.existsSync(round2SecretPath)) {\n throw new Error(`Round 2 secret not found at ${round2SecretPath}. Did you run round2?`);\n }\n\n // Mirrors Rust `frost::keys::dkg::round2::SecretPackage` JSON\n // (`frost-rust/frost-core/src/keys/dkg.rs:269-287`):\n //\n // {\n // \"identifier\": \"<lowercase hex scalar>\",\n // \"commitment\": [\"<hex>\", \"<hex>\", ...],\n // \"secret_share\": \"<hex>\",\n // \"min_signers\": <u16>,\n // \"max_signers\": <u16>\n // }\n //\n // The struct is `#[serde(deny_unknown_fields)]` and the\n // `commitment` is a `VerifiableSecretSharingCommitment` (a\n // single-field tuple struct over `Vec<CoefficientCommitment>`),\n // which serde flattens to a bare JSON array. The earlier port\n // emitted camelCase keys plus a nested `commitment.coefficients`\n // shape and a numeric `identifier`, which Rust would reject and\n // which had no chance of being read by Rust's standard derive.\n const secretJson = JSON.parse(fs.readFileSync(round2SecretPath, \"utf-8\")) as {\n identifier: string;\n commitment: string[];\n secret_share: string;\n min_signers: number;\n max_signers: number;\n };\n\n // Identifier hex → little-endian u16 (the FROST 1-indexed\n // participant position). The scalar bytes are 32-LE for Ed25519, so\n // the first two bytes hold the u16 value when the identifier is in\n // the small-integer range (1..=N) used by the DKG.\n const idBytes = hexToBytes(secretJson.identifier);\n let identifierU16 = 1;\n if (idBytes.length >= 2) {\n identifierU16 = idBytes[0] | (idBytes[1] << 8);\n }\n if (identifierU16 === 0) {\n identifierU16 = 1;\n }\n const identifier = identifierFromU16(identifierU16);\n\n const coefficientCommitments = secretJson.commitment.map((hex) =>\n CoefficientCommitment.deserialize(Ed25519Sha512, hexToBytes(hex)),\n );\n\n const commitment = new VerifiableSecretSharingCommitment(Ed25519Sha512, coefficientCommitments);\n\n const secretShareScalar = Ed25519Sha512.deserializeScalar(hexToBytes(secretJson.secret_share));\n\n const secretPackage: DkgRound2SecretPackage = new round2.SecretPackage(\n Ed25519Sha512,\n identifier,\n commitment,\n secretShareScalar,\n secretJson.min_signers,\n secretJson.max_signers,\n );\n\n // Load collected Round 1 packages (from round2 phase)\n const round1Path = path.join(stateDir, \"collected_round1.json\");\n if (!fs.existsSync(round1Path)) {\n throw new Error(`Round 1 packages not found at ${round1Path}. Did you receive earlier phases?`);\n }\n\n const round1Json = JSON.parse(fs.readFileSync(round1Path, \"utf-8\")) as Record<string, unknown>;\n\n // Convert to Map<string, DkgRound1Package> - keyed by XID UR string\n const round1Packages = new Map<string, DkgRound1Package>();\n for (const [xidStr, value] of Object.entries(round1Json)) {\n const packageJson = value as {\n header: { version: number; ciphersuite: string };\n commitment: string[];\n proof_of_knowledge: string;\n };\n const pkg = serde.round1PackageFromJson(packageJson);\n round1Packages.set(xidStr, pkg);\n }\n\n return { secretPackage, round1Packages };\n}\n\n/**\n * Validate the finalize request from the coordinator.\n *\n * Port of request validation from cmd/dkg/participant/finalize.rs lines 139-161.\n */\nfunction validateFinalizeRequest(\n sealedRequest: SealedRequest,\n groupId: ARID,\n expectedCoordinator: XID,\n): ARID {\n // Validate the request function\n if (!sealedRequest.function().equals(EnvelopeFunction.fromString(\"dkgFinalize\"))) {\n throw new Error(`Unexpected request function: ${sealedRequest.function().toString()}`);\n }\n\n // Validate the sender is the expected coordinator\n if (sealedRequest.sender().xid().urString() !== expectedCoordinator.urString()) {\n throw new Error(\n `Unexpected request sender: ${sealedRequest.sender().xid().urString()} ` +\n `(expected coordinator ${expectedCoordinator.urString()})`,\n );\n }\n\n // Validate the group ID matches\n const requestGroupIdEnvelope = sealedRequest.objectForParameter(\"group\");\n if (requestGroupIdEnvelope === undefined) {\n throw new Error(\"Request missing group parameter\");\n }\n const requestGroupId = requestGroupIdEnvelope.extractSubject((cbor) => ARID.fromTaggedCbor(cbor));\n if (requestGroupId.urString() !== groupId.urString()) {\n throw new Error(\n `Request group ID ${requestGroupId.urString()} does not match expected ${groupId.urString()}`,\n );\n }\n\n // Extract where we should post our response\n const responseAridEnvelope = sealedRequest.objectForParameter(\"responseArid\");\n if (responseAridEnvelope === undefined) {\n throw new Error(\"Request missing responseArid parameter\");\n }\n const responseArid = responseAridEnvelope.extractSubject((cbor) => ARID.fromTaggedCbor(cbor));\n\n return responseArid;\n}\n\n/**\n * Extract round 2 packages from the finalize request.\n *\n * Port of round2 package extraction from cmd/dkg/participant/finalize.rs lines 209-229.\n */\nfunction extractFinalizePackages(\n request: SealedRequest,\n groupRecord: GroupRecord,\n ownerXid: XID,\n): Map<string, DkgRound2Package> {\n // Build XID -> Identifier mapping based on sorted participant order\n const sortedXids: XID[] = groupRecord.participants().map((p) => p.xid());\n\n // Add owner if not already in list\n const ownerUrString = ownerXid.urString();\n if (!sortedXids.some((xid) => xid.urString() === ownerUrString)) {\n sortedXids.push(ownerXid);\n }\n\n // Sort by XID byte order — mirrors Rust `XID::cmp` (raw 32-byte\n // lex compare). The earlier port used `urString().localeCompare(...)`,\n // which differs from byte order for any byte ≥ 0x80 and is locale-\n // aware, producing different FROST identifier assignments than Rust.\n sortedXids.sort((a, b) => compareXidBytes(a.toData(), b.toData()));\n\n // Deduplicate\n const deduped: XID[] = [];\n for (const xid of sortedXids) {\n if (deduped.length === 0 || deduped[deduped.length - 1].urString() !== xid.urString()) {\n deduped.push(xid);\n }\n }\n\n // Build XID -> Identifier mapping (1-indexed)\n const xidToIdentifier = new Map<string, FrostIdentifier>();\n for (let i = 0; i < deduped.length; i++) {\n const identifier = identifierFromU16(i + 1);\n xidToIdentifier.set(deduped[i].urString(), identifier);\n }\n\n const myXidStr = ownerXid.urString();\n\n // Extract all round2Package parameters\n const packages = new Map<string, DkgRound2Package>();\n\n const packageEnvelopes = request.objectsForParameter(\"round2Package\");\n for (const packageEnvelope of packageEnvelopes) {\n // Extract sender XID from the envelope\n const senderEnvelope = packageEnvelope.objectForPredicate(\"sender\");\n if (senderEnvelope === undefined) {\n throw new Error(\"round2Package missing sender predicate\");\n }\n const senderXid = senderEnvelope.extractSubject((cbor) => XID.fromTaggedCbor(cbor));\n\n // Skip our own package\n if (senderXid.urString() === myXidStr) {\n continue;\n }\n\n // Get the identifier for this sender\n const identifier = xidToIdentifier.get(senderXid.urString());\n if (identifier === undefined) {\n throw new Error(`Unknown sender XID in round2Package: ${senderXid.urString()}`);\n }\n\n // Extract the package bytes (stored as JSON tag)\n const packageJson = packageEnvelope.extractSubject((cbor) => JSONWrapper.fromTaggedCbor(cbor));\n const packageData = JSON.parse(new TextDecoder().decode(packageJson.toData())) as {\n header: { version: number; ciphersuite: string };\n signing_share: string;\n };\n\n const pkg = serde.round2PackageFromJson(packageData);\n packages.set(identifierToHex(identifier), pkg);\n }\n\n return packages;\n}\n\n/**\n * Build the response body for the finalize response.\n *\n * Port of `build_response_body()` from cmd/dkg/participant/finalize.rs lines 344-359.\n */\nfunction buildResponseBody(\n groupId: ARID,\n participantXid: XID,\n keyPackage: FrostKeyPackage,\n publicKeyPackage: FrostPublicKeyPackage,\n): Envelope {\n // Serialize key packages to JSON\n const keyPackageJson = serializeKeyPackage(keyPackage);\n const publicKeyPackageJson = serializePublicKeyPackage(publicKeyPackage);\n\n const keyJsonBytes = new TextEncoder().encode(JSON.stringify(keyPackageJson));\n const keyJsonWrapper = JSONWrapper.fromData(keyJsonBytes);\n\n const pubJsonBytes = new TextEncoder().encode(JSON.stringify(publicKeyPackageJson));\n const pubJsonWrapper = JSONWrapper.fromData(pubJsonBytes);\n\n return Envelope.unit()\n .addType(\"dkgFinalizeResponse\")\n .addAssertion(\"group\", groupId)\n .addAssertion(\"participant\", participantXid)\n .addAssertion(\"key_package\", keyJsonWrapper)\n .addAssertion(\"public_key_package\", pubJsonWrapper);\n}\n\n/**\n * Persist finalize state (key packages) to disk.\n *\n * Port of key package persistence from cmd/dkg/participant/finalize.rs lines 251-257.\n */\nfunction persistFinalizeState(\n registryPath: string,\n groupId: ARID,\n keyPackage: FrostKeyPackage,\n publicKeyPackage: FrostPublicKeyPackage,\n): { keyPackagePath: string; publicKeyPackagePath: string } {\n const stateDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n // Serialize and save key package\n const serializedKeyPackage = serializeKeyPackage(keyPackage);\n const keyPackagePath = path.join(stateDir, \"key_package.json\");\n fs.writeFileSync(keyPackagePath, JSON.stringify(serializedKeyPackage, null, 2));\n\n // Serialize and save public key package\n const serializedPublicKeyPackage = serializePublicKeyPackage(publicKeyPackage);\n const publicKeyPackagePath = path.join(stateDir, \"public_key_package.json\");\n fs.writeFileSync(publicKeyPackagePath, JSON.stringify(serializedPublicKeyPackage, null, 2));\n\n return { keyPackagePath, publicKeyPackagePath };\n}\n\n/**\n * Execute the DKG participant finalize command.\n *\n * Responds to the finalize request from the coordinator, runs FROST DKG part3\n * to generate the final key package, and posts the response back.\n *\n * Port of `CommandArgs::exec()` from cmd/dkg/participant/finalize.rs lines 52-341.\n */\nexport async function finalize(\n _client: StorageClient | undefined,\n options: DkgFinalizeOptions,\n cwd: string,\n): Promise<DkgFinalizeResult> {\n if (options.storageSelection === undefined) {\n throw new Error(\"Hubert storage is required for finalize respond\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n // Get the ARID where we're listening for the finalize request\n const listeningAtArid = groupRecord.listeningAtArid();\n if (listeningAtArid === undefined) {\n throw new Error(\"No listening ARID for this group. Did you receive finalize send?\");\n }\n\n // Load Round 2 state (secret and collected round1 packages)\n const round2State = loadRound2State(registryPath, groupId);\n\n if (isVerbose() || options.verbose === true) {\n console.error(\"Fetching finalize request from Hubert...\");\n }\n\n const client = await createStorageClient(options.storageSelection);\n\n // Fetch the finalize request from where we're listening\n const requestEnvelope = await getWithIndicator(\n client,\n listeningAtArid,\n \"Finalize request\",\n options.timeoutSeconds,\n options.verbose ?? false,\n );\n\n if (requestEnvelope === null || requestEnvelope === undefined) {\n throw new Error(\"Finalize request not found in Hubert storage\");\n }\n\n // Decrypt and validate the request\n const ownerPrivateKeys = owner.xidDocument().inceptionPrivateKeys();\n if (ownerPrivateKeys === undefined) {\n throw new Error(\"Owner XID document has no private keys\");\n }\n\n const now = CborDate.now().datetime();\n const sealedRequest = SealedRequest.tryFromEnvelope(\n requestEnvelope,\n undefined,\n now,\n ownerPrivateKeys,\n );\n\n // Validate the request and extract response ARID\n const expectedCoordinator = groupRecord.coordinator().xid();\n const responseArid = validateFinalizeRequest(sealedRequest, groupId, expectedCoordinator);\n\n // Build identifier mapping for round1 packages (XID UR -> Identifier hex)\n const sortedXids: XID[] = groupRecord.participants().map((p) => p.xid());\n\n // Add owner if not already in list\n const ownerUrString = owner.xid().urString();\n if (!sortedXids.some((xid) => xid.urString() === ownerUrString)) {\n sortedXids.push(owner.xid());\n }\n\n // Sort by XID byte order — mirrors Rust `XID::cmp` (raw 32-byte\n // lex compare). The earlier port used `urString().localeCompare(...)`,\n // which differs from byte order for any byte ≥ 0x80 and is locale-\n // aware, producing different FROST identifier assignments than Rust.\n sortedXids.sort((a, b) => compareXidBytes(a.toData(), b.toData()));\n\n // Deduplicate\n const deduped: XID[] = [];\n for (const xid of sortedXids) {\n if (deduped.length === 0 || deduped[deduped.length - 1].urString() !== xid.urString()) {\n deduped.push(xid);\n }\n }\n\n // Build XID -> Identifier mapping (1-indexed)\n const xidToIdentifier = new Map<string, FrostIdentifier>();\n for (let i = 0; i < deduped.length; i++) {\n const identifier = identifierFromU16(i + 1);\n xidToIdentifier.set(deduped[i].urString(), identifier);\n }\n\n // Convert round1 packages from XID-keyed to identifier-keyed (exclude self)\n const round1PackagesById = new Map<string, DkgRound1Package>();\n for (const [xidStr, pkg] of round2State.round1Packages) {\n if (xidStr === ownerUrString) {\n continue;\n }\n const identifier = xidToIdentifier.get(xidStr);\n if (identifier === undefined) {\n throw new Error(`Unknown participant XID ${xidStr}`);\n }\n round1PackagesById.set(identifierToHex(identifier), pkg);\n }\n\n // Extract Round 2 packages from the request (exclude self)\n const round2PackagesById = extractFinalizePackages(sealedRequest, groupRecord, owner.xid());\n\n if (isVerbose() || options.verbose === true) {\n console.error(`Received ${round2PackagesById.size} Round 2 packages. Running DKG part3...`);\n }\n\n // Run FROST DKG part3 (finalize)\n const [keyPackage, publicKeyPackage] = await dkgPart3(\n round2State.secretPackage,\n round1PackagesById,\n round2PackagesById,\n );\n\n // Get the group verifying key\n const verifyingKeyBytes = publicKeyPackage.verifyingKey;\n const groupVerifyingKey = signingKeyFromVerifying(verifyingKeyBytes);\n\n if (isVerbose() || options.verbose === true) {\n console.error(\"Generated key package and public key package.\");\n }\n\n // Persist key packages\n const { keyPackagePath, publicKeyPackagePath } = persistFinalizeState(\n registryPath,\n groupId,\n keyPackage,\n publicKeyPackage,\n );\n\n // Build response body\n const responseBody = buildResponseBody(groupId, owner.xid(), keyPackage, publicKeyPackage);\n\n const signerPrivateKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Owner XID document has no signing keys\");\n }\n\n // Get coordinator's XID document for encryption\n const coordinatorXid = groupRecord.coordinator().xid();\n const coordinatorRecord = registry.participant(coordinatorXid);\n let coordinatorDoc: XIDDocument;\n if (coordinatorRecord !== undefined) {\n coordinatorDoc = coordinatorRecord.xidDocument();\n } else {\n // Check if coordinator is the owner\n if (owner.xid().urString() === coordinatorXid.urString()) {\n coordinatorDoc = owner.xidDocument();\n } else {\n throw new Error(`Coordinator ${coordinatorXid.urString()} not found in registry`);\n }\n }\n\n // Get peer continuation from the request\n const peerContinuation = sealedRequest.peerContinuation();\n\n let sealed = SealedResponse.newSuccess(sealedRequest.id(), owner.xidDocument()).withResult(\n responseBody,\n );\n\n if (peerContinuation !== undefined) {\n sealed = sealed.withPeerContinuation(peerContinuation);\n }\n\n if (options.preview === true) {\n // Show the response envelope structure without encryption\n if (isVerbose() || options.verbose === true) {\n // Cast to access urString method\n const verifyingKeyWithUrString = groupVerifyingKey as { urString?: () => string };\n if (typeof verifyingKeyWithUrString.urString === \"function\") {\n console.error(verifyingKeyWithUrString.urString());\n }\n }\n const unsealedEnvelope = sealed.toEnvelope(\n undefined, // No expiration for responses\n signerPrivateKeys,\n undefined,\n );\n console.log(unsealedEnvelope.urString());\n\n return {\n verifyingKey: bytesToHex(verifyingKeyBytes),\n keyPackagePath,\n publicKeyPackagePath,\n };\n }\n\n const responseEnvelope = sealed.toEnvelope(\n undefined, // No expiration for responses\n signerPrivateKeys,\n coordinatorDoc,\n );\n\n // Post the response\n await putWithIndicator(\n client,\n responseArid,\n responseEnvelope,\n \"Finalize Response\",\n options.verbose ?? false,\n );\n\n // Update registry: contributions and verifying key\n const updatedGroupRecord = registry.group(groupId);\n if (updatedGroupRecord !== undefined) {\n const contributions = updatedGroupRecord.contributions();\n contributions.keyPackage = keyPackagePath;\n updatedGroupRecord.setContributions(contributions);\n updatedGroupRecord.clearListeningAtArid();\n\n // Set verifying key if the method exists\n const recordWithVerifyingKey = updatedGroupRecord as {\n setVerifyingKey?: (key: unknown) => void;\n };\n if (typeof recordWithVerifyingKey.setVerifyingKey === \"function\") {\n recordWithVerifyingKey.setVerifyingKey(groupVerifyingKey);\n }\n\n registry.save(registryPath);\n }\n\n // Get verifying key for output\n const verifyingKeyHex = bytesToHex(verifyingKeyBytes);\n\n if (isVerbose() || options.verbose === true) {\n console.error(`Posted finalize response to ${responseArid.urString()}`);\n // Cast to access urString method\n const verifyingKeyWithUrString = groupVerifyingKey as { urString?: () => string };\n if (typeof verifyingKeyWithUrString.urString === \"function\") {\n console.error(verifyingKeyWithUrString.urString());\n }\n } else {\n // Cast to access urString method\n const verifyingKeyWithUrString = groupVerifyingKey as { urString?: () => string };\n if (typeof verifyingKeyWithUrString.urString === \"function\") {\n console.log(verifyingKeyWithUrString.urString());\n }\n }\n\n return {\n verifyingKey: verifyingKeyHex,\n keyPackagePath,\n publicKeyPackagePath,\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"finalize-DQ0VGUHO.cjs","names":["groupStateDir","path","fs","hexToBytes","identifierFromU16","VerifiableSecretSharingCommitment","Ed25519Sha512","CoefficientCommitment","round2","serde","EnvelopeFunction","ARID","compareXidBytes","XID","JSONWrapper","identifierToHex","serializeKeyPackage","serializePublicKeyPackage","Envelope","resolveRegistryPath","Registry","parseAridUr","isVerbose","createStorageClient","getWithIndicator","CborDate","SealedRequest","dkgPart3","signingKeyFromVerifying","SealedResponse","bytesToHex","putWithIndicator"],"sources":["../src/cmd/dkg/participant/finalize.ts"],"sourcesContent":["/**\n * Copyright © 2023-2026 Blockchain Commons, LLC\n * Copyright © 2025-2026 Parity Technologies\n *\n *\n * DKG participant finalize command.\n *\n * Port of cmd/dkg/participant/finalize.rs from frost-hubert-rust.\n *\n * @module\n */\n\nimport * as fs from \"node:fs\";\nimport * as path from \"node:path\";\n\nimport { ARID, JSON as JSONWrapper, XID } from \"@bcts/components\";\nimport { compareXidBytes } from \"../../../dkg/proposed-participant.js\";\nimport { CborDate } from \"@bcts/dcbor\";\nimport { Envelope, Function as EnvelopeFunction } from \"@bcts/envelope\";\nimport { SealedRequest, SealedResponse } from \"@bcts/gstp\";\nimport type { XIDDocument } from \"@bcts/xid\";\n\nimport { type GroupRecord, Registry, resolveRegistryPath } from \"../../../registry/index.js\";\nimport { getWithIndicator, putWithIndicator } from \"../../busy.js\";\nimport { groupStateDir, isVerbose } from \"../../common.js\";\nimport { createStorageClient, type StorageClient, type StorageSelection } from \"../../storage.js\";\nimport { parseAridUr, signingKeyFromVerifying } from \"../common.js\";\nimport {\n dkgPart3,\n identifierFromU16,\n identifierToHex,\n hexToBytes,\n bytesToHex,\n serializeKeyPackage,\n serializePublicKeyPackage,\n type DkgRound1Package,\n type DkgRound2Package,\n type DkgRound2SecretPackage,\n type FrostIdentifier,\n type FrostKeyPackage,\n type FrostPublicKeyPackage,\n} from \"../../../frost/index.js\";\nimport { Ed25519Sha512, serde } from \"@frosts/ed25519\";\nimport { round2, CoefficientCommitment, VerifiableSecretSharingCommitment } from \"@frosts/core\";\n\n/**\n * Options for the DKG finalize command.\n */\nexport interface DkgFinalizeOptions {\n registryPath?: string;\n groupId: string;\n timeoutSeconds?: number;\n preview?: boolean;\n storageSelection?: StorageSelection;\n verbose?: boolean;\n}\n\n/**\n * Result of the DKG finalize command.\n */\nexport interface DkgFinalizeResult {\n verifyingKey: string;\n keyPackagePath: string;\n publicKeyPackagePath: string;\n}\n\n/**\n * Persisted round 2 state loaded from disk.\n */\ninterface Round2State {\n secretPackage: DkgRound2SecretPackage;\n round1Packages: Map<string, DkgRound1Package>;\n}\n\n/**\n * Load persisted round 2 state from disk.\n *\n * Port of round2_secret loading from cmd/dkg/participant/finalize.rs lines 82-106.\n */\nfunction loadRound2State(registryPath: string, groupId: ARID): Round2State {\n const stateDir = groupStateDir(registryPath, groupId.hex());\n\n // Load Round 2 secret\n const round2SecretPath = path.join(stateDir, \"round2_secret.json\");\n if (!fs.existsSync(round2SecretPath)) {\n throw new Error(`Round 2 secret not found at ${round2SecretPath}. Did you run round2?`);\n }\n\n // Mirrors Rust `frost::keys::dkg::round2::SecretPackage` JSON\n // (`frost-rust/frost-core/src/keys/dkg.rs:269-287`):\n //\n // {\n // \"identifier\": \"<lowercase hex scalar>\",\n // \"commitment\": [\"<hex>\", \"<hex>\", ...],\n // \"secret_share\": \"<hex>\",\n // \"min_signers\": <u16>,\n // \"max_signers\": <u16>\n // }\n //\n // The struct is `#[serde(deny_unknown_fields)]` and the\n // `commitment` is a `VerifiableSecretSharingCommitment` (a\n // single-field tuple struct over `Vec<CoefficientCommitment>`),\n // which serde flattens to a bare JSON array. The earlier port\n // emitted camelCase keys plus a nested `commitment.coefficients`\n // shape and a numeric `identifier`, which Rust would reject and\n // which had no chance of being read by Rust's standard derive.\n const secretJson = JSON.parse(fs.readFileSync(round2SecretPath, \"utf-8\")) as {\n identifier: string;\n commitment: string[];\n secret_share: string;\n min_signers: number;\n max_signers: number;\n };\n\n // Identifier hex → little-endian u16 (the FROST 1-indexed\n // participant position). The scalar bytes are 32-LE for Ed25519, so\n // the first two bytes hold the u16 value when the identifier is in\n // the small-integer range (1..=N) used by the DKG.\n const idBytes = hexToBytes(secretJson.identifier);\n let identifierU16 = 1;\n if (idBytes.length >= 2) {\n identifierU16 = idBytes[0] | (idBytes[1] << 8);\n }\n if (identifierU16 === 0) {\n identifierU16 = 1;\n }\n const identifier = identifierFromU16(identifierU16);\n\n const coefficientCommitments = secretJson.commitment.map((hex) =>\n CoefficientCommitment.deserialize(Ed25519Sha512, hexToBytes(hex)),\n );\n\n const commitment = new VerifiableSecretSharingCommitment(Ed25519Sha512, coefficientCommitments);\n\n const secretShareScalar = Ed25519Sha512.deserializeScalar(hexToBytes(secretJson.secret_share));\n\n const secretPackage: DkgRound2SecretPackage = new round2.SecretPackage(\n Ed25519Sha512,\n identifier,\n commitment,\n secretShareScalar,\n secretJson.min_signers,\n secretJson.max_signers,\n );\n\n // Load collected Round 1 packages (from round2 phase)\n const round1Path = path.join(stateDir, \"collected_round1.json\");\n if (!fs.existsSync(round1Path)) {\n throw new Error(`Round 1 packages not found at ${round1Path}. Did you receive earlier phases?`);\n }\n\n const round1Json = JSON.parse(fs.readFileSync(round1Path, \"utf-8\")) as Record<string, unknown>;\n\n // Convert to Map<string, DkgRound1Package> - keyed by XID UR string\n const round1Packages = new Map<string, DkgRound1Package>();\n for (const [xidStr, value] of Object.entries(round1Json)) {\n const packageJson = value as {\n header: { version: number; ciphersuite: string };\n commitment: string[];\n proof_of_knowledge: string;\n };\n const pkg = serde.round1PackageFromJson(packageJson);\n round1Packages.set(xidStr, pkg);\n }\n\n return { secretPackage, round1Packages };\n}\n\n/**\n * Validate the finalize request from the coordinator.\n *\n * Port of request validation from cmd/dkg/participant/finalize.rs lines 139-161.\n */\nfunction validateFinalizeRequest(\n sealedRequest: SealedRequest,\n groupId: ARID,\n expectedCoordinator: XID,\n): ARID {\n // Validate the request function\n if (!sealedRequest.function().equals(EnvelopeFunction.fromString(\"dkgFinalize\"))) {\n throw new Error(`Unexpected request function: ${sealedRequest.function().toString()}`);\n }\n\n // Validate the sender is the expected coordinator\n if (sealedRequest.sender().xid().urString() !== expectedCoordinator.urString()) {\n throw new Error(\n `Unexpected request sender: ${sealedRequest.sender().xid().urString()} ` +\n `(expected coordinator ${expectedCoordinator.urString()})`,\n );\n }\n\n // Validate the group ID matches\n const requestGroupIdEnvelope = sealedRequest.objectForParameter(\"group\");\n if (requestGroupIdEnvelope === undefined) {\n throw new Error(\"Request missing group parameter\");\n }\n const requestGroupId = requestGroupIdEnvelope.extractSubject((cbor) => ARID.fromTaggedCbor(cbor));\n if (requestGroupId.urString() !== groupId.urString()) {\n throw new Error(\n `Request group ID ${requestGroupId.urString()} does not match expected ${groupId.urString()}`,\n );\n }\n\n // Extract where we should post our response\n const responseAridEnvelope = sealedRequest.objectForParameter(\"responseArid\");\n if (responseAridEnvelope === undefined) {\n throw new Error(\"Request missing responseArid parameter\");\n }\n const responseArid = responseAridEnvelope.extractSubject((cbor) => ARID.fromTaggedCbor(cbor));\n\n return responseArid;\n}\n\n/**\n * Extract round 2 packages from the finalize request.\n *\n * Port of round2 package extraction from cmd/dkg/participant/finalize.rs lines 209-229.\n */\nfunction extractFinalizePackages(\n request: SealedRequest,\n groupRecord: GroupRecord,\n ownerXid: XID,\n): Map<string, DkgRound2Package> {\n // Build XID -> Identifier mapping based on sorted participant order\n const sortedXids: XID[] = groupRecord.participants().map((p) => p.xid());\n\n // Add owner if not already in list\n const ownerUrString = ownerXid.urString();\n if (!sortedXids.some((xid) => xid.urString() === ownerUrString)) {\n sortedXids.push(ownerXid);\n }\n\n // Sort by XID byte order — mirrors Rust `XID::cmp` (raw 32-byte\n // lex compare). The earlier port used `urString().localeCompare(...)`,\n // which differs from byte order for any byte ≥ 0x80 and is locale-\n // aware, producing different FROST identifier assignments than Rust.\n sortedXids.sort((a, b) => compareXidBytes(a.toData(), b.toData()));\n\n // Deduplicate\n const deduped: XID[] = [];\n for (const xid of sortedXids) {\n if (deduped.length === 0 || deduped[deduped.length - 1].urString() !== xid.urString()) {\n deduped.push(xid);\n }\n }\n\n // Build XID -> Identifier mapping (1-indexed)\n const xidToIdentifier = new Map<string, FrostIdentifier>();\n for (let i = 0; i < deduped.length; i++) {\n const identifier = identifierFromU16(i + 1);\n xidToIdentifier.set(deduped[i].urString(), identifier);\n }\n\n const myXidStr = ownerXid.urString();\n\n // Extract all round2Package parameters\n const packages = new Map<string, DkgRound2Package>();\n\n const packageEnvelopes = request.objectsForParameter(\"round2Package\");\n for (const packageEnvelope of packageEnvelopes) {\n // Extract sender XID from the envelope\n const senderEnvelope = packageEnvelope.objectForPredicate(\"sender\");\n if (senderEnvelope === undefined) {\n throw new Error(\"round2Package missing sender predicate\");\n }\n const senderXid = senderEnvelope.extractSubject((cbor) => XID.fromTaggedCbor(cbor));\n\n // Skip our own package\n if (senderXid.urString() === myXidStr) {\n continue;\n }\n\n // Get the identifier for this sender\n const identifier = xidToIdentifier.get(senderXid.urString());\n if (identifier === undefined) {\n throw new Error(`Unknown sender XID in round2Package: ${senderXid.urString()}`);\n }\n\n // Extract the package bytes (stored as JSON tag)\n const packageJson = packageEnvelope.extractSubject((cbor) => JSONWrapper.fromTaggedCbor(cbor));\n const packageData = JSON.parse(new TextDecoder().decode(packageJson.toData())) as {\n header: { version: number; ciphersuite: string };\n signing_share: string;\n };\n\n const pkg = serde.round2PackageFromJson(packageData);\n packages.set(identifierToHex(identifier), pkg);\n }\n\n return packages;\n}\n\n/**\n * Build the response body for the finalize response.\n *\n * Port of `build_response_body()` from cmd/dkg/participant/finalize.rs lines 344-359.\n */\nfunction buildResponseBody(\n groupId: ARID,\n participantXid: XID,\n keyPackage: FrostKeyPackage,\n publicKeyPackage: FrostPublicKeyPackage,\n): Envelope {\n // Serialize key packages to JSON\n const keyPackageJson = serializeKeyPackage(keyPackage);\n const publicKeyPackageJson = serializePublicKeyPackage(publicKeyPackage);\n\n const keyJsonBytes = new TextEncoder().encode(JSON.stringify(keyPackageJson));\n const keyJsonWrapper = JSONWrapper.fromData(keyJsonBytes);\n\n const pubJsonBytes = new TextEncoder().encode(JSON.stringify(publicKeyPackageJson));\n const pubJsonWrapper = JSONWrapper.fromData(pubJsonBytes);\n\n return Envelope.unit()\n .addType(\"dkgFinalizeResponse\")\n .addAssertion(\"group\", groupId)\n .addAssertion(\"participant\", participantXid)\n .addAssertion(\"key_package\", keyJsonWrapper)\n .addAssertion(\"public_key_package\", pubJsonWrapper);\n}\n\n/**\n * Persist finalize state (key packages) to disk.\n *\n * Port of key package persistence from cmd/dkg/participant/finalize.rs lines 251-257.\n */\nfunction persistFinalizeState(\n registryPath: string,\n groupId: ARID,\n keyPackage: FrostKeyPackage,\n publicKeyPackage: FrostPublicKeyPackage,\n): { keyPackagePath: string; publicKeyPackagePath: string } {\n const stateDir = groupStateDir(registryPath, groupId.hex());\n fs.mkdirSync(stateDir, { recursive: true });\n\n // Serialize and save key package\n const serializedKeyPackage = serializeKeyPackage(keyPackage);\n const keyPackagePath = path.join(stateDir, \"key_package.json\");\n fs.writeFileSync(keyPackagePath, JSON.stringify(serializedKeyPackage, null, 2));\n\n // Serialize and save public key package\n const serializedPublicKeyPackage = serializePublicKeyPackage(publicKeyPackage);\n const publicKeyPackagePath = path.join(stateDir, \"public_key_package.json\");\n fs.writeFileSync(publicKeyPackagePath, JSON.stringify(serializedPublicKeyPackage, null, 2));\n\n return { keyPackagePath, publicKeyPackagePath };\n}\n\n/**\n * Execute the DKG participant finalize command.\n *\n * Responds to the finalize request from the coordinator, runs FROST DKG part3\n * to generate the final key package, and posts the response back.\n *\n * Port of `CommandArgs::exec()` from cmd/dkg/participant/finalize.rs lines 52-341.\n */\nexport async function finalize(\n _client: StorageClient | undefined,\n options: DkgFinalizeOptions,\n cwd: string,\n): Promise<DkgFinalizeResult> {\n if (options.storageSelection === undefined) {\n throw new Error(\"Hubert storage is required for finalize respond\");\n }\n\n const registryPath = resolveRegistryPath(options.registryPath, cwd);\n const registry = Registry.load(registryPath);\n\n const owner = registry.owner();\n if (owner === undefined) {\n throw new Error(\"Registry owner is required\");\n }\n\n const groupId = parseAridUr(options.groupId);\n const groupRecord = registry.group(groupId);\n if (groupRecord === undefined) {\n throw new Error(\"Group not found in registry\");\n }\n\n // Get the ARID where we're listening for the finalize request\n const listeningAtArid = groupRecord.listeningAtArid();\n if (listeningAtArid === undefined) {\n throw new Error(\"No listening ARID for this group. Did you receive finalize send?\");\n }\n\n // Load Round 2 state (secret and collected round1 packages)\n const round2State = loadRound2State(registryPath, groupId);\n\n if (isVerbose() || options.verbose === true) {\n console.error(\"Fetching finalize request from Hubert...\");\n }\n\n const client = await createStorageClient(options.storageSelection);\n\n // Fetch the finalize request from where we're listening\n const requestEnvelope = await getWithIndicator(\n client,\n listeningAtArid,\n \"Finalize request\",\n options.timeoutSeconds,\n options.verbose ?? false,\n );\n\n if (requestEnvelope === null || requestEnvelope === undefined) {\n throw new Error(\"Finalize request not found in Hubert storage\");\n }\n\n // Decrypt and validate the request\n const ownerPrivateKeys = owner.xidDocument().inceptionPrivateKeys();\n if (ownerPrivateKeys === undefined) {\n throw new Error(\"Owner XID document has no private keys\");\n }\n\n const now = CborDate.now().datetime();\n const sealedRequest = SealedRequest.tryFromEnvelope(\n requestEnvelope,\n undefined,\n now,\n ownerPrivateKeys,\n );\n\n // Validate the request and extract response ARID\n const expectedCoordinator = groupRecord.coordinator().xid();\n const responseArid = validateFinalizeRequest(sealedRequest, groupId, expectedCoordinator);\n\n // Build identifier mapping for round1 packages (XID UR -> Identifier hex)\n const sortedXids: XID[] = groupRecord.participants().map((p) => p.xid());\n\n // Add owner if not already in list\n const ownerUrString = owner.xid().urString();\n if (!sortedXids.some((xid) => xid.urString() === ownerUrString)) {\n sortedXids.push(owner.xid());\n }\n\n // Sort by XID byte order — mirrors Rust `XID::cmp` (raw 32-byte\n // lex compare). The earlier port used `urString().localeCompare(...)`,\n // which differs from byte order for any byte ≥ 0x80 and is locale-\n // aware, producing different FROST identifier assignments than Rust.\n sortedXids.sort((a, b) => compareXidBytes(a.toData(), b.toData()));\n\n // Deduplicate\n const deduped: XID[] = [];\n for (const xid of sortedXids) {\n if (deduped.length === 0 || deduped[deduped.length - 1].urString() !== xid.urString()) {\n deduped.push(xid);\n }\n }\n\n // Build XID -> Identifier mapping (1-indexed)\n const xidToIdentifier = new Map<string, FrostIdentifier>();\n for (let i = 0; i < deduped.length; i++) {\n const identifier = identifierFromU16(i + 1);\n xidToIdentifier.set(deduped[i].urString(), identifier);\n }\n\n // Convert round1 packages from XID-keyed to identifier-keyed (exclude self)\n const round1PackagesById = new Map<string, DkgRound1Package>();\n for (const [xidStr, pkg] of round2State.round1Packages) {\n if (xidStr === ownerUrString) {\n continue;\n }\n const identifier = xidToIdentifier.get(xidStr);\n if (identifier === undefined) {\n throw new Error(`Unknown participant XID ${xidStr}`);\n }\n round1PackagesById.set(identifierToHex(identifier), pkg);\n }\n\n // Extract Round 2 packages from the request (exclude self)\n const round2PackagesById = extractFinalizePackages(sealedRequest, groupRecord, owner.xid());\n\n if (isVerbose() || options.verbose === true) {\n console.error(`Received ${round2PackagesById.size} Round 2 packages. Running DKG part3...`);\n }\n\n // Run FROST DKG part3 (finalize)\n const [keyPackage, publicKeyPackage] = await dkgPart3(\n round2State.secretPackage,\n round1PackagesById,\n round2PackagesById,\n );\n\n // Get the group verifying key\n const verifyingKeyBytes = publicKeyPackage.verifyingKey;\n const groupVerifyingKey = signingKeyFromVerifying(verifyingKeyBytes);\n\n if (isVerbose() || options.verbose === true) {\n console.error(\"Generated key package and public key package.\");\n }\n\n // Persist key packages\n const { keyPackagePath, publicKeyPackagePath } = persistFinalizeState(\n registryPath,\n groupId,\n keyPackage,\n publicKeyPackage,\n );\n\n // Build response body\n const responseBody = buildResponseBody(groupId, owner.xid(), keyPackage, publicKeyPackage);\n\n const signerPrivateKeys = owner.xidDocument().inceptionPrivateKeys();\n if (signerPrivateKeys === undefined) {\n throw new Error(\"Owner XID document has no signing keys\");\n }\n\n // Get coordinator's XID document for encryption\n const coordinatorXid = groupRecord.coordinator().xid();\n const coordinatorRecord = registry.participant(coordinatorXid);\n let coordinatorDoc: XIDDocument;\n if (coordinatorRecord !== undefined) {\n coordinatorDoc = coordinatorRecord.xidDocument();\n } else {\n // Check if coordinator is the owner\n if (owner.xid().urString() === coordinatorXid.urString()) {\n coordinatorDoc = owner.xidDocument();\n } else {\n throw new Error(`Coordinator ${coordinatorXid.urString()} not found in registry`);\n }\n }\n\n // Get peer continuation from the request\n const peerContinuation = sealedRequest.peerContinuation();\n\n let sealed = SealedResponse.newSuccess(sealedRequest.id(), owner.xidDocument()).withResult(\n responseBody,\n );\n\n if (peerContinuation !== undefined) {\n sealed = sealed.withPeerContinuation(peerContinuation);\n }\n\n if (options.preview === true) {\n // Show the response envelope structure without encryption\n if (isVerbose() || options.verbose === true) {\n // Cast to access urString method\n const verifyingKeyWithUrString = groupVerifyingKey as { urString?: () => string };\n if (typeof verifyingKeyWithUrString.urString === \"function\") {\n console.error(verifyingKeyWithUrString.urString());\n }\n }\n const unsealedEnvelope = sealed.toEnvelope(\n undefined, // No expiration for responses\n signerPrivateKeys,\n undefined,\n );\n console.log(unsealedEnvelope.urString());\n\n return {\n verifyingKey: bytesToHex(verifyingKeyBytes),\n keyPackagePath,\n publicKeyPackagePath,\n };\n }\n\n const responseEnvelope = sealed.toEnvelope(\n undefined, // No expiration for responses\n signerPrivateKeys,\n coordinatorDoc,\n );\n\n // Post the response\n await putWithIndicator(\n client,\n responseArid,\n responseEnvelope,\n \"Finalize Response\",\n options.verbose ?? false,\n );\n\n // Update registry: contributions and verifying key\n const updatedGroupRecord = registry.group(groupId);\n if (updatedGroupRecord !== undefined) {\n const contributions = updatedGroupRecord.contributions();\n contributions.keyPackage = keyPackagePath;\n updatedGroupRecord.setContributions(contributions);\n updatedGroupRecord.clearListeningAtArid();\n\n // Set verifying key if the method exists\n const recordWithVerifyingKey = updatedGroupRecord as {\n setVerifyingKey?: (key: unknown) => void;\n };\n if (typeof recordWithVerifyingKey.setVerifyingKey === \"function\") {\n recordWithVerifyingKey.setVerifyingKey(groupVerifyingKey);\n }\n\n registry.save(registryPath);\n }\n\n // Get verifying key for output\n const verifyingKeyHex = bytesToHex(verifyingKeyBytes);\n\n if (isVerbose() || options.verbose === true) {\n console.error(`Posted finalize response to ${responseArid.urString()}`);\n // Cast to access urString method\n const verifyingKeyWithUrString = groupVerifyingKey as { urString?: () => string };\n if (typeof verifyingKeyWithUrString.urString === \"function\") {\n console.error(verifyingKeyWithUrString.urString());\n }\n } else {\n // Cast to access urString method\n const verifyingKeyWithUrString = groupVerifyingKey as { urString?: () => string };\n if (typeof verifyingKeyWithUrString.urString === \"function\") {\n console.log(verifyingKeyWithUrString.urString());\n }\n }\n\n return {\n verifyingKey: verifyingKeyHex,\n keyPackagePath,\n publicKeyPackagePath,\n };\n}\n"],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { n as __require, t as __exportAll } from "./chunk-
|
|
1
|
+
import { n as __require, t as __exportAll } from "./chunk-z9aeyW2b.mjs";
|
|
2
2
|
import { Registry, resolveRegistryPath } from "./registry/index.mjs";
|
|
3
|
-
import { c as parseAridUr, h as signingKeyFromVerifying, n as isVerbose, t as groupStateDir } from "./common-
|
|
4
|
-
import { t as getWithIndicator } from "./busy-
|
|
5
|
-
import { f as parallelFetch, p as parallelFetchConfigWithTimeout } from "./parallel-
|
|
3
|
+
import { c as parseAridUr, h as signingKeyFromVerifying, n as isVerbose, t as groupStateDir } from "./common-Cf1UvJaP.mjs";
|
|
4
|
+
import { t as getWithIndicator } from "./busy-BlU8_pS2.mjs";
|
|
5
|
+
import { f as parallelFetch, p as parallelFetchConfigWithTimeout } from "./parallel-PZiwHZT8.mjs";
|
|
6
6
|
import { SealedResponse } from "@bcts/gstp";
|
|
7
7
|
import * as fs from "node:fs";
|
|
8
8
|
import * as path from "node:path";
|
|
@@ -287,4 +287,4 @@ async function finalize(client, options, cwd) {
|
|
|
287
287
|
//#endregion
|
|
288
288
|
export { finalize_exports as n, finalize as t };
|
|
289
289
|
|
|
290
|
-
//# sourceMappingURL=finalize-
|
|
290
|
+
//# sourceMappingURL=finalize-DtRxHZ7H.mjs.map
|