@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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@did-btcr2/method",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.42.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",
|
|
@@ -80,11 +80,11 @@
|
|
|
80
80
|
"helia": "^5.5.1",
|
|
81
81
|
"multiformats": "^13.4.2",
|
|
82
82
|
"nostr-tools": "^2.23.3",
|
|
83
|
-
"@did-btcr2/bitcoin": "^0.8.0",
|
|
84
|
-
"@did-btcr2/cryptosuite": "^8.0.0",
|
|
85
|
-
"@did-btcr2/smt": "^0.3.0",
|
|
86
83
|
"@did-btcr2/common": "^9.1.0",
|
|
87
|
-
"@did-btcr2/
|
|
84
|
+
"@did-btcr2/smt": "^0.3.0",
|
|
85
|
+
"@did-btcr2/cryptosuite": "^9.0.0",
|
|
86
|
+
"@did-btcr2/keypair": "^0.13.1",
|
|
87
|
+
"@did-btcr2/bitcoin": "^0.8.0"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
90
|
"@eslint/js": "^9.39.4",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { AddressUtxo, BitcoinConnection, BTCNetwork } from '@did-btcr2/bitcoin';
|
|
2
2
|
import type { KeyBytes } from '@did-btcr2/common';
|
|
3
|
-
import type { SignedBTCR2Update } from '
|
|
3
|
+
import type { SignedBTCR2Update } from '../btcr2-update.js';
|
|
4
4
|
import type { Signer } from '@did-btcr2/keypair';
|
|
5
5
|
import { concatBytes, hexToBytes } from '@noble/hashes/utils.js';
|
|
6
6
|
import { Address, OutScript, p2pkh, p2tr, p2wpkh, Script, SigHash, Transaction } from '@scure/btc-signer';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
2
|
import { canonicalHash, canonicalize, decode, encode, hash } from '@did-btcr2/common';
|
|
3
|
-
import type { SignedBTCR2Update } from '
|
|
3
|
+
import type { SignedBTCR2Update } from '../btcr2-update.js';
|
|
4
4
|
import type { Signer } from '@did-btcr2/keypair';
|
|
5
5
|
import type { BeaconProcessResult, DataNeed } from '../resolver.js';
|
|
6
6
|
import type { SidecarData } from '../types.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
2
|
import { canonicalize, hash } from '@did-btcr2/common';
|
|
3
|
-
import type { SignedBTCR2Update } from '
|
|
3
|
+
import type { SignedBTCR2Update } from '../btcr2-update.js';
|
|
4
4
|
import type { Signer } from '@did-btcr2/keypair';
|
|
5
5
|
import type { BeaconProcessResult, DataNeed } from '../resolver.js';
|
|
6
6
|
import type { SidecarData } from '../types.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
2
|
import { canonicalize } from '@did-btcr2/common';
|
|
3
|
-
import type { SignedBTCR2Update } from '
|
|
3
|
+
import type { SignedBTCR2Update } from '../btcr2-update.js';
|
|
4
4
|
import type { Signer } from '@did-btcr2/keypair';
|
|
5
5
|
import { base64UrlToHash, blockHash, BTCR2MerkleTree, didToIndex, hashToHex, verifySerializedProof } from '@did-btcr2/smt';
|
|
6
6
|
import { randomBytes } from '@noble/hashes/utils';
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import type { PatchOperation } from '@did-btcr2/common';
|
|
2
|
+
import type { DataIntegrityProofObject, DataIntegrityProofOptions } from '@did-btcr2/cryptosuite';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* A {@link https://dcdpr.github.io/did-btcr2/terminology.html#btcr2-update | BTCR2 Update} without a data integrity proof.
|
|
6
|
+
* See {@link https://dcdpr.github.io/did-btcr2/data-structures.html#btcr2-unsigned-update | BTCR2 Unsigned Update (data structure)}.
|
|
7
|
+
*
|
|
8
|
+
* This is the did:btcr2-specific document the generic `@did-btcr2/cryptosuite`
|
|
9
|
+
* suite secures; the suite itself is method-agnostic and knows nothing about it.
|
|
10
|
+
* Declared as a type alias (not an interface) so it satisfies the suite's
|
|
11
|
+
* generic `UnsecuredDocument` (a plain JSON record) constraint.
|
|
12
|
+
*/
|
|
13
|
+
export type UnsignedBTCR2Update = {
|
|
14
|
+
/**
|
|
15
|
+
* JSON-LD context URIs for interpreting this payload, including contexts
|
|
16
|
+
* for ZCAP (capabilities), Data Integrity proofs, and JSON-LD patch ops.
|
|
17
|
+
*/
|
|
18
|
+
'@context': string[];
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* A JSON Patch (or JSON-LD Patch) object defining the mutations to apply to
|
|
22
|
+
* the DID Document. Applying this patch to the current DID Document yields
|
|
23
|
+
* the new DID Document (which must remain valid per DID Core spec).
|
|
24
|
+
*/
|
|
25
|
+
patch: Array<PatchOperation>;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The multihash of the current (source) DID Document, encoded as a multibase
|
|
29
|
+
* base58-btc string. This is a SHA-256 hash of the canonicalized source DID
|
|
30
|
+
* Document, used to ensure the patch is applied to the correct document state.
|
|
31
|
+
*/
|
|
32
|
+
sourceHash: string;
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The multihash of the updated (target) DID Document, encoded as multibase
|
|
36
|
+
* base58-btc. This is the SHA-256 hash of the canonicalized DID Document
|
|
37
|
+
* after applying the patch, used to verify the update result.
|
|
38
|
+
*/
|
|
39
|
+
targetHash: string;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The version number of the DID Document after this update.
|
|
43
|
+
* It is equal to the previous document version + 1.
|
|
44
|
+
*/
|
|
45
|
+
targetVersionId: number;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A Data Integrity proof on a BTCR2 update: the generic proof object plus the
|
|
50
|
+
* ZCAP capability-invocation fields a did:btcr2 update proof carries.
|
|
51
|
+
*/
|
|
52
|
+
export type Btcr2DataIntegrityProof = DataIntegrityProofObject & {
|
|
53
|
+
/** The root capability being invoked, e.g. `urn:zcap:root:<urlencoded-did>`. */
|
|
54
|
+
capability?: string;
|
|
55
|
+
|
|
56
|
+
/** The action performed under the capability, set to `"Write"` for DID document updates. */
|
|
57
|
+
capabilityAction?: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* A {@link https://dcdpr.github.io/did-btcr2/terminology.html#btcr2-signed-update | BTCR2 Update} with a data integrity proof.
|
|
62
|
+
* See {@link https://dcdpr.github.io/did-btcr2/data-structures.html#btcr2-signed-update | BTCR2 Signed Update (data structure)}.
|
|
63
|
+
*/
|
|
64
|
+
export type SignedBTCR2Update = UnsignedBTCR2Update & {
|
|
65
|
+
/** The Data Integrity proof that converts an unsigned update into a signed update. */
|
|
66
|
+
proof: Btcr2DataIntegrityProof;
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/** Either form of a BTCR2 Update. */
|
|
70
|
+
export type BTCR2Update = UnsignedBTCR2Update | SignedBTCR2Update;
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Data Integrity proof options for a BTCR2 update: the standard
|
|
74
|
+
* {@link DataIntegrityProofOptions} plus the ZCAP capability-invocation fields a
|
|
75
|
+
* did:btcr2 update proof carries. See
|
|
76
|
+
* {@link https://dcdpr.github.io/did-btcr2/data-structures.html#data-integrity-config | Data Integrity Config}.
|
|
77
|
+
*/
|
|
78
|
+
export type Btcr2DataIntegrityConfig = DataIntegrityProofOptions & {
|
|
79
|
+
/** JSON-LD context URIs for the proof (ZCAP, Data Integrity, JSON-LD patch). */
|
|
80
|
+
'@context': string[];
|
|
81
|
+
|
|
82
|
+
/** The root capability being invoked, e.g. `urn:zcap:root:<urlencoded-did>`. */
|
|
83
|
+
capability?: string;
|
|
84
|
+
|
|
85
|
+
/** The action performed under the capability, set to `"Write"` for DID document updates. */
|
|
86
|
+
capabilityAction?: string;
|
|
87
|
+
};
|
package/src/core/interfaces.ts
CHANGED
|
@@ -35,6 +35,14 @@ export interface ResolutionOptions extends DidResolutionOptions {
|
|
|
35
35
|
* Includes Singleton beacon updates, CAS announcements, and SMT proofs.
|
|
36
36
|
*/
|
|
37
37
|
sidecar?: Sidecar;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Maximum number of multi-round beacon-discovery passes before resolution
|
|
41
|
+
* fails. Each pass applies the updates found so far, then looks for new beacon
|
|
42
|
+
* services those updates added. A document whose updates keep adding beacon
|
|
43
|
+
* services would otherwise drive discovery without bound. Default: 10.
|
|
44
|
+
*/
|
|
45
|
+
maxDiscoveryRounds?: number;
|
|
38
46
|
}
|
|
39
47
|
|
|
40
48
|
/**
|
package/src/core/resolver.ts
CHANGED
|
@@ -17,7 +17,7 @@ import type { HashBytes } from '@did-btcr2/common';
|
|
|
17
17
|
import type {
|
|
18
18
|
SignedBTCR2Update,
|
|
19
19
|
UnsignedBTCR2Update
|
|
20
|
-
} from '
|
|
20
|
+
} from './btcr2-update.js';
|
|
21
21
|
import {
|
|
22
22
|
BIP340Cryptosuite,
|
|
23
23
|
BIP340DataIntegrityProof,
|
|
@@ -36,6 +36,14 @@ import type { SMTProof } from './interfaces.js';
|
|
|
36
36
|
import type { CASAnnouncement, Sidecar, SidecarData } from './types.js';
|
|
37
37
|
import { equalBytes } from '@noble/curves/utils.js';
|
|
38
38
|
|
|
39
|
+
/**
|
|
40
|
+
* Default upper bound on multi-round beacon discovery. Each round applies the
|
|
41
|
+
* updates found so far and looks for beacon services those updates added; a
|
|
42
|
+
* document whose updates keep adding services would otherwise loop unbounded.
|
|
43
|
+
* Overridable via `ResolutionOptions.maxDiscoveryRounds`.
|
|
44
|
+
*/
|
|
45
|
+
export const DEFAULT_MAX_DISCOVERY_ROUNDS = 10;
|
|
46
|
+
|
|
39
47
|
/**
|
|
40
48
|
* The response object for DID Resolution.
|
|
41
49
|
*/
|
|
@@ -111,6 +119,38 @@ export interface BeaconProcessResult {
|
|
|
111
119
|
needs: Array<DataNeed>;
|
|
112
120
|
}
|
|
113
121
|
|
|
122
|
+
// ─── provide() payload guards ────────────────────────────────────────────────
|
|
123
|
+
// Runtime shape checks so a malformed payload fails fast at the provide()
|
|
124
|
+
// boundary rather than flowing downstream as an unchecked `as` cast.
|
|
125
|
+
|
|
126
|
+
/** True if `value` is a non-null, non-array object. */
|
|
127
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
128
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/** True if `value` has the shape of a CAS Announcement (a flat record of string hashes). */
|
|
132
|
+
function isCASAnnouncement(value: unknown): value is CASAnnouncement {
|
|
133
|
+
return isRecord(value) && Object.values(value).every(v => typeof v === 'string');
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/** True if `value` has the shape of a signed BTCR2 update. */
|
|
137
|
+
function isSignedBTCR2Update(value: unknown): value is SignedBTCR2Update {
|
|
138
|
+
if(!isRecord(value)) return false;
|
|
139
|
+
return Array.isArray(value.patch)
|
|
140
|
+
&& typeof value.sourceHash === 'string'
|
|
141
|
+
&& typeof value.targetHash === 'string'
|
|
142
|
+
&& typeof value.targetVersionId === 'number'
|
|
143
|
+
&& isRecord(value.proof);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/** True if `value` has the shape of an SMT inclusion / non-inclusion proof. */
|
|
147
|
+
function isSMTProof(value: unknown): value is SMTProof {
|
|
148
|
+
if(!isRecord(value)) return false;
|
|
149
|
+
return typeof value.id === 'string'
|
|
150
|
+
&& typeof value.collapsed === 'string'
|
|
151
|
+
&& Array.isArray(value.hashes);
|
|
152
|
+
}
|
|
153
|
+
|
|
114
154
|
/**
|
|
115
155
|
* Different possible Resolver states representing phases in the resolution process.
|
|
116
156
|
*/
|
|
@@ -163,6 +203,11 @@ export class Resolver {
|
|
|
163
203
|
#unsortedUpdates: Array<[SignedBTCR2Update, BlockMetadata]> = [];
|
|
164
204
|
#resolvedResponse: DidResolutionResponse | null = null;
|
|
165
205
|
|
|
206
|
+
/** Upper bound on multi-round beacon-discovery passes; see {@link DEFAULT_MAX_DISCOVERY_ROUNDS}. */
|
|
207
|
+
readonly #maxDiscoveryRounds: number;
|
|
208
|
+
/** Count of beacon-discovery passes driven by updates adding new beacon services. */
|
|
209
|
+
#discoveryRounds = 0;
|
|
210
|
+
|
|
166
211
|
/**
|
|
167
212
|
* @internal Use {@link DidBtcr2.resolve} to create instances.
|
|
168
213
|
*/
|
|
@@ -170,13 +215,14 @@ export class Resolver {
|
|
|
170
215
|
didComponents: DidComponents,
|
|
171
216
|
sidecarData: SidecarData,
|
|
172
217
|
currentDocument: DidDocument | null,
|
|
173
|
-
options?: { versionId?: string; versionTime?: string; genesisDocument?: object }
|
|
218
|
+
options?: { versionId?: string; versionTime?: string; genesisDocument?: object; maxDiscoveryRounds?: number }
|
|
174
219
|
) {
|
|
175
220
|
this.#didComponents = didComponents;
|
|
176
221
|
this.#sidecarData = sidecarData;
|
|
177
222
|
this.#currentDocument = currentDocument;
|
|
178
223
|
this.#versionId = options?.versionId;
|
|
179
224
|
this.#versionTime = options?.versionTime;
|
|
225
|
+
this.#maxDiscoveryRounds = options?.maxDiscoveryRounds ?? DEFAULT_MAX_DISCOVERY_ROUNDS;
|
|
180
226
|
|
|
181
227
|
// If a genesis document was provided (from sidecar), pre-seed it for validation
|
|
182
228
|
if(options?.genesisDocument) {
|
|
@@ -653,6 +699,17 @@ export class Resolver {
|
|
|
653
699
|
});
|
|
654
700
|
|
|
655
701
|
if(hasNewServices) {
|
|
702
|
+
// Bound multi-round discovery: a document whose updates keep adding
|
|
703
|
+
// beacon services would otherwise loop without end. Fail closed once
|
|
704
|
+
// the configured number of rounds is exceeded.
|
|
705
|
+
if(++this.#discoveryRounds > this.#maxDiscoveryRounds) {
|
|
706
|
+
throw new ResolveError(
|
|
707
|
+
`Exceeded maximum beacon-discovery rounds (${this.#maxDiscoveryRounds}); `
|
|
708
|
+
+ 'the DID document may chain beacon services without terminating.',
|
|
709
|
+
INVALID_DID_DOCUMENT,
|
|
710
|
+
{ maxDiscoveryRounds: this.#maxDiscoveryRounds }
|
|
711
|
+
);
|
|
712
|
+
}
|
|
656
713
|
// Loop back to discover signals for new beacon services
|
|
657
714
|
this.#phase = ResolverPhase.BeaconDiscovery;
|
|
658
715
|
continue;
|
|
@@ -697,42 +754,85 @@ export class Resolver {
|
|
|
697
754
|
provide(need: DataNeed, data: object | Map<BeaconService, Array<BeaconSignal>> | CASAnnouncement | SignedBTCR2Update | SMTProof): void {
|
|
698
755
|
switch(need.kind) {
|
|
699
756
|
case 'NeedGenesisDocument': {
|
|
757
|
+
if(!isRecord(data)) {
|
|
758
|
+
throw new ResolveError(
|
|
759
|
+
'Provided data for NeedGenesisDocument must be a document object.',
|
|
760
|
+
INVALID_DID_UPDATE, { kind: need.kind }
|
|
761
|
+
);
|
|
762
|
+
}
|
|
700
763
|
this.#providedGenesisDocument = data;
|
|
701
764
|
break;
|
|
702
765
|
}
|
|
703
766
|
|
|
704
767
|
case 'NeedBeaconSignals': {
|
|
705
|
-
|
|
706
|
-
|
|
768
|
+
if(!(data instanceof Map)) {
|
|
769
|
+
throw new ResolveError(
|
|
770
|
+
'Provided data for NeedBeaconSignals must be a Map of beacon services to signals.',
|
|
771
|
+
INVALID_DID_UPDATE, { kind: need.kind }
|
|
772
|
+
);
|
|
773
|
+
}
|
|
774
|
+
for(const [service, serviceSignals] of data) {
|
|
707
775
|
this.#beaconServicesSignals.set(service, serviceSignals);
|
|
708
776
|
}
|
|
709
777
|
break;
|
|
710
778
|
}
|
|
711
779
|
|
|
712
780
|
case 'NeedCASAnnouncement': {
|
|
713
|
-
|
|
714
|
-
|
|
781
|
+
if(!isCASAnnouncement(data)) {
|
|
782
|
+
throw new ResolveError(
|
|
783
|
+
'Provided data for NeedCASAnnouncement is not a CAS announcement.',
|
|
784
|
+
INVALID_DID_UPDATE, { kind: need.kind }
|
|
785
|
+
);
|
|
786
|
+
}
|
|
787
|
+
// Fail fast if the provided announcement is not the one the on-chain
|
|
788
|
+
// signal requested: its canonical hash must equal the need's hash.
|
|
789
|
+
const announcementHash = canonicalHash(data, { encoding: 'hex' });
|
|
790
|
+
if(announcementHash !== need.announcementHash) {
|
|
791
|
+
throw new ResolveError(
|
|
792
|
+
`CAS announcement hash mismatch: expected ${need.announcementHash}, got ${announcementHash}.`,
|
|
793
|
+
INVALID_DID_UPDATE, { expected: need.announcementHash, actual: announcementHash }
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
this.#sidecarData.casMap.set(announcementHash, data);
|
|
715
797
|
break;
|
|
716
798
|
}
|
|
717
799
|
|
|
718
800
|
case 'NeedSignedUpdate': {
|
|
719
|
-
|
|
720
|
-
|
|
801
|
+
if(!isSignedBTCR2Update(data)) {
|
|
802
|
+
throw new ResolveError(
|
|
803
|
+
'Provided data for NeedSignedUpdate is not a signed BTCR2 update.',
|
|
804
|
+
INVALID_DID_UPDATE, { kind: need.kind }
|
|
805
|
+
);
|
|
806
|
+
}
|
|
807
|
+
// Fail fast if the provided update is not the one the on-chain signal
|
|
808
|
+
// requested: its canonical hash must equal the need's hash.
|
|
809
|
+
const updateHash = canonicalHash(data, { encoding: 'hex' });
|
|
810
|
+
if(updateHash !== need.updateHash) {
|
|
811
|
+
throw new ResolveError(
|
|
812
|
+
`Signed update hash mismatch: expected ${need.updateHash}, got ${updateHash}.`,
|
|
813
|
+
INVALID_DID_UPDATE, { expected: need.updateHash, actual: updateHash }
|
|
814
|
+
);
|
|
815
|
+
}
|
|
816
|
+
this.#sidecarData.updateMap.set(updateHash, data);
|
|
721
817
|
break;
|
|
722
818
|
}
|
|
723
819
|
|
|
724
820
|
case 'NeedSMTProof': {
|
|
725
|
-
|
|
726
|
-
|
|
821
|
+
if(!isSMTProof(data)) {
|
|
822
|
+
throw new ResolveError(
|
|
823
|
+
'Provided data for NeedSMTProof is not an SMT proof.',
|
|
824
|
+
INVALID_DID_UPDATE, { kind: need.kind }
|
|
825
|
+
);
|
|
826
|
+
}
|
|
727
827
|
// proof.id is base64url per spec; smtRootHash is the hex on-chain signal.
|
|
728
|
-
const proofIdHex = encodeHash(decodeHash(
|
|
729
|
-
if(proofIdHex !==
|
|
828
|
+
const proofIdHex = encodeHash(decodeHash(data.id, 'base64urlnopad'), 'hex');
|
|
829
|
+
if(proofIdHex !== need.smtRootHash) {
|
|
730
830
|
throw new ResolveError(
|
|
731
|
-
`SMT proof root hash mismatch: expected ${
|
|
732
|
-
INVALID_DID_UPDATE, { expected:
|
|
831
|
+
`SMT proof root hash mismatch: expected ${need.smtRootHash}, got ${proofIdHex}`,
|
|
832
|
+
INVALID_DID_UPDATE, { expected: need.smtRootHash, actual: proofIdHex }
|
|
733
833
|
);
|
|
734
834
|
}
|
|
735
|
-
this.#sidecarData.smtMap.set(
|
|
835
|
+
this.#sidecarData.smtMap.set(need.smtRootHash, data);
|
|
736
836
|
break;
|
|
737
837
|
}
|
|
738
838
|
}
|
package/src/core/types.ts
CHANGED
package/src/core/updater.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
2
|
import type { PatchOperation } from '@did-btcr2/common';
|
|
3
3
|
import { canonicalHash, INVALID_DID_UPDATE, JSONPatch, UpdateError } from '@did-btcr2/common';
|
|
4
|
-
import { SchnorrMultikey
|
|
4
|
+
import { SchnorrMultikey } from '@did-btcr2/cryptosuite';
|
|
5
5
|
import type { Signer } from '@did-btcr2/keypair';
|
|
6
|
+
import type { Btcr2DataIntegrityConfig, SignedBTCR2Update, UnsignedBTCR2Update } from './btcr2-update.js';
|
|
6
7
|
import { DidDocument, type Btcr2DidDocument, type DidVerificationMethod } from '../utils/did-document.js';
|
|
7
8
|
import { BeaconFactory } from './beacon/factory.js';
|
|
8
9
|
import type { BeaconService } from './beacon/interfaces.js';
|
|
@@ -287,7 +288,7 @@ export class Updater {
|
|
|
287
288
|
);
|
|
288
289
|
}
|
|
289
290
|
|
|
290
|
-
const config:
|
|
291
|
+
const config: Btcr2DataIntegrityConfig = {
|
|
291
292
|
'@context' : [
|
|
292
293
|
'https://w3id.org/security/v2',
|
|
293
294
|
'https://w3id.org/zcap/v1',
|
package/src/did-btcr2.ts
CHANGED
|
@@ -124,9 +124,10 @@ export class DidBtcr2 implements DidMethod {
|
|
|
124
124
|
|
|
125
125
|
// Return the sans-I/O state machine
|
|
126
126
|
return new Resolver(didComponents, sidecarData, currentDocument, {
|
|
127
|
-
versionId
|
|
128
|
-
versionTime
|
|
129
|
-
genesisDocument
|
|
127
|
+
versionId : resolutionOptions.versionId,
|
|
128
|
+
versionTime : resolutionOptions.versionTime,
|
|
129
|
+
genesisDocument : resolutionOptions.sidecar?.genesisDocument,
|
|
130
|
+
maxDiscoveryRounds : resolutionOptions.maxDiscoveryRounds
|
|
130
131
|
});
|
|
131
132
|
}
|
|
132
133
|
|
package/src/index.ts
CHANGED
|
@@ -11,6 +11,7 @@ export * from './core/beacon/smt-beacon.js';
|
|
|
11
11
|
export * from './core/beacon/utils.js';
|
|
12
12
|
|
|
13
13
|
// Core
|
|
14
|
+
export * from './core/btcr2-update.js';
|
|
14
15
|
export * from './core/did-sender-resolver.js';
|
|
15
16
|
export * from './core/identifier.js';
|
|
16
17
|
export * from './core/interfaces.js';
|