@did-btcr2/method 0.32.0 → 0.34.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 (62) hide show
  1. package/README.md +25 -13
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/browser.js +332 -582
  4. package/dist/browser.mjs +332 -582
  5. package/dist/cjs/index.js +213 -35
  6. package/dist/esm/core/aggregation/beacon-strategy.js +5 -4
  7. package/dist/esm/core/aggregation/beacon-strategy.js.map +1 -1
  8. package/dist/esm/core/aggregation/runner/aggregation-runner.js +66 -0
  9. package/dist/esm/core/aggregation/runner/aggregation-runner.js.map +1 -0
  10. package/dist/esm/core/aggregation/runner/index.js +1 -0
  11. package/dist/esm/core/aggregation/runner/index.js.map +1 -1
  12. package/dist/esm/core/aggregation/transport/in-memory.js +146 -0
  13. package/dist/esm/core/aggregation/transport/in-memory.js.map +1 -0
  14. package/dist/esm/core/aggregation/transport/index.js +1 -0
  15. package/dist/esm/core/aggregation/transport/index.js.map +1 -1
  16. package/dist/esm/core/beacon/beacon.js +10 -8
  17. package/dist/esm/core/beacon/beacon.js.map +1 -1
  18. package/dist/esm/core/beacon/cas-beacon.js +4 -4
  19. package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
  20. package/dist/esm/core/beacon/factory.js +1 -1
  21. package/dist/esm/core/beacon/singleton-beacon.js +4 -4
  22. package/dist/esm/core/beacon/singleton-beacon.js.map +1 -1
  23. package/dist/esm/core/beacon/smt-beacon.js +23 -15
  24. package/dist/esm/core/beacon/smt-beacon.js.map +1 -1
  25. package/dist/esm/core/resolver.js +7 -4
  26. package/dist/esm/core/resolver.js.map +1 -1
  27. package/dist/types/core/aggregation/beacon-strategy.d.ts.map +1 -1
  28. package/dist/types/core/aggregation/runner/aggregation-runner.d.ts +56 -0
  29. package/dist/types/core/aggregation/runner/aggregation-runner.d.ts.map +1 -0
  30. package/dist/types/core/aggregation/runner/index.d.ts +1 -0
  31. package/dist/types/core/aggregation/runner/index.d.ts.map +1 -1
  32. package/dist/types/core/aggregation/transport/in-memory.d.ts +64 -0
  33. package/dist/types/core/aggregation/transport/in-memory.d.ts.map +1 -0
  34. package/dist/types/core/aggregation/transport/index.d.ts +1 -0
  35. package/dist/types/core/aggregation/transport/index.d.ts.map +1 -1
  36. package/dist/types/core/beacon/beacon.d.ts +12 -10
  37. package/dist/types/core/beacon/beacon.d.ts.map +1 -1
  38. package/dist/types/core/beacon/cas-beacon.d.ts +4 -4
  39. package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
  40. package/dist/types/core/beacon/factory.d.ts +3 -3
  41. package/dist/types/core/beacon/factory.d.ts.map +1 -1
  42. package/dist/types/core/beacon/singleton-beacon.d.ts +4 -4
  43. package/dist/types/core/beacon/singleton-beacon.d.ts.map +1 -1
  44. package/dist/types/core/beacon/smt-beacon.d.ts +4 -4
  45. package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -1
  46. package/dist/types/core/interfaces.d.ts +14 -11
  47. package/dist/types/core/interfaces.d.ts.map +1 -1
  48. package/dist/types/core/resolver.d.ts +1 -1
  49. package/dist/types/core/resolver.d.ts.map +1 -1
  50. package/package.json +20 -8
  51. package/src/core/aggregation/beacon-strategy.ts +5 -4
  52. package/src/core/aggregation/runner/aggregation-runner.ts +96 -0
  53. package/src/core/aggregation/runner/index.ts +1 -0
  54. package/src/core/aggregation/transport/in-memory.ts +174 -0
  55. package/src/core/aggregation/transport/index.ts +1 -0
  56. package/src/core/beacon/beacon.ts +12 -10
  57. package/src/core/beacon/cas-beacon.ts +4 -4
  58. package/src/core/beacon/factory.ts +3 -3
  59. package/src/core/beacon/singleton-beacon.ts +4 -4
  60. package/src/core/beacon/smt-beacon.ts +24 -16
  61. package/src/core/interfaces.ts +14 -11
  62. package/src/core/resolver.ts +9 -6
package/dist/browser.js CHANGED
@@ -46578,11 +46578,11 @@ ${[...listenStats.errors.entries()].map(([addr, err]) => {
46578
46578
  return "";
46579
46579
  }
46580
46580
  const dif = fullLength - str.length;
46581
- const padding3 = new Array(dif);
46581
+ const padding2 = new Array(dif);
46582
46582
  for (let i4 = 0; i4 < dif; i4++) {
46583
- padding3[i4] = "0";
46583
+ padding2[i4] = "0";
46584
46584
  }
46585
- const paddingString = padding3.join("");
46585
+ const paddingString = padding2.join("");
46586
46586
  return paddingString.concat(str);
46587
46587
  }
46588
46588
  var log22;
@@ -93157,6 +93157,7 @@ a=end-of-candidates
93157
93157
  AggregationParticipant: () => AggregationParticipant,
93158
93158
  AggregationParticipantError: () => AggregationParticipantError,
93159
93159
  AggregationParticipantRunner: () => AggregationParticipantRunner,
93160
+ AggregationRunner: () => AggregationRunner,
93160
93161
  AggregationService: () => AggregationService,
93161
93162
  AggregationServiceError: () => AggregationServiceError,
93162
93163
  AggregationServiceRunner: () => AggregationServiceRunner,
@@ -93164,7 +93165,6 @@ a=end-of-candidates
93164
93165
  BECH32M_CHARS: () => BECH32M_CHARS,
93165
93166
  BTCR2_DID_DOCUMENT_CONTEXT: () => BTCR2_DID_DOCUMENT_CONTEXT,
93166
93167
  BaseMessage: () => BaseMessage,
93167
- Beacon: () => Beacon,
93168
93168
  BeaconError: () => BeaconError,
93169
93169
  BeaconFactory: () => BeaconFactory,
93170
93170
  BeaconSignalDiscovery: () => BeaconSignalDiscovery,
@@ -93199,7 +93199,9 @@ a=end-of-candidates
93199
93199
  HttpTransportError: () => HttpTransportError,
93200
93200
  ID_PLACEHOLDER_VALUE: () => ID_PLACEHOLDER_VALUE,
93201
93201
  Identifier: () => Identifier,
93202
+ InMemoryBus: () => InMemoryBus,
93202
93203
  InMemoryRateLimitStore: () => InMemoryRateLimitStore,
93204
+ InMemoryTransport: () => InMemoryTransport,
93203
93205
  InboxBuffer: () => InboxBuffer,
93204
93206
  NONCE_CONTRIBUTION: () => NONCE_CONTRIBUTION,
93205
93207
  NonceCache: () => NonceCache,
@@ -93221,6 +93223,7 @@ a=end-of-candidates
93221
93223
  ServiceCohortPhase: () => ServiceCohortPhase,
93222
93224
  SigningSessionError: () => SigningSessionError,
93223
93225
  SigningSessionPhase: () => SigningSessionPhase,
93226
+ SinglePartyBeacon: () => SinglePartyBeacon,
93224
93227
  SingletonBeacon: () => SingletonBeacon,
93225
93228
  SingletonBeaconError: () => SingletonBeaconError,
93226
93229
  StaticFeeEstimator: () => StaticFeeEstimator,
@@ -93384,32 +93387,6 @@ a=end-of-candidates
93384
93387
  };
93385
93388
  }
93386
93389
  // @__NO_SIDE_EFFECTS__
93387
- function padding(bits, chr = "=") {
93388
- anumber2(bits);
93389
- astr("padding", chr);
93390
- return {
93391
- encode(data) {
93392
- astrArr("padding.encode", data);
93393
- while (data.length * bits % 8)
93394
- data.push(chr);
93395
- return data;
93396
- },
93397
- decode(input) {
93398
- astrArr("padding.decode", input);
93399
- let end = input.length;
93400
- if (end * bits % 8)
93401
- throw new Error("padding: invalid, string should have whole number of bytes");
93402
- for (; end > 0 && input[end - 1] === chr; end--) {
93403
- const last = end - 1;
93404
- const byte = last * bits;
93405
- if (byte % 8 === 0)
93406
- throw new Error("padding: invalid, string has too much padding");
93407
- }
93408
- return input.slice(0, end);
93409
- }
93410
- };
93411
- }
93412
- // @__NO_SIDE_EFFECTS__
93413
93390
  function normalize(fn) {
93414
93391
  afn(fn);
93415
93392
  return { encode: (from8) => from8, decode: (to) => fn(to) };
@@ -93470,7 +93447,7 @@ a=end-of-candidates
93470
93447
  res.push(2 ** i4);
93471
93448
  return res;
93472
93449
  })();
93473
- function convertRadix2(data, from8, to, padding3) {
93450
+ function convertRadix2(data, from8, to, padding2) {
93474
93451
  aArr(data);
93475
93452
  if (from8 <= 0 || from8 > 32)
93476
93453
  throw new Error(`convertRadix2: wrong from=${from8}`);
@@ -93500,11 +93477,11 @@ a=end-of-candidates
93500
93477
  carry &= pow3 - 1;
93501
93478
  }
93502
93479
  carry = carry << to - pos & mask;
93503
- if (!padding3 && pos >= from8)
93480
+ if (!padding2 && pos >= from8)
93504
93481
  throw new Error("Excess padding");
93505
- if (!padding3 && carry > 0)
93482
+ if (!padding2 && carry > 0)
93506
93483
  throw new Error(`Non-zero padding: ${carry}`);
93507
- if (padding3 && pos > 0)
93484
+ if (padding2 && pos > 0)
93508
93485
  res.push(carry >>> 0);
93509
93486
  return res;
93510
93487
  }
@@ -93578,24 +93555,6 @@ a=end-of-candidates
93578
93555
  }
93579
93556
  };
93580
93557
  }
93581
- var hasBase64Builtin = /* @__PURE__ */ (() => typeof Uint8Array.from([]).toBase64 === "function" && typeof Uint8Array.fromBase64 === "function")();
93582
- var decodeBase64Builtin = (s2, isUrl) => {
93583
- astr("base64", s2);
93584
- const re = isUrl ? /^[A-Za-z0-9=_-]+$/ : /^[A-Za-z0-9=+/]+$/;
93585
- const alphabet5 = isUrl ? "base64url" : "base64";
93586
- if (s2.length > 0 && !re.test(s2))
93587
- throw new Error("invalid base64");
93588
- return Uint8Array.fromBase64(s2, { alphabet: alphabet5, lastChunkHandling: "strict" });
93589
- };
93590
- var base64 = hasBase64Builtin ? {
93591
- encode(b) {
93592
- abytes2(b);
93593
- return b.toBase64();
93594
- },
93595
- decode(s2) {
93596
- return decodeBase64Builtin(s2, false);
93597
- }
93598
- } : /* @__PURE__ */ chain(/* @__PURE__ */ radix2(6), /* @__PURE__ */ alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), /* @__PURE__ */ padding(6), /* @__PURE__ */ join(""));
93599
93558
  var base64urlnopad = /* @__PURE__ */ chain(/* @__PURE__ */ radix2(6), /* @__PURE__ */ alphabet("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"), /* @__PURE__ */ join(""));
93600
93559
  var genBase58 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain(/* @__PURE__ */ radix(58), /* @__PURE__ */ alphabet(abc), /* @__PURE__ */ join(""));
93601
93560
  var base58 = /* @__PURE__ */ genBase58("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
@@ -98030,7 +97989,7 @@ a=end-of-candidates
98030
97989
  };
98031
97990
  }
98032
97991
  // @__NO_SIDE_EFFECTS__
98033
- function padding2(bits, chr = "=") {
97992
+ function padding(bits, chr = "=") {
98034
97993
  anumber4(bits);
98035
97994
  astr2("padding", chr);
98036
97995
  return {
@@ -98111,7 +98070,7 @@ a=end-of-candidates
98111
98070
  res.push(2 ** i4);
98112
98071
  return res;
98113
98072
  })();
98114
- function convertRadix22(data, from8, to, padding3) {
98073
+ function convertRadix22(data, from8, to, padding2) {
98115
98074
  aArr2(data);
98116
98075
  if (from8 <= 0 || from8 > 32)
98117
98076
  throw new Error(`convertRadix2: wrong from=${from8}`);
@@ -98141,11 +98100,11 @@ a=end-of-candidates
98141
98100
  carry &= pow3 - 1;
98142
98101
  }
98143
98102
  carry = carry << to - pos & mask;
98144
- if (!padding3 && pos >= from8)
98103
+ if (!padding2 && pos >= from8)
98145
98104
  throw new Error("Excess padding");
98146
- if (!padding3 && carry > 0)
98105
+ if (!padding2 && carry > 0)
98147
98106
  throw new Error(`Non-zero padding: ${carry}`);
98148
- if (padding3 && pos > 0)
98107
+ if (padding2 && pos > 0)
98149
98108
  res.push(carry >>> 0);
98150
98109
  return res;
98151
98110
  }
@@ -98193,8 +98152,8 @@ a=end-of-candidates
98193
98152
  }
98194
98153
  };
98195
98154
  }
98196
- var hasBase64Builtin2 = /* @__PURE__ */ (() => typeof Uint8Array.from([]).toBase64 === "function" && typeof Uint8Array.fromBase64 === "function")();
98197
- var decodeBase64Builtin2 = (s2, isUrl) => {
98155
+ var hasBase64Builtin = /* @__PURE__ */ (() => typeof Uint8Array.from([]).toBase64 === "function" && typeof Uint8Array.fromBase64 === "function")();
98156
+ var decodeBase64Builtin = (s2, isUrl) => {
98198
98157
  astr2("base64", s2);
98199
98158
  const re = isUrl ? /^[A-Za-z0-9=_-]+$/ : /^[A-Za-z0-9=+/]+$/;
98200
98159
  const alphabet5 = isUrl ? "base64url" : "base64";
@@ -98202,15 +98161,15 @@ a=end-of-candidates
98202
98161
  throw new Error("invalid base64");
98203
98162
  return Uint8Array.fromBase64(s2, { alphabet: alphabet5, lastChunkHandling: "strict" });
98204
98163
  };
98205
- var base642 = hasBase64Builtin2 ? {
98164
+ var base64 = hasBase64Builtin ? {
98206
98165
  encode(b) {
98207
98166
  abytes4(b);
98208
98167
  return b.toBase64();
98209
98168
  },
98210
98169
  decode(s2) {
98211
- return decodeBase64Builtin2(s2, false);
98170
+ return decodeBase64Builtin(s2, false);
98212
98171
  }
98213
- } : /* @__PURE__ */ chain2(/* @__PURE__ */ radix22(6), /* @__PURE__ */ alphabet2("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), /* @__PURE__ */ padding2(6), /* @__PURE__ */ join2(""));
98172
+ } : /* @__PURE__ */ chain2(/* @__PURE__ */ radix22(6), /* @__PURE__ */ alphabet2("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"), /* @__PURE__ */ padding(6), /* @__PURE__ */ join2(""));
98214
98173
  var genBase582 = /* @__NO_SIDE_EFFECTS__ */ (abc) => /* @__PURE__ */ chain2(/* @__PURE__ */ radix3(58), /* @__PURE__ */ alphabet2(abc), /* @__PURE__ */ join2(""));
98215
98174
  var base582 = /* @__PURE__ */ genBase582("123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz");
98216
98175
  var BECH_ALPHABET2 = /* @__PURE__ */ chain2(/* @__PURE__ */ alphabet2("qpzry9x8gf2tvdw0s3jn54khce6mua7l"), /* @__PURE__ */ join2(""));
@@ -100466,125 +100425,25 @@ a=end-of-candidates
100466
100425
  }
100467
100426
  return s2;
100468
100427
  }
100469
- function hexToHash(hex2) {
100470
- validateHex(hex2, true);
100471
- const hash3 = new Uint8Array(HASH_BYTE_LENGTH);
100472
- for (let i4 = 0; i4 < HASH_BYTE_LENGTH; i4++) {
100473
- hash3[i4] = Number.parseInt(hex2.substring(i4 * 2, i4 * 2 + 2), 16);
100474
- }
100475
- return hash3;
100476
- }
100477
- function bigIntToHex(value2, padded) {
100478
- const s2 = value2.toString(16);
100479
- return padded ? s2.padStart(HASH_HEX_LENGTH, "0") : s2;
100480
- }
100481
- function hexToBigInt(hex2, padded) {
100482
- validateHex(hex2, padded);
100483
- return BigInt(`0x${hex2}`);
100484
- }
100485
100428
  function hashesEqual(a2, b) {
100486
100429
  if (!isValidHash(a2) || !isValidHash(b))
100487
100430
  return false;
100488
100431
  return equalBytes(a2, b);
100489
100432
  }
100490
- function hashToBase64(hash3) {
100433
+ function hashToBase64Url(hash3) {
100491
100434
  validateHash(hash3);
100492
- return base64.encode(hash3);
100435
+ return base64urlnopad.encode(hash3);
100493
100436
  }
100494
- function base64ToHash(b64) {
100495
- const hash3 = base64.decode(b64);
100437
+ function base64UrlToHash(b64u) {
100438
+ const hash3 = base64urlnopad.decode(b64u);
100496
100439
  if (hash3.length !== HASH_BYTE_LENGTH) {
100497
- throw new RangeError(`Invalid base64 hash: expected ${HASH_BYTE_LENGTH} decoded bytes, got ${hash3.length}`);
100440
+ throw new RangeError(`Invalid base64url hash: expected ${HASH_BYTE_LENGTH} decoded bytes, got ${hash3.length}`);
100498
100441
  }
100499
100442
  return hash3;
100500
100443
  }
100501
- function bigIntToBase64(value2, padded) {
100502
- let bytes3 = bigIntToHash(value2);
100503
- if (!padded) {
100504
- const firstNonZero = bytes3.findIndex((b) => b !== 0);
100505
- bytes3 = firstNonZero === -1 ? new Uint8Array(1) : bytes3.slice(firstNonZero);
100506
- }
100507
- return base64.encode(bytes3);
100508
- }
100509
- function base64ToBigInt(b64, padded) {
100510
- const bytes3 = base64.decode(b64);
100511
- if (padded && bytes3.length !== HASH_BYTE_LENGTH) {
100512
- throw new RangeError(`Invalid padded base64 bigint: expected ${HASH_BYTE_LENGTH} decoded bytes, got ${bytes3.length}`);
100513
- }
100514
- if (bytes3.length > HASH_BYTE_LENGTH) {
100515
- throw new RangeError(`Value exceeds ${HASH_BYTE_LENGTH} bytes`);
100516
- }
100517
- let value2 = 0n;
100518
- for (const byte of bytes3) {
100519
- value2 = value2 << 8n | BigInt(byte);
100520
- }
100521
- return value2;
100522
- }
100523
- var HEX_RE = /^[0-9A-Fa-f]+$/;
100524
- function validateHex(s2, requireHashLength) {
100525
- const len = s2.length;
100526
- const minLen = requireHashLength ? HASH_HEX_LENGTH : 1;
100527
- if (len < minLen || len > HASH_HEX_LENGTH || !HEX_RE.test(s2)) {
100528
- throw new RangeError(`Invalid hex string: expected ${requireHashLength ? HASH_HEX_LENGTH : "1-" + HASH_HEX_LENGTH} hex characters, got ${len}`);
100529
- }
100530
- }
100531
100444
 
100532
100445
  // ../smt/dist/esm/node.js
100533
100446
  init_shim();
100534
- var BaseNode = class {
100535
- #index;
100536
- #depth;
100537
- constructor(index, depth) {
100538
- this.#index = index;
100539
- this.#depth = depth;
100540
- }
100541
- get index() {
100542
- return this.#index;
100543
- }
100544
- get depth() {
100545
- return this.#depth;
100546
- }
100547
- };
100548
- var LeafNode = class extends BaseNode {
100549
- #hash = null;
100550
- get hash() {
100551
- return this.#hash;
100552
- }
100553
- set hash(value2) {
100554
- if (this.#hash !== null) {
100555
- throw new RangeError("Leaf hash already set");
100556
- }
100557
- this.#hash = value2;
100558
- }
100559
- reset() {
100560
- this.#hash = null;
100561
- }
100562
- };
100563
- var ParentNode = class extends BaseNode {
100564
- #left;
100565
- #right;
100566
- constructor(index, depth, left, right) {
100567
- super(index, depth);
100568
- this.#left = left;
100569
- this.#right = right;
100570
- }
100571
- get left() {
100572
- return this.#left;
100573
- }
100574
- set left(node) {
100575
- this.#left = node;
100576
- }
100577
- get right() {
100578
- return this.#right;
100579
- }
100580
- set right(node) {
100581
- this.#right = node;
100582
- }
100583
- reset() {
100584
- this.#left.reset();
100585
- this.#right.reset();
100586
- }
100587
- };
100588
100447
 
100589
100448
  // ../smt/dist/esm/smt-proof.js
100590
100449
  init_shim();
@@ -100594,377 +100453,84 @@ a=end-of-candidates
100594
100453
  ValidationState2[ValidationState2["Valid"] = 1] = "Valid";
100595
100454
  ValidationState2[ValidationState2["Invalid"] = 2] = "Invalid";
100596
100455
  })(ValidationState || (ValidationState = {}));
100597
- var SMTProof = class _SMTProof {
100598
- #converge;
100599
- #hashes;
100600
- constructor(converge, hashes2) {
100601
- this.#converge = converge;
100602
- this.#hashes = hashes2;
100603
- }
100604
- /** Converge bitmap: bit `i` set means a sibling hash exists at depth `256 - i - 1`. */
100605
- get converge() {
100606
- return this.#converge;
100607
- }
100608
- /** Sibling hashes at converge points, ordered leaf-to-root. */
100609
- get hashes() {
100610
- return this.#hashes;
100611
- }
100612
- /**
100613
- * Verify this proof for a single leaf.
100614
- *
100615
- * @param index - Leaf index in the 256-bit key space.
100616
- * @param candidateHash - Expected leaf hash.
100617
- * @param rootHash - Expected root hash.
100618
- * @returns `true` if the proof is valid.
100619
- */
100620
- isValid(index, candidateHash, rootHash) {
100621
- return this.#validate(index, candidateHash, rootHash);
100622
- }
100623
- /**
100624
- * Batch-validate multiple proofs against the same root hash.
100625
- *
100626
- * Caches intermediate (partial) proofs so that subsequent candidates
100627
- * sharing an ancestor path can short-circuit once a cached match is found.
100628
- *
100629
- * @yields One {@link SMTProofResult} per candidate.
100630
- */
100631
- static *isValidBatch(candidates, rootHash) {
100632
- const cache4 = /* @__PURE__ */ new Map();
100633
- for (const candidate of candidates) {
100634
- const added = [];
100635
- const { index } = candidate;
100636
- const valid = candidate.proof.#validate(index | OUTER_BIT, candidate.hash, rootHash, (nodeIndex, partial) => {
100637
- const cached = cache4.get(nodeIndex);
100638
- if (cached === void 0) {
100639
- cache4.set(nodeIndex, partial);
100640
- added.push(nodeIndex);
100641
- return ValidationState.Pending;
100642
- }
100643
- if (hashesEqual(partial.hash, cached.hash) && partial.converge === cached.converge && partial.hashes.length === cached.hashes.length && partial.hashes.every((h, i4) => hashesEqual(h, cached.hashes[i4]))) {
100644
- return ValidationState.Valid;
100645
- }
100646
- return ValidationState.Invalid;
100647
- });
100648
- if (!valid) {
100649
- for (const key of added)
100650
- cache4.delete(key);
100651
- }
100652
- yield { index, valid, additional: candidate.additional };
100653
- }
100654
- }
100655
- /**
100656
- * Export to JSON.
100657
- * @param base64 - Use base64 encoding instead of hex (default: `false`).
100658
- * @param compact - Omit whitespace (default: `true`).
100659
- */
100660
- toJSON(base646 = false, compact = true) {
100661
- const convergeStr = base646 ? bigIntToBase64(this.#converge, false) : bigIntToHex(this.#converge, false);
100662
- const hashStrs = this.#hashes.map((h) => base646 ? hashToBase64(h) : hashToHex(h));
100663
- const obj = { converge: convergeStr, hashes: hashStrs };
100664
- return JSON.stringify(obj, null, compact ? 0 : 2);
100665
- }
100666
- /**
100667
- * Import from JSON.
100668
- * @param json - JSON string.
100669
- * @param base64 - Parse base64 instead of hex (default: `false`).
100670
- */
100671
- static fromJSON(json, base646 = false) {
100672
- const raw = JSON.parse(json);
100673
- if (typeof raw?.converge !== "string" || !Array.isArray(raw.hashes)) {
100674
- throw new RangeError("Invalid SMTProof JSON: expected { converge, hashes }");
100675
- }
100676
- const converge = base646 ? base64ToBigInt(raw.converge, false) : hexToBigInt(raw.converge, false);
100677
- const hashes2 = raw.hashes.map((h) => base646 ? base64ToHash(h) : hexToHash(h));
100678
- return new _SMTProof(converge, hashes2);
100679
- }
100680
- /**
100681
- * Export to compact binary format.
100682
- *
100683
- * Layout: `[convergeZeroCount : 1] [truncatedConverge : 32-zc] [hashCount : 1] [hashes : N*32]`
100684
- */
100685
- toBinary() {
100686
- const convergeBin = bigIntToHash(this.#converge);
100687
- let zc = 0;
100688
- while (zc < HASH_BYTE_LENGTH && convergeBin[zc] === 0)
100689
- zc++;
100690
- const truncated = convergeBin.slice(zc);
100691
- const hashCount = this.#hashes.length;
100692
- const totalBytes = 1 + truncated.length + 1 + hashCount * HASH_BYTE_LENGTH;
100693
- const out = new Uint8Array(totalBytes);
100694
- let pos = 0;
100695
- out[pos++] = zc;
100696
- out.set(truncated, pos);
100697
- pos += truncated.length;
100698
- out[pos++] = hashCount;
100699
- for (const h of this.#hashes) {
100700
- out.set(h, pos);
100701
- pos += HASH_BYTE_LENGTH;
100702
- }
100703
- return out;
100704
- }
100705
- /**
100706
- * Import from compact binary format.
100707
- * Accepts any sync or async byte iterable (e.g. `Uint8Array`, `ReadableStream`).
100708
- */
100709
- static async fromBinary(source) {
100710
- const iter = Symbol.iterator in source ? source[Symbol.iterator]() : source[Symbol.asyncIterator]();
100711
- async function readBytes(n2) {
100712
- const buf2 = new Uint8Array(n2);
100713
- for (let i4 = 0; i4 < n2; i4++) {
100714
- const r2 = await iter.next();
100715
- if (r2.done)
100716
- throw new Error("Unexpected end of binary source");
100717
- buf2[i4] = r2.value;
100718
- }
100719
- return buf2;
100720
- }
100721
- const zc = (await readBytes(1))[0];
100722
- const convergeBin = new Uint8Array(HASH_BYTE_LENGTH);
100723
- convergeBin.set(await readBytes(HASH_BYTE_LENGTH - zc), zc);
100724
- const hashCount = (await readBytes(1))[0];
100725
- const hashes2 = new Array(hashCount);
100726
- for (let i4 = 0; i4 < hashCount; i4++) {
100727
- hashes2[i4] = await readBytes(HASH_BYTE_LENGTH);
100728
- }
100729
- return new _SMTProof(hashToBigInt(convergeBin), hashes2);
100730
- }
100731
- #validate(index, candidateHash, rootHash, onMerge) {
100732
- let nodeIndex = index;
100733
- let nodeHash = candidateHash;
100734
- let remaining = this.#converge;
100735
- const hashes2 = this.#hashes;
100736
- let hi = 0;
100737
- const leftPad = [];
100738
- const rightPad = [];
100739
- const finalizePadding = () => {
100740
- if (leftPad.length > 0 || rightPad.length > 0) {
100741
- nodeHash = blockHash(new Uint8Array(leftPad), nodeHash, new Uint8Array(rightPad));
100742
- leftPad.length = 0;
100743
- rightPad.length = 0;
100744
- }
100745
- };
100746
- let state = ValidationState.Pending;
100747
- for (let i4 = 0; state === ValidationState.Pending && i4 < HASH_BIT_LENGTH; i4++) {
100748
- const isLeft = (nodeIndex & 1n) === 0n;
100749
- nodeIndex >>= 1n;
100750
- const bit = BITS[i4];
100751
- if ((remaining & bit) !== 0n) {
100752
- remaining ^= bit;
100753
- finalizePadding();
100754
- if (hi >= hashes2.length) {
100755
- state = ValidationState.Invalid;
100756
- } else {
100757
- const peer = hashes2[hi++];
100758
- nodeHash = isLeft ? blockHash(nodeHash, peer) : blockHash(peer, nodeHash);
100759
- if (onMerge !== void 0) {
100760
- state = onMerge(nodeIndex, {
100761
- hash: nodeHash,
100762
- converge: remaining,
100763
- hashes: hashes2.slice(hi)
100764
- });
100765
- }
100766
- }
100767
- } else {
100768
- const depth = HASH_BIT_LENGTH - i4 - 1;
100769
- if (isLeft) {
100770
- rightPad.push(depth);
100771
- } else {
100772
- leftPad.unshift(depth);
100773
- }
100774
- }
100775
- }
100776
- finalizePadding();
100777
- if (state === ValidationState.Pending) {
100778
- state = hi === hashes2.length && hashesEqual(nodeHash, rootHash) ? ValidationState.Valid : ValidationState.Invalid;
100779
- }
100780
- return state === ValidationState.Valid;
100781
- }
100782
- };
100783
100456
 
100784
100457
  // ../smt/dist/esm/optimized-smt.js
100785
100458
  init_shim();
100786
- var OptimizedSMT = class _OptimizedSMT {
100787
- /** `2^256` — sentinel bit above the key space. Used by batch validation. */
100788
- static OUTER_BIT = OUTER_BIT;
100789
- /** Pre-computed MSB-first bit masks for tree traversal. */
100790
- static BITS = BITS;
100791
- #allowNonInclusion;
100792
- #root = null;
100793
- #rootHash = null;
100794
- #proofs = /* @__PURE__ */ new Map();
100795
- constructor(allowNonInclusion) {
100796
- this.#allowNonInclusion = allowNonInclusion;
100797
- }
100798
- get allowNonInclusion() {
100799
- return this.#allowNonInclusion;
100800
- }
100801
- /** Root hash. Throws if tree has not been finalized. */
100802
- get rootHash() {
100803
- if (this.#rootHash === null)
100804
- throw new RangeError("SMT not finalized");
100805
- return this.#rootHash;
100459
+
100460
+ // ../smt/dist/esm/zero-hash.js
100461
+ init_shim();
100462
+ var TREE_DEPTH = HASH_BIT_LENGTH;
100463
+ function bitAt(index, position) {
100464
+ return Number(index >> BigInt(position) & 1n);
100465
+ }
100466
+ var CACHED_ZERO = (() => {
100467
+ const arr = new Array(TREE_DEPTH + 1);
100468
+ let z = new Uint8Array(HASH_BYTE_LENGTH);
100469
+ for (let h = 0; h <= TREE_DEPTH; h++) {
100470
+ z = blockHash(z, z);
100471
+ arr[h] = z;
100806
100472
  }
100807
- // -----------------------------------------------------------------------
100808
- // Build phase
100809
- // -----------------------------------------------------------------------
100810
- /**
100811
- * Add leaf indexes to the tree.
100812
- * May be called multiple times before finalization. Duplicate indexes throw.
100813
- */
100814
- add(indexes) {
100815
- this.#checkNotFinalized();
100816
- for (const index of indexes) {
100817
- if (index < 0n || index >= _OptimizedSMT.OUTER_BIT) {
100818
- throw new RangeError("Index out of range");
100819
- }
100820
- const leaf = new LeafNode(index, HASH_BIT_LENGTH);
100821
- if (this.#root === null) {
100822
- this.#root = leaf;
100473
+ return arr;
100474
+ })();
100475
+ function subtreeHash(leaves, height) {
100476
+ if (leaves.length === 0)
100477
+ return CACHED_ZERO[height];
100478
+ if (height === 0)
100479
+ return leaves[0].leaf;
100480
+ const bit = TREE_DEPTH - height;
100481
+ const left = [];
100482
+ const right = [];
100483
+ for (const e2 of leaves)
100484
+ (bitAt(e2.index, bit) === 0 ? left : right).push(e2);
100485
+ return blockHash(subtreeHash(left, height - 1), subtreeHash(right, height - 1));
100486
+ }
100487
+ function zeroHashRoot(leaves) {
100488
+ return subtreeHash(leaves, TREE_DEPTH);
100489
+ }
100490
+ function generateZeroHashProof(leaves, targetIndex) {
100491
+ let collapsed = 0n;
100492
+ const hashes2 = [];
100493
+ for (let height = 1; height <= TREE_DEPTH; height++) {
100494
+ const bit = TREE_DEPTH - height;
100495
+ const siblingLeaves = [];
100496
+ for (const e2 of leaves) {
100497
+ if (e2.index === targetIndex)
100823
100498
  continue;
100824
- }
100825
- let replaceNode = (node2) => {
100826
- this.#root = node2;
100827
- };
100828
- let node = this.#root;
100829
- let commonIndex = 0n;
100830
- let commonDepth = 0;
100831
- let done = false;
100832
- while (!done) {
100833
- const bit = BITS[commonDepth];
100834
- const indexBit = index & bit;
100835
- const isLeft = indexBit === 0n;
100836
- if (commonDepth === node.depth) {
100837
- if (node instanceof ParentNode) {
100838
- const parent = node;
100839
- if (isLeft) {
100840
- node = parent.left;
100841
- replaceNode = (n2) => {
100842
- parent.left = n2;
100843
- };
100844
- } else {
100845
- node = parent.right;
100846
- replaceNode = (n2) => {
100847
- parent.right = n2;
100848
- };
100849
- }
100850
- } else {
100851
- throw new RangeError("Duplicate index");
100852
- }
100853
- } else if ((node.index & bit) === indexBit) {
100854
- commonIndex |= indexBit;
100855
- commonDepth++;
100856
- } else {
100857
- replaceNode(new ParentNode(commonIndex, commonDepth, isLeft ? leaf : node, isLeft ? node : leaf));
100858
- done = true;
100499
+ let sharesLowerPath = true;
100500
+ for (let lower = 0; lower < bit; lower++) {
100501
+ if (bitAt(e2.index, lower) !== bitAt(targetIndex, lower)) {
100502
+ sharesLowerPath = false;
100503
+ break;
100859
100504
  }
100860
100505
  }
100506
+ if (sharesLowerPath && bitAt(e2.index, bit) !== bitAt(targetIndex, bit))
100507
+ siblingLeaves.push(e2);
100861
100508
  }
100862
- }
100863
- /**
100864
- * Set the hash for a leaf at the given index.
100865
- * The index must have been previously added via {@link add}.
100866
- * Each leaf's hash can only be set once (until {@link reset}).
100867
- */
100868
- setHash(index, hash3) {
100869
- this.#checkNotFinalized();
100870
- validateHash(hash3);
100871
- let node = this.#root;
100872
- if (node === null)
100873
- throw new RangeError("Empty SMT");
100874
- while (node instanceof ParentNode) {
100875
- node = (index & BITS[node.depth]) === 0n ? node.left : node.right;
100876
- }
100877
- if (node.index !== index)
100878
- throw new RangeError("Index not found");
100879
- node.hash = hash3;
100880
- }
100881
- // -----------------------------------------------------------------------
100882
- // Finalize phase
100883
- // -----------------------------------------------------------------------
100884
- /**
100885
- * Compute root hash and generate all proofs in a single recursive pass.
100886
- * Must be called after all hashes are set.
100887
- */
100888
- finalize() {
100889
- if (this.#root === null) {
100890
- this.#rootHash = NULL_HASH;
100891
- return;
100509
+ if (siblingLeaves.length === 0) {
100510
+ collapsed |= 1n << BigInt(bit);
100511
+ } else {
100512
+ hashes2.push(subtreeHash(siblingLeaves, height - 1));
100892
100513
  }
100893
- const result = this.#finalizeStep(this.#root, 0n, 0);
100894
- this.#rootHash = result.hash;
100895
- result.saveProofs([]);
100896
- }
100897
- /** Retrieve the proof for an index. Only valid after {@link finalize}. */
100898
- proof(index) {
100899
- const p2 = this.#proofs.get(index);
100900
- if (p2 === void 0)
100901
- throw new RangeError("Proof not found");
100902
- return p2;
100903
- }
100904
- /** Clear hashes and proofs, keeping the tree structure for reuse. */
100905
- reset() {
100906
- this.#root?.reset();
100907
- this.#rootHash = null;
100908
- this.#proofs.clear();
100909
- }
100910
- /**
100911
- * Check if the SMT has not been finalized yet.
100912
- * @throws {Error} If the SMT has already been finalized.
100913
- */
100914
- #checkNotFinalized() {
100915
- if (this.#rootHash !== null)
100916
- throw new Error("SMT already finalized");
100917
100514
  }
100918
- /**
100919
- * Perform a single step of finalization on the given node.
100920
- * @param {Node} node The node to finalize.
100921
- * @param {bigint} parentConverge The convergence value from the parent node.
100922
- * @param {number} depth The current depth in the tree.
100923
- * @returns {FinalizeStepResult} The result of the finalization step.
100924
- */
100925
- #finalizeStep(node, parentConverge, depth) {
100926
- const converge = parentConverge | BITS[HASH_BIT_LENGTH - depth];
100927
- let hash3;
100928
- let saveProofs;
100929
- if (node instanceof ParentNode) {
100930
- const childDepth = node.depth + 1;
100931
- const leftResult = this.#finalizeStep(node.left, converge, childDepth);
100932
- const rightResult = this.#finalizeStep(node.right, converge, childDepth);
100933
- hash3 = blockHash(leftResult.hash, rightResult.hash);
100934
- saveProofs = (hashes2) => {
100935
- const leftHashes = hashes2;
100936
- const rightHashes = hashes2.slice();
100937
- leftHashes.unshift(rightResult.hash);
100938
- rightHashes.unshift(leftResult.hash);
100939
- leftResult.saveProofs(leftHashes);
100940
- rightResult.saveProofs(rightHashes);
100941
- };
100515
+ return { collapsed, hashes: hashes2 };
100516
+ }
100517
+ function verifyZeroHash(collapsed, hashes2, index, candidate, root) {
100518
+ let acc = candidate;
100519
+ let hashPtr = 0;
100520
+ for (let n2 = 0; n2 < TREE_DEPTH; n2++) {
100521
+ const i4 = TREE_DEPTH - 1 - n2;
100522
+ let sibling;
100523
+ if ((collapsed >> BigInt(i4) & 1n) === 1n) {
100524
+ sibling = CACHED_ZERO[n2];
100942
100525
  } else {
100943
- if (node.hash === null) {
100944
- if (!this.#allowNonInclusion)
100945
- throw new RangeError("Hash missing");
100946
- node.hash = NULL_HASH;
100947
- }
100948
- hash3 = node.hash;
100949
- saveProofs = (hashes2) => {
100950
- this.#proofs.set(node.index, new SMTProof(converge, hashes2));
100951
- };
100952
- }
100953
- if (node.depth !== depth) {
100954
- const leftPad = [];
100955
- const rightPad = [];
100956
- for (let i4 = node.depth - 1; i4 >= depth; i4--) {
100957
- if ((node.index & BITS[i4]) === 0n) {
100958
- rightPad.push(i4);
100959
- } else {
100960
- leftPad.unshift(i4);
100961
- }
100962
- }
100963
- hash3 = blockHash(new Uint8Array(leftPad), hash3, new Uint8Array(rightPad));
100526
+ if (hashPtr >= hashes2.length)
100527
+ return false;
100528
+ sibling = hashes2[hashPtr++];
100964
100529
  }
100965
- return { hash: hash3, saveProofs };
100530
+ acc = bitAt(index, i4) === 1 ? blockHash(sibling, acc) : blockHash(acc, sibling);
100966
100531
  }
100967
- };
100532
+ return hashPtr === hashes2.length && hashesEqual(acc, root);
100533
+ }
100968
100534
 
100969
100535
  // ../smt/dist/esm/btcr2-leaf.js
100970
100536
  init_shim();
@@ -100981,51 +100547,53 @@ a=end-of-candidates
100981
100547
 
100982
100548
  // ../smt/dist/esm/btcr2-proof.js
100983
100549
  init_shim();
100984
- function serializeProof(proof, rootHash, options2) {
100550
+ function serializeProof(rootHash, proof, options2) {
100985
100551
  const result = {
100986
- id: hashToHex(rootHash),
100987
- collapsed: bigIntToHex(proof.converge, false),
100988
- hashes: proof.hashes.map((h) => hashToHex(h))
100552
+ id: hashToBase64Url(rootHash),
100553
+ collapsed: hashToBase64Url(bigIntToHash(proof.collapsed)),
100554
+ hashes: proof.hashes.map((h) => hashToBase64Url(h))
100989
100555
  };
100990
100556
  if (options2?.nonce)
100991
- result.nonce = hashToHex(options2.nonce);
100557
+ result.nonce = hashToBase64Url(options2.nonce);
100992
100558
  if (options2?.updateId)
100993
- result.updateId = hashToHex(options2.updateId);
100559
+ result.updateId = hashToBase64Url(options2.updateId);
100994
100560
  return result;
100995
100561
  }
100996
100562
  function deserializeProof(serialized) {
100997
- const converge = hexToBigInt(serialized.collapsed, false);
100998
- const hashes2 = serialized.hashes.map((h) => hexToHash(h));
100999
100563
  const result = {
101000
- proof: new SMTProof(converge, hashes2),
101001
- rootHash: hexToHash(serialized.id)
100564
+ rootHash: base64UrlToHash(serialized.id),
100565
+ collapsed: hashToBigInt(base64UrlToHash(serialized.collapsed)),
100566
+ hashes: serialized.hashes.map((h) => base64UrlToHash(h))
101002
100567
  };
101003
100568
  if (serialized.nonce)
101004
- result.nonce = hexToHash(serialized.nonce);
100569
+ result.nonce = base64UrlToHash(serialized.nonce);
101005
100570
  if (serialized.updateId)
101006
- result.updateId = hexToHash(serialized.updateId);
100571
+ result.updateId = base64UrlToHash(serialized.updateId);
101007
100572
  return result;
101008
100573
  }
101009
100574
  function verifySerializedProof(serialized, index, candidateHash) {
101010
- const { proof, rootHash } = deserializeProof(serialized);
101011
- return proof.isValid(index, candidateHash, rootHash);
100575
+ const { rootHash, collapsed, hashes: hashes2 } = deserializeProof(serialized);
100576
+ return verifyZeroHash(collapsed, hashes2, index, candidateHash, rootHash);
101012
100577
  }
101013
100578
 
101014
100579
  // ../smt/dist/esm/btcr2-tree.js
101015
100580
  init_shim();
101016
100581
  var BTCR2MerkleTree = class {
101017
- #smt;
101018
100582
  #entries = /* @__PURE__ */ new Map();
101019
100583
  #indexByDid = /* @__PURE__ */ new Map();
101020
- constructor(allowNonInclusion = true) {
101021
- this.#smt = new OptimizedSMT(allowNonInclusion);
100584
+ #leaves = null;
100585
+ #root = null;
100586
+ /**
100587
+ * @param _allowNonInclusion Retained for API compatibility; non-inclusion
100588
+ * leaves are always supported (an entry without `signedUpdate`).
100589
+ */
100590
+ constructor(_allowNonInclusion = true) {
101022
100591
  }
101023
100592
  /**
101024
100593
  * Add entries to the tree. May be called multiple times before
101025
100594
  * {@link finalize}. Duplicate DIDs (same index) throw.
101026
100595
  */
101027
100596
  addEntries(entries) {
101028
- const indexes = [];
101029
100597
  for (const entry of entries) {
101030
100598
  const index = didToIndex(entry.did);
101031
100599
  if (this.#entries.has(index)) {
@@ -101033,24 +100601,28 @@ a=end-of-candidates
101033
100601
  }
101034
100602
  this.#entries.set(index, entry);
101035
100603
  this.#indexByDid.set(entry.did, index);
101036
- indexes.push(index);
101037
100604
  }
101038
- this.#smt.add(indexes);
100605
+ this.#leaves = null;
100606
+ this.#root = null;
101039
100607
  }
101040
100608
  /**
101041
- * Compute leaf hashes and finalize the tree.
100609
+ * Compute leaf hashes and the zero-hash root.
101042
100610
  * After this call, {@link rootHash} and {@link proof} become available.
101043
100611
  */
101044
100612
  finalize() {
100613
+ const leaves = [];
101045
100614
  for (const [index, entry] of this.#entries) {
101046
- const leafHash = entry.signedUpdate !== void 0 ? inclusionLeafHash(entry.nonce, entry.signedUpdate) : nonInclusionLeafHash(entry.nonce);
101047
- this.#smt.setHash(index, leafHash);
100615
+ const leaf = entry.signedUpdate !== void 0 ? inclusionLeafHash(entry.nonce, entry.signedUpdate) : nonInclusionLeafHash(entry.nonce);
100616
+ leaves.push({ index, leaf });
101048
100617
  }
101049
- this.#smt.finalize();
100618
+ this.#leaves = leaves;
100619
+ this.#root = zeroHashRoot(leaves);
101050
100620
  }
101051
100621
  /** Root hash of the finalized tree. Throws if not finalized. */
101052
100622
  get rootHash() {
101053
- return this.#smt.rootHash;
100623
+ if (this.#root === null)
100624
+ throw new Error("Tree not finalized: call finalize() first");
100625
+ return this.#root;
101054
100626
  }
101055
100627
  /**
101056
100628
  * Get the did:btcr2 serialized proof for a DID.
@@ -101060,14 +100632,18 @@ a=end-of-candidates
101060
100632
  const index = this.#indexByDid.get(did);
101061
100633
  if (index === void 0)
101062
100634
  throw new RangeError(`DID not in tree: ${did}`);
100635
+ if (this.#leaves === null || this.#root === null) {
100636
+ throw new Error("Tree not finalized: call finalize() first");
100637
+ }
101063
100638
  const entry = this.#entries.get(index);
101064
- const smtProof = this.#smt.proof(index);
100639
+ const proof = generateZeroHashProof(this.#leaves, index);
101065
100640
  const updateId = entry.signedUpdate !== void 0 ? blockHash(entry.signedUpdate) : void 0;
101066
- return serializeProof(smtProof, this.#smt.rootHash, { nonce: entry.nonce, updateId });
100641
+ return serializeProof(this.#root, proof, { nonce: entry.nonce, updateId });
101067
100642
  }
101068
- /** Clear hashes and proofs, keeping tree structure. Entries are preserved. */
100643
+ /** Clear computed leaves and root, keeping entries. */
101069
100644
  reset() {
101070
- this.#smt.reset();
100645
+ this.#leaves = null;
100646
+ this.#root = null;
101071
100647
  }
101072
100648
  };
101073
100649
 
@@ -101102,12 +100678,12 @@ a=end-of-candidates
101102
100678
  const smtProof = body.smtProof;
101103
100679
  if (!smtProof?.updateId || !smtProof?.nonce) return { matches: false };
101104
100680
  const canonicalBytes = new TextEncoder().encode(canonicalize2(submittedUpdate));
101105
- const expectedUpdateId = hashToHex(blockHash(canonicalBytes));
100681
+ const expectedUpdateId = hashToBase64Url(blockHash(canonicalBytes));
101106
100682
  if (smtProof.updateId !== expectedUpdateId) {
101107
100683
  return { matches: false, smtProof };
101108
100684
  }
101109
100685
  const index = didToIndex(participantDid);
101110
- const candidateHash = blockHash(blockHash(hexToHash(smtProof.nonce)), hexToHash(smtProof.updateId));
100686
+ const candidateHash = blockHash(blockHash(base64UrlToHash(smtProof.nonce)), base64UrlToHash(smtProof.updateId));
101111
100687
  return {
101112
100688
  matches: verifySerializedProof(smtProof, index, candidateHash),
101113
100689
  smtProof
@@ -108444,8 +108020,8 @@ ${value2}`;
108444
108020
  let iv = Uint8Array.from(randomBytes2(16));
108445
108021
  let plaintext = utf8Encoder.encode(text);
108446
108022
  let ciphertext = cbc(normalizedKey, iv).encrypt(plaintext);
108447
- let ctb64 = base642.encode(new Uint8Array(ciphertext));
108448
- let ivb64 = base642.encode(new Uint8Array(iv.buffer));
108023
+ let ctb64 = base64.encode(new Uint8Array(ciphertext));
108024
+ let ivb64 = base64.encode(new Uint8Array(iv.buffer));
108449
108025
  return `${ctb64}?iv=${ivb64}`;
108450
108026
  }
108451
108027
  function decrypt2(secretKey, pubkey, data) {
@@ -108453,8 +108029,8 @@ ${value2}`;
108453
108029
  let [ctb64, ivb64] = data.split("?iv=");
108454
108030
  let key = secp256k1.getSharedSecret(privkey, hexToBytes2("02" + pubkey));
108455
108031
  let normalizedKey = getNormalizedX(key);
108456
- let iv = base642.decode(ivb64);
108457
- let ciphertext = base642.decode(ctb64);
108032
+ let iv = base64.decode(ivb64);
108033
+ let ciphertext = base64.decode(ctb64);
108458
108034
  let plaintext = cbc(normalizedKey, iv).decrypt(ciphertext);
108459
108035
  return utf8Decoder.decode(plaintext);
108460
108036
  }
@@ -108774,7 +108350,7 @@ ${value2}`;
108774
108350
  throw new Error("unknown encryption version");
108775
108351
  let data;
108776
108352
  try {
108777
- data = base642.decode(payload);
108353
+ data = base64.decode(payload);
108778
108354
  } catch (error) {
108779
108355
  throw new Error("invalid base64: " + error.message);
108780
108356
  }
@@ -108795,7 +108371,7 @@ ${value2}`;
108795
108371
  const padded = pad(plaintext);
108796
108372
  const ciphertext = chacha20(chacha_key, chacha_nonce, padded);
108797
108373
  const mac = hmacAad(hmac_key, ciphertext, nonce);
108798
- return base642.encode(concatBytes2(new Uint8Array([2]), nonce, ciphertext, mac));
108374
+ return base64.encode(concatBytes2(new Uint8Array([2]), nonce, ciphertext, mac));
108799
108375
  }
108800
108376
  function decrypt22(payload, conversationKey) {
108801
108377
  const { nonce, ciphertext, mac } = decodePayload(payload);
@@ -110070,7 +109646,7 @@ ${value2}`;
110070
109646
  }
110071
109647
  const signedEvent = await sign(event);
110072
109648
  const authorizationScheme = includeAuthorizationScheme ? _authorizationScheme : "";
110073
- return authorizationScheme + base642.encode(utf8Encoder.encode(JSON.stringify(signedEvent)));
109649
+ return authorizationScheme + base64.encode(utf8Encoder.encode(JSON.stringify(signedEvent)));
110074
109650
  }
110075
109651
  async function validateToken(token, url, method) {
110076
109652
  const event = await unpackEventFromToken(token).catch((error) => {
@@ -110086,7 +109662,7 @@ ${value2}`;
110086
109662
  throw new Error("Missing token");
110087
109663
  }
110088
109664
  token = token.replace(_authorizationScheme, "");
110089
- const eventB64 = utf8Decoder.decode(base642.decode(token));
109665
+ const eventB64 = utf8Decoder.decode(base64.decode(token));
110090
109666
  if (!eventB64 || eventB64.length === 0 || !eventB64.startsWith("{")) {
110091
109667
  throw new Error("Invalid token");
110092
109668
  }
@@ -111553,6 +111129,120 @@ ${value2}`;
111553
111129
  }
111554
111130
  };
111555
111131
 
111132
+ // src/core/aggregation/transport/in-memory.ts
111133
+ init_shim();
111134
+ init_utils();
111135
+ var InMemoryBus = class {
111136
+ #transports = /* @__PURE__ */ new Set();
111137
+ /** Attach a transport to this bus. Called by the transport's constructor. */
111138
+ register(transport) {
111139
+ this.#transports.add(transport);
111140
+ }
111141
+ /** Detach a transport from this bus. */
111142
+ unregister(transport) {
111143
+ this.#transports.delete(transport);
111144
+ }
111145
+ /**
111146
+ * Deliver a message. With no `recipient` the message is broadcast to every
111147
+ * actor on the bus; otherwise it is routed to the single transport that owns
111148
+ * the recipient DID.
111149
+ */
111150
+ async deliver(message2, _sender, recipient) {
111151
+ const type = message2.type;
111152
+ if (!type) return;
111153
+ const replacer = (_k, v) => v instanceof Uint8Array ? { __bytes: bytesToHex(v) } : v;
111154
+ const reviver = (_k, v) => v && typeof v === "object" && "__bytes" in v ? hexToBytes(v.__bytes) : v;
111155
+ const raw = JSON.parse(JSON.stringify(message2, replacer), reviver);
111156
+ const serialized = { ...raw, ...raw.body ?? {} };
111157
+ if (!recipient) {
111158
+ for (const t2 of this.#transports) {
111159
+ await t2.dispatchBroadcast(type, serialized);
111160
+ }
111161
+ return;
111162
+ }
111163
+ for (const t2 of this.#transports) {
111164
+ if (t2.hasActor(recipient)) {
111165
+ await t2.dispatchDirected(recipient, type, serialized);
111166
+ return;
111167
+ }
111168
+ }
111169
+ }
111170
+ };
111171
+ var InMemoryTransport = class {
111172
+ name = "in-memory";
111173
+ bus;
111174
+ #actors = /* @__PURE__ */ new Map();
111175
+ #peers = /* @__PURE__ */ new Map();
111176
+ /** @param bus Shared bus. Pass the same bus to connect multiple transports. */
111177
+ constructor(bus = new InMemoryBus()) {
111178
+ this.bus = bus;
111179
+ this.bus.register(this);
111180
+ }
111181
+ start() {
111182
+ }
111183
+ registerActor(did, keys) {
111184
+ this.#actors.set(did, { keys, handlers: /* @__PURE__ */ new Map() });
111185
+ }
111186
+ getActorPk(did) {
111187
+ return this.#actors.get(did)?.keys.publicKey.compressed;
111188
+ }
111189
+ /** True if `did` is registered on this transport. Used by the bus for routing. */
111190
+ hasActor(did) {
111191
+ return this.#actors.has(did);
111192
+ }
111193
+ registerPeer(did, communicationPk) {
111194
+ this.#peers.set(did, communicationPk);
111195
+ }
111196
+ getPeerPk(did) {
111197
+ return this.#peers.get(did);
111198
+ }
111199
+ registerMessageHandler(actorDid, messageType, handler) {
111200
+ const actor = this.#actors.get(actorDid);
111201
+ if (actor) actor.handlers.set(messageType, handler);
111202
+ }
111203
+ unregisterMessageHandler(actorDid, messageType) {
111204
+ const actor = this.#actors.get(actorDid);
111205
+ if (actor) actor.handlers.delete(messageType);
111206
+ }
111207
+ unregisterActor(did) {
111208
+ const actor = this.#actors.get(did);
111209
+ if (!actor) return;
111210
+ actor.handlers.clear();
111211
+ this.#actors.delete(did);
111212
+ this.#peers.delete(did);
111213
+ }
111214
+ async sendMessage(message2, sender, recipient) {
111215
+ await this.bus.deliver(message2, sender, recipient);
111216
+ }
111217
+ publishRepeating(message2, sender, intervalMs, recipient) {
111218
+ let stopped = false;
111219
+ void this.sendMessage(message2, sender, recipient).catch(() => {
111220
+ });
111221
+ const timer = setInterval(() => {
111222
+ if (stopped) return;
111223
+ void this.sendMessage(message2, sender, recipient).catch(() => {
111224
+ });
111225
+ }, intervalMs);
111226
+ return () => {
111227
+ if (stopped) return;
111228
+ stopped = true;
111229
+ clearInterval(timer);
111230
+ };
111231
+ }
111232
+ /** Deliver a broadcast message to every actor on this transport that handles `type`. */
111233
+ async dispatchBroadcast(type, message2) {
111234
+ for (const actor of this.#actors.values()) {
111235
+ const handler = actor.handlers.get(type);
111236
+ if (handler) await handler(message2);
111237
+ }
111238
+ }
111239
+ /** Deliver a directed message to the recipient actor's handler for `type`. */
111240
+ async dispatchDirected(recipientDid, type, message2) {
111241
+ const handler = this.#actors.get(recipientDid)?.handlers.get(type);
111242
+ if (handler) await handler(message2);
111243
+ }
111244
+ };
111245
+
111556
111246
  // src/core/aggregation/transport/didcomm.ts
111557
111247
  init_shim();
111558
111248
  var DidCommTransport = class {
@@ -112293,6 +111983,63 @@ ${value2}`;
112293
111983
  }
112294
111984
  };
112295
111985
 
111986
+ // src/core/aggregation/runner/aggregation-runner.ts
111987
+ init_shim();
111988
+ var AggregationRunner = class {
111989
+ /**
111990
+ * Run a cohort of ONE participant entirely in-process and return the
111991
+ * aggregated MuSig2 result.
111992
+ *
111993
+ * One party plays both the coordinating service and the lone participant,
111994
+ * connected over an {@link InMemoryTransport} (no relay or HTTP server). This
111995
+ * makes the single-participant aggregate-beacon path — the N=1 corner of the
111996
+ * two-axis beacon matrix (see ADR 037) — first-class, useful for generating
111997
+ * and reproducing single-participant aggregate test vectors.
111998
+ *
111999
+ * The service advertises a cohort with `minParticipants: 1`; the participant
112000
+ * joins, submits its update, and the two complete keygen, data distribution,
112001
+ * validation, and a one-signer MuSig2 P2TR key-path signing round.
112002
+ *
112003
+ * @param options Service + participant identities, cohort config, and the
112004
+ * update / tx-data callbacks.
112005
+ * @returns The {@link AggregationResult} (cohort id, aggregated signature, signed tx).
112006
+ */
112007
+ static async solo(options2) {
112008
+ const transport = new InMemoryTransport(new InMemoryBus());
112009
+ transport.registerActor(options2.service.did, options2.service.keys);
112010
+ transport.registerActor(options2.participant.did, options2.participant.keys);
112011
+ transport.registerPeer(options2.participant.did, options2.participant.keys.publicKey.compressed);
112012
+ transport.registerPeer(options2.service.did, options2.service.keys.publicKey.compressed);
112013
+ transport.start();
112014
+ const service = new AggregationServiceRunner({
112015
+ transport,
112016
+ did: options2.service.did,
112017
+ keys: options2.service.keys,
112018
+ config: { minParticipants: 1, network: options2.config.network, beaconType: options2.config.beaconType },
112019
+ onProvideTxData: options2.onProvideTxData,
112020
+ cohortTtlMs: options2.cohortTtlMs,
112021
+ phaseTimeoutMs: options2.phaseTimeoutMs,
112022
+ // In-process bus with the participant already listening: a single advert
112023
+ // suffices, so disable the republish loop (no dangling interval).
112024
+ advertRepeatIntervalMs: 0
112025
+ });
112026
+ const participant = new AggregationParticipantRunner({
112027
+ transport,
112028
+ did: options2.participant.did,
112029
+ keys: options2.participant.keys,
112030
+ shouldJoin: async () => true,
112031
+ onProvideUpdate: options2.onProvideUpdate
112032
+ });
112033
+ await participant.start();
112034
+ try {
112035
+ return await service.run();
112036
+ } finally {
112037
+ participant.stop();
112038
+ service.stop();
112039
+ }
112040
+ }
112041
+ };
112042
+
112296
112043
  // src/core/beacon/beacon.ts
112297
112044
  init_shim();
112298
112045
  init_utils();
@@ -112463,7 +112210,7 @@ ${value2}`;
112463
112210
  tx.finalize();
112464
112211
  return tx.hex;
112465
112212
  }
112466
- var Beacon = class {
112213
+ var SinglePartyBeacon = class {
112467
112214
  /**
112468
112215
  * The Beacon service configuration parsed from the DID Document.
112469
112216
  */
@@ -112600,7 +112347,7 @@ ${value2}`;
112600
112347
 
112601
112348
  // src/core/beacon/cas-beacon.ts
112602
112349
  init_shim();
112603
- var CASBeacon = class extends Beacon {
112350
+ var CASBeacon = class extends SinglePartyBeacon {
112604
112351
  /**
112605
112352
  * Creates an instance of CASBeacon.
112606
112353
  * @param {BeaconService} service The service of the Beacon.
@@ -112660,7 +112407,7 @@ ${value2}`;
112660
112407
  * Creates a CAS Announcement mapping the DID to the update hash, broadcasts the hash of the
112661
112408
  * announcement via OP_RETURN, and optionally publishes the announcement off-chain via the
112662
112409
  * supplied `casPublish` callback. UTXO selection, PSBT construction, fee estimation, signing,
112663
- * and broadcast are delegated to {@link Beacon.buildSignAndBroadcast}.
112410
+ * and broadcast are delegated to {@link SinglePartyBeacon.buildSignAndBroadcast}.
112664
112411
  *
112665
112412
  * @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
112666
112413
  * @param {Signer} signer Signer that produces the ECDSA signature for the Bitcoin transaction.
@@ -112688,7 +112435,7 @@ ${value2}`;
112688
112435
 
112689
112436
  // src/core/beacon/singleton-beacon.ts
112690
112437
  init_shim();
112691
- var SingletonBeacon = class extends Beacon {
112438
+ var SingletonBeacon = class extends SinglePartyBeacon {
112692
112439
  /**
112693
112440
  * Creates an instance of SingletonBeacon.
112694
112441
  * @param {BeaconService} service The BeaconService object representing the funded beacon to announce the update to.
@@ -112725,7 +112472,7 @@ ${value2}`;
112725
112472
  *
112726
112473
  * The signal bytes embedded in OP_RETURN are the SHA-256 canonical hash of the signed update.
112727
112474
  * UTXO selection, PSBT construction, fee estimation, signing, and broadcast are delegated to
112728
- * {@link Beacon.buildSignAndBroadcast}.
112475
+ * {@link SinglePartyBeacon.buildSignAndBroadcast}.
112729
112476
  *
112730
112477
  * @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
112731
112478
  * @param {Signer} signer Signer that produces the ECDSA signature for the Bitcoin transaction.
@@ -112744,7 +112491,7 @@ ${value2}`;
112744
112491
  // src/core/beacon/smt-beacon.ts
112745
112492
  init_shim();
112746
112493
  init_utils();
112747
- var SMTBeacon = class extends Beacon {
112494
+ var SMTBeacon = class extends SinglePartyBeacon {
112748
112495
  /**
112749
112496
  * Creates an instance of SMTBeacon.
112750
112497
  * @param {BeaconService} service The Beacon service.
@@ -112779,9 +112526,6 @@ ${value2}`;
112779
112526
  });
112780
112527
  continue;
112781
112528
  }
112782
- if (!smtProof.updateId) {
112783
- continue;
112784
- }
112785
112529
  if (!smtProof.nonce) {
112786
112530
  throw new SMTBeaconError(
112787
112531
  "SMT proof missing required nonce field.",
@@ -112790,7 +112534,8 @@ ${value2}`;
112790
112534
  );
112791
112535
  }
112792
112536
  const index = didToIndex(did);
112793
- const candidateHash = blockHash(blockHash(hexToHash(smtProof.nonce)), hexToHash(smtProof.updateId));
112537
+ const nonceHash2 = base64UrlToHash(smtProof.nonce);
112538
+ const candidateHash = smtProof.updateId ? blockHash(blockHash(nonceHash2), base64UrlToHash(smtProof.updateId)) : blockHash(blockHash(nonceHash2));
112794
112539
  const valid = verifySerializedProof(smtProof, index, candidateHash);
112795
112540
  if (!valid) {
112796
112541
  throw new SMTBeaconError(
@@ -112799,11 +112544,15 @@ ${value2}`;
112799
112544
  { smtProof, did }
112800
112545
  );
112801
112546
  }
112802
- const signedUpdate = sidecar.updateMap.get(smtProof.updateId);
112547
+ if (!smtProof.updateId) {
112548
+ continue;
112549
+ }
112550
+ const updateHashHex = hashToHex(base64UrlToHash(smtProof.updateId));
112551
+ const signedUpdate = sidecar.updateMap.get(updateHashHex);
112803
112552
  if (!signedUpdate) {
112804
112553
  needs.push({
112805
112554
  kind: "NeedSignedUpdate",
112806
- updateHash: smtProof.updateId,
112555
+ updateHash: updateHashHex,
112807
112556
  beaconServiceId: this.service.id
112808
112557
  });
112809
112558
  continue;
@@ -112818,7 +112567,7 @@ ${value2}`;
112818
112567
  * Builds a single-entry Sparse Merkle Tree from the signed update, then broadcasts the tree's
112819
112568
  * root hash via OP_RETURN. For multi-party aggregation, use the {@link AggregationService}
112820
112569
  * subsystem directly instead of this method. UTXO selection, PSBT construction, fee estimation,
112821
- * signing, and broadcast are delegated to {@link Beacon.buildSignAndBroadcast}.
112570
+ * signing, and broadcast are delegated to {@link SinglePartyBeacon.buildSignAndBroadcast}.
112822
112571
  *
112823
112572
  * @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
112824
112573
  * @param {Signer} signer Signer that produces the ECDSA signature for the Bitcoin transaction.
@@ -112844,7 +112593,7 @@ ${value2}`;
112844
112593
  /**
112845
112594
  * Establish a Beacon instance based on the provided service and optional sidecar data.
112846
112595
  * @param {BeaconService} service The beacon service configuration.
112847
- * @returns {Beacon} The established Beacon instance.
112596
+ * @returns {SinglePartyBeacon} The established Beacon instance.
112848
112597
  */
112849
112598
  static establish(service) {
112850
112599
  switch (service.type) {
@@ -128993,7 +128742,7 @@ ${value2}`;
128993
128742
  const smtMap = /* @__PURE__ */ new Map();
128994
128743
  if (sidecar.smtProofs?.length)
128995
128744
  for (const proof of sidecar.smtProofs) {
128996
- smtMap.set(proof.id, proof);
128745
+ smtMap.set(encode(decode(proof.id, "base64urlnopad"), "hex"), proof);
128997
128746
  }
128998
128747
  return { updateMap, casMap, smtMap };
128999
128748
  }
@@ -129281,11 +129030,12 @@ ${value2}`;
129281
129030
  case "NeedSMTProof": {
129282
129031
  const smtNeed = need;
129283
129032
  const proof = data;
129284
- if (proof.id !== smtNeed.smtRootHash) {
129033
+ const proofIdHex = encode(decode(proof.id, "base64urlnopad"), "hex");
129034
+ if (proofIdHex !== smtNeed.smtRootHash) {
129285
129035
  throw new ResolveError(
129286
- `SMT proof root hash mismatch: expected ${smtNeed.smtRootHash}, got ${proof.id}`,
129036
+ `SMT proof root hash mismatch: expected ${smtNeed.smtRootHash}, got ${proofIdHex}`,
129287
129037
  INVALID_DID_UPDATE,
129288
- { expected: smtNeed.smtRootHash, actual: proof.id }
129038
+ { expected: smtNeed.smtRootHash, actual: proofIdHex }
129289
129039
  );
129290
129040
  }
129291
129041
  this.#sidecarData.smtMap.set(smtNeed.smtRootHash, proof);