@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/README.md +5 -1
- package/dist/.tsbuildinfo +1 -1
- package/dist/browser.js +3 -3
- package/dist/browser.mjs +3 -3
- package/dist/cjs/index.js +199 -149
- package/dist/esm/core/beacon/signal-discovery.js +34 -1
- package/dist/esm/core/beacon/signal-discovery.js.map +1 -1
- package/dist/esm/core/resolver.js +205 -195
- package/dist/esm/core/resolver.js.map +1 -1
- package/dist/types/core/beacon/interfaces.d.ts +9 -1
- package/dist/types/core/beacon/interfaces.d.ts.map +1 -1
- package/dist/types/core/beacon/signal-discovery.d.ts +12 -0
- package/dist/types/core/beacon/signal-discovery.d.ts.map +1 -1
- package/dist/types/core/interfaces.d.ts +16 -5
- package/dist/types/core/interfaces.d.ts.map +1 -1
- package/dist/types/core/resolver.d.ts +3 -23
- package/dist/types/core/resolver.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/core/beacon/interfaces.ts +10 -1
- package/src/core/beacon/signal-discovery.ts +44 -1
- package/src/core/interfaces.ts +16 -5
- package/src/core/resolver.ts +248 -243
|
@@ -31,9 +31,17 @@ export interface BlockMetadata {
|
|
|
31
31
|
*/
|
|
32
32
|
height: number;
|
|
33
33
|
/**
|
|
34
|
-
* The timestamp of the block
|
|
34
|
+
* The timestamp in the header of the block that contains the Beacon Signal.
|
|
35
|
+
* The resolver reports it as `updated` in the document metadata.
|
|
35
36
|
*/
|
|
36
37
|
time: UnixTimestamp;
|
|
38
|
+
/**
|
|
39
|
+
* The median time past of the block that contains the Beacon Signal: the
|
|
40
|
+
* median of the header timestamps of that block and the ten blocks before it.
|
|
41
|
+
* The value does not decrease from one block to the next, and no single miner
|
|
42
|
+
* can change it. The resolver compares it with `ResolutionOptions.versionTime`.
|
|
43
|
+
*/
|
|
44
|
+
mediantime: UnixTimestamp;
|
|
37
45
|
/**
|
|
38
46
|
* The number of confirmations for the block containing the Beacon Signal.
|
|
39
47
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC7C,eAAe,EAAE,kBAAkB,CAAC;CACvC;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACtD;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC3B;;MAEE;IACH,MAAM,EAAE,MAAM,CAAC;IAEf
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC/E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,KAAK,EAAE,kBAAkB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAEjE;;;;;GAKG;AACH,MAAM,WAAW,aAAc,SAAQ,UAAU;IAC7C,eAAe,EAAE,kBAAkB,CAAC;CACvC;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACtD;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,WAAW,aAAa;IAC3B;;MAEE;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,IAAI,EAAE,aAAa,CAAC;IAEpB;;;;;OAKG;IACH,UAAU,EAAE,aAAa,CAAC;IAE1B;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B;;OAEG;IACH,EAAE,EAAE,kBAAkB,GAAG,gBAAgB,CAAC;IAE1C;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,aAAa,EAAE,aAAa,CAAC;CAC9B;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,YAAY,GAAG,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -70,6 +70,18 @@ export declare class BeaconSignalDiscovery {
|
|
|
70
70
|
* @returns {Promise<Map<BeaconService, Array<BeaconSignal>>>} Map of beacon service to its discovered signals
|
|
71
71
|
*/
|
|
72
72
|
static indexer(beaconServices: Array<BeaconService>, bitcoin: BitcoinConnection): Promise<Map<BeaconService, Array<BeaconSignal>>>;
|
|
73
|
+
/**
|
|
74
|
+
* Return the median time past of a block, from the per-run cache or from the
|
|
75
|
+
* Esplora block record (`GET /block/:hash`). The specification compares
|
|
76
|
+
* `versionTime` with the block `mediantime`, and the address listing does not
|
|
77
|
+
* carry it. One block record serves every signal in that block.
|
|
78
|
+
* @param {string} blockhash The hash of the block that contains a signal.
|
|
79
|
+
* @param {BitcoinConnection} bitcoin Bitcoin network connection to use for REST calls.
|
|
80
|
+
* @param {Map<string, number>} cache The median time past values fetched so far, keyed by block hash.
|
|
81
|
+
* @returns {Promise<number>} The median time past of the block, in Unix seconds.
|
|
82
|
+
* @throws {ResolveError} `INTERNAL_ERROR` if the backend returns no block record or no `mediantime` for the hash.
|
|
83
|
+
*/
|
|
84
|
+
private static mediantime;
|
|
73
85
|
/**
|
|
74
86
|
* Traverse the full blockchain from genesis to chain top looking for beacon signals.
|
|
75
87
|
* @param {Array<BeaconService>} beaconServices Array of BeaconService objects to search for signals.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signal-discovery.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/signal-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAGA,MAAM,oBAAoB,CAAC;AAM9C,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAWnE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAWzF;AAED;;;;;GAKG;AACH,qBAAa,qBAAqB;IAEhC;;;;;;;;;;;;;;;;;;OAkBG;mBACkB,iBAAiB;IA2BtC;;;;;;;;;;;;;;;;;;;;OAoBG;WACU,OAAO,CAClB,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,EACpC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"signal-discovery.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/signal-discovery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,iBAAiB,EAGA,MAAM,oBAAoB,CAAC;AAM9C,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAWnE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,yBAAyB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAWzF;AAED;;;;;GAKG;AACH,qBAAa,qBAAqB;IAEhC;;;;;;;;;;;;;;;;;;OAkBG;mBACkB,iBAAiB;IA2BtC;;;;;;;;;;;;;;;;;;;;OAoBG;WACU,OAAO,CAClB,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,EACpC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;IAyFnD;;;;;;;;;;OAUG;mBACkB,UAAU;IAqB/B;;;;;OAKG;WACU,QAAQ,CACnB,cAAc,EAAE,KAAK,CAAC,aAAa,CAAC,EACpC,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC,CAAC;CAiKpD"}
|
|
@@ -16,14 +16,25 @@ export interface RootCapability {
|
|
|
16
16
|
*/
|
|
17
17
|
export interface ResolutionOptions extends DidResolutionOptions {
|
|
18
18
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
19
|
+
* The version of the DID document to resolve, as an ASCII string of an integer
|
|
20
|
+
* (for example `"2"`). The versions start at `"1"`, the genesis document. The
|
|
21
|
+
* resolver stops before it applies the update that yields the next version, so
|
|
22
|
+
* `"1"` returns the genesis document also when updates exist. A version that the
|
|
23
|
+
* history does not reach, also a version after a deactivation, fails with a
|
|
24
|
+
* `ResolveError` of type `NOT_FOUND`. A value that is not an ASCII string of an
|
|
25
|
+
* integer fails with `INVALID_OPTIONS`. Mutually exclusive with `versionTime`:
|
|
26
|
+
* a request with both fails with `INVALID_OPTIONS`.
|
|
21
27
|
*/
|
|
22
28
|
versionId?: string;
|
|
23
29
|
/**
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
30
|
+
* An XML Datetime in UTC with the `Z` designator and no fraction (for example
|
|
31
|
+
* `"2026-07-01T00:00:00Z"`), the form that DID Resolution v1 requires. The
|
|
32
|
+
* resolver applies each update whose block `mediantime` (median time past) is
|
|
33
|
+
* at or before this instant, and stops at the first update whose block
|
|
34
|
+
* `mediantime` is after it. The boundary is inclusive. Every conformant resolver
|
|
35
|
+
* reads the same `mediantime` from the block chain, so every resolver selects
|
|
36
|
+
* the same version. A value in another form fails with `INVALID_OPTIONS`.
|
|
37
|
+
* Mutually exclusive with `versionId`.
|
|
27
38
|
*/
|
|
28
39
|
versionTime?: string;
|
|
29
40
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../src/core/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAkB,SAAQ,oBAAoB;IAC7D
|
|
1
|
+
{"version":3,"file":"interfaces.d.ts","sourceRoot":"","sources":["../../../src/core/interfaces.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AACvD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAE1C,MAAM,WAAW,cAAc;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAkB,SAAQ,oBAAoB;IAC7D;;;;;;;;;OASG;IACH,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;;;;;;;OASG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;;;OAQG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAE5B;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,MAAM,WAAW,QAAQ;IACvB;;OAEG;IACH,EAAE,EAAE,MAAM,CAAC;IACX;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { HashBytes } from '@did-btcr2/common';
|
|
2
1
|
import type { SignedBTCR2Update } from './btcr2-update.js';
|
|
3
2
|
import { DidDocument } from '../utils/did-document.js';
|
|
4
3
|
import type { BeaconService, BeaconSignal, BlockMetadata } from './beacon/interfaces.js';
|
|
@@ -150,26 +149,7 @@ export declare class Resolver {
|
|
|
150
149
|
*/
|
|
151
150
|
static sidecarData(sidecar?: Sidecar): SidecarData;
|
|
152
151
|
/**
|
|
153
|
-
* Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#
|
|
154
|
-
* @param {DidDocument} currentDocument The current DID Document to apply the updates to.
|
|
155
|
-
* @param {Array<[SignedBTCR2Update, BlockMetadata]>} unsortedUpdates The unsorted array of BTCR2 Signed Updates and their associated Block Metadata.
|
|
156
|
-
* @param {string} [versionTime] The optional version time to limit updates to.
|
|
157
|
-
* @param {string} [versionId] The optional version id to limit updates to.
|
|
158
|
-
* @param {{ currentVersionId: number; updateHashHistory: HashBytes[] }} [resolutionState]
|
|
159
|
-
* Version counter and update-hash history carried from earlier discovery rounds.
|
|
160
|
-
* Standalone callers omit it and start fresh at version 1 with an empty history.
|
|
161
|
-
* @returns {DidResolutionResponse} The updated DID Document, number of confirmations, and version id.
|
|
162
|
-
*
|
|
163
|
-
* Confirmation depth is not checked here. The BeaconProcess phase excludes a
|
|
164
|
-
* signal below `ResolutionOptions.minConf` before its update reaches this method,
|
|
165
|
-
* so every tuple here comes from a block at or above the threshold.
|
|
166
|
-
*/
|
|
167
|
-
static updates(currentDocument: DidDocument, unsortedUpdates: Array<[SignedBTCR2Update, BlockMetadata]>, versionTime?: string, versionId?: string, resolutionState?: {
|
|
168
|
-
currentVersionId: number;
|
|
169
|
-
updateHashHistory: HashBytes[];
|
|
170
|
-
}): DidResolutionResponse;
|
|
171
|
-
/**
|
|
172
|
-
* Implements subsection {@link https://dcdpr.github.io/did-btcr2/#confirm-duplicate-update | 7.2.f.1 Confirm Duplicate Update}.
|
|
152
|
+
* Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#confirm-duplicate-update | Confirm Duplicate Update}.
|
|
173
153
|
* This step confirms that an update with a lower-than-expected targetVersionId is a true duplicate.
|
|
174
154
|
* @param {SignedBTCR2Update} update The BTCR2 Signed Update to confirm as a duplicate.
|
|
175
155
|
* @param {HashBytes[]} updateHashHistory The accumulated hash history for comparison.
|
|
@@ -177,12 +157,12 @@ export declare class Resolver {
|
|
|
177
157
|
*/
|
|
178
158
|
private static confirmDuplicate;
|
|
179
159
|
/**
|
|
180
|
-
* Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#apply-update |
|
|
160
|
+
* Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#apply-update | Apply update}
|
|
181
161
|
* and its step {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#check-update-proof | Check update.proof}.
|
|
182
162
|
* @param {DidDocument} currentDocument The current DID Document to apply the update to.
|
|
183
163
|
* @param {SignedBTCR2Update} update The BTCR2 Signed Update to apply.
|
|
184
164
|
* @returns {DidDocument} The updated DID Document after applying the update.
|
|
185
|
-
* @throws {ResolveError}
|
|
165
|
+
* @throws {ResolveError} `INVALID_DID_UPDATE` if the update is invalid or cannot be applied.
|
|
186
166
|
*/
|
|
187
167
|
private static applyUpdate;
|
|
188
168
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../../src/core/resolver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../../../src/core/resolver.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@did-btcr2/method",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.63.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Reference implementation for the did:btcr2 DID method written in TypeScript and JavaScript. did:btcr2 is a censorship resistant DID Method using the Bitcoin blockchain as a Verifiable Data Registry to announce changes to the DID document. This is the core method implementation for the did-btcr2-js monorepo.",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -71,9 +71,9 @@
|
|
|
71
71
|
"@web5/dids": "^1.2.0",
|
|
72
72
|
"@did-btcr2/bitcoin": "^0.11.0",
|
|
73
73
|
"@did-btcr2/common": "^9.5.0",
|
|
74
|
-
"@did-btcr2/
|
|
74
|
+
"@did-btcr2/cryptosuite": "^10.0.0",
|
|
75
75
|
"@did-btcr2/keypair": "^0.13.1",
|
|
76
|
-
"@did-btcr2/
|
|
76
|
+
"@did-btcr2/smt": "^0.3.0"
|
|
77
77
|
},
|
|
78
78
|
"devDependencies": {
|
|
79
79
|
"@eslint/js": "^9.39.4",
|
|
@@ -35,10 +35,19 @@ export interface BlockMetadata {
|
|
|
35
35
|
height: number;
|
|
36
36
|
|
|
37
37
|
/**
|
|
38
|
-
* The timestamp of the block
|
|
38
|
+
* The timestamp in the header of the block that contains the Beacon Signal.
|
|
39
|
+
* The resolver reports it as `updated` in the document metadata.
|
|
39
40
|
*/
|
|
40
41
|
time: UnixTimestamp;
|
|
41
42
|
|
|
43
|
+
/**
|
|
44
|
+
* The median time past of the block that contains the Beacon Signal: the
|
|
45
|
+
* median of the header timestamps of that block and the ten blocks before it.
|
|
46
|
+
* The value does not decrease from one block to the next, and no single miner
|
|
47
|
+
* can change it. The resolver compares it with `ResolutionOptions.versionTime`.
|
|
48
|
+
*/
|
|
49
|
+
mediantime: UnixTimestamp;
|
|
50
|
+
|
|
42
51
|
/**
|
|
43
52
|
* The number of confirmations for the block containing the Beacon Signal.
|
|
44
53
|
*/
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
GENESIS_TX_ID,
|
|
8
8
|
TXIN_WITNESS_COINBASE
|
|
9
9
|
} from '@did-btcr2/bitcoin';
|
|
10
|
-
import { ResolveError } from '@did-btcr2/common';
|
|
10
|
+
import { INTERNAL_ERROR, ResolveError } from '@did-btcr2/common';
|
|
11
11
|
import type { BeaconService, BeaconSignal } from './interfaces.js';
|
|
12
12
|
import { BeaconUtils } from './utils.js';
|
|
13
13
|
|
|
@@ -136,6 +136,10 @@ export class BeaconSignalDiscovery {
|
|
|
136
136
|
// Fetch the current block count once before the loop
|
|
137
137
|
const currentBlockCount = await bitcoin.rest.block.count();
|
|
138
138
|
|
|
139
|
+
// The median time past of each block that holds a signal, keyed by block hash.
|
|
140
|
+
// One fetch per distinct block for the whole run.
|
|
141
|
+
const mediantimes = new Map<string, number>();
|
|
142
|
+
|
|
139
143
|
// Iterate over each beacon
|
|
140
144
|
for (const beaconService of beaconServices) {
|
|
141
145
|
beaconServiceSignals.set(beaconService, []);
|
|
@@ -193,6 +197,11 @@ export class BeaconSignalDiscovery {
|
|
|
193
197
|
// Use the pre-fetched block count instead of calling per-signal
|
|
194
198
|
const confirmations = currentBlockCount - status.block_height + 1;
|
|
195
199
|
|
|
200
|
+
// The address listing carries the header time of the block, not its median
|
|
201
|
+
// time past. The resolver compares `versionTime` with the median time past,
|
|
202
|
+
// so read it from the block record.
|
|
203
|
+
const mediantime = await BeaconSignalDiscovery.mediantime(status.block_hash, bitcoin, mediantimes);
|
|
204
|
+
|
|
196
205
|
// Push the beacon signal object to the signals array for the beacon service
|
|
197
206
|
beaconServiceSignals.get(beaconService)?.push({
|
|
198
207
|
tx : beaconSignal,
|
|
@@ -201,6 +210,7 @@ export class BeaconSignalDiscovery {
|
|
|
201
210
|
confirmations,
|
|
202
211
|
height : status.block_height,
|
|
203
212
|
time : status.block_time,
|
|
213
|
+
mediantime,
|
|
204
214
|
}
|
|
205
215
|
});
|
|
206
216
|
}
|
|
@@ -209,6 +219,38 @@ export class BeaconSignalDiscovery {
|
|
|
209
219
|
return beaconServiceSignals;
|
|
210
220
|
}
|
|
211
221
|
|
|
222
|
+
/**
|
|
223
|
+
* Return the median time past of a block, from the per-run cache or from the
|
|
224
|
+
* Esplora block record (`GET /block/:hash`). The specification compares
|
|
225
|
+
* `versionTime` with the block `mediantime`, and the address listing does not
|
|
226
|
+
* carry it. One block record serves every signal in that block.
|
|
227
|
+
* @param {string} blockhash The hash of the block that contains a signal.
|
|
228
|
+
* @param {BitcoinConnection} bitcoin Bitcoin network connection to use for REST calls.
|
|
229
|
+
* @param {Map<string, number>} cache The median time past values fetched so far, keyed by block hash.
|
|
230
|
+
* @returns {Promise<number>} The median time past of the block, in Unix seconds.
|
|
231
|
+
* @throws {ResolveError} `INTERNAL_ERROR` if the backend returns no block record or no `mediantime` for the hash.
|
|
232
|
+
*/
|
|
233
|
+
private static async mediantime(
|
|
234
|
+
blockhash: string,
|
|
235
|
+
bitcoin: BitcoinConnection,
|
|
236
|
+
cache: Map<string, number>
|
|
237
|
+
): Promise<number> {
|
|
238
|
+
const cached = cache.get(blockhash);
|
|
239
|
+
if(cached !== undefined) {
|
|
240
|
+
return cached;
|
|
241
|
+
}
|
|
242
|
+
const block = await bitcoin.rest.block.get({ blockhash });
|
|
243
|
+
const mediantime = block?.mediantime;
|
|
244
|
+
if(typeof mediantime !== 'number' || !Number.isFinite(mediantime)) {
|
|
245
|
+
throw new ResolveError(
|
|
246
|
+
`Block ${blockhash} has no mediantime in the block record of the Bitcoin REST backend.`,
|
|
247
|
+
INTERNAL_ERROR, { blockhash, block }
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
cache.set(blockhash, mediantime);
|
|
251
|
+
return mediantime;
|
|
252
|
+
}
|
|
253
|
+
|
|
212
254
|
/**
|
|
213
255
|
* Traverse the full blockchain from genesis to chain top looking for beacon signals.
|
|
214
256
|
* @param {Array<BeaconService>} beaconServices Array of BeaconService objects to search for signals.
|
|
@@ -357,6 +399,7 @@ export class BeaconSignalDiscovery {
|
|
|
357
399
|
blockMetadata : {
|
|
358
400
|
height : block.height,
|
|
359
401
|
time : block.time,
|
|
402
|
+
mediantime : block.mediantime,
|
|
360
403
|
confirmations : block.confirmations
|
|
361
404
|
}
|
|
362
405
|
});
|
package/src/core/interfaces.ts
CHANGED
|
@@ -18,15 +18,26 @@ export interface RootCapability {
|
|
|
18
18
|
*/
|
|
19
19
|
export interface ResolutionOptions extends DidResolutionOptions {
|
|
20
20
|
/**
|
|
21
|
-
*
|
|
22
|
-
*
|
|
21
|
+
* The version of the DID document to resolve, as an ASCII string of an integer
|
|
22
|
+
* (for example `"2"`). The versions start at `"1"`, the genesis document. The
|
|
23
|
+
* resolver stops before it applies the update that yields the next version, so
|
|
24
|
+
* `"1"` returns the genesis document also when updates exist. A version that the
|
|
25
|
+
* history does not reach, also a version after a deactivation, fails with a
|
|
26
|
+
* `ResolveError` of type `NOT_FOUND`. A value that is not an ASCII string of an
|
|
27
|
+
* integer fails with `INVALID_OPTIONS`. Mutually exclusive with `versionTime`:
|
|
28
|
+
* a request with both fails with `INVALID_OPTIONS`.
|
|
23
29
|
*/
|
|
24
30
|
versionId?: string
|
|
25
31
|
|
|
26
32
|
/**
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
33
|
+
* An XML Datetime in UTC with the `Z` designator and no fraction (for example
|
|
34
|
+
* `"2026-07-01T00:00:00Z"`), the form that DID Resolution v1 requires. The
|
|
35
|
+
* resolver applies each update whose block `mediantime` (median time past) is
|
|
36
|
+
* at or before this instant, and stops at the first update whose block
|
|
37
|
+
* `mediantime` is after it. The boundary is inclusive. Every conformant resolver
|
|
38
|
+
* reads the same `mediantime` from the block chain, so every resolver selects
|
|
39
|
+
* the same version. A value in another form fails with `INVALID_OPTIONS`.
|
|
40
|
+
* Mutually exclusive with `versionId`.
|
|
30
41
|
*/
|
|
31
42
|
versionTime?: string;
|
|
32
43
|
|