@did-btcr2/method 0.35.0 → 0.36.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.
Files changed (55) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/browser.js +460 -223
  3. package/dist/browser.mjs +460 -223
  4. package/dist/cjs/index.js +461 -223
  5. package/dist/esm/core/aggregation/cohort.js +3 -1
  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 +20 -7
  14. package/dist/esm/core/aggregation/participant.js.map +1 -1
  15. package/dist/esm/core/aggregation/runner/participant-runner.js +37 -2
  16. package/dist/esm/core/aggregation/runner/participant-runner.js.map +1 -1
  17. package/dist/esm/core/aggregation/runner/service-runner.js +323 -189
  18. package/dist/esm/core/aggregation/runner/service-runner.js.map +1 -1
  19. package/dist/esm/core/aggregation/service.js +23 -3
  20. package/dist/esm/core/aggregation/service.js.map +1 -1
  21. package/dist/esm/index.js +1 -0
  22. package/dist/esm/index.js.map +1 -1
  23. package/dist/types/core/aggregation/cohort.d.ts.map +1 -1
  24. package/dist/types/core/aggregation/conditions.d.ts +58 -0
  25. package/dist/types/core/aggregation/conditions.d.ts.map +1 -0
  26. package/dist/types/core/aggregation/messages/base.d.ts +2 -3
  27. package/dist/types/core/aggregation/messages/base.d.ts.map +1 -1
  28. package/dist/types/core/aggregation/messages/bodies.d.ts +2 -3
  29. package/dist/types/core/aggregation/messages/bodies.d.ts.map +1 -1
  30. package/dist/types/core/aggregation/messages/factories.d.ts +2 -3
  31. package/dist/types/core/aggregation/messages/factories.d.ts.map +1 -1
  32. package/dist/types/core/aggregation/participant.d.ts +16 -4
  33. package/dist/types/core/aggregation/participant.d.ts.map +1 -1
  34. package/dist/types/core/aggregation/runner/events.d.ts +22 -11
  35. package/dist/types/core/aggregation/runner/events.d.ts.map +1 -1
  36. package/dist/types/core/aggregation/runner/participant-runner.d.ts +21 -12
  37. package/dist/types/core/aggregation/runner/participant-runner.d.ts.map +1 -1
  38. package/dist/types/core/aggregation/runner/service-runner.d.ts +76 -22
  39. package/dist/types/core/aggregation/runner/service-runner.d.ts.map +1 -1
  40. package/dist/types/core/aggregation/service.d.ts +8 -4
  41. package/dist/types/core/aggregation/service.d.ts.map +1 -1
  42. package/dist/types/index.d.ts +1 -0
  43. package/dist/types/index.d.ts.map +1 -1
  44. package/package.json +4 -4
  45. package/src/core/aggregation/cohort.ts +3 -1
  46. package/src/core/aggregation/conditions.ts +116 -0
  47. package/src/core/aggregation/messages/base.ts +6 -3
  48. package/src/core/aggregation/messages/bodies.ts +18 -6
  49. package/src/core/aggregation/messages/factories.ts +2 -3
  50. package/src/core/aggregation/participant.ts +28 -11
  51. package/src/core/aggregation/runner/events.ts +23 -14
  52. package/src/core/aggregation/runner/participant-runner.ts +43 -13
  53. package/src/core/aggregation/runner/service-runner.ts +375 -195
  54. package/src/core/aggregation/service.ts +39 -7
  55. package/src/index.ts +1 -0
@@ -6,6 +6,7 @@ import { bytesToHex } from '@noble/hashes/utils';
6
6
  import type { Transaction } from '@scure/btc-signer';
7
7
  import { getBeaconStrategy } from './beacon-strategy.js';
8
8
  import { AggregationCohort } from './cohort.js';
9
+ import { validateCohortConditions, type CohortConditions } from './conditions.js';
9
10
  import { AggregationServiceError } from './errors.js';
10
11
  import type { BaseMessage } from './messages/base.js';
11
12
  import { AGGREGATION_WIRE_VERSION } from './messages/base.js';
@@ -28,11 +29,14 @@ import type { ServiceCohortPhaseType } from './phases.js';
28
29
  import { ServiceCohortPhase } from './phases.js';
29
30
  import { BeaconSigningSession } from './signing-session.js';
30
31
 
31
- /** Cohort configuration set by the service operator. */
32
- export interface CohortConfig {
33
- minParticipants: number;
32
+ /**
33
+ * Cohort configuration set by the service operator: the advertised cohort
34
+ * {@link CohortConditions} plus the Bitcoin network. `beaconType` and
35
+ * `minParticipants` are required; the other conditions are optional (absent =
36
+ * unconstrained). See ADR 039.
37
+ */
38
+ export interface CohortConfig extends CohortConditions {
34
39
  network: string;
35
- beaconType: string;
36
40
  }
37
41
 
38
42
  /** Pending opt-in awaiting service operator approval. */
@@ -201,6 +205,14 @@ export class AggregationService {
201
205
  * Cohort starts in `Created` phase — call `advertise()` to broadcast.
202
206
  */
203
207
  createCohort(config: CohortConfig): string {
208
+ // Fail fast on invalid conditions rather than discovering them at finalize.
209
+ const problems = validateCohortConditions(config);
210
+ if(problems.length > 0) {
211
+ throw new AggregationServiceError(
212
+ `Invalid cohort conditions: ${problems.join('; ')}`,
213
+ 'INVALID_COHORT_CONDITIONS', { problems }
214
+ );
215
+ }
204
216
  const cohort = new AggregationCohort({
205
217
  serviceDid : this.did,
206
218
  minParticipants : config.minParticipants,
@@ -234,13 +246,15 @@ export class AggregationService {
234
246
  );
235
247
  }
236
248
 
249
+ // Advertise the full condition set (flat fields, per ADR 039). network is
250
+ // a separate cohort parameter; everything else in config is a condition.
251
+ const { network, ...conditions } = state.config;
237
252
  const message = createCohortAdvertMessage({
238
253
  from : this.did,
239
254
  cohortId,
240
- cohortSize : state.config.minParticipants,
241
- beaconType : state.config.beaconType,
242
- network : state.config.network,
255
+ network,
243
256
  communicationPk : this.publicKey.compressed,
257
+ ...conditions,
244
258
  });
245
259
 
246
260
  state.phase = ServiceCohortPhase.Advertised;
@@ -310,6 +324,15 @@ export class AggregationService {
310
324
  'ALREADY_ACCEPTED', { cohortId, participantDid }
311
325
  );
312
326
  }
327
+ // Enforce the maxParticipants condition: a cohort cannot grow past its
328
+ // advertised ceiling (closes the unbounded-growth path; see ADR 039).
329
+ const maxParticipants = state.config.maxParticipants;
330
+ if(maxParticipants !== undefined && state.acceptedParticipants.size >= maxParticipants) {
331
+ throw new AggregationServiceError(
332
+ `Cohort ${cohortId} is full: ${maxParticipants} participants already accepted.`,
333
+ 'COHORT_FULL', { cohortId, maxParticipants }
334
+ );
335
+ }
313
336
 
314
337
  state.acceptedParticipants.add(participantDid);
315
338
  state.cohort.participants.push(participantDid);
@@ -344,6 +367,15 @@ export class AggregationService {
344
367
  'NOT_ENOUGH_PARTICIPANTS', { cohortId }
345
368
  );
346
369
  }
370
+ // Ceiling defense: acceptParticipant already rejects past max, so reaching
371
+ // here over max means state was mutated out-of-band.
372
+ const maxParticipants = state.config.maxParticipants;
373
+ if(maxParticipants !== undefined && state.acceptedParticipants.size > maxParticipants) {
374
+ throw new AggregationServiceError(
375
+ `Cohort ${cohortId} has ${state.acceptedParticipants.size} accepted participants, exceeds max ${maxParticipants}.`,
376
+ 'TOO_MANY_PARTICIPANTS', { cohortId, maxParticipants }
377
+ );
378
+ }
347
379
 
348
380
  const beaconAddress = state.cohort.computeBeaconAddress();
349
381
  state.phase = ServiceCohortPhase.CohortSet;
package/src/index.ts CHANGED
@@ -2,6 +2,7 @@
2
2
  export * from './core/aggregation/service.js';
3
3
  export * from './core/aggregation/participant.js';
4
4
  export * from './core/aggregation/signer.js';
5
+ export * from './core/aggregation/conditions.js';
5
6
  export * from './core/aggregation/cohort.js';
6
7
  export * from './core/aggregation/signing-session.js';
7
8
  export * from './core/aggregation/phases.js';