@did-btcr2/method 0.34.0 → 0.36.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/browser.js +335 -167
  3. package/dist/browser.mjs +335 -167
  4. package/dist/cjs/index.js +275 -114
  5. package/dist/esm/core/aggregation/cohort.js +8 -2
  6. package/dist/esm/core/aggregation/cohort.js.map +1 -1
  7. package/dist/esm/core/aggregation/conditions.js +75 -0
  8. package/dist/esm/core/aggregation/conditions.js.map +1 -0
  9. package/dist/esm/core/aggregation/messages/base.js.map +1 -1
  10. package/dist/esm/core/aggregation/messages/bodies.js +16 -2
  11. package/dist/esm/core/aggregation/messages/bodies.js.map +1 -1
  12. package/dist/esm/core/aggregation/messages/factories.js.map +1 -1
  13. package/dist/esm/core/aggregation/participant.js +34 -15
  14. package/dist/esm/core/aggregation/participant.js.map +1 -1
  15. package/dist/esm/core/aggregation/runner/participant-runner.js +9 -1
  16. package/dist/esm/core/aggregation/runner/participant-runner.js.map +1 -1
  17. package/dist/esm/core/aggregation/runner/service-runner.js +12 -1
  18. package/dist/esm/core/aggregation/runner/service-runner.js.map +1 -1
  19. package/dist/esm/core/aggregation/service.js +27 -7
  20. package/dist/esm/core/aggregation/service.js.map +1 -1
  21. package/dist/esm/core/aggregation/signer.js +33 -0
  22. package/dist/esm/core/aggregation/signer.js.map +1 -0
  23. package/dist/esm/core/aggregation/signing-session.js +34 -11
  24. package/dist/esm/core/aggregation/signing-session.js.map +1 -1
  25. package/dist/esm/core/aggregation/transport/in-memory.js +5 -2
  26. package/dist/esm/core/aggregation/transport/in-memory.js.map +1 -1
  27. package/dist/esm/index.js +2 -0
  28. package/dist/esm/index.js.map +1 -1
  29. package/dist/types/core/aggregation/cohort.d.ts.map +1 -1
  30. package/dist/types/core/aggregation/conditions.d.ts +58 -0
  31. package/dist/types/core/aggregation/conditions.d.ts.map +1 -0
  32. package/dist/types/core/aggregation/messages/base.d.ts +2 -3
  33. package/dist/types/core/aggregation/messages/base.d.ts.map +1 -1
  34. package/dist/types/core/aggregation/messages/bodies.d.ts +2 -3
  35. package/dist/types/core/aggregation/messages/bodies.d.ts.map +1 -1
  36. package/dist/types/core/aggregation/messages/factories.d.ts +2 -3
  37. package/dist/types/core/aggregation/messages/factories.d.ts.map +1 -1
  38. package/dist/types/core/aggregation/participant.d.ts +24 -8
  39. package/dist/types/core/aggregation/participant.d.ts.map +1 -1
  40. package/dist/types/core/aggregation/runner/participant-runner.d.ts.map +1 -1
  41. package/dist/types/core/aggregation/runner/service-runner.d.ts.map +1 -1
  42. package/dist/types/core/aggregation/service.d.ts +18 -8
  43. package/dist/types/core/aggregation/service.d.ts.map +1 -1
  44. package/dist/types/core/aggregation/signer.d.ts +50 -0
  45. package/dist/types/core/aggregation/signer.d.ts.map +1 -0
  46. package/dist/types/core/aggregation/signing-session.d.ts +13 -5
  47. package/dist/types/core/aggregation/signing-session.d.ts.map +1 -1
  48. package/dist/types/core/aggregation/transport/in-memory.d.ts.map +1 -1
  49. package/dist/types/index.d.ts +2 -0
  50. package/dist/types/index.d.ts.map +1 -1
  51. package/package.json +4 -4
  52. package/src/core/aggregation/cohort.ts +8 -2
  53. package/src/core/aggregation/conditions.ts +116 -0
  54. package/src/core/aggregation/messages/base.ts +6 -3
  55. package/src/core/aggregation/messages/bodies.ts +18 -6
  56. package/src/core/aggregation/messages/factories.ts +2 -3
  57. package/src/core/aggregation/participant.ts +54 -23
  58. package/src/core/aggregation/runner/participant-runner.ts +9 -1
  59. package/src/core/aggregation/runner/service-runner.ts +13 -1
  60. package/src/core/aggregation/service.ts +51 -13
  61. package/src/core/aggregation/signer.ts +67 -0
  62. package/src/core/aggregation/signing-session.ts +34 -11
  63. package/src/core/aggregation/transport/in-memory.ts +7 -3
  64. package/src/index.ts +2 -0
package/dist/cjs/index.js CHANGED
@@ -86,6 +86,8 @@ __export(index_exports, {
86
86
  InMemoryRateLimitStore: () => InMemoryRateLimitStore,
87
87
  InMemoryTransport: () => InMemoryTransport,
88
88
  InboxBuffer: () => InboxBuffer,
89
+ KNOWN_BEACON_TYPES: () => KNOWN_BEACON_TYPES,
90
+ KeyPairAggregationSigner: () => KeyPairAggregationSigner,
89
91
  NONCE_CONTRIBUTION: () => NONCE_CONTRIBUTION,
90
92
  NonceCache: () => NonceCache,
91
93
  NostrTransport: () => NostrTransport,
@@ -157,6 +159,7 @@ __export(index_exports, {
157
159
  registerBeaconStrategy: () => registerBeaconStrategy,
158
160
  reviveFromWire: () => reviveFromWire,
159
161
  signEnvelope: () => signEnvelope,
162
+ validateCohortConditions: () => validateCohortConditions,
160
163
  verifyEnvelope: () => verifyEnvelope,
161
164
  verifyRequestAuth: () => verifyRequestAuth
162
165
  });
@@ -224,6 +227,7 @@ function getBeaconStrategy(type) {
224
227
  }
225
228
 
226
229
  // src/core/aggregation/cohort.ts
230
+ var import_bitcoin = require("@did-btcr2/bitcoin");
227
231
  var import_common3 = require("@did-btcr2/common");
228
232
  var import_smt2 = require("@did-btcr2/smt");
229
233
  var import_secp256k1 = require("@noble/curves/secp256k1.js");
@@ -299,7 +303,7 @@ var AggregationCohort = class {
299
303
  validationRejections = /* @__PURE__ */ new Set();
300
304
  constructor({ id, minParticipants, serviceDid, network, beaconType }) {
301
305
  this.id = id || crypto.randomUUID();
302
- this.minParticipants = minParticipants || 2;
306
+ this.minParticipants = minParticipants ?? 2;
303
307
  this.serviceDid = serviceDid || "";
304
308
  this.network = network;
305
309
  this.beaconType = beaconType || "CASBeacon";
@@ -325,7 +329,7 @@ var AggregationCohort = class {
325
329
  }
326
330
  const keyAggContext = (0, import_musig2.keyAggregate)(this.#cohortKeys);
327
331
  const aggPubkey = (0, import_musig2.keyAggExport)(keyAggContext);
328
- const payment = (0, import_btc_signer.p2tr)(aggPubkey);
332
+ const payment = (0, import_btc_signer.p2tr)(aggPubkey, void 0, (0, import_bitcoin.getNetwork)(this.network));
329
333
  this.tapTweak = import_secp256k1.schnorr.utils.taggedHash("TapTweak", aggPubkey);
330
334
  if (!payment.address) {
331
335
  throw new AggregationCohortError(
@@ -465,6 +469,56 @@ var AggregationCohort = class {
465
469
  }
466
470
  };
467
471
 
472
+ // src/core/aggregation/conditions.ts
473
+ var KNOWN_BEACON_TYPES = ["CASBeacon", "SMTBeacon"];
474
+ function checkPair(problems, label, min, max) {
475
+ if (min !== void 0 && (!Number.isInteger(min) || min < 0)) {
476
+ problems.push(`min${label} must be an integer >= 0`);
477
+ }
478
+ if (max !== void 0 && (!Number.isInteger(max) || max < 0)) {
479
+ problems.push(`max${label} must be an integer >= 0`);
480
+ }
481
+ if (min !== void 0 && max !== void 0 && Number.isInteger(min) && Number.isInteger(max) && max < min) {
482
+ problems.push(`max${label} must be >= min${label}`);
483
+ }
484
+ }
485
+ function checkCost(problems, label, cost) {
486
+ if (cost === void 0) return;
487
+ if (typeof cost.amount !== "number" || !Number.isFinite(cost.amount) || cost.amount < 0) {
488
+ problems.push(`${label}.amount must be a finite number >= 0`);
489
+ }
490
+ if (typeof cost.unit !== "string" || cost.unit.length === 0) {
491
+ problems.push(`${label}.unit must be a non-empty string`);
492
+ }
493
+ if (cost.basis !== void 0 && cost.basis !== "per-did" && cost.basis !== "per-participant") {
494
+ problems.push(`${label}.basis must be 'per-did' or 'per-participant'`);
495
+ }
496
+ }
497
+ function validateCohortConditions(c) {
498
+ const problems = [];
499
+ if (!KNOWN_BEACON_TYPES.includes(c.beaconType)) {
500
+ problems.push(`beaconType must be one of ${KNOWN_BEACON_TYPES.join(", ")}`);
501
+ }
502
+ if (!Number.isInteger(c.minParticipants) || c.minParticipants < 1) {
503
+ problems.push("minParticipants must be an integer >= 1");
504
+ }
505
+ if (c.maxParticipants !== void 0) {
506
+ if (!Number.isInteger(c.maxParticipants) || c.maxParticipants < 1) {
507
+ problems.push("maxParticipants must be an integer >= 1");
508
+ } else if (Number.isInteger(c.minParticipants) && c.maxParticipants < c.minParticipants) {
509
+ problems.push("maxParticipants must be >= minParticipants");
510
+ }
511
+ }
512
+ checkPair(problems, "DidsPerParticipant", c.minDidsPerParticipant, c.maxDidsPerParticipant);
513
+ checkPair(problems, "SecondsBetweenAnnouncements", c.minSecondsBetweenAnnouncements, c.maxSecondsBetweenAnnouncements);
514
+ if (c.pendingUpdateTrigger !== void 0 && (!Number.isInteger(c.pendingUpdateTrigger) || c.pendingUpdateTrigger < 1)) {
515
+ problems.push("pendingUpdateTrigger must be an integer >= 1");
516
+ }
517
+ checkCost(problems, "costOfEnrollment", c.costOfEnrollment);
518
+ checkCost(problems, "costPerAnnouncement", c.costPerAnnouncement);
519
+ return problems;
520
+ }
521
+
468
522
  // src/core/aggregation/messages/base.ts
469
523
  var AGGREGATION_WIRE_VERSION = 1;
470
524
  var BaseMessage = class {
@@ -596,6 +650,7 @@ var SigningSessionPhase = /* @__PURE__ */ ((SigningSessionPhase2) => {
596
650
  })(SigningSessionPhase || {});
597
651
 
598
652
  // src/core/aggregation/signing-session.ts
653
+ var import_keypair = require("@did-btcr2/keypair");
599
654
  var import_btc_signer2 = require("@scure/btc-signer");
600
655
  var musig2 = __toESM(require("@scure/btc-signer/musig2"), 1);
601
656
  var BeaconSigningSession = class {
@@ -619,8 +674,14 @@ var BeaconSigningSession = class {
619
674
  signature;
620
675
  /** Current signing session phase. */
621
676
  phase;
622
- /** Participant's secret nonce (held only by the participant during signing). */
623
- secretNonce;
677
+ /**
678
+ * Participant's MuSig2 secret nonce, held only on the participant side
679
+ * between {@link generateNonceContribution} and {@link generatePartialSignature}.
680
+ * Private and cleared on every terminal path (success, failure, or teardown
681
+ * via {@link clearSecrets}) so a spent or abandoned nonce cannot be reused or
682
+ * serialized.
683
+ */
684
+ #secretNonce;
624
685
  constructor({ id, cohort, pendingTx, prevOutScripts, prevOutValues }) {
625
686
  this.id = id || crypto.randomUUID();
626
687
  this.cohort = cohort;
@@ -772,22 +833,24 @@ var BeaconSigningSession = class {
772
833
  generateNonceContribution(participantPublicKey, participantSecretKey) {
773
834
  const aggPublicKey = musig2.keyAggExport(musig2.keyAggregate(this.cohort.cohortKeys));
774
835
  const nonces = musig2.nonceGen(participantPublicKey, participantSecretKey, aggPublicKey);
775
- this.secretNonce = nonces.secret;
836
+ this.#secretNonce = nonces.secret;
776
837
  return nonces.public;
777
838
  }
778
839
  /**
779
840
  * Generates a partial signature using the participant's secret key + secret nonce.
780
841
  * Requires the aggregated nonce to have been set first (via the service).
781
842
  *
782
- * Zeros the stored `secretNonce` after use. JS cannot truly erase memory (GC
783
- * and immutable strings), but overwriting the bytes shortens the exposure
784
- * window and prevents accidental reuse or serialization of a spent nonce.
843
+ * Clears the stored secret nonce after use on every path (success or throw)
844
+ * via {@link clearSecrets}. JS cannot truly erase memory (GC may relocate
845
+ * buffers), but overwriting the bytes shortens the exposure window and
846
+ * prevents accidental reuse or serialization of a spent nonce - reuse of a
847
+ * MuSig2 nonce leaks the secret key.
785
848
  */
786
849
  generatePartialSignature(participantSecretKey) {
787
850
  if (!this.aggregatedNonce) {
788
851
  throw new SigningSessionError("Aggregated nonce not available.", "MISSING_AGGREGATED_NONCE");
789
852
  }
790
- if (!this.secretNonce) {
853
+ if (!this.#secretNonce) {
791
854
  throw new SigningSessionError("Secret nonce not available \u2014 generateNonceContribution() must be called first.", "MISSING_SECRET_NONCE");
792
855
  }
793
856
  const session = new musig2.Session(
@@ -797,10 +860,23 @@ var BeaconSigningSession = class {
797
860
  [this.cohort.tapTweak],
798
861
  [true]
799
862
  );
800
- const partialSig = session.sign(this.secretNonce, participantSecretKey);
801
- this.secretNonce.fill(0);
802
- this.secretNonce = void 0;
803
- return partialSig;
863
+ try {
864
+ return session.sign(this.#secretNonce, participantSecretKey);
865
+ } finally {
866
+ this.clearSecrets();
867
+ }
868
+ }
869
+ /**
870
+ * Zeroize any retained secret nonce. Safe to call repeatedly and on any path
871
+ * (completion, failure, or teardown of an abandoned session). Callers that
872
+ * drop a session before it reaches a partial signature should invoke this so
873
+ * the secret nonce does not linger on the live object.
874
+ */
875
+ clearSecrets() {
876
+ if (this.#secretNonce) {
877
+ (0, import_keypair.wipe)(this.#secretNonce);
878
+ this.#secretNonce = void 0;
879
+ }
804
880
  }
805
881
  isComplete() {
806
882
  return this.phase === "Complete" /* Complete */;
@@ -814,13 +890,13 @@ var BeaconSigningSession = class {
814
890
  var DEFAULT_MAX_UPDATE_SIZE_BYTES = 256 * 1024;
815
891
  var AggregationService = class {
816
892
  did;
817
- keys;
893
+ publicKey;
818
894
  maxUpdateSizeBytes;
819
895
  /** Per-cohort state, keyed by cohortId. */
820
896
  #cohortStates = /* @__PURE__ */ new Map();
821
- constructor({ did, keys, maxUpdateSizeBytes }) {
897
+ constructor({ did, publicKey, maxUpdateSizeBytes }) {
822
898
  this.did = did;
823
- this.keys = keys;
899
+ this.publicKey = publicKey;
824
900
  this.maxUpdateSizeBytes = maxUpdateSizeBytes ?? DEFAULT_MAX_UPDATE_SIZE_BYTES;
825
901
  }
826
902
  receive(message) {
@@ -875,6 +951,14 @@ var AggregationService = class {
875
951
  * Cohort starts in `Created` phase — call `advertise()` to broadcast.
876
952
  */
877
953
  createCohort(config) {
954
+ const problems = validateCohortConditions(config);
955
+ if (problems.length > 0) {
956
+ throw new AggregationServiceError(
957
+ `Invalid cohort conditions: ${problems.join("; ")}`,
958
+ "INVALID_COHORT_CONDITIONS",
959
+ { problems }
960
+ );
961
+ }
878
962
  const cohort = new AggregationCohort({
879
963
  serviceDid: this.did,
880
964
  minParticipants: config.minParticipants,
@@ -907,13 +991,13 @@ var AggregationService = class {
907
991
  { cohortId, phase: state.phase }
908
992
  );
909
993
  }
994
+ const { network, ...conditions } = state.config;
910
995
  const message = createCohortAdvertMessage({
911
996
  from: this.did,
912
997
  cohortId,
913
- cohortSize: state.config.minParticipants,
914
- beaconType: state.config.beaconType,
915
- network: state.config.network,
916
- communicationPk: this.keys.publicKey.compressed
998
+ network,
999
+ communicationPk: this.publicKey.compressed,
1000
+ ...conditions
917
1001
  });
918
1002
  state.phase = "Advertised" /* Advertised */;
919
1003
  return [message];
@@ -972,6 +1056,14 @@ var AggregationService = class {
972
1056
  { cohortId, participantDid }
973
1057
  );
974
1058
  }
1059
+ const maxParticipants = state.config.maxParticipants;
1060
+ if (maxParticipants !== void 0 && state.acceptedParticipants.size >= maxParticipants) {
1061
+ throw new AggregationServiceError(
1062
+ `Cohort ${cohortId} is full: ${maxParticipants} participants already accepted.`,
1063
+ "COHORT_FULL",
1064
+ { cohortId, maxParticipants }
1065
+ );
1066
+ }
975
1067
  state.acceptedParticipants.add(participantDid);
976
1068
  state.cohort.participants.push(participantDid);
977
1069
  state.cohort.participantKeys.set(participantDid, optIn.participantPk);
@@ -1005,6 +1097,14 @@ var AggregationService = class {
1005
1097
  { cohortId }
1006
1098
  );
1007
1099
  }
1100
+ const maxParticipants = state.config.maxParticipants;
1101
+ if (maxParticipants !== void 0 && state.acceptedParticipants.size > maxParticipants) {
1102
+ throw new AggregationServiceError(
1103
+ `Cohort ${cohortId} has ${state.acceptedParticipants.size} accepted participants, exceeds max ${maxParticipants}.`,
1104
+ "TOO_MANY_PARTICIPANTS",
1105
+ { cohortId, maxParticipants }
1106
+ );
1107
+ }
1008
1108
  const beaconAddress = state.cohort.computeBeaconAddress();
1009
1109
  state.phase = "CohortSet" /* CohortSet */;
1010
1110
  const messages = [];
@@ -1323,14 +1423,71 @@ var AggregationService = class {
1323
1423
  var import_common5 = require("@did-btcr2/common");
1324
1424
  var import_utils3 = require("@noble/hashes/utils");
1325
1425
  var import_btc_signer3 = require("@scure/btc-signer");
1426
+
1427
+ // src/core/aggregation/messages/bodies.ts
1428
+ var hasStr = (b, k) => !!b && typeof b[k] === "string";
1429
+ var hasIntMin = (b, k, min) => {
1430
+ const v = b ? b[k] : void 0;
1431
+ return typeof v === "number" && Number.isInteger(v) && v >= min;
1432
+ };
1433
+ var optIntMin = (b, k, min) => {
1434
+ const v = b ? b[k] : void 0;
1435
+ return v === void 0 || typeof v === "number" && Number.isInteger(v) && v >= min;
1436
+ };
1437
+ var hasBool = (b, k) => !!b && typeof b[k] === "boolean";
1438
+ var hasBytes = (b, k) => !!b && b[k] instanceof Uint8Array;
1439
+ var hasBytesArray = (b, k) => {
1440
+ const v = b ? b[k] : void 0;
1441
+ return Array.isArray(v) && v.every((x) => x instanceof Uint8Array);
1442
+ };
1443
+ function isCohortAdvertMessage(m) {
1444
+ return m.type === COHORT_ADVERT && hasStr(m.body, "cohortId") && hasIntMin(m.body, "minParticipants", 1) && optIntMin(m.body, "maxParticipants", 1) && hasStr(m.body, "beaconType") && hasStr(m.body, "network") && hasBytes(m.body, "communicationPk");
1445
+ }
1446
+ function isCohortOptInMessage(m) {
1447
+ return m.type === COHORT_OPT_IN && hasStr(m.body, "cohortId") && hasBytes(m.body, "participantPk") && hasBytes(m.body, "communicationPk");
1448
+ }
1449
+ function isCohortOptInAcceptMessage(m) {
1450
+ return m.type === COHORT_OPT_IN_ACCEPT && hasStr(m.body, "cohortId");
1451
+ }
1452
+ function isCohortReadyMessage(m) {
1453
+ return m.type === COHORT_READY && hasStr(m.body, "cohortId") && hasStr(m.body, "beaconAddress") && hasBytesArray(m.body, "cohortKeys");
1454
+ }
1455
+ function isSubmitUpdateMessage(m) {
1456
+ return m.type === SUBMIT_UPDATE && hasStr(m.body, "cohortId") && !!m.body && typeof m.body.signedUpdate === "object";
1457
+ }
1458
+ function isDistributeAggregatedDataMessage(m) {
1459
+ return m.type === DISTRIBUTE_AGGREGATED_DATA && hasStr(m.body, "cohortId") && hasStr(m.body, "beaconType") && hasStr(m.body, "signalBytesHex");
1460
+ }
1461
+ function isValidationAckMessage(m) {
1462
+ return m.type === VALIDATION_ACK && hasStr(m.body, "cohortId") && hasBool(m.body, "approved");
1463
+ }
1464
+ function isAuthorizationRequestMessage(m) {
1465
+ return m.type === AUTHORIZATION_REQUEST && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasStr(m.body, "pendingTx") && hasStr(m.body, "prevOutScriptHex") && hasStr(m.body, "prevOutValue");
1466
+ }
1467
+ function isNonceContributionMessage(m) {
1468
+ return m.type === NONCE_CONTRIBUTION && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasBytes(m.body, "nonceContribution");
1469
+ }
1470
+ function isAggregatedNonceMessage(m) {
1471
+ return m.type === AGGREGATED_NONCE && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasBytes(m.body, "aggregatedNonce");
1472
+ }
1473
+ function isSignatureAuthorizationMessage(m) {
1474
+ return m.type === SIGNATURE_AUTHORIZATION && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasBytes(m.body, "partialSignature");
1475
+ }
1476
+
1477
+ // src/core/aggregation/participant.ts
1326
1478
  var AggregationParticipant = class {
1327
1479
  did;
1328
- keys;
1480
+ /** MuSig2 signing capability. The raw secret never lives as a field here. */
1481
+ #signer;
1329
1482
  /** Per-cohort state, keyed by cohortId. */
1330
1483
  #cohortStates = /* @__PURE__ */ new Map();
1331
- constructor({ did, keys }) {
1484
+ constructor({ did, signer }) {
1332
1485
  this.did = did;
1333
- this.keys = keys;
1486
+ this.#signer = signer;
1487
+ }
1488
+ /** The participant's compressed (33-byte) MuSig2 public key. Not secret. */
1489
+ get publicKey() {
1490
+ return this.#signer.publicKey;
1334
1491
  }
1335
1492
  /**
1336
1493
  * Process an incoming message. Updates internal state but never produces
@@ -1375,16 +1532,15 @@ var AggregationParticipant = class {
1375
1532
  return map;
1376
1533
  }
1377
1534
  #handleCohortAdvert(message) {
1378
- const cohortId = message.body?.cohortId;
1379
- if (!cohortId) return;
1535
+ if (!isCohortAdvertMessage(message)) return;
1536
+ const { cohortId, network, communicationPk, ...conditions } = message.body;
1380
1537
  if (this.#cohortStates.has(cohortId)) return;
1381
1538
  const advert = {
1382
1539
  cohortId,
1383
1540
  serviceDid: message.from,
1384
- cohortSize: message.body?.cohortSize ?? 0,
1385
- network: message.body?.network ?? "",
1386
- beaconType: message.body?.beaconType ?? "CASBeacon",
1387
- serviceCommunicationPk: message.body?.communicationPk ?? new Uint8Array()
1541
+ network,
1542
+ serviceCommunicationPk: communicationPk,
1543
+ ...conditions
1388
1544
  };
1389
1545
  this.#cohortStates.set(cohortId, {
1390
1546
  phase: "Discovered" /* Discovered */,
@@ -1409,7 +1565,7 @@ var AggregationParticipant = class {
1409
1565
  const cohort = new AggregationCohort({
1410
1566
  id: cohortId,
1411
1567
  serviceDid: state.serviceDid,
1412
- minParticipants: state.advert.cohortSize,
1568
+ minParticipants: state.advert.minParticipants,
1413
1569
  network: state.advert.network,
1414
1570
  beaconType: state.advert.beaconType
1415
1571
  });
@@ -1419,8 +1575,8 @@ var AggregationParticipant = class {
1419
1575
  from: this.did,
1420
1576
  to: state.serviceDid,
1421
1577
  cohortId,
1422
- participantPk: this.keys.publicKey.compressed,
1423
- communicationPk: this.keys.publicKey.compressed
1578
+ participantPk: this.publicKey,
1579
+ communicationPk: this.publicKey
1424
1580
  });
1425
1581
  return [optInMessage];
1426
1582
  }
@@ -1451,7 +1607,7 @@ var AggregationParticipant = class {
1451
1607
  const beaconAddress = message.body?.beaconAddress;
1452
1608
  const cohortKeys = message.body?.cohortKeys;
1453
1609
  if (!beaconAddress || !cohortKeys) return;
1454
- const participantPkHex = (0, import_utils3.bytesToHex)(this.keys.publicKey.compressed);
1610
+ const participantPkHex = (0, import_utils3.bytesToHex)(this.publicKey);
1455
1611
  const cohortKeysHex = cohortKeys.map((k) => (0, import_utils3.bytesToHex)(new Uint8Array(k)));
1456
1612
  state.cohort.validateMembership(participantPkHex, cohortKeysHex, beaconAddress);
1457
1613
  state.phase = "CohortReady" /* CohortReady */;
@@ -1618,9 +1774,8 @@ var AggregationParticipant = class {
1618
1774
  prevOutValues
1619
1775
  });
1620
1776
  state.signingSession = session;
1621
- const nonceContribution = session.generateNonceContribution(
1622
- this.keys.publicKey.compressed,
1623
- this.keys.secretKey.bytes
1777
+ const nonceContribution = this.#signer.withSecret(
1778
+ (secretKey) => session.generateNonceContribution(this.publicKey, secretKey)
1624
1779
  );
1625
1780
  state.phase = "NonceSent" /* NonceSent */;
1626
1781
  return [createNonceContributionMessage({
@@ -1663,7 +1818,10 @@ var AggregationParticipant = class {
1663
1818
  { cohortId }
1664
1819
  );
1665
1820
  }
1666
- const partialSig = state.signingSession.generatePartialSignature(this.keys.secretKey.bytes);
1821
+ const signingSession = state.signingSession;
1822
+ const partialSig = this.#signer.withSecret(
1823
+ (secretKey) => signingSession.generatePartialSignature(secretKey)
1824
+ );
1667
1825
  state.phase = "Complete" /* Complete */;
1668
1826
  return [createSignatureAuthorizationMessage({
1669
1827
  from: this.did,
@@ -1676,6 +1834,37 @@ var AggregationParticipant = class {
1676
1834
  getCohortPhase(cohortId) {
1677
1835
  return this.#cohortStates.get(cohortId)?.phase;
1678
1836
  }
1837
+ /**
1838
+ * Zeroize any retained MuSig2 secret nonces across all cohorts. The raw
1839
+ * signing key is never held here (it lives behind the {@link AggregationSigner}
1840
+ * and is wiped per-operation), but an abandoned signing session can still hold
1841
+ * a secret nonce; call this on teardown to clear it deterministically.
1842
+ */
1843
+ clearSecrets() {
1844
+ for (const state of this.#cohortStates.values()) {
1845
+ state.signingSession?.clearSecrets();
1846
+ }
1847
+ }
1848
+ };
1849
+
1850
+ // src/core/aggregation/signer.ts
1851
+ var import_keypair2 = require("@did-btcr2/keypair");
1852
+ var KeyPairAggregationSigner = class {
1853
+ publicKey;
1854
+ #keys;
1855
+ /** @param {SchnorrKeyPair} keys The keypair whose secret backs this signer. */
1856
+ constructor(keys) {
1857
+ this.#keys = keys;
1858
+ this.publicKey = keys.publicKey.compressed;
1859
+ }
1860
+ withSecret(fn) {
1861
+ const secretKey = this.#keys.secretKey.bytes;
1862
+ try {
1863
+ return fn(secretKey);
1864
+ } finally {
1865
+ (0, import_keypair2.wipe)(secretKey);
1866
+ }
1867
+ }
1679
1868
  };
1680
1869
 
1681
1870
  // src/core/aggregation/logger.ts
@@ -1696,49 +1885,6 @@ var SILENT_LOGGER = {
1696
1885
  }
1697
1886
  };
1698
1887
 
1699
- // src/core/aggregation/messages/bodies.ts
1700
- var hasStr = (b, k) => !!b && typeof b[k] === "string";
1701
- var hasNum = (b, k) => !!b && typeof b[k] === "number";
1702
- var hasBool = (b, k) => !!b && typeof b[k] === "boolean";
1703
- var hasBytes = (b, k) => !!b && b[k] instanceof Uint8Array;
1704
- var hasBytesArray = (b, k) => {
1705
- const v = b ? b[k] : void 0;
1706
- return Array.isArray(v) && v.every((x) => x instanceof Uint8Array);
1707
- };
1708
- function isCohortAdvertMessage(m) {
1709
- return m.type === COHORT_ADVERT && hasStr(m.body, "cohortId") && hasNum(m.body, "cohortSize") && hasStr(m.body, "beaconType") && hasStr(m.body, "network") && hasBytes(m.body, "communicationPk");
1710
- }
1711
- function isCohortOptInMessage(m) {
1712
- return m.type === COHORT_OPT_IN && hasStr(m.body, "cohortId") && hasBytes(m.body, "participantPk") && hasBytes(m.body, "communicationPk");
1713
- }
1714
- function isCohortOptInAcceptMessage(m) {
1715
- return m.type === COHORT_OPT_IN_ACCEPT && hasStr(m.body, "cohortId");
1716
- }
1717
- function isCohortReadyMessage(m) {
1718
- return m.type === COHORT_READY && hasStr(m.body, "cohortId") && hasStr(m.body, "beaconAddress") && hasBytesArray(m.body, "cohortKeys");
1719
- }
1720
- function isSubmitUpdateMessage(m) {
1721
- return m.type === SUBMIT_UPDATE && hasStr(m.body, "cohortId") && !!m.body && typeof m.body.signedUpdate === "object";
1722
- }
1723
- function isDistributeAggregatedDataMessage(m) {
1724
- return m.type === DISTRIBUTE_AGGREGATED_DATA && hasStr(m.body, "cohortId") && hasStr(m.body, "beaconType") && hasStr(m.body, "signalBytesHex");
1725
- }
1726
- function isValidationAckMessage(m) {
1727
- return m.type === VALIDATION_ACK && hasStr(m.body, "cohortId") && hasBool(m.body, "approved");
1728
- }
1729
- function isAuthorizationRequestMessage(m) {
1730
- return m.type === AUTHORIZATION_REQUEST && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasStr(m.body, "pendingTx") && hasStr(m.body, "prevOutScriptHex") && hasStr(m.body, "prevOutValue");
1731
- }
1732
- function isNonceContributionMessage(m) {
1733
- return m.type === NONCE_CONTRIBUTION && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasBytes(m.body, "nonceContribution");
1734
- }
1735
- function isAggregatedNonceMessage(m) {
1736
- return m.type === AGGREGATED_NONCE && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasBytes(m.body, "aggregatedNonce");
1737
- }
1738
- function isSignatureAuthorizationMessage(m) {
1739
- return m.type === SIGNATURE_AUTHORIZATION && hasStr(m.body, "cohortId") && hasStr(m.body, "sessionId") && hasBytes(m.body, "partialSignature");
1740
- }
1741
-
1742
1888
  // src/core/aggregation/messages/guards.ts
1743
1889
  var KEYGEN_VALUES = /* @__PURE__ */ new Set([
1744
1890
  COHORT_ADVERT,
@@ -1787,11 +1933,11 @@ var TransportAdapterError = class extends import_common6.MethodError {
1787
1933
  var import_common10 = require("@did-btcr2/common");
1788
1934
 
1789
1935
  // src/core/aggregation/transport/http/client.ts
1790
- var import_keypair2 = require("@did-btcr2/keypair");
1936
+ var import_keypair4 = require("@did-btcr2/keypair");
1791
1937
 
1792
1938
  // src/core/identifier.ts
1793
1939
  var import_common7 = require("@did-btcr2/common");
1794
- var import_keypair = require("@did-btcr2/keypair");
1940
+ var import_keypair3 = require("@did-btcr2/keypair");
1795
1941
  var import_base4 = require("@scure/base");
1796
1942
  var Identifier = class _Identifier {
1797
1943
  /**
@@ -1824,7 +1970,7 @@ var Identifier = class _Identifier {
1824
1970
  }
1825
1971
  if (idType === "KEY") {
1826
1972
  try {
1827
- new import_keypair.CompressedSecp256k1PublicKey(genesisBytes);
1973
+ new import_keypair3.CompressedSecp256k1PublicKey(genesisBytes);
1828
1974
  } catch {
1829
1975
  throw new import_common7.IdentifierError(
1830
1976
  'Expected "genesisBytes" to be a valid compressed secp256k1 public key',
@@ -1926,7 +2072,7 @@ var Identifier = class _Identifier {
1926
2072
  const genesisBytes = dataBytes.slice(byteIndex + 1);
1927
2073
  if (idType === "KEY") {
1928
2074
  try {
1929
- new import_keypair.CompressedSecp256k1PublicKey(genesisBytes);
2075
+ new import_keypair3.CompressedSecp256k1PublicKey(genesisBytes);
1930
2076
  } catch {
1931
2077
  throw new import_common7.IdentifierError(`Invalid genesisBytes: ${genesisBytes}`, import_common7.INVALID_DID, { identifier });
1932
2078
  }
@@ -1938,7 +2084,7 @@ var Identifier = class _Identifier {
1938
2084
  * @returns {string} The new did:btcr2 identifier.
1939
2085
  */
1940
2086
  static generate() {
1941
- const keyPair = import_keypair.SchnorrKeyPair.generate();
2087
+ const keyPair = import_keypair3.SchnorrKeyPair.generate();
1942
2088
  const did = this.encode(
1943
2089
  keyPair.publicKey.compressed,
1944
2090
  {
@@ -1964,7 +2110,7 @@ var Identifier = class _Identifier {
1964
2110
  { did, idType }
1965
2111
  );
1966
2112
  }
1967
- return new import_keypair.CompressedSecp256k1PublicKey(genesisBytes);
2113
+ return new import_keypair3.CompressedSecp256k1PublicKey(genesisBytes);
1968
2114
  }
1969
2115
  /**
1970
2116
  * Validates a did:btcr2 identifier.
@@ -2371,7 +2517,7 @@ var HttpClientTransport = class {
2371
2517
  }
2372
2518
  registerPeer(did, communicationPk) {
2373
2519
  try {
2374
- new import_keypair2.CompressedSecp256k1PublicKey(communicationPk);
2520
+ new import_keypair4.CompressedSecp256k1PublicKey(communicationPk);
2375
2521
  } catch {
2376
2522
  throw new HttpTransportError(
2377
2523
  `Invalid communication public key for peer ${did}: expected a 33-byte compressed secp256k1 key.`,
@@ -2567,14 +2713,14 @@ var HttpClientTransport = class {
2567
2713
  const peerBytes = this.#peers.get(did);
2568
2714
  if (peerBytes) {
2569
2715
  try {
2570
- return new import_keypair2.CompressedSecp256k1PublicKey(peerBytes);
2716
+ return new import_keypair4.CompressedSecp256k1PublicKey(peerBytes);
2571
2717
  } catch {
2572
2718
  }
2573
2719
  }
2574
2720
  try {
2575
2721
  const components = Identifier.decode(did);
2576
2722
  if (components.idType === "KEY") {
2577
- return new import_keypair2.CompressedSecp256k1PublicKey(components.genesisBytes);
2723
+ return new import_keypair4.CompressedSecp256k1PublicKey(components.genesisBytes);
2578
2724
  }
2579
2725
  } catch {
2580
2726
  }
@@ -2619,7 +2765,7 @@ function flattenMessage(msg) {
2619
2765
  }
2620
2766
 
2621
2767
  // src/core/aggregation/transport/http/server.ts
2622
- var import_keypair3 = require("@did-btcr2/keypair");
2768
+ var import_keypair5 = require("@did-btcr2/keypair");
2623
2769
 
2624
2770
  // src/core/aggregation/transport/http/inbox-buffer.ts
2625
2771
  var InboxBuffer = class {
@@ -2784,7 +2930,7 @@ var HttpServerTransport = class {
2784
2930
  }
2785
2931
  registerPeer(did, communicationPk) {
2786
2932
  try {
2787
- new import_keypair3.CompressedSecp256k1PublicKey(communicationPk);
2933
+ new import_keypair5.CompressedSecp256k1PublicKey(communicationPk);
2788
2934
  } catch {
2789
2935
  throw new HttpTransportError(
2790
2936
  `Invalid peer public key for ${did}`,
@@ -3062,14 +3208,14 @@ var HttpServerTransport = class {
3062
3208
  const peerBytes = this.#peers.get(did);
3063
3209
  if (peerBytes) {
3064
3210
  try {
3065
- return new import_keypair3.CompressedSecp256k1PublicKey(peerBytes);
3211
+ return new import_keypair5.CompressedSecp256k1PublicKey(peerBytes);
3066
3212
  } catch {
3067
3213
  }
3068
3214
  }
3069
3215
  try {
3070
3216
  const components = Identifier.decode(did);
3071
3217
  if (components.idType === "KEY") {
3072
- return new import_keypair3.CompressedSecp256k1PublicKey(components.genesisBytes);
3218
+ return new import_keypair5.CompressedSecp256k1PublicKey(components.genesisBytes);
3073
3219
  }
3074
3220
  } catch {
3075
3221
  }
@@ -3168,7 +3314,7 @@ function flattenMessage2(msg) {
3168
3314
  }
3169
3315
 
3170
3316
  // src/core/aggregation/transport/nostr.ts
3171
- var import_keypair4 = require("@did-btcr2/keypair");
3317
+ var import_keypair6 = require("@did-btcr2/keypair");
3172
3318
  var import_utils6 = require("@noble/hashes/utils");
3173
3319
  var import_nostr_tools = require("nostr-tools");
3174
3320
  var import_pool = require("nostr-tools/pool");
@@ -3266,7 +3412,7 @@ var NostrTransport = class _NostrTransport {
3266
3412
  */
3267
3413
  registerPeer(did, communicationPk) {
3268
3414
  try {
3269
- new import_keypair4.CompressedSecp256k1PublicKey(communicationPk);
3415
+ new import_keypair6.CompressedSecp256k1PublicKey(communicationPk);
3270
3416
  } catch {
3271
3417
  throw new TransportAdapterError(
3272
3418
  `Invalid communication public key for peer ${did}: expected a 33-byte compressed secp256k1 key.`,
@@ -3373,7 +3519,7 @@ var NostrTransport = class _NostrTransport {
3373
3519
  if (to) {
3374
3520
  const recipientPkBytes = this.#peerRegistry.get(to);
3375
3521
  if (recipientPkBytes) {
3376
- const recipientPk = new import_keypair4.CompressedSecp256k1PublicKey(recipientPkBytes);
3522
+ const recipientPk = new import_keypair6.CompressedSecp256k1PublicKey(recipientPkBytes);
3377
3523
  tags.push(["p", (0, import_utils6.bytesToHex)(recipientPk.x)]);
3378
3524
  }
3379
3525
  }
@@ -3404,7 +3550,7 @@ var NostrTransport = class _NostrTransport {
3404
3550
  { adapter: this.name, did: to }
3405
3551
  );
3406
3552
  }
3407
- const recipientPk = new import_keypair4.CompressedSecp256k1PublicKey(recipientPkBytes);
3553
+ const recipientPk = new import_keypair6.CompressedSecp256k1PublicKey(recipientPkBytes);
3408
3554
  const conversationKey = import_nostr_tools.nip44.v2.utils.getConversationKey(
3409
3555
  senderKeys.secretKey.bytes,
3410
3556
  (0, import_utils6.bytesToHex)(recipientPk.x)
@@ -3695,10 +3841,10 @@ var InMemoryTransport = class {
3695
3841
  start() {
3696
3842
  }
3697
3843
  registerActor(did, keys) {
3698
- this.#actors.set(did, { keys, handlers: /* @__PURE__ */ new Map() });
3844
+ this.#actors.set(did, { publicKey: keys.publicKey.compressed, handlers: /* @__PURE__ */ new Map() });
3699
3845
  }
3700
3846
  getActorPk(did) {
3701
- return this.#actors.get(did)?.keys.publicKey.compressed;
3847
+ return this.#actors.get(did)?.publicKey;
3702
3848
  }
3703
3849
  /** True if `did` is registered on this transport. Used by the bus for routing. */
3704
3850
  hasActor(did) {
@@ -3909,8 +4055,11 @@ var AggregationServiceRunner = class _AggregationServiceRunner extends TypedEven
3909
4055
  this.#phaseTimeoutMs = options.phaseTimeoutMs;
3910
4056
  this.#advertRepeatIntervalMs = options.advertRepeatIntervalMs ?? DEFAULT_ADVERT_REPEAT_INTERVAL_MS;
3911
4057
  this.session = new AggregationService({
4058
+ // The coordinator never signs, so the state machine receives only the
4059
+ // public half of the operator's keypair (see ADR 038). The full keypair
4060
+ // remains the operator's transport/communication identity.
3912
4061
  did: options.did,
3913
- keys: options.keys,
4062
+ publicKey: options.keys.publicKey,
3914
4063
  maxUpdateSizeBytes: options.maxUpdateSizeBytes
3915
4064
  });
3916
4065
  }
@@ -4081,6 +4230,11 @@ var AggregationServiceRunner = class _AggregationServiceRunner extends TypedEven
4081
4230
  }
4082
4231
  const decision = await this.#onOptInReceived(optIn);
4083
4232
  if (!decision.accepted) return;
4233
+ const maxParticipants = this.#config.maxParticipants;
4234
+ const cohortNow = this.session.getCohort(this.#cohortId);
4235
+ if (maxParticipants !== void 0 && cohortNow && cohortNow.participants.length >= maxParticipants) {
4236
+ return;
4237
+ }
4084
4238
  await this.#sendAll(this.session.acceptParticipant(this.#cohortId, msg.from));
4085
4239
  this.emit("participant-accepted", { participantDid: msg.from });
4086
4240
  const cohort = this.session.getCohort(this.#cohortId);
@@ -4262,7 +4416,10 @@ var AggregationParticipantRunner = class _AggregationParticipantRunner extends T
4262
4416
  this.#onProvideUpdate = options.onProvideUpdate;
4263
4417
  this.#onValidateData = options.onValidateData ?? (async (info) => ({ approved: info.matches }));
4264
4418
  this.#onApproveSigning = options.onApproveSigning ?? (async () => ({ approved: true }));
4265
- this.session = new AggregationParticipant({ did: options.did, keys: options.keys });
4419
+ this.session = new AggregationParticipant({
4420
+ did: options.did,
4421
+ signer: new KeyPairAggregationSigner(options.keys)
4422
+ });
4266
4423
  }
4267
4424
  /**
4268
4425
  * Start listening for cohorts. The runner stays active until {@link stop}
@@ -4275,6 +4432,7 @@ var AggregationParticipantRunner = class _AggregationParticipantRunner extends T
4275
4432
  stop() {
4276
4433
  this.#stopped = true;
4277
4434
  this.#unregisterHandlers();
4435
+ this.session.clearSecrets();
4278
4436
  }
4279
4437
  /** Message types this runner listens for on the transport. */
4280
4438
  static #HANDLED_MESSAGE_TYPES = [
@@ -5110,11 +5268,11 @@ var BeaconFactory = class {
5110
5268
  };
5111
5269
 
5112
5270
  // src/core/beacon/signal-discovery.ts
5113
- var import_bitcoin2 = require("@did-btcr2/bitcoin");
5271
+ var import_bitcoin3 = require("@did-btcr2/bitcoin");
5114
5272
  var import_common18 = require("@did-btcr2/common");
5115
5273
 
5116
5274
  // src/core/beacon/utils.ts
5117
- var import_bitcoin = require("@did-btcr2/bitcoin");
5275
+ var import_bitcoin2 = require("@did-btcr2/bitcoin");
5118
5276
  var import_common17 = require("@did-btcr2/common");
5119
5277
  var import_btc_signer5 = require("@scure/btc-signer");
5120
5278
 
@@ -6221,7 +6379,7 @@ var BeaconUtils = class {
6221
6379
  static createBeaconService(did, addressType, beaconType) {
6222
6380
  try {
6223
6381
  const components = Identifier.decode(did);
6224
- const network = (0, import_bitcoin.getNetwork)(components.network);
6382
+ const network = (0, import_bitcoin2.getNetwork)(components.network);
6225
6383
  const pubkey = components.genesisBytes;
6226
6384
  const id = `${did}#initial${addressType.toUpperCase()}`;
6227
6385
  const address = addressType === "p2tr" ? (0, import_btc_signer5.p2tr)(pubkey.slice(1, 33), void 0, network).address : addressType === "p2wpkh" ? (0, import_btc_signer5.p2wpkh)(pubkey, network).address : (0, import_btc_signer5.p2pkh)(pubkey, network).address;
@@ -6372,14 +6530,14 @@ var BeaconSignalDiscovery = class {
6372
6530
  console.info(`Searching for beacon signals, please wait ...`);
6373
6531
  while (block.height <= targetHeight) {
6374
6532
  for (const tx of block.tx) {
6375
- if (tx.txid === import_bitcoin2.GENESIS_TX_ID) {
6533
+ if (tx.txid === import_bitcoin3.GENESIS_TX_ID) {
6376
6534
  continue;
6377
6535
  }
6378
6536
  for (const vin of tx.vin) {
6379
6537
  if (vin.coinbase) {
6380
6538
  continue;
6381
6539
  }
6382
- if (vin.txinwitness && vin.txinwitness.length === 1 && vin.txinwitness[0] === import_bitcoin2.TXIN_WITNESS_COINBASE) {
6540
+ if (vin.txinwitness && vin.txinwitness.length === 1 && vin.txinwitness[0] === import_bitcoin3.TXIN_WITNESS_COINBASE) {
6383
6541
  continue;
6384
6542
  }
6385
6543
  if (!vin.txid) {
@@ -6433,10 +6591,10 @@ var BeaconSignalDiscovery = class {
6433
6591
  };
6434
6592
 
6435
6593
  // src/core/resolver.ts
6436
- var import_bitcoin4 = require("@did-btcr2/bitcoin");
6594
+ var import_bitcoin5 = require("@did-btcr2/bitcoin");
6437
6595
  var import_common22 = require("@did-btcr2/common");
6438
6596
  var import_cryptosuite3 = require("@did-btcr2/cryptosuite");
6439
- var import_keypair6 = require("@did-btcr2/keypair");
6597
+ var import_keypair8 = require("@did-btcr2/keypair");
6440
6598
 
6441
6599
  // src/did-btcr2.ts
6442
6600
  var import_common21 = require("@did-btcr2/common");
@@ -6447,9 +6605,9 @@ var import_common20 = require("@did-btcr2/common");
6447
6605
  var import_cryptosuite2 = require("@did-btcr2/cryptosuite");
6448
6606
 
6449
6607
  // src/utils/did-document.ts
6450
- var import_bitcoin3 = require("@did-btcr2/bitcoin");
6608
+ var import_bitcoin4 = require("@did-btcr2/bitcoin");
6451
6609
  var import_common19 = require("@did-btcr2/common");
6452
- var import_keypair5 = require("@did-btcr2/keypair");
6610
+ var import_keypair7 = require("@did-btcr2/keypair");
6453
6611
  var import_utils11 = require("@web5/dids/utils");
6454
6612
  var import_btc_signer6 = require("@scure/btc-signer");
6455
6613
  var BTCR2_DID_DOCUMENT_CONTEXT = [
@@ -6771,9 +6929,9 @@ var GenesisDocument = class _GenesisDocument extends DidDocument {
6771
6929
  * @returns {GenesisDocument} A new GenesisDocument with the placeholder ID.
6772
6930
  */
6773
6931
  static fromPublicKey(publicKey, network) {
6774
- const pk = new import_keypair5.CompressedSecp256k1PublicKey(publicKey);
6932
+ const pk = new import_keypair7.CompressedSecp256k1PublicKey(publicKey);
6775
6933
  const id = ID_PLACEHOLDER_VALUE;
6776
- const address = (0, import_btc_signer6.p2pkh)(pk.compressed, (0, import_bitcoin3.getNetwork)(network)).address;
6934
+ const address = (0, import_btc_signer6.p2pkh)(pk.compressed, (0, import_bitcoin4.getNetwork)(network)).address;
6777
6935
  const services = [{
6778
6936
  id: `${id}#service-0`,
6779
6937
  serviceEndpoint: `bitcoin:${address}`,
@@ -7280,11 +7438,11 @@ var Resolver = class _Resolver {
7280
7438
  static deterministic(didComponents) {
7281
7439
  const genesisBytes = didComponents.genesisBytes;
7282
7440
  const did = Identifier.encode(genesisBytes, didComponents);
7283
- const { multibase } = new import_keypair6.CompressedSecp256k1PublicKey(genesisBytes);
7441
+ const { multibase } = new import_keypair8.CompressedSecp256k1PublicKey(genesisBytes);
7284
7442
  const service = BeaconUtils.generateBeaconServices({
7285
7443
  id: did,
7286
7444
  publicKey: genesisBytes,
7287
- network: (0, import_bitcoin4.getNetwork)(didComponents.network),
7445
+ network: (0, import_bitcoin5.getNetwork)(didComponents.network),
7288
7446
  beaconType: "SingletonBeacon"
7289
7447
  });
7290
7448
  return new DidDocument({
@@ -7757,6 +7915,8 @@ var DidDocumentBuilder = class {
7757
7915
  InMemoryRateLimitStore,
7758
7916
  InMemoryTransport,
7759
7917
  InboxBuffer,
7918
+ KNOWN_BEACON_TYPES,
7919
+ KeyPairAggregationSigner,
7760
7920
  NONCE_CONTRIBUTION,
7761
7921
  NonceCache,
7762
7922
  NostrTransport,
@@ -7828,6 +7988,7 @@ var DidDocumentBuilder = class {
7828
7988
  registerBeaconStrategy,
7829
7989
  reviveFromWire,
7830
7990
  signEnvelope,
7991
+ validateCohortConditions,
7831
7992
  verifyEnvelope,
7832
7993
  verifyRequestAuth
7833
7994
  });