@did-btcr2/method 0.62.0 → 0.63.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/cjs/index.js CHANGED
@@ -1814,6 +1814,7 @@ var BeaconSignalDiscovery = class _BeaconSignalDiscovery {
1814
1814
  static async indexer(beaconServices, bitcoin) {
1815
1815
  const beaconServiceSignals = /* @__PURE__ */ new Map();
1816
1816
  const currentBlockCount = await bitcoin.rest.block.count();
1817
+ const mediantimes = /* @__PURE__ */ new Map();
1817
1818
  for (const beaconService of beaconServices) {
1818
1819
  beaconServiceSignals.set(beaconService, []);
1819
1820
  const beaconAddress = BeaconUtils.parseBitcoinAddress(beaconService.serviceEndpoint);
@@ -1838,19 +1839,49 @@ var BeaconSignalDiscovery = class _BeaconSignalDiscovery {
1838
1839
  continue;
1839
1840
  }
1840
1841
  const confirmations = currentBlockCount - status.block_height + 1;
1842
+ const mediantime = await _BeaconSignalDiscovery.mediantime(status.block_hash, bitcoin, mediantimes);
1841
1843
  beaconServiceSignals.get(beaconService)?.push({
1842
1844
  tx: beaconSignal,
1843
1845
  signalBytes: updateHash,
1844
1846
  blockMetadata: {
1845
1847
  confirmations,
1846
1848
  height: status.block_height,
1847
- time: status.block_time
1849
+ time: status.block_time,
1850
+ mediantime
1848
1851
  }
1849
1852
  });
1850
1853
  }
1851
1854
  }
1852
1855
  return beaconServiceSignals;
1853
1856
  }
1857
+ /**
1858
+ * Return the median time past of a block, from the per-run cache or from the
1859
+ * Esplora block record (`GET /block/:hash`). The specification compares
1860
+ * `versionTime` with the block `mediantime`, and the address listing does not
1861
+ * carry it. One block record serves every signal in that block.
1862
+ * @param {string} blockhash The hash of the block that contains a signal.
1863
+ * @param {BitcoinConnection} bitcoin Bitcoin network connection to use for REST calls.
1864
+ * @param {Map<string, number>} cache The median time past values fetched so far, keyed by block hash.
1865
+ * @returns {Promise<number>} The median time past of the block, in Unix seconds.
1866
+ * @throws {ResolveError} `INTERNAL_ERROR` if the backend returns no block record or no `mediantime` for the hash.
1867
+ */
1868
+ static async mediantime(blockhash, bitcoin, cache) {
1869
+ const cached = cache.get(blockhash);
1870
+ if (cached !== void 0) {
1871
+ return cached;
1872
+ }
1873
+ const block = await bitcoin.rest.block.get({ blockhash });
1874
+ const mediantime = block?.mediantime;
1875
+ if (typeof mediantime !== "number" || !Number.isFinite(mediantime)) {
1876
+ throw new import_common10.ResolveError(
1877
+ `Block ${blockhash} has no mediantime in the block record of the Bitcoin REST backend.`,
1878
+ import_common10.INTERNAL_ERROR,
1879
+ { blockhash, block }
1880
+ );
1881
+ }
1882
+ cache.set(blockhash, mediantime);
1883
+ return mediantime;
1884
+ }
1854
1885
  /**
1855
1886
  * Traverse the full blockchain from genesis to chain top looking for beacon signals.
1856
1887
  * @param {Array<BeaconService>} beaconServices Array of BeaconService objects to search for signals.
@@ -1920,6 +1951,7 @@ var BeaconSignalDiscovery = class _BeaconSignalDiscovery {
1920
1951
  blockMetadata: {
1921
1952
  height: block.height,
1922
1953
  time: block.time,
1954
+ mediantime: block.mediantime,
1923
1955
  confirmations: block.confirmations
1924
1956
  }
1925
1957
  });
@@ -2439,17 +2471,46 @@ function isSMTProof(value) {
2439
2471
  function validateMinConf(value) {
2440
2472
  if (value === void 0) return DEFAULT_MIN_CONF;
2441
2473
  if (typeof value === "number" && Number.isInteger(value) && value >= 1) return value;
2442
- const shown = typeof value === "string" ? JSON.stringify(value) : String(value);
2443
2474
  throw new import_common13.ResolveError(
2444
- `Invalid resolution option minConf: expected a positive integer (minimum 1), got ${shown}.`,
2475
+ `Invalid resolution option minConf: expected a positive integer (minimum 1), got ${shown(value)}.`,
2445
2476
  import_common13.INVALID_OPTIONS,
2446
2477
  { minConf: value }
2447
2478
  );
2448
2479
  }
2480
+ function shown(value) {
2481
+ return typeof value === "string" ? JSON.stringify(value) : String(value);
2482
+ }
2483
+ var ASCII_INTEGER = /^-?[0-9]+$/;
2484
+ function validateVersionId(value) {
2485
+ if (value === void 0) return void 0;
2486
+ if (typeof value === "string" && ASCII_INTEGER.test(value) && Number.isSafeInteger(Number(value))) {
2487
+ return Number(value);
2488
+ }
2489
+ throw new import_common13.ResolveError(
2490
+ `Invalid resolution option versionId: expected an ASCII string of an integer, got ${shown(value)}.`,
2491
+ import_common13.INVALID_OPTIONS,
2492
+ { versionId: value }
2493
+ );
2494
+ }
2495
+ var UTC_XSD_DATETIME = /^-?\d{4,}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$/;
2496
+ function validateVersionTime(value) {
2497
+ if (value === void 0) return void 0;
2498
+ if (typeof value === "string" && UTC_XSD_DATETIME.test(value) && import_common13.DateUtils.isValidXsdDateTime(value)) {
2499
+ const ms = Date.parse(value);
2500
+ if (Number.isFinite(ms)) return ms;
2501
+ }
2502
+ throw new import_common13.ResolveError(
2503
+ `Invalid resolution option versionTime: expected an XML Datetime in UTC without a fraction (for example "2026-07-01T00:00:00Z"), got ${shown(value)}.`,
2504
+ import_common13.INVALID_OPTIONS,
2505
+ { versionTime: value }
2506
+ );
2507
+ }
2449
2508
  var Resolver = class _Resolver {
2450
2509
  // --- Immutable inputs ---
2451
2510
  #didComponents;
2511
+ /** The parsed `ResolutionOptions.versionId`, or `undefined` when the option is absent. */
2452
2512
  #versionId;
2513
+ /** The parsed `ResolutionOptions.versionTime` in milliseconds since the Unix epoch, or `undefined`. */
2453
2514
  #versionTime;
2454
2515
  /**
2455
2516
  * The specific phase the Resolver is current in.
@@ -2460,22 +2521,28 @@ var Resolver = class _Resolver {
2460
2521
  #providedGenesisDocument = null;
2461
2522
  #beaconServicesSignals = /* @__PURE__ */ new Map();
2462
2523
  #processedServices = /* @__PURE__ */ new Set();
2524
+ /** The beacon addresses the resolver requested signals for: `scanned_beacons` of the specification. */
2463
2525
  #requestCache = /* @__PURE__ */ new Set();
2526
+ /**
2527
+ * The tuples of the specification's `updates` list: a signed update and the metadata of
2528
+ * the block that announced it. BeaconProcess appends; ProcessUpdate sorts the list and
2529
+ * removes one tuple per step. A tuple that one pass does not reach waits for the next.
2530
+ */
2464
2531
  #unsortedUpdates = [];
2465
2532
  #resolvedResponse = null;
2466
2533
  /**
2467
- * Monotonic DID-document version counter and the update-hash history that backs
2468
- * duplicate confirmation, both carried across the entire resolution. The spec's
2469
- * read algorithm keeps a single version counter and a single update-hash history
2470
- * for the whole signal-processing loop, re-deriving beacons from the contemporary
2471
- * document on each pass. This sans-I/O resolver splits that one loop into discovery
2472
- * rounds, so the two must persist across rounds rather than restart each pass.
2473
- * Restarting them would reject a legitimate linear history whose later updates are
2474
- * announced on beacons that earlier updates added: round two would forget it had
2475
- * already reached version two, see version three, and raise a late-publishing error.
2534
+ * The state of the specification loop, carried across every pass: the version counter
2535
+ * (`current_version_id`), the update-hash history that backs duplicate confirmation
2536
+ * (`update_hash_history`), the confirmations of the block that contains the most
2537
+ * recently applied unique update (`block_confirmations`), and the header time of that
2538
+ * block as `updated`. A pass that finds a new beacon address returns to discovery, so
2539
+ * the state must not restart: a restart would reject a linear history whose later
2540
+ * updates are announced on beacons that earlier updates added.
2476
2541
  */
2477
2542
  #currentVersionId = 1;
2478
2543
  #updateHashHistory = [];
2544
+ #blockConfirmations = 0;
2545
+ #updated;
2479
2546
  /**
2480
2547
  * Opt-in upper bound on multi-round beacon-discovery passes. `Infinity` (the
2481
2548
  * default) leaves discovery unbounded; termination is already guaranteed by
@@ -2500,8 +2567,15 @@ var Resolver = class _Resolver {
2500
2567
  this.#didComponents = didComponents;
2501
2568
  this.#sidecarData = sidecarData;
2502
2569
  this.#currentDocument = currentDocument;
2503
- this.#versionId = options?.versionId;
2504
- this.#versionTime = options?.versionTime;
2570
+ if (options?.versionId !== void 0 && options?.versionTime !== void 0) {
2571
+ throw new import_common13.ResolveError(
2572
+ "Invalid resolution options: versionId and versionTime are mutually exclusive. Pass one of them.",
2573
+ import_common13.INVALID_OPTIONS,
2574
+ { versionId: options.versionId, versionTime: options.versionTime }
2575
+ );
2576
+ }
2577
+ this.#versionId = validateVersionId(options?.versionId);
2578
+ this.#versionTime = validateVersionTime(options?.versionTime);
2505
2579
  const rounds = options?.maxDiscoveryRounds;
2506
2580
  this.#maxDiscoveryRounds = typeof rounds === "number" && rounds > 0 ? rounds : Infinity;
2507
2581
  this.#minConf = validateMinConf(options?.minConf);
@@ -2585,88 +2659,7 @@ var Resolver = class _Resolver {
2585
2659
  return { updateMap, casMap, smtMap };
2586
2660
  }
2587
2661
  /**
2588
- * Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#process-updates | 7.2.f Process updates Array}.
2589
- * @param {DidDocument} currentDocument The current DID Document to apply the updates to.
2590
- * @param {Array<[SignedBTCR2Update, BlockMetadata]>} unsortedUpdates The unsorted array of BTCR2 Signed Updates and their associated Block Metadata.
2591
- * @param {string} [versionTime] The optional version time to limit updates to.
2592
- * @param {string} [versionId] The optional version id to limit updates to.
2593
- * @param {{ currentVersionId: number; updateHashHistory: HashBytes[] }} [resolutionState]
2594
- * Version counter and update-hash history carried from earlier discovery rounds.
2595
- * Standalone callers omit it and start fresh at version 1 with an empty history.
2596
- * @returns {DidResolutionResponse} The updated DID Document, number of confirmations, and version id.
2597
- *
2598
- * Confirmation depth is not checked here. The BeaconProcess phase excludes a
2599
- * signal below `ResolutionOptions.minConf` before its update reaches this method,
2600
- * so every tuple here comes from a block at or above the threshold.
2601
- */
2602
- static updates(currentDocument, unsortedUpdates, versionTime, versionId, resolutionState = { currentVersionId: 1, updateHashHistory: [] }) {
2603
- let currentVersionId = resolutionState.currentVersionId;
2604
- const updateHashHistory = resolutionState.updateHashHistory;
2605
- const updates = unsortedUpdates.sort(
2606
- ([upd0, blk0], [upd1, blk1]) => upd0.targetVersionId - upd1.targetVersionId || blk0.height - blk1.height
2607
- );
2608
- const response = {
2609
- didDocument: currentDocument,
2610
- metadata: {
2611
- versionId: `${currentVersionId}`,
2612
- confirmations: 0,
2613
- deactivated: currentDocument.deactivated || false
2614
- }
2615
- };
2616
- for (const [update, block] of updates) {
2617
- const currentDocumentHash = (0, import_common13.canonicalHashBytes)(response.didDocument);
2618
- const blocktime = import_common13.DateUtils.blocktimeToTimestamp(block.time);
2619
- response.metadata.updated = import_common13.DateUtils.toISOStringNonFractional(blocktime);
2620
- response.metadata.confirmations = block.confirmations;
2621
- if (update.targetVersionId <= currentVersionId) {
2622
- this.confirmDuplicate(update, updateHashHistory);
2623
- continue;
2624
- }
2625
- if (versionTime) {
2626
- if (blocktime > import_common13.DateUtils.dateStringToTimestamp(versionTime)) {
2627
- return response;
2628
- }
2629
- }
2630
- if (update.targetVersionId === currentVersionId + 1) {
2631
- const sourceHashBytes = (0, import_common13.decode)(update.sourceHash, "base64urlnopad");
2632
- if (!(0, import_utils7.equalBytes)(sourceHashBytes, currentDocumentHash)) {
2633
- throw new import_common13.ResolveError(
2634
- `Hash mismatch: update.sourceHash !== currentDocumentHash`,
2635
- import_common13.INVALID_DID_UPDATE,
2636
- {
2637
- sourceHash: update.sourceHash,
2638
- currentDocumentHash: (0, import_common13.encode)(currentDocumentHash, "hex")
2639
- }
2640
- );
2641
- }
2642
- response.didDocument = this.applyUpdate(response.didDocument, update);
2643
- const unsignedUpdate = import_common13.JSONUtils.deleteKeys(update, ["proof"]);
2644
- updateHashHistory.push((0, import_common13.canonicalHashBytes)(unsignedUpdate));
2645
- } else {
2646
- throw new import_common13.ResolveError(
2647
- `Version Id Mismatch: targetVersionId cannot be > currentVersionId + 1`,
2648
- import_common13.LATE_PUBLISHING_ERROR,
2649
- {
2650
- targetVersionId: update.targetVersionId,
2651
- currentVersionId: currentVersionId + 1
2652
- }
2653
- );
2654
- }
2655
- currentVersionId++;
2656
- response.metadata.versionId = `${currentVersionId}`;
2657
- const versionIdNumber = Number(versionId);
2658
- if (!isNaN(versionIdNumber) && versionIdNumber <= currentVersionId) {
2659
- return response;
2660
- }
2661
- if (response.didDocument.deactivated) {
2662
- response.metadata.deactivated = response.didDocument.deactivated;
2663
- return response;
2664
- }
2665
- }
2666
- return response;
2667
- }
2668
- /**
2669
- * Implements subsection {@link https://dcdpr.github.io/did-btcr2/#confirm-duplicate-update | 7.2.f.1 Confirm Duplicate Update}.
2662
+ * Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#confirm-duplicate-update | Confirm Duplicate Update}.
2670
2663
  * This step confirms that an update with a lower-than-expected targetVersionId is a true duplicate.
2671
2664
  * @param {SignedBTCR2Update} update The BTCR2 Signed Update to confirm as a duplicate.
2672
2665
  * @param {HashBytes[]} updateHashHistory The accumulated hash history for comparison.
@@ -2705,14 +2698,26 @@ var Resolver = class _Resolver {
2705
2698
  }
2706
2699
  }
2707
2700
  /**
2708
- * Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#apply-update | 7.2.f.3 Apply Update}
2701
+ * Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#apply-update | Apply update}
2709
2702
  * and its step {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#check-update-proof | Check update.proof}.
2710
2703
  * @param {DidDocument} currentDocument The current DID Document to apply the update to.
2711
2704
  * @param {SignedBTCR2Update} update The BTCR2 Signed Update to apply.
2712
2705
  * @returns {DidDocument} The updated DID Document after applying the update.
2713
- * @throws {ResolveError} If the update is invalid or cannot be applied.
2706
+ * @throws {ResolveError} `INVALID_DID_UPDATE` if the update is invalid or cannot be applied.
2714
2707
  */
2715
2708
  static applyUpdate(currentDocument, update) {
2709
+ const currentDocumentHash = (0, import_common13.canonicalHashBytes)(currentDocument);
2710
+ const sourceHashBytes = (0, import_common13.decode)(update.sourceHash, "base64urlnopad");
2711
+ if (!(0, import_utils7.equalBytes)(sourceHashBytes, currentDocumentHash)) {
2712
+ throw new import_common13.ResolveError(
2713
+ `Hash mismatch: update.sourceHash !== currentDocumentHash`,
2714
+ import_common13.INVALID_DID_UPDATE,
2715
+ {
2716
+ sourceHash: update.sourceHash,
2717
+ currentDocumentHash: (0, import_common13.encode)(currentDocumentHash, "hex")
2718
+ }
2719
+ );
2720
+ }
2716
2721
  if (!isBtcr2UpdateContext(update["@context"])) {
2717
2722
  throw new import_common13.ResolveError(
2718
2723
  "Invalid update: @context is not the array the specification pins for a BTCR2 Update",
@@ -2773,13 +2778,13 @@ var Resolver = class _Resolver {
2773
2778
  }
2774
2779
  const updatedDocument = import_common13.JSONPatch.apply(currentDocument, update.patch);
2775
2780
  DidDocument.validate(updatedDocument);
2776
- const currentDocumentHash = (0, import_common13.canonicalHashBytes)(updatedDocument);
2781
+ const updatedDocumentHash = (0, import_common13.canonicalHashBytes)(updatedDocument);
2777
2782
  const updateTargetHash = (0, import_common13.decode)(update.targetHash);
2778
- if (!(0, import_utils7.equalBytes)(updateTargetHash, currentDocumentHash)) {
2783
+ if (!(0, import_utils7.equalBytes)(updateTargetHash, updatedDocumentHash)) {
2779
2784
  throw new import_common13.ResolveError(
2780
- `Invalid update: update.targetHash !== currentDocumentHash`,
2785
+ `Invalid update: update.targetHash !== updatedDocumentHash`,
2781
2786
  import_common13.INVALID_DID_UPDATE,
2782
- { updateTargetHash, currentDocumentHash }
2787
+ { updateTargetHash, updatedDocumentHash }
2783
2788
  );
2784
2789
  }
2785
2790
  return updatedDocument;
@@ -2853,61 +2858,99 @@ var Resolver = class _Resolver {
2853
2858
  if (allNeeds.length > 0) {
2854
2859
  return { status: "action-required", needs: allNeeds };
2855
2860
  }
2856
- this.#phase = "ApplyUpdates" /* ApplyUpdates */;
2861
+ this.#phase = "ProcessUpdate" /* ProcessUpdate */;
2857
2862
  continue;
2858
2863
  }
2859
- // Phase: ApplyUpdates
2860
- // Apply collected updates, then check for new beacon services (multi-round).
2861
- case "ApplyUpdates" /* ApplyUpdates */: {
2862
- if (this.#unsortedUpdates.length > 0) {
2863
- this.#resolvedResponse = _Resolver.updates(
2864
- this.#currentDocument,
2865
- this.#unsortedUpdates,
2866
- this.#versionTime,
2867
- this.#versionId,
2868
- { currentVersionId: this.#currentVersionId, updateHashHistory: this.#updateHashHistory }
2869
- );
2870
- this.#currentVersionId = Number(this.#resolvedResponse.metadata.versionId);
2871
- this.#currentDocument = this.#resolvedResponse.didDocument;
2872
- this.#unsortedUpdates = [];
2873
- const beaconServices = BeaconUtils.getBeaconServices(this.#currentDocument);
2874
- const hasNewServices = beaconServices.some((service) => {
2875
- const address = BeaconUtils.parseBitcoinAddress(service.serviceEndpoint);
2876
- return !this.#requestCache.has(address);
2877
- });
2878
- if (hasNewServices) {
2879
- if (++this.#discoveryRounds > this.#maxDiscoveryRounds) {
2880
- throw new import_common13.ResolveError(
2881
- `Exceeded the configured maximum of ${this.#maxDiscoveryRounds} beacon-discovery rounds. Raise or remove ResolutionOptions.maxDiscoveryRounds to resolve this DID.`,
2882
- import_common13.INTERNAL_ERROR,
2883
- { maxDiscoveryRounds: this.#maxDiscoveryRounds, discoveryRounds: this.#discoveryRounds }
2884
- );
2864
+ // Phase: ProcessUpdate
2865
+ // Spec "Process Next Update": one tuple per step. The phase repeats until
2866
+ // the document resolves, or until an applied update adds a beacon address
2867
+ // that the resolver did not scan (then the pass returns to BeaconDiscovery).
2868
+ case "ProcessUpdate" /* ProcessUpdate */: {
2869
+ const document = this.#currentDocument;
2870
+ if (this.#versionId !== void 0 && this.#currentVersionId === this.#versionId) {
2871
+ this.#phase = "Complete" /* Complete */;
2872
+ continue;
2873
+ }
2874
+ if (this.#unsortedUpdates.length === 0 || document.deactivated) {
2875
+ if (this.#versionId !== void 0) {
2876
+ throw new import_common13.ResolveError(
2877
+ `Version ${this.#versionId} of the DID does not exist: the history ` + (document.deactivated ? `ends with the deactivation at version ${this.#currentVersionId}.` : `ends at version ${this.#currentVersionId}.`),
2878
+ import_common13.NOT_FOUND,
2879
+ { versionId: this.#versionId, currentVersionId: this.#currentVersionId }
2880
+ );
2881
+ }
2882
+ this.#phase = "Complete" /* Complete */;
2883
+ continue;
2884
+ }
2885
+ this.#unsortedUpdates.sort(
2886
+ ([upd0, blk0], [upd1, blk1]) => upd0.targetVersionId - upd1.targetVersionId || blk0.height - blk1.height
2887
+ );
2888
+ const [update, block] = this.#unsortedUpdates.shift();
2889
+ if (update.targetVersionId <= this.#currentVersionId) {
2890
+ _Resolver.confirmDuplicate(update, this.#updateHashHistory);
2891
+ continue;
2892
+ }
2893
+ if (this.#versionTime !== void 0 && block.mediantime * 1e3 > this.#versionTime) {
2894
+ this.#phase = "Complete" /* Complete */;
2895
+ continue;
2896
+ }
2897
+ if (update.targetVersionId !== this.#currentVersionId + 1) {
2898
+ throw new import_common13.ResolveError(
2899
+ `Version Id Mismatch: targetVersionId cannot be > currentVersionId + 1`,
2900
+ import_common13.LATE_PUBLISHING_ERROR,
2901
+ {
2902
+ targetVersionId: update.targetVersionId,
2903
+ currentVersionId: this.#currentVersionId + 1
2885
2904
  }
2886
- this.#phase = "BeaconDiscovery" /* BeaconDiscovery */;
2887
- continue;
2905
+ );
2906
+ }
2907
+ this.#currentDocument = _Resolver.applyUpdate(document, update);
2908
+ const unsignedUpdate = import_common13.JSONUtils.deleteKeys(update, ["proof"]);
2909
+ this.#updateHashHistory.push((0, import_common13.canonicalHashBytes)(unsignedUpdate));
2910
+ this.#currentVersionId++;
2911
+ this.#blockConfirmations = block.confirmations;
2912
+ this.#updated = import_common13.DateUtils.toISOStringNonFractional(import_common13.DateUtils.blocktimeToTimestamp(block.time));
2913
+ if (this.#hasUnscannedBeacons()) {
2914
+ if (++this.#discoveryRounds > this.#maxDiscoveryRounds) {
2915
+ throw new import_common13.ResolveError(
2916
+ `Exceeded the configured maximum of ${this.#maxDiscoveryRounds} beacon-discovery rounds. Raise or remove ResolutionOptions.maxDiscoveryRounds to resolve this DID.`,
2917
+ import_common13.INTERNAL_ERROR,
2918
+ { maxDiscoveryRounds: this.#maxDiscoveryRounds, discoveryRounds: this.#discoveryRounds }
2919
+ );
2888
2920
  }
2921
+ this.#phase = "BeaconDiscovery" /* BeaconDiscovery */;
2889
2922
  }
2890
- this.#phase = "Complete" /* Complete */;
2891
2923
  continue;
2892
2924
  }
2893
2925
  // Phase: Complete
2926
+ // The document metadata of the specification: versionId is current_version_id,
2927
+ // confirmations is block_confirmations (0 when no update applied), deactivated
2928
+ // is the flag of the document. `updated` is present after the first apply.
2894
2929
  case "Complete" /* Complete */: {
2895
- return {
2896
- status: "resolved",
2897
- // No update applied: confirmations is 0 per the specification.
2898
- result: this.#resolvedResponse ?? {
2899
- didDocument: this.#currentDocument,
2900
- metadata: {
2901
- versionId: this.#versionId ?? "1",
2902
- confirmations: 0,
2903
- deactivated: this.#currentDocument.deactivated || false
2904
- }
2930
+ this.#resolvedResponse ??= {
2931
+ didDocument: this.#currentDocument,
2932
+ metadata: {
2933
+ versionId: `${this.#currentVersionId}`,
2934
+ confirmations: this.#blockConfirmations,
2935
+ ...this.#updated !== void 0 ? { updated: this.#updated } : {},
2936
+ deactivated: this.#currentDocument.deactivated || false
2905
2937
  }
2906
2938
  };
2939
+ return { status: "resolved", result: this.#resolvedResponse };
2907
2940
  }
2908
2941
  }
2909
2942
  }
2910
2943
  }
2944
+ /**
2945
+ * True if the current document carries a beacon service whose address the resolver
2946
+ * did not request signals for. "Find Beacon Signals" scans such an address on the
2947
+ * next pass.
2948
+ */
2949
+ #hasUnscannedBeacons() {
2950
+ return BeaconUtils.getBeaconServices(this.#currentDocument).some(
2951
+ (service) => !this.#requestCache.has(BeaconUtils.parseBitcoinAddress(service.serviceEndpoint))
2952
+ );
2953
+ }
2911
2954
  /**
2912
2955
  * Return the signals of one beacon service that resolution may process: the
2913
2956
  * signals with at least `#minConf` confirmations. The specification removes a
@@ -2916,10 +2959,11 @@ var Resolver = class _Resolver {
2916
2959
  * integer confirmation count is excluded too: that is a mempool transaction
2917
2960
  * from a driver that did not skip it.
2918
2961
  *
2919
- * An eligible signal must carry a finite block height and block time. A
2920
- * signal that passes the count but lacks them is malformed. It fails fast
2921
- * here with a typed error, in the style of the {@link provide} guards, and
2922
- * not later with an invalid date inside {@link updates}.
2962
+ * An eligible signal must carry a finite block height, block time, and block
2963
+ * median time past. A signal that passes the count but lacks them is
2964
+ * malformed. It fails fast here with a typed error, in the style of the
2965
+ * {@link provide} guards, and not later with an invalid date or a false
2966
+ * `versionTime` comparison in the ProcessUpdate phase.
2923
2967
  * @param {Array<BeaconSignal>} signals The signals the caller provided for one service.
2924
2968
  * @returns {Array<BeaconSignal>} The signals at or above the threshold, in the given order.
2925
2969
  * @throws {ResolveError} `INVALID_DID_UPDATE` for an eligible signal with no valid block metadata.
@@ -2932,11 +2976,17 @@ var Resolver = class _Resolver {
2932
2976
  if (!Number.isInteger(confirmations) || confirmations < this.#minConf) {
2933
2977
  continue;
2934
2978
  }
2935
- if (!Number.isFinite(block?.height) || !Number.isFinite(block?.time)) {
2979
+ if (!Number.isFinite(block?.height) || !Number.isFinite(block?.time) || !Number.isFinite(block?.mediantime)) {
2936
2980
  throw new import_common13.ResolveError(
2937
- `Beacon signal ${signal.signalBytes} has ${confirmations} confirmations but no valid block height or block time.`,
2981
+ `Beacon signal ${signal.signalBytes} has ${confirmations} confirmations but no valid block height, block time, or block mediantime.`,
2938
2982
  import_common13.INVALID_DID_UPDATE,
2939
- { signalBytes: signal.signalBytes, confirmations, height: block?.height, time: block?.time }
2983
+ {
2984
+ signalBytes: signal.signalBytes,
2985
+ confirmations,
2986
+ height: block?.height,
2987
+ time: block?.time,
2988
+ mediantime: block?.mediantime
2989
+ }
2940
2990
  );
2941
2991
  }
2942
2992
  eligible.push(signal);
@@ -1,5 +1,5 @@
1
1
  import { GENESIS_TX_ID, TXIN_WITNESS_COINBASE } from '@did-btcr2/bitcoin';
2
- import { ResolveError } from '@did-btcr2/common';
2
+ import { INTERNAL_ERROR, ResolveError } from '@did-btcr2/common';
3
3
  import { BeaconUtils } from './utils.js';
4
4
  /**
5
5
  * The serialized form of a Beacon Signal output: `OP_RETURN` (`0x6a`), the 32-byte push
@@ -107,6 +107,9 @@ export class BeaconSignalDiscovery {
107
107
  const beaconServiceSignals = new Map();
108
108
  // Fetch the current block count once before the loop
109
109
  const currentBlockCount = await bitcoin.rest.block.count();
110
+ // The median time past of each block that holds a signal, keyed by block hash.
111
+ // One fetch per distinct block for the whole run.
112
+ const mediantimes = new Map();
110
113
  // Iterate over each beacon
111
114
  for (const beaconService of beaconServices) {
112
115
  beaconServiceSignals.set(beaconService, []);
@@ -156,6 +159,10 @@ export class BeaconSignalDiscovery {
156
159
  }
157
160
  // Use the pre-fetched block count instead of calling per-signal
158
161
  const confirmations = currentBlockCount - status.block_height + 1;
162
+ // The address listing carries the header time of the block, not its median
163
+ // time past. The resolver compares `versionTime` with the median time past,
164
+ // so read it from the block record.
165
+ const mediantime = await BeaconSignalDiscovery.mediantime(status.block_hash, bitcoin, mediantimes);
159
166
  // Push the beacon signal object to the signals array for the beacon service
160
167
  beaconServiceSignals.get(beaconService)?.push({
161
168
  tx: beaconSignal,
@@ -164,12 +171,37 @@ export class BeaconSignalDiscovery {
164
171
  confirmations,
165
172
  height: status.block_height,
166
173
  time: status.block_time,
174
+ mediantime,
167
175
  }
168
176
  });
169
177
  }
170
178
  }
171
179
  return beaconServiceSignals;
172
180
  }
181
+ /**
182
+ * Return the median time past of a block, from the per-run cache or from the
183
+ * Esplora block record (`GET /block/:hash`). The specification compares
184
+ * `versionTime` with the block `mediantime`, and the address listing does not
185
+ * carry it. One block record serves every signal in that block.
186
+ * @param {string} blockhash The hash of the block that contains a signal.
187
+ * @param {BitcoinConnection} bitcoin Bitcoin network connection to use for REST calls.
188
+ * @param {Map<string, number>} cache The median time past values fetched so far, keyed by block hash.
189
+ * @returns {Promise<number>} The median time past of the block, in Unix seconds.
190
+ * @throws {ResolveError} `INTERNAL_ERROR` if the backend returns no block record or no `mediantime` for the hash.
191
+ */
192
+ static async mediantime(blockhash, bitcoin, cache) {
193
+ const cached = cache.get(blockhash);
194
+ if (cached !== undefined) {
195
+ return cached;
196
+ }
197
+ const block = await bitcoin.rest.block.get({ blockhash });
198
+ const mediantime = block?.mediantime;
199
+ if (typeof mediantime !== 'number' || !Number.isFinite(mediantime)) {
200
+ throw new ResolveError(`Block ${blockhash} has no mediantime in the block record of the Bitcoin REST backend.`, INTERNAL_ERROR, { blockhash, block });
201
+ }
202
+ cache.set(blockhash, mediantime);
203
+ return mediantime;
204
+ }
173
205
  /**
174
206
  * Traverse the full blockchain from genesis to chain top looking for beacon signals.
175
207
  * @param {Array<BeaconService>} beaconServices Array of BeaconService objects to search for signals.
@@ -290,6 +322,7 @@ export class BeaconSignalDiscovery {
290
322
  blockMetadata: {
291
323
  height: block.height,
292
324
  time: block.time,
325
+ mediantime: block.mediantime,
293
326
  confirmations: block.confirmations
294
327
  }
295
328
  });
@@ -1 +1 @@
1
- {"version":3,"file":"signal-discovery.js","sourceRoot":"","sources":["../../../../src/core/beacon/signal-discovery.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"signal-discovery.js","sourceRoot":"","sources":["../../../../src/core/beacon/signal-discovery.ts"],"names":[],"mappings":"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"}