@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.
- package/dist/.tsbuildinfo +1 -1
- package/dist/browser.js +335 -167
- package/dist/browser.mjs +335 -167
- package/dist/cjs/index.js +275 -114
- package/dist/esm/core/aggregation/cohort.js +8 -2
- package/dist/esm/core/aggregation/cohort.js.map +1 -1
- package/dist/esm/core/aggregation/conditions.js +75 -0
- package/dist/esm/core/aggregation/conditions.js.map +1 -0
- package/dist/esm/core/aggregation/messages/base.js.map +1 -1
- package/dist/esm/core/aggregation/messages/bodies.js +16 -2
- package/dist/esm/core/aggregation/messages/bodies.js.map +1 -1
- package/dist/esm/core/aggregation/messages/factories.js.map +1 -1
- package/dist/esm/core/aggregation/participant.js +34 -15
- package/dist/esm/core/aggregation/participant.js.map +1 -1
- package/dist/esm/core/aggregation/runner/participant-runner.js +9 -1
- package/dist/esm/core/aggregation/runner/participant-runner.js.map +1 -1
- package/dist/esm/core/aggregation/runner/service-runner.js +12 -1
- package/dist/esm/core/aggregation/runner/service-runner.js.map +1 -1
- package/dist/esm/core/aggregation/service.js +27 -7
- package/dist/esm/core/aggregation/service.js.map +1 -1
- package/dist/esm/core/aggregation/signer.js +33 -0
- package/dist/esm/core/aggregation/signer.js.map +1 -0
- package/dist/esm/core/aggregation/signing-session.js +34 -11
- package/dist/esm/core/aggregation/signing-session.js.map +1 -1
- package/dist/esm/core/aggregation/transport/in-memory.js +5 -2
- package/dist/esm/core/aggregation/transport/in-memory.js.map +1 -1
- package/dist/esm/index.js +2 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/types/core/aggregation/cohort.d.ts.map +1 -1
- package/dist/types/core/aggregation/conditions.d.ts +58 -0
- package/dist/types/core/aggregation/conditions.d.ts.map +1 -0
- package/dist/types/core/aggregation/messages/base.d.ts +2 -3
- package/dist/types/core/aggregation/messages/base.d.ts.map +1 -1
- package/dist/types/core/aggregation/messages/bodies.d.ts +2 -3
- package/dist/types/core/aggregation/messages/bodies.d.ts.map +1 -1
- package/dist/types/core/aggregation/messages/factories.d.ts +2 -3
- package/dist/types/core/aggregation/messages/factories.d.ts.map +1 -1
- package/dist/types/core/aggregation/participant.d.ts +24 -8
- package/dist/types/core/aggregation/participant.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/participant-runner.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/service-runner.d.ts.map +1 -1
- package/dist/types/core/aggregation/service.d.ts +18 -8
- package/dist/types/core/aggregation/service.d.ts.map +1 -1
- package/dist/types/core/aggregation/signer.d.ts +50 -0
- package/dist/types/core/aggregation/signer.d.ts.map +1 -0
- package/dist/types/core/aggregation/signing-session.d.ts +13 -5
- package/dist/types/core/aggregation/signing-session.d.ts.map +1 -1
- package/dist/types/core/aggregation/transport/in-memory.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/core/aggregation/cohort.ts +8 -2
- package/src/core/aggregation/conditions.ts +116 -0
- package/src/core/aggregation/messages/base.ts +6 -3
- package/src/core/aggregation/messages/bodies.ts +18 -6
- package/src/core/aggregation/messages/factories.ts +2 -3
- package/src/core/aggregation/participant.ts +54 -23
- package/src/core/aggregation/runner/participant-runner.ts +9 -1
- package/src/core/aggregation/runner/service-runner.ts +13 -1
- package/src/core/aggregation/service.ts +51 -13
- package/src/core/aggregation/signer.ts +67 -0
- package/src/core/aggregation/signing-session.ts +34 -11
- package/src/core/aggregation/transport/in-memory.ts +7 -3
- 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
|
|
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
|
-
/**
|
|
623
|
-
|
|
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
|
|
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
|
-
*
|
|
783
|
-
*
|
|
784
|
-
*
|
|
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
|
|
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
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
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
|
-
|
|
893
|
+
publicKey;
|
|
818
894
|
maxUpdateSizeBytes;
|
|
819
895
|
/** Per-cohort state, keyed by cohortId. */
|
|
820
896
|
#cohortStates = /* @__PURE__ */ new Map();
|
|
821
|
-
constructor({ did,
|
|
897
|
+
constructor({ did, publicKey, maxUpdateSizeBytes }) {
|
|
822
898
|
this.did = did;
|
|
823
|
-
this.
|
|
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
|
-
|
|
914
|
-
|
|
915
|
-
|
|
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
|
-
|
|
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,
|
|
1484
|
+
constructor({ did, signer }) {
|
|
1332
1485
|
this.did = did;
|
|
1333
|
-
this
|
|
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
|
-
|
|
1379
|
-
|
|
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
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
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.
|
|
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.
|
|
1423
|
-
communicationPk: this.
|
|
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.
|
|
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 =
|
|
1622
|
-
this.
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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)?.
|
|
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
|
-
|
|
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({
|
|
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
|
|
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
|
|
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,
|
|
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 ===
|
|
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] ===
|
|
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
|
|
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
|
|
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
|
|
6608
|
+
var import_bitcoin4 = require("@did-btcr2/bitcoin");
|
|
6451
6609
|
var import_common19 = require("@did-btcr2/common");
|
|
6452
|
-
var
|
|
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
|
|
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,
|
|
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
|
|
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,
|
|
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
|
});
|