@did-btcr2/method 0.40.2 → 0.42.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/.tsbuildinfo +1 -1
- package/dist/browser.js +102 -24
- package/dist/browser.mjs +102 -24
- package/dist/cjs/index.js +90 -14
- package/dist/esm/core/btcr2-update.js +2 -0
- package/dist/esm/core/btcr2-update.js.map +1 -0
- package/dist/esm/core/resolver.js +82 -12
- package/dist/esm/core/resolver.js.map +1 -1
- package/dist/esm/core/updater.js.map +1 -1
- package/dist/esm/did-btcr2.js +2 -1
- package/dist/esm/did-btcr2.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/types/core/beacon/beacon.d.ts +1 -1
- package/dist/types/core/beacon/beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/cas-beacon.d.ts +1 -1
- package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/singleton-beacon.d.ts +1 -1
- package/dist/types/core/beacon/singleton-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/smt-beacon.d.ts +1 -1
- package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -1
- package/dist/types/core/btcr2-update.d.ts +76 -0
- package/dist/types/core/btcr2-update.d.ts.map +1 -0
- package/dist/types/core/interfaces.d.ts +7 -0
- package/dist/types/core/interfaces.d.ts.map +1 -1
- package/dist/types/core/resolver.d.ts +9 -1
- package/dist/types/core/resolver.d.ts.map +1 -1
- package/dist/types/core/types.d.ts +1 -1
- package/dist/types/core/types.d.ts.map +1 -1
- package/dist/types/core/updater.d.ts +1 -1
- package/dist/types/core/updater.d.ts.map +1 -1
- package/dist/types/did-btcr2.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/core/beacon/beacon.ts +1 -1
- package/src/core/beacon/cas-beacon.ts +1 -1
- package/src/core/beacon/singleton-beacon.ts +1 -1
- package/src/core/beacon/smt-beacon.ts +1 -1
- package/src/core/btcr2-update.ts +87 -0
- package/src/core/interfaces.ts +8 -0
- package/src/core/resolver.ts +115 -15
- package/src/core/types.ts +1 -1
- package/src/core/updater.ts +3 -2
- package/src/did-btcr2.ts +4 -3
- package/src/index.ts +1 -0
package/dist/browser.js
CHANGED
|
@@ -93159,6 +93159,7 @@ a=end-of-candidates
|
|
|
93159
93159
|
CASBeaconError: () => CASBeaconError,
|
|
93160
93160
|
CHANGE_OUTPUT_VBYTES: () => CHANGE_OUTPUT_VBYTES,
|
|
93161
93161
|
DEFAULT_FEE_ESTIMATOR: () => DEFAULT_FEE_ESTIMATOR,
|
|
93162
|
+
DEFAULT_MAX_DISCOVERY_ROUNDS: () => DEFAULT_MAX_DISCOVERY_ROUNDS,
|
|
93162
93163
|
DID_REGEX: () => DID_REGEX,
|
|
93163
93164
|
DUST_LIMIT_SATS: () => DUST_LIMIT_SATS,
|
|
93164
93165
|
DidBtcr2: () => DidBtcr2,
|
|
@@ -117822,6 +117823,9 @@ a=end-of-candidates
|
|
|
117822
117823
|
}
|
|
117823
117824
|
};
|
|
117824
117825
|
|
|
117826
|
+
// src/core/btcr2-update.ts
|
|
117827
|
+
init_shim();
|
|
117828
|
+
|
|
117825
117829
|
// src/core/did-sender-resolver.ts
|
|
117826
117830
|
init_shim();
|
|
117827
117831
|
function resolveBtcr2SenderPk(did) {
|
|
@@ -118140,9 +118144,9 @@ a=end-of-candidates
|
|
|
118140
118144
|
}
|
|
118141
118145
|
/**
|
|
118142
118146
|
* Add a proof to a document.
|
|
118143
|
-
* @param {
|
|
118144
|
-
* @param {
|
|
118145
|
-
* @returns {
|
|
118147
|
+
* @param {UnsecuredDocument} unsignedDocument The document to add the proof to.
|
|
118148
|
+
* @param {DataIntegrityProofOptions} config The proof options for generating the proof.
|
|
118149
|
+
* @returns {SecuredDocument} A document with a proof added.
|
|
118146
118150
|
*/
|
|
118147
118151
|
addProof(unsignedDocument, config) {
|
|
118148
118152
|
const proof = this.cryptosuite.createProof(unsignedDocument, config);
|
|
@@ -118235,7 +118239,7 @@ a=end-of-candidates
|
|
|
118235
118239
|
/**
|
|
118236
118240
|
* Create a proof for an insecure document.
|
|
118237
118241
|
* @param {DidUpdatePayload} document The document to create a proof for.
|
|
118238
|
-
* @param {
|
|
118242
|
+
* @param {DataIntegrityProofOptions} config The options to use when creating the proof.
|
|
118239
118243
|
* @returns {DataIntegrityProofObject} The proof for the document.
|
|
118240
118244
|
*/
|
|
118241
118245
|
createProof(document2, config) {
|
|
@@ -118252,7 +118256,7 @@ a=end-of-candidates
|
|
|
118252
118256
|
}
|
|
118253
118257
|
/**
|
|
118254
118258
|
* Verify a proof for a secure document.
|
|
118255
|
-
* @param {
|
|
118259
|
+
* @param {SecuredDocument} secureDocument The secured document to verify.
|
|
118256
118260
|
* @returns {VerificationResult} The result of the verification.
|
|
118257
118261
|
*/
|
|
118258
118262
|
verifyProof(secureDocument) {
|
|
@@ -118267,8 +118271,8 @@ a=end-of-candidates
|
|
|
118267
118271
|
}
|
|
118268
118272
|
/**
|
|
118269
118273
|
* Transform a document into canonical form.
|
|
118270
|
-
* @param {
|
|
118271
|
-
* @param {
|
|
118274
|
+
* @param {UnsecuredDocument} document The document to transform.
|
|
118275
|
+
* @param {DataIntegrityProofOptions} config The config to use when transforming the document.
|
|
118272
118276
|
* @returns {string} The canonicalized document.
|
|
118273
118277
|
* @throws {MethodError} if the document cannot be transformed.
|
|
118274
118278
|
*/
|
|
@@ -118295,7 +118299,7 @@ a=end-of-candidates
|
|
|
118295
118299
|
}
|
|
118296
118300
|
/**
|
|
118297
118301
|
* Configure the proof by canonicalzing it.
|
|
118298
|
-
* @param {
|
|
118302
|
+
* @param {DataIntegrityProofOptions} config The config to use when transforming the proof.
|
|
118299
118303
|
* @returns {string} The canonicalized proof configuration.
|
|
118300
118304
|
* @throws {CryptosuiteError} if the proof configuration cannot be canonicalized.
|
|
118301
118305
|
*/
|
|
@@ -118315,7 +118319,7 @@ a=end-of-candidates
|
|
|
118315
118319
|
/**
|
|
118316
118320
|
* Serialize the proof into a byte array.
|
|
118317
118321
|
* @param {HashBytes} hash The canonicalized proof configuration.
|
|
118318
|
-
* @param {
|
|
118322
|
+
* @param {DataIntegrityProofOptions} config The config to use when serializing the proof.
|
|
118319
118323
|
* @returns {SignatureBytes} The serialized proof.
|
|
118320
118324
|
* @throws {CryptosuiteError} if the multikey does not match the verification method.
|
|
118321
118325
|
*/
|
|
@@ -118329,7 +118333,7 @@ a=end-of-candidates
|
|
|
118329
118333
|
* Verify the proof by comparing the hash of the proof configuration and document to the proof bytes.
|
|
118330
118334
|
* @param {HashBytes} hash The canonicalized proof configuration and document hash.
|
|
118331
118335
|
* @param {SignatureBytes} signature The proof bytes to verify against.
|
|
118332
|
-
* @param {
|
|
118336
|
+
* @param {DataIntegrityProofOptions} config The config to use when verifying the proof.
|
|
118333
118337
|
* @returns {boolean} True if the proof is verified, false otherwise.
|
|
118334
118338
|
* @throws {CryptosuiteError} if the multikey does not match the verification method.
|
|
118335
118339
|
*/
|
|
@@ -119286,7 +119290,8 @@ a=end-of-candidates
|
|
|
119286
119290
|
return new Resolver(didComponents, sidecarData, currentDocument, {
|
|
119287
119291
|
versionId: resolutionOptions.versionId,
|
|
119288
119292
|
versionTime: resolutionOptions.versionTime,
|
|
119289
|
-
genesisDocument: resolutionOptions.sidecar?.genesisDocument
|
|
119293
|
+
genesisDocument: resolutionOptions.sidecar?.genesisDocument,
|
|
119294
|
+
maxDiscoveryRounds: resolutionOptions.maxDiscoveryRounds
|
|
119290
119295
|
});
|
|
119291
119296
|
}
|
|
119292
119297
|
/**
|
|
@@ -119395,6 +119400,21 @@ a=end-of-candidates
|
|
|
119395
119400
|
|
|
119396
119401
|
// src/core/resolver.ts
|
|
119397
119402
|
init_utils2();
|
|
119403
|
+
var DEFAULT_MAX_DISCOVERY_ROUNDS = 10;
|
|
119404
|
+
function isRecord(value2) {
|
|
119405
|
+
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
119406
|
+
}
|
|
119407
|
+
function isCASAnnouncement(value2) {
|
|
119408
|
+
return isRecord(value2) && Object.values(value2).every((v) => typeof v === "string");
|
|
119409
|
+
}
|
|
119410
|
+
function isSignedBTCR2Update(value2) {
|
|
119411
|
+
if (!isRecord(value2)) return false;
|
|
119412
|
+
return Array.isArray(value2.patch) && typeof value2.sourceHash === "string" && typeof value2.targetHash === "string" && typeof value2.targetVersionId === "number" && isRecord(value2.proof);
|
|
119413
|
+
}
|
|
119414
|
+
function isSMTProof(value2) {
|
|
119415
|
+
if (!isRecord(value2)) return false;
|
|
119416
|
+
return typeof value2.id === "string" && typeof value2.collapsed === "string" && Array.isArray(value2.hashes);
|
|
119417
|
+
}
|
|
119398
119418
|
var Resolver = class _Resolver {
|
|
119399
119419
|
// --- Immutable inputs ---
|
|
119400
119420
|
#didComponents;
|
|
@@ -119412,6 +119432,10 @@ a=end-of-candidates
|
|
|
119412
119432
|
#requestCache = /* @__PURE__ */ new Set();
|
|
119413
119433
|
#unsortedUpdates = [];
|
|
119414
119434
|
#resolvedResponse = null;
|
|
119435
|
+
/** Upper bound on multi-round beacon-discovery passes; see {@link DEFAULT_MAX_DISCOVERY_ROUNDS}. */
|
|
119436
|
+
#maxDiscoveryRounds;
|
|
119437
|
+
/** Count of beacon-discovery passes driven by updates adding new beacon services. */
|
|
119438
|
+
#discoveryRounds = 0;
|
|
119415
119439
|
/**
|
|
119416
119440
|
* @internal Use {@link DidBtcr2.resolve} to create instances.
|
|
119417
119441
|
*/
|
|
@@ -119421,6 +119445,7 @@ a=end-of-candidates
|
|
|
119421
119445
|
this.#currentDocument = currentDocument;
|
|
119422
119446
|
this.#versionId = options2?.versionId;
|
|
119423
119447
|
this.#versionTime = options2?.versionTime;
|
|
119448
|
+
this.#maxDiscoveryRounds = options2?.maxDiscoveryRounds ?? DEFAULT_MAX_DISCOVERY_ROUNDS;
|
|
119424
119449
|
if (options2?.genesisDocument) {
|
|
119425
119450
|
this.#providedGenesisDocument = options2.genesisDocument;
|
|
119426
119451
|
}
|
|
@@ -119735,6 +119760,13 @@ a=end-of-candidates
|
|
|
119735
119760
|
return !this.#requestCache.has(address);
|
|
119736
119761
|
});
|
|
119737
119762
|
if (hasNewServices) {
|
|
119763
|
+
if (++this.#discoveryRounds > this.#maxDiscoveryRounds) {
|
|
119764
|
+
throw new ResolveError(
|
|
119765
|
+
`Exceeded maximum beacon-discovery rounds (${this.#maxDiscoveryRounds}); the DID document may chain beacon services without terminating.`,
|
|
119766
|
+
INVALID_DID_DOCUMENT,
|
|
119767
|
+
{ maxDiscoveryRounds: this.#maxDiscoveryRounds }
|
|
119768
|
+
);
|
|
119769
|
+
}
|
|
119738
119770
|
this.#phase = "BeaconDiscovery" /* BeaconDiscovery */;
|
|
119739
119771
|
continue;
|
|
119740
119772
|
}
|
|
@@ -119761,38 +119793,84 @@ a=end-of-candidates
|
|
|
119761
119793
|
provide(need, data) {
|
|
119762
119794
|
switch (need.kind) {
|
|
119763
119795
|
case "NeedGenesisDocument": {
|
|
119796
|
+
if (!isRecord(data)) {
|
|
119797
|
+
throw new ResolveError(
|
|
119798
|
+
"Provided data for NeedGenesisDocument must be a document object.",
|
|
119799
|
+
INVALID_DID_UPDATE,
|
|
119800
|
+
{ kind: need.kind }
|
|
119801
|
+
);
|
|
119802
|
+
}
|
|
119764
119803
|
this.#providedGenesisDocument = data;
|
|
119765
119804
|
break;
|
|
119766
119805
|
}
|
|
119767
119806
|
case "NeedBeaconSignals": {
|
|
119768
|
-
|
|
119769
|
-
|
|
119807
|
+
if (!(data instanceof Map)) {
|
|
119808
|
+
throw new ResolveError(
|
|
119809
|
+
"Provided data for NeedBeaconSignals must be a Map of beacon services to signals.",
|
|
119810
|
+
INVALID_DID_UPDATE,
|
|
119811
|
+
{ kind: need.kind }
|
|
119812
|
+
);
|
|
119813
|
+
}
|
|
119814
|
+
for (const [service, serviceSignals] of data) {
|
|
119770
119815
|
this.#beaconServicesSignals.set(service, serviceSignals);
|
|
119771
119816
|
}
|
|
119772
119817
|
break;
|
|
119773
119818
|
}
|
|
119774
119819
|
case "NeedCASAnnouncement": {
|
|
119775
|
-
|
|
119776
|
-
|
|
119820
|
+
if (!isCASAnnouncement(data)) {
|
|
119821
|
+
throw new ResolveError(
|
|
119822
|
+
"Provided data for NeedCASAnnouncement is not a CAS announcement.",
|
|
119823
|
+
INVALID_DID_UPDATE,
|
|
119824
|
+
{ kind: need.kind }
|
|
119825
|
+
);
|
|
119826
|
+
}
|
|
119827
|
+
const announcementHash = canonicalHash(data, { encoding: "hex" });
|
|
119828
|
+
if (announcementHash !== need.announcementHash) {
|
|
119829
|
+
throw new ResolveError(
|
|
119830
|
+
`CAS announcement hash mismatch: expected ${need.announcementHash}, got ${announcementHash}.`,
|
|
119831
|
+
INVALID_DID_UPDATE,
|
|
119832
|
+
{ expected: need.announcementHash, actual: announcementHash }
|
|
119833
|
+
);
|
|
119834
|
+
}
|
|
119835
|
+
this.#sidecarData.casMap.set(announcementHash, data);
|
|
119777
119836
|
break;
|
|
119778
119837
|
}
|
|
119779
119838
|
case "NeedSignedUpdate": {
|
|
119780
|
-
|
|
119781
|
-
|
|
119839
|
+
if (!isSignedBTCR2Update(data)) {
|
|
119840
|
+
throw new ResolveError(
|
|
119841
|
+
"Provided data for NeedSignedUpdate is not a signed BTCR2 update.",
|
|
119842
|
+
INVALID_DID_UPDATE,
|
|
119843
|
+
{ kind: need.kind }
|
|
119844
|
+
);
|
|
119845
|
+
}
|
|
119846
|
+
const updateHash = canonicalHash(data, { encoding: "hex" });
|
|
119847
|
+
if (updateHash !== need.updateHash) {
|
|
119848
|
+
throw new ResolveError(
|
|
119849
|
+
`Signed update hash mismatch: expected ${need.updateHash}, got ${updateHash}.`,
|
|
119850
|
+
INVALID_DID_UPDATE,
|
|
119851
|
+
{ expected: need.updateHash, actual: updateHash }
|
|
119852
|
+
);
|
|
119853
|
+
}
|
|
119854
|
+
this.#sidecarData.updateMap.set(updateHash, data);
|
|
119782
119855
|
break;
|
|
119783
119856
|
}
|
|
119784
119857
|
case "NeedSMTProof": {
|
|
119785
|
-
|
|
119786
|
-
|
|
119787
|
-
|
|
119788
|
-
|
|
119858
|
+
if (!isSMTProof(data)) {
|
|
119859
|
+
throw new ResolveError(
|
|
119860
|
+
"Provided data for NeedSMTProof is not an SMT proof.",
|
|
119861
|
+
INVALID_DID_UPDATE,
|
|
119862
|
+
{ kind: need.kind }
|
|
119863
|
+
);
|
|
119864
|
+
}
|
|
119865
|
+
const proofIdHex = encode(decode(data.id, "base64urlnopad"), "hex");
|
|
119866
|
+
if (proofIdHex !== need.smtRootHash) {
|
|
119789
119867
|
throw new ResolveError(
|
|
119790
|
-
`SMT proof root hash mismatch: expected ${
|
|
119868
|
+
`SMT proof root hash mismatch: expected ${need.smtRootHash}, got ${proofIdHex}`,
|
|
119791
119869
|
INVALID_DID_UPDATE,
|
|
119792
|
-
{ expected:
|
|
119870
|
+
{ expected: need.smtRootHash, actual: proofIdHex }
|
|
119793
119871
|
);
|
|
119794
119872
|
}
|
|
119795
|
-
this.#sidecarData.smtMap.set(
|
|
119873
|
+
this.#sidecarData.smtMap.set(need.smtRootHash, data);
|
|
119796
119874
|
break;
|
|
119797
119875
|
}
|
|
119798
119876
|
}
|
package/dist/browser.mjs
CHANGED
|
@@ -117775,6 +117775,9 @@ var BeaconSignalDiscovery = class {
|
|
|
117775
117775
|
}
|
|
117776
117776
|
};
|
|
117777
117777
|
|
|
117778
|
+
// src/core/btcr2-update.ts
|
|
117779
|
+
init_shim();
|
|
117780
|
+
|
|
117778
117781
|
// src/core/did-sender-resolver.ts
|
|
117779
117782
|
init_shim();
|
|
117780
117783
|
function resolveBtcr2SenderPk(did) {
|
|
@@ -118093,9 +118096,9 @@ var BIP340DataIntegrityProof = class {
|
|
|
118093
118096
|
}
|
|
118094
118097
|
/**
|
|
118095
118098
|
* Add a proof to a document.
|
|
118096
|
-
* @param {
|
|
118097
|
-
* @param {
|
|
118098
|
-
* @returns {
|
|
118099
|
+
* @param {UnsecuredDocument} unsignedDocument The document to add the proof to.
|
|
118100
|
+
* @param {DataIntegrityProofOptions} config The proof options for generating the proof.
|
|
118101
|
+
* @returns {SecuredDocument} A document with a proof added.
|
|
118099
118102
|
*/
|
|
118100
118103
|
addProof(unsignedDocument, config) {
|
|
118101
118104
|
const proof = this.cryptosuite.createProof(unsignedDocument, config);
|
|
@@ -118188,7 +118191,7 @@ var BIP340Cryptosuite = class {
|
|
|
118188
118191
|
/**
|
|
118189
118192
|
* Create a proof for an insecure document.
|
|
118190
118193
|
* @param {DidUpdatePayload} document The document to create a proof for.
|
|
118191
|
-
* @param {
|
|
118194
|
+
* @param {DataIntegrityProofOptions} config The options to use when creating the proof.
|
|
118192
118195
|
* @returns {DataIntegrityProofObject} The proof for the document.
|
|
118193
118196
|
*/
|
|
118194
118197
|
createProof(document2, config) {
|
|
@@ -118205,7 +118208,7 @@ var BIP340Cryptosuite = class {
|
|
|
118205
118208
|
}
|
|
118206
118209
|
/**
|
|
118207
118210
|
* Verify a proof for a secure document.
|
|
118208
|
-
* @param {
|
|
118211
|
+
* @param {SecuredDocument} secureDocument The secured document to verify.
|
|
118209
118212
|
* @returns {VerificationResult} The result of the verification.
|
|
118210
118213
|
*/
|
|
118211
118214
|
verifyProof(secureDocument) {
|
|
@@ -118220,8 +118223,8 @@ var BIP340Cryptosuite = class {
|
|
|
118220
118223
|
}
|
|
118221
118224
|
/**
|
|
118222
118225
|
* Transform a document into canonical form.
|
|
118223
|
-
* @param {
|
|
118224
|
-
* @param {
|
|
118226
|
+
* @param {UnsecuredDocument} document The document to transform.
|
|
118227
|
+
* @param {DataIntegrityProofOptions} config The config to use when transforming the document.
|
|
118225
118228
|
* @returns {string} The canonicalized document.
|
|
118226
118229
|
* @throws {MethodError} if the document cannot be transformed.
|
|
118227
118230
|
*/
|
|
@@ -118248,7 +118251,7 @@ var BIP340Cryptosuite = class {
|
|
|
118248
118251
|
}
|
|
118249
118252
|
/**
|
|
118250
118253
|
* Configure the proof by canonicalzing it.
|
|
118251
|
-
* @param {
|
|
118254
|
+
* @param {DataIntegrityProofOptions} config The config to use when transforming the proof.
|
|
118252
118255
|
* @returns {string} The canonicalized proof configuration.
|
|
118253
118256
|
* @throws {CryptosuiteError} if the proof configuration cannot be canonicalized.
|
|
118254
118257
|
*/
|
|
@@ -118268,7 +118271,7 @@ var BIP340Cryptosuite = class {
|
|
|
118268
118271
|
/**
|
|
118269
118272
|
* Serialize the proof into a byte array.
|
|
118270
118273
|
* @param {HashBytes} hash The canonicalized proof configuration.
|
|
118271
|
-
* @param {
|
|
118274
|
+
* @param {DataIntegrityProofOptions} config The config to use when serializing the proof.
|
|
118272
118275
|
* @returns {SignatureBytes} The serialized proof.
|
|
118273
118276
|
* @throws {CryptosuiteError} if the multikey does not match the verification method.
|
|
118274
118277
|
*/
|
|
@@ -118282,7 +118285,7 @@ var BIP340Cryptosuite = class {
|
|
|
118282
118285
|
* Verify the proof by comparing the hash of the proof configuration and document to the proof bytes.
|
|
118283
118286
|
* @param {HashBytes} hash The canonicalized proof configuration and document hash.
|
|
118284
118287
|
* @param {SignatureBytes} signature The proof bytes to verify against.
|
|
118285
|
-
* @param {
|
|
118288
|
+
* @param {DataIntegrityProofOptions} config The config to use when verifying the proof.
|
|
118286
118289
|
* @returns {boolean} True if the proof is verified, false otherwise.
|
|
118287
118290
|
* @throws {CryptosuiteError} if the multikey does not match the verification method.
|
|
118288
118291
|
*/
|
|
@@ -119239,7 +119242,8 @@ var DidBtcr2 = class {
|
|
|
119239
119242
|
return new Resolver(didComponents, sidecarData, currentDocument, {
|
|
119240
119243
|
versionId: resolutionOptions.versionId,
|
|
119241
119244
|
versionTime: resolutionOptions.versionTime,
|
|
119242
|
-
genesisDocument: resolutionOptions.sidecar?.genesisDocument
|
|
119245
|
+
genesisDocument: resolutionOptions.sidecar?.genesisDocument,
|
|
119246
|
+
maxDiscoveryRounds: resolutionOptions.maxDiscoveryRounds
|
|
119243
119247
|
});
|
|
119244
119248
|
}
|
|
119245
119249
|
/**
|
|
@@ -119348,6 +119352,21 @@ var DidBtcr2 = class {
|
|
|
119348
119352
|
|
|
119349
119353
|
// src/core/resolver.ts
|
|
119350
119354
|
init_utils2();
|
|
119355
|
+
var DEFAULT_MAX_DISCOVERY_ROUNDS = 10;
|
|
119356
|
+
function isRecord(value2) {
|
|
119357
|
+
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
119358
|
+
}
|
|
119359
|
+
function isCASAnnouncement(value2) {
|
|
119360
|
+
return isRecord(value2) && Object.values(value2).every((v) => typeof v === "string");
|
|
119361
|
+
}
|
|
119362
|
+
function isSignedBTCR2Update(value2) {
|
|
119363
|
+
if (!isRecord(value2)) return false;
|
|
119364
|
+
return Array.isArray(value2.patch) && typeof value2.sourceHash === "string" && typeof value2.targetHash === "string" && typeof value2.targetVersionId === "number" && isRecord(value2.proof);
|
|
119365
|
+
}
|
|
119366
|
+
function isSMTProof(value2) {
|
|
119367
|
+
if (!isRecord(value2)) return false;
|
|
119368
|
+
return typeof value2.id === "string" && typeof value2.collapsed === "string" && Array.isArray(value2.hashes);
|
|
119369
|
+
}
|
|
119351
119370
|
var Resolver = class _Resolver {
|
|
119352
119371
|
// --- Immutable inputs ---
|
|
119353
119372
|
#didComponents;
|
|
@@ -119365,6 +119384,10 @@ var Resolver = class _Resolver {
|
|
|
119365
119384
|
#requestCache = /* @__PURE__ */ new Set();
|
|
119366
119385
|
#unsortedUpdates = [];
|
|
119367
119386
|
#resolvedResponse = null;
|
|
119387
|
+
/** Upper bound on multi-round beacon-discovery passes; see {@link DEFAULT_MAX_DISCOVERY_ROUNDS}. */
|
|
119388
|
+
#maxDiscoveryRounds;
|
|
119389
|
+
/** Count of beacon-discovery passes driven by updates adding new beacon services. */
|
|
119390
|
+
#discoveryRounds = 0;
|
|
119368
119391
|
/**
|
|
119369
119392
|
* @internal Use {@link DidBtcr2.resolve} to create instances.
|
|
119370
119393
|
*/
|
|
@@ -119374,6 +119397,7 @@ var Resolver = class _Resolver {
|
|
|
119374
119397
|
this.#currentDocument = currentDocument;
|
|
119375
119398
|
this.#versionId = options2?.versionId;
|
|
119376
119399
|
this.#versionTime = options2?.versionTime;
|
|
119400
|
+
this.#maxDiscoveryRounds = options2?.maxDiscoveryRounds ?? DEFAULT_MAX_DISCOVERY_ROUNDS;
|
|
119377
119401
|
if (options2?.genesisDocument) {
|
|
119378
119402
|
this.#providedGenesisDocument = options2.genesisDocument;
|
|
119379
119403
|
}
|
|
@@ -119688,6 +119712,13 @@ var Resolver = class _Resolver {
|
|
|
119688
119712
|
return !this.#requestCache.has(address);
|
|
119689
119713
|
});
|
|
119690
119714
|
if (hasNewServices) {
|
|
119715
|
+
if (++this.#discoveryRounds > this.#maxDiscoveryRounds) {
|
|
119716
|
+
throw new ResolveError(
|
|
119717
|
+
`Exceeded maximum beacon-discovery rounds (${this.#maxDiscoveryRounds}); the DID document may chain beacon services without terminating.`,
|
|
119718
|
+
INVALID_DID_DOCUMENT,
|
|
119719
|
+
{ maxDiscoveryRounds: this.#maxDiscoveryRounds }
|
|
119720
|
+
);
|
|
119721
|
+
}
|
|
119691
119722
|
this.#phase = "BeaconDiscovery" /* BeaconDiscovery */;
|
|
119692
119723
|
continue;
|
|
119693
119724
|
}
|
|
@@ -119714,38 +119745,84 @@ var Resolver = class _Resolver {
|
|
|
119714
119745
|
provide(need, data) {
|
|
119715
119746
|
switch (need.kind) {
|
|
119716
119747
|
case "NeedGenesisDocument": {
|
|
119748
|
+
if (!isRecord(data)) {
|
|
119749
|
+
throw new ResolveError(
|
|
119750
|
+
"Provided data for NeedGenesisDocument must be a document object.",
|
|
119751
|
+
INVALID_DID_UPDATE,
|
|
119752
|
+
{ kind: need.kind }
|
|
119753
|
+
);
|
|
119754
|
+
}
|
|
119717
119755
|
this.#providedGenesisDocument = data;
|
|
119718
119756
|
break;
|
|
119719
119757
|
}
|
|
119720
119758
|
case "NeedBeaconSignals": {
|
|
119721
|
-
|
|
119722
|
-
|
|
119759
|
+
if (!(data instanceof Map)) {
|
|
119760
|
+
throw new ResolveError(
|
|
119761
|
+
"Provided data for NeedBeaconSignals must be a Map of beacon services to signals.",
|
|
119762
|
+
INVALID_DID_UPDATE,
|
|
119763
|
+
{ kind: need.kind }
|
|
119764
|
+
);
|
|
119765
|
+
}
|
|
119766
|
+
for (const [service, serviceSignals] of data) {
|
|
119723
119767
|
this.#beaconServicesSignals.set(service, serviceSignals);
|
|
119724
119768
|
}
|
|
119725
119769
|
break;
|
|
119726
119770
|
}
|
|
119727
119771
|
case "NeedCASAnnouncement": {
|
|
119728
|
-
|
|
119729
|
-
|
|
119772
|
+
if (!isCASAnnouncement(data)) {
|
|
119773
|
+
throw new ResolveError(
|
|
119774
|
+
"Provided data for NeedCASAnnouncement is not a CAS announcement.",
|
|
119775
|
+
INVALID_DID_UPDATE,
|
|
119776
|
+
{ kind: need.kind }
|
|
119777
|
+
);
|
|
119778
|
+
}
|
|
119779
|
+
const announcementHash = canonicalHash(data, { encoding: "hex" });
|
|
119780
|
+
if (announcementHash !== need.announcementHash) {
|
|
119781
|
+
throw new ResolveError(
|
|
119782
|
+
`CAS announcement hash mismatch: expected ${need.announcementHash}, got ${announcementHash}.`,
|
|
119783
|
+
INVALID_DID_UPDATE,
|
|
119784
|
+
{ expected: need.announcementHash, actual: announcementHash }
|
|
119785
|
+
);
|
|
119786
|
+
}
|
|
119787
|
+
this.#sidecarData.casMap.set(announcementHash, data);
|
|
119730
119788
|
break;
|
|
119731
119789
|
}
|
|
119732
119790
|
case "NeedSignedUpdate": {
|
|
119733
|
-
|
|
119734
|
-
|
|
119791
|
+
if (!isSignedBTCR2Update(data)) {
|
|
119792
|
+
throw new ResolveError(
|
|
119793
|
+
"Provided data for NeedSignedUpdate is not a signed BTCR2 update.",
|
|
119794
|
+
INVALID_DID_UPDATE,
|
|
119795
|
+
{ kind: need.kind }
|
|
119796
|
+
);
|
|
119797
|
+
}
|
|
119798
|
+
const updateHash = canonicalHash(data, { encoding: "hex" });
|
|
119799
|
+
if (updateHash !== need.updateHash) {
|
|
119800
|
+
throw new ResolveError(
|
|
119801
|
+
`Signed update hash mismatch: expected ${need.updateHash}, got ${updateHash}.`,
|
|
119802
|
+
INVALID_DID_UPDATE,
|
|
119803
|
+
{ expected: need.updateHash, actual: updateHash }
|
|
119804
|
+
);
|
|
119805
|
+
}
|
|
119806
|
+
this.#sidecarData.updateMap.set(updateHash, data);
|
|
119735
119807
|
break;
|
|
119736
119808
|
}
|
|
119737
119809
|
case "NeedSMTProof": {
|
|
119738
|
-
|
|
119739
|
-
|
|
119740
|
-
|
|
119741
|
-
|
|
119810
|
+
if (!isSMTProof(data)) {
|
|
119811
|
+
throw new ResolveError(
|
|
119812
|
+
"Provided data for NeedSMTProof is not an SMT proof.",
|
|
119813
|
+
INVALID_DID_UPDATE,
|
|
119814
|
+
{ kind: need.kind }
|
|
119815
|
+
);
|
|
119816
|
+
}
|
|
119817
|
+
const proofIdHex = encode(decode(data.id, "base64urlnopad"), "hex");
|
|
119818
|
+
if (proofIdHex !== need.smtRootHash) {
|
|
119742
119819
|
throw new ResolveError(
|
|
119743
|
-
`SMT proof root hash mismatch: expected ${
|
|
119820
|
+
`SMT proof root hash mismatch: expected ${need.smtRootHash}, got ${proofIdHex}`,
|
|
119744
119821
|
INVALID_DID_UPDATE,
|
|
119745
|
-
{ expected:
|
|
119822
|
+
{ expected: need.smtRootHash, actual: proofIdHex }
|
|
119746
119823
|
);
|
|
119747
119824
|
}
|
|
119748
|
-
this.#sidecarData.smtMap.set(
|
|
119825
|
+
this.#sidecarData.smtMap.set(need.smtRootHash, data);
|
|
119749
119826
|
break;
|
|
119750
119827
|
}
|
|
119751
119828
|
}
|
|
@@ -119822,6 +119899,7 @@ export {
|
|
|
119822
119899
|
CASBeaconError,
|
|
119823
119900
|
CHANGE_OUTPUT_VBYTES,
|
|
119824
119901
|
DEFAULT_FEE_ESTIMATOR,
|
|
119902
|
+
DEFAULT_MAX_DISCOVERY_ROUNDS,
|
|
119825
119903
|
DID_REGEX,
|
|
119826
119904
|
DUST_LIMIT_SATS,
|
|
119827
119905
|
DidBtcr2,
|
package/dist/cjs/index.js
CHANGED
|
@@ -42,6 +42,7 @@ __export(index_exports, {
|
|
|
42
42
|
CASBeaconError: () => CASBeaconError,
|
|
43
43
|
CHANGE_OUTPUT_VBYTES: () => CHANGE_OUTPUT_VBYTES,
|
|
44
44
|
DEFAULT_FEE_ESTIMATOR: () => DEFAULT_FEE_ESTIMATOR,
|
|
45
|
+
DEFAULT_MAX_DISCOVERY_ROUNDS: () => DEFAULT_MAX_DISCOVERY_ROUNDS,
|
|
45
46
|
DID_REGEX: () => DID_REGEX,
|
|
46
47
|
DUST_LIMIT_SATS: () => DUST_LIMIT_SATS,
|
|
47
48
|
DidBtcr2: () => DidBtcr2,
|
|
@@ -2913,7 +2914,8 @@ var DidBtcr2 = class {
|
|
|
2913
2914
|
return new Resolver(didComponents, sidecarData, currentDocument, {
|
|
2914
2915
|
versionId: resolutionOptions.versionId,
|
|
2915
2916
|
versionTime: resolutionOptions.versionTime,
|
|
2916
|
-
genesisDocument: resolutionOptions.sidecar?.genesisDocument
|
|
2917
|
+
genesisDocument: resolutionOptions.sidecar?.genesisDocument,
|
|
2918
|
+
maxDiscoveryRounds: resolutionOptions.maxDiscoveryRounds
|
|
2917
2919
|
});
|
|
2918
2920
|
}
|
|
2919
2921
|
/**
|
|
@@ -3022,6 +3024,21 @@ var DidBtcr2 = class {
|
|
|
3022
3024
|
|
|
3023
3025
|
// src/core/resolver.ts
|
|
3024
3026
|
var import_utils6 = require("@noble/curves/utils.js");
|
|
3027
|
+
var DEFAULT_MAX_DISCOVERY_ROUNDS = 10;
|
|
3028
|
+
function isRecord(value) {
|
|
3029
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
3030
|
+
}
|
|
3031
|
+
function isCASAnnouncement(value) {
|
|
3032
|
+
return isRecord(value) && Object.values(value).every((v) => typeof v === "string");
|
|
3033
|
+
}
|
|
3034
|
+
function isSignedBTCR2Update(value) {
|
|
3035
|
+
if (!isRecord(value)) return false;
|
|
3036
|
+
return Array.isArray(value.patch) && typeof value.sourceHash === "string" && typeof value.targetHash === "string" && typeof value.targetVersionId === "number" && isRecord(value.proof);
|
|
3037
|
+
}
|
|
3038
|
+
function isSMTProof(value) {
|
|
3039
|
+
if (!isRecord(value)) return false;
|
|
3040
|
+
return typeof value.id === "string" && typeof value.collapsed === "string" && Array.isArray(value.hashes);
|
|
3041
|
+
}
|
|
3025
3042
|
var Resolver = class _Resolver {
|
|
3026
3043
|
// --- Immutable inputs ---
|
|
3027
3044
|
#didComponents;
|
|
@@ -3039,6 +3056,10 @@ var Resolver = class _Resolver {
|
|
|
3039
3056
|
#requestCache = /* @__PURE__ */ new Set();
|
|
3040
3057
|
#unsortedUpdates = [];
|
|
3041
3058
|
#resolvedResponse = null;
|
|
3059
|
+
/** Upper bound on multi-round beacon-discovery passes; see {@link DEFAULT_MAX_DISCOVERY_ROUNDS}. */
|
|
3060
|
+
#maxDiscoveryRounds;
|
|
3061
|
+
/** Count of beacon-discovery passes driven by updates adding new beacon services. */
|
|
3062
|
+
#discoveryRounds = 0;
|
|
3042
3063
|
/**
|
|
3043
3064
|
* @internal Use {@link DidBtcr2.resolve} to create instances.
|
|
3044
3065
|
*/
|
|
@@ -3048,6 +3069,7 @@ var Resolver = class _Resolver {
|
|
|
3048
3069
|
this.#currentDocument = currentDocument;
|
|
3049
3070
|
this.#versionId = options?.versionId;
|
|
3050
3071
|
this.#versionTime = options?.versionTime;
|
|
3072
|
+
this.#maxDiscoveryRounds = options?.maxDiscoveryRounds ?? DEFAULT_MAX_DISCOVERY_ROUNDS;
|
|
3051
3073
|
if (options?.genesisDocument) {
|
|
3052
3074
|
this.#providedGenesisDocument = options.genesisDocument;
|
|
3053
3075
|
}
|
|
@@ -3362,6 +3384,13 @@ var Resolver = class _Resolver {
|
|
|
3362
3384
|
return !this.#requestCache.has(address);
|
|
3363
3385
|
});
|
|
3364
3386
|
if (hasNewServices) {
|
|
3387
|
+
if (++this.#discoveryRounds > this.#maxDiscoveryRounds) {
|
|
3388
|
+
throw new import_common12.ResolveError(
|
|
3389
|
+
`Exceeded maximum beacon-discovery rounds (${this.#maxDiscoveryRounds}); the DID document may chain beacon services without terminating.`,
|
|
3390
|
+
import_common12.INVALID_DID_DOCUMENT,
|
|
3391
|
+
{ maxDiscoveryRounds: this.#maxDiscoveryRounds }
|
|
3392
|
+
);
|
|
3393
|
+
}
|
|
3365
3394
|
this.#phase = "BeaconDiscovery" /* BeaconDiscovery */;
|
|
3366
3395
|
continue;
|
|
3367
3396
|
}
|
|
@@ -3388,38 +3417,84 @@ var Resolver = class _Resolver {
|
|
|
3388
3417
|
provide(need, data) {
|
|
3389
3418
|
switch (need.kind) {
|
|
3390
3419
|
case "NeedGenesisDocument": {
|
|
3420
|
+
if (!isRecord(data)) {
|
|
3421
|
+
throw new import_common12.ResolveError(
|
|
3422
|
+
"Provided data for NeedGenesisDocument must be a document object.",
|
|
3423
|
+
import_common12.INVALID_DID_UPDATE,
|
|
3424
|
+
{ kind: need.kind }
|
|
3425
|
+
);
|
|
3426
|
+
}
|
|
3391
3427
|
this.#providedGenesisDocument = data;
|
|
3392
3428
|
break;
|
|
3393
3429
|
}
|
|
3394
3430
|
case "NeedBeaconSignals": {
|
|
3395
|
-
|
|
3396
|
-
|
|
3431
|
+
if (!(data instanceof Map)) {
|
|
3432
|
+
throw new import_common12.ResolveError(
|
|
3433
|
+
"Provided data for NeedBeaconSignals must be a Map of beacon services to signals.",
|
|
3434
|
+
import_common12.INVALID_DID_UPDATE,
|
|
3435
|
+
{ kind: need.kind }
|
|
3436
|
+
);
|
|
3437
|
+
}
|
|
3438
|
+
for (const [service, serviceSignals] of data) {
|
|
3397
3439
|
this.#beaconServicesSignals.set(service, serviceSignals);
|
|
3398
3440
|
}
|
|
3399
3441
|
break;
|
|
3400
3442
|
}
|
|
3401
3443
|
case "NeedCASAnnouncement": {
|
|
3402
|
-
|
|
3403
|
-
|
|
3444
|
+
if (!isCASAnnouncement(data)) {
|
|
3445
|
+
throw new import_common12.ResolveError(
|
|
3446
|
+
"Provided data for NeedCASAnnouncement is not a CAS announcement.",
|
|
3447
|
+
import_common12.INVALID_DID_UPDATE,
|
|
3448
|
+
{ kind: need.kind }
|
|
3449
|
+
);
|
|
3450
|
+
}
|
|
3451
|
+
const announcementHash = (0, import_common12.canonicalHash)(data, { encoding: "hex" });
|
|
3452
|
+
if (announcementHash !== need.announcementHash) {
|
|
3453
|
+
throw new import_common12.ResolveError(
|
|
3454
|
+
`CAS announcement hash mismatch: expected ${need.announcementHash}, got ${announcementHash}.`,
|
|
3455
|
+
import_common12.INVALID_DID_UPDATE,
|
|
3456
|
+
{ expected: need.announcementHash, actual: announcementHash }
|
|
3457
|
+
);
|
|
3458
|
+
}
|
|
3459
|
+
this.#sidecarData.casMap.set(announcementHash, data);
|
|
3404
3460
|
break;
|
|
3405
3461
|
}
|
|
3406
3462
|
case "NeedSignedUpdate": {
|
|
3407
|
-
|
|
3408
|
-
|
|
3463
|
+
if (!isSignedBTCR2Update(data)) {
|
|
3464
|
+
throw new import_common12.ResolveError(
|
|
3465
|
+
"Provided data for NeedSignedUpdate is not a signed BTCR2 update.",
|
|
3466
|
+
import_common12.INVALID_DID_UPDATE,
|
|
3467
|
+
{ kind: need.kind }
|
|
3468
|
+
);
|
|
3469
|
+
}
|
|
3470
|
+
const updateHash = (0, import_common12.canonicalHash)(data, { encoding: "hex" });
|
|
3471
|
+
if (updateHash !== need.updateHash) {
|
|
3472
|
+
throw new import_common12.ResolveError(
|
|
3473
|
+
`Signed update hash mismatch: expected ${need.updateHash}, got ${updateHash}.`,
|
|
3474
|
+
import_common12.INVALID_DID_UPDATE,
|
|
3475
|
+
{ expected: need.updateHash, actual: updateHash }
|
|
3476
|
+
);
|
|
3477
|
+
}
|
|
3478
|
+
this.#sidecarData.updateMap.set(updateHash, data);
|
|
3409
3479
|
break;
|
|
3410
3480
|
}
|
|
3411
3481
|
case "NeedSMTProof": {
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3482
|
+
if (!isSMTProof(data)) {
|
|
3483
|
+
throw new import_common12.ResolveError(
|
|
3484
|
+
"Provided data for NeedSMTProof is not an SMT proof.",
|
|
3485
|
+
import_common12.INVALID_DID_UPDATE,
|
|
3486
|
+
{ kind: need.kind }
|
|
3487
|
+
);
|
|
3488
|
+
}
|
|
3489
|
+
const proofIdHex = (0, import_common12.encode)((0, import_common12.decode)(data.id, "base64urlnopad"), "hex");
|
|
3490
|
+
if (proofIdHex !== need.smtRootHash) {
|
|
3416
3491
|
throw new import_common12.ResolveError(
|
|
3417
|
-
`SMT proof root hash mismatch: expected ${
|
|
3492
|
+
`SMT proof root hash mismatch: expected ${need.smtRootHash}, got ${proofIdHex}`,
|
|
3418
3493
|
import_common12.INVALID_DID_UPDATE,
|
|
3419
|
-
{ expected:
|
|
3494
|
+
{ expected: need.smtRootHash, actual: proofIdHex }
|
|
3420
3495
|
);
|
|
3421
3496
|
}
|
|
3422
|
-
this.#sidecarData.smtMap.set(
|
|
3497
|
+
this.#sidecarData.smtMap.set(need.smtRootHash, data);
|
|
3423
3498
|
break;
|
|
3424
3499
|
}
|
|
3425
3500
|
}
|
|
@@ -3494,6 +3569,7 @@ var DidDocumentBuilder = class {
|
|
|
3494
3569
|
CASBeaconError,
|
|
3495
3570
|
CHANGE_OUTPUT_VBYTES,
|
|
3496
3571
|
DEFAULT_FEE_ESTIMATOR,
|
|
3572
|
+
DEFAULT_MAX_DISCOVERY_ROUNDS,
|
|
3497
3573
|
DID_REGEX,
|
|
3498
3574
|
DUST_LIMIT_SATS,
|
|
3499
3575
|
DidBtcr2,
|