@did-btcr2/method 0.19.0 → 0.22.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 +223 -1
- package/dist/browser.js +3496 -4202
- package/dist/browser.mjs +3496 -4202
- package/dist/cjs/core/beacon/beacon.js +25 -0
- package/dist/cjs/core/beacon/beacon.js.map +1 -0
- package/dist/cjs/core/beacon/cas-beacon.js +20 -36
- package/dist/cjs/core/beacon/cas-beacon.js.map +1 -1
- package/dist/cjs/core/beacon/error.js +4 -4
- package/dist/cjs/core/beacon/error.js.map +1 -1
- package/dist/cjs/core/beacon/factory.js +5 -7
- package/dist/cjs/core/beacon/factory.js.map +1 -1
- package/dist/cjs/core/beacon/interfaces.js +1 -31
- package/dist/cjs/core/beacon/interfaces.js.map +1 -1
- package/dist/cjs/core/beacon/signal-discovery.js +183 -0
- package/dist/cjs/core/beacon/signal-discovery.js.map +1 -0
- package/dist/cjs/core/beacon/singleton.js +56 -86
- package/dist/cjs/core/beacon/singleton.js.map +1 -1
- package/dist/cjs/core/beacon/smt-beacon.js +22 -39
- package/dist/cjs/core/beacon/smt-beacon.js.map +1 -1
- package/dist/cjs/core/beacon/utils.js +4 -9
- package/dist/cjs/core/beacon/utils.js.map +1 -1
- package/dist/cjs/core/resolve.js +121 -307
- package/dist/cjs/core/resolve.js.map +1 -1
- package/dist/cjs/core/update.js +62 -154
- package/dist/cjs/core/update.js.map +1 -1
- package/dist/cjs/did-btcr2.js +100 -91
- package/dist/cjs/did-btcr2.js.map +1 -1
- package/dist/cjs/index.js +3 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/utils/appendix.js +6 -15
- package/dist/cjs/utils/appendix.js.map +1 -1
- package/dist/cjs/utils/did-document-builder.js +5 -6
- package/dist/cjs/utils/did-document-builder.js.map +1 -1
- package/dist/cjs/utils/did-document.js +42 -38
- package/dist/cjs/utils/did-document.js.map +1 -1
- package/dist/esm/core/beacon/beacon.js +25 -0
- package/dist/esm/core/beacon/beacon.js.map +1 -0
- package/dist/esm/core/beacon/cas-beacon.js +20 -36
- package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
- package/dist/esm/core/beacon/error.js +4 -4
- package/dist/esm/core/beacon/error.js.map +1 -1
- package/dist/esm/core/beacon/factory.js +5 -7
- package/dist/esm/core/beacon/factory.js.map +1 -1
- package/dist/esm/core/beacon/interfaces.js +1 -31
- package/dist/esm/core/beacon/interfaces.js.map +1 -1
- package/dist/esm/core/beacon/signal-discovery.js +183 -0
- package/dist/esm/core/beacon/signal-discovery.js.map +1 -0
- package/dist/esm/core/beacon/singleton.js +56 -86
- package/dist/esm/core/beacon/singleton.js.map +1 -1
- package/dist/esm/core/beacon/smt-beacon.js +22 -39
- package/dist/esm/core/beacon/smt-beacon.js.map +1 -1
- package/dist/esm/core/beacon/utils.js +4 -9
- package/dist/esm/core/beacon/utils.js.map +1 -1
- package/dist/esm/core/resolve.js +121 -307
- package/dist/esm/core/resolve.js.map +1 -1
- package/dist/esm/core/update.js +62 -154
- package/dist/esm/core/update.js.map +1 -1
- package/dist/esm/did-btcr2.js +100 -91
- package/dist/esm/did-btcr2.js.map +1 -1
- package/dist/esm/index.js +3 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/utils/appendix.js +6 -15
- package/dist/esm/utils/appendix.js.map +1 -1
- package/dist/esm/utils/did-document-builder.js +5 -6
- package/dist/esm/utils/did-document-builder.js.map +1 -1
- package/dist/esm/utils/did-document.js +42 -38
- package/dist/esm/utils/did-document.js.map +1 -1
- package/dist/types/core/beacon/beacon.d.ts +44 -0
- package/dist/types/core/beacon/beacon.d.ts.map +1 -0
- package/dist/types/core/beacon/cas-beacon.d.ts +19 -30
- package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/error.d.ts +2 -2
- package/dist/types/core/beacon/error.d.ts.map +1 -1
- package/dist/types/core/beacon/factory.d.ts +4 -6
- package/dist/types/core/beacon/factory.d.ts.map +1 -1
- package/dist/types/core/beacon/interfaces.d.ts +7 -46
- package/dist/types/core/beacon/interfaces.d.ts.map +1 -1
- package/dist/types/core/beacon/signal-discovery.d.ts +25 -0
- package/dist/types/core/beacon/signal-discovery.d.ts.map +1 -0
- package/dist/types/core/beacon/singleton.d.ts +17 -30
- package/dist/types/core/beacon/singleton.d.ts.map +1 -1
- package/dist/types/core/beacon/smt-beacon.d.ts +21 -33
- package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/utils.d.ts.map +1 -1
- package/dist/types/core/interfaces.d.ts +1 -8
- package/dist/types/core/interfaces.d.ts.map +1 -1
- package/dist/types/core/resolve.d.ts +34 -47
- package/dist/types/core/resolve.d.ts.map +1 -1
- package/dist/types/core/types.d.ts +21 -8
- package/dist/types/core/types.d.ts.map +1 -1
- package/dist/types/core/update.d.ts +30 -73
- package/dist/types/core/update.d.ts.map +1 -1
- package/dist/types/did-btcr2.d.ts +44 -47
- package/dist/types/did-btcr2.d.ts.map +1 -1
- package/dist/types/index.d.ts +3 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/utils/appendix.d.ts.map +1 -1
- package/dist/types/utils/did-document-builder.d.ts +5 -1
- package/dist/types/utils/did-document-builder.d.ts.map +1 -1
- package/dist/types/utils/did-document.d.ts +26 -21
- package/dist/types/utils/did-document.d.ts.map +1 -1
- package/package.json +8 -7
- package/src/core/beacon/beacon.ts +58 -0
- package/src/core/beacon/cas-beacon.ts +30 -44
- package/src/core/beacon/error.ts +5 -6
- package/src/core/beacon/factory.ts +7 -9
- package/src/core/beacon/interfaces.ts +7 -64
- package/src/core/beacon/signal-discovery.ts +237 -0
- package/src/core/beacon/singleton.ts +78 -100
- package/src/core/beacon/smt-beacon.ts +32 -49
- package/src/core/beacon/utils.ts +16 -13
- package/src/core/interfaces.ts +1 -9
- package/src/core/resolve.ts +163 -395
- package/src/core/types.ts +25 -8
- package/src/core/update.ts +91 -236
- package/src/did-btcr2.ts +154 -116
- package/src/index.ts +8 -1
- package/src/utils/appendix.ts +8 -22
- package/src/utils/did-document-builder.ts +5 -7
- package/src/utils/did-document.ts +80 -73
package/src/did-btcr2.ts
CHANGED
|
@@ -1,16 +1,19 @@
|
|
|
1
1
|
import { BitcoinNetworkConnection } from '@did-btcr2/bitcoin';
|
|
2
2
|
import {
|
|
3
|
-
Canonicalization,
|
|
4
3
|
DocumentBytes,
|
|
4
|
+
HexString,
|
|
5
5
|
IdentifierHrp,
|
|
6
6
|
INVALID_DID_DOCUMENT,
|
|
7
|
+
INVALID_DID_UPDATE,
|
|
7
8
|
KeyBytes,
|
|
8
9
|
METHOD_NOT_SUPPORTED,
|
|
9
10
|
MethodError,
|
|
10
11
|
MISSING_UPDATE_DATA,
|
|
11
12
|
PatchOperation,
|
|
12
|
-
ResolveError
|
|
13
|
+
ResolveError,
|
|
14
|
+
UpdateError
|
|
13
15
|
} from '@did-btcr2/common';
|
|
16
|
+
import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
14
17
|
import {
|
|
15
18
|
Did,
|
|
16
19
|
DidError,
|
|
@@ -21,17 +24,14 @@ import {
|
|
|
21
24
|
} from '@web5/dids';
|
|
22
25
|
import { initEccLib } from 'bitcoinjs-lib';
|
|
23
26
|
import * as tinysecp from 'tiny-secp256k1';
|
|
27
|
+
import { BeaconService } from './core/beacon/interfaces.js';
|
|
24
28
|
import { BeaconUtils } from './core/beacon/utils.js';
|
|
25
29
|
import { Identifier } from './core/identifier.js';
|
|
26
30
|
import { ResolutionOptions } from './core/interfaces.js';
|
|
27
31
|
import { Resolve } from './core/resolve.js';
|
|
28
|
-
import { SidecarData } from './core/types.js';
|
|
29
32
|
import { Update } from './core/update.js';
|
|
30
33
|
import { Appendix } from './utils/appendix.js';
|
|
31
|
-
import {
|
|
32
|
-
|
|
33
|
-
// TODO: convert to API driver
|
|
34
|
-
export const canonicalization = new Canonicalization();
|
|
34
|
+
import { Btcr2DidDocument, DidVerificationMethod } from './utils/did-document.js';
|
|
35
35
|
|
|
36
36
|
export type Btcr2Identifier = string;
|
|
37
37
|
|
|
@@ -44,7 +44,7 @@ export interface DidCreateOptions {
|
|
|
44
44
|
network?: string;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
// TODO: convert to API driver
|
|
47
|
+
// TODO: convert to API driver?
|
|
48
48
|
/** Initialize tiny secp256k1 */
|
|
49
49
|
initEccLib(tinysecp);
|
|
50
50
|
|
|
@@ -62,7 +62,9 @@ initEccLib(tinysecp);
|
|
|
62
62
|
* @implements {DidMethod}
|
|
63
63
|
*/
|
|
64
64
|
export class DidBtcr2 implements DidMethod {
|
|
65
|
-
/**
|
|
65
|
+
/**
|
|
66
|
+
* Name of the DID method, as defined in the DID BTCR2 specification
|
|
67
|
+
*/
|
|
66
68
|
static methodName: string = 'btcr2';
|
|
67
69
|
|
|
68
70
|
/**
|
|
@@ -75,11 +77,16 @@ export class DidBtcr2 implements DidMethod {
|
|
|
75
77
|
* @param {string} options.network The Bitcoin network to use for the identifier, e.g. 'bitcoin', 'testnet', etc. Defaults to 'bitcoin'.
|
|
76
78
|
* @returns {Promise<Btcr2Identifier>} Promise resolving to a Btcr2Identifier string.
|
|
77
79
|
* @throws {MethodError} if any of the checks fail
|
|
80
|
+
* @example
|
|
81
|
+
* ```ts
|
|
82
|
+
* const genesisBytes = SchnorrKeyPair.generate().publicKey.compressed;
|
|
83
|
+
* const did = DidBtcr2.create(genesisBytes, { idType: 'KEY', network: 'regtest' });
|
|
84
|
+
* ```
|
|
78
85
|
*/
|
|
79
|
-
static
|
|
86
|
+
static create(
|
|
80
87
|
genesisBytes: KeyBytes | DocumentBytes,
|
|
81
88
|
options?: DidCreateOptions
|
|
82
|
-
):
|
|
89
|
+
): Btcr2Identifier {
|
|
83
90
|
// Deconstruct the idType, version and network from the options, setting defaults if not given
|
|
84
91
|
const { idType, version = 1, network = 'bitcoin' } = options || {};
|
|
85
92
|
|
|
@@ -95,7 +102,7 @@ export class DidBtcr2 implements DidMethod {
|
|
|
95
102
|
}
|
|
96
103
|
|
|
97
104
|
/**
|
|
98
|
-
* Entry point for section {@link https://dcdpr.github.io/did-btcr2
|
|
105
|
+
* Entry point for section {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html | 7.2 Resolve}.
|
|
99
106
|
* See specification for the {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#process | Resolve Process}.
|
|
100
107
|
* See {@link Resolve | Resolve (class)} for class implementation.
|
|
101
108
|
*
|
|
@@ -104,32 +111,33 @@ export class DidBtcr2 implements DidMethod {
|
|
|
104
111
|
* blockchain by Authorized Beacon Signals. The Initial DID Document is either
|
|
105
112
|
* deterministically created from the DID or provided by Sidecar Data.
|
|
106
113
|
*
|
|
107
|
-
* @param {string} did
|
|
108
|
-
* @param {ResolutionOptions} resolutionOptions
|
|
109
|
-
* @param {number} resolutionOptions.versionId optional version of the identifier and/or DID document
|
|
110
|
-
* @param {number} resolutionOptions.versionTime optional timestamp used during resolution as a bound for when to stop resolving
|
|
111
|
-
* @param {DidDocument} resolutionOptions.sidecar optional data necessary for resolving a DID
|
|
114
|
+
* @param {string} did The did:btcr2 identifier to be resolved.
|
|
115
|
+
* @param {ResolutionOptions} resolutionOptions Options used during the resolution process.
|
|
112
116
|
* @returns {Promise<DidResolutionResult>} Promise resolving to a DID Resolution Result containing the `targetDocument`
|
|
113
|
-
* @throws {
|
|
114
|
-
* @throws {DidError} InvalidDid if the identifier is invalid
|
|
117
|
+
* @throws {ResolveError} If the resolution process fails at any step.
|
|
115
118
|
* @example
|
|
116
119
|
* ```ts
|
|
117
120
|
* const resolution = await DidBtcr2.resolve(
|
|
118
|
-
* 'did:btcr2:
|
|
121
|
+
* 'did:btcr2:k1qgpr45cheptyjekl3cex80xfnkwhxnlclecwwf92gvdjrszm2uwhzlcxu5xte'
|
|
119
122
|
* )
|
|
120
123
|
* ```
|
|
121
124
|
*/
|
|
122
|
-
static async resolve(
|
|
125
|
+
static async resolve(
|
|
126
|
+
did: string,
|
|
127
|
+
resolutionOptions: ResolutionOptions = {}
|
|
128
|
+
): Promise<DidResolutionResult> {
|
|
123
129
|
try {
|
|
130
|
+
// Set versionId from resolutionOptions
|
|
131
|
+
const versionId = resolutionOptions.versionId;
|
|
124
132
|
|
|
125
133
|
// Initialize an empty DID Resolution Result
|
|
126
134
|
const didResolutionResult: DidResolutionResult = {
|
|
127
135
|
'@context' : 'https://w3id.org/did-resolution/v1',
|
|
128
136
|
didResolutionMetadata : { contentType: 'application/ld+json' },
|
|
129
137
|
didDocumentMetadata : {
|
|
138
|
+
versionId,
|
|
130
139
|
deactivated : false,
|
|
131
140
|
updated : undefined,
|
|
132
|
-
versionId : resolutionOptions.versionId,
|
|
133
141
|
confirmations : undefined,
|
|
134
142
|
},
|
|
135
143
|
didDocument : null,
|
|
@@ -139,68 +147,72 @@ export class DidBtcr2 implements DidMethod {
|
|
|
139
147
|
const didComponents = Identifier.decode(did);
|
|
140
148
|
|
|
141
149
|
// Process sidecar if provided
|
|
142
|
-
const sidecarData = Resolve.
|
|
143
|
-
|
|
144
|
-
// Establish a connection to a bitcoin network
|
|
145
|
-
if(!resolutionOptions.drivers.bitcoin) {
|
|
146
|
-
resolutionOptions.drivers.bitcoin = new BitcoinNetworkConnection();
|
|
147
|
-
// Set the network based on the decoded identifier
|
|
148
|
-
resolutionOptions.drivers.bitcoin.setActiveNetwork(didComponents.network);
|
|
149
|
-
}
|
|
150
|
+
const sidecarData = Resolve.sidecarData(resolutionOptions.sidecar);
|
|
150
151
|
|
|
151
152
|
// Parse the genesis document from the resolution options if provided
|
|
152
153
|
const genesisDocument = resolutionOptions.sidecar?.genesisDocument;
|
|
154
|
+
|
|
153
155
|
// Since genesisDocument is optional, check if it exists
|
|
154
156
|
if(!genesisDocument) {
|
|
155
157
|
// If no genesisDocument and x HRP, throw MISSING_UPDATE_DATA error
|
|
156
158
|
if(didComponents.hrp === IdentifierHrp.x)
|
|
157
159
|
throw new ResolveError(
|
|
158
160
|
'External resolution requires genesisDocument',
|
|
159
|
-
MISSING_UPDATE_DATA,
|
|
161
|
+
MISSING_UPDATE_DATA, resolutionOptions
|
|
160
162
|
);
|
|
161
163
|
}
|
|
162
164
|
|
|
163
165
|
// Establish the current document
|
|
164
|
-
const currentDocument = await Resolve.
|
|
166
|
+
const currentDocument = await Resolve.currentDocument(didComponents, genesisDocument);
|
|
165
167
|
|
|
166
168
|
// Extract all Beacon services from the current DID Document
|
|
167
169
|
const beaconServices = currentDocument.service
|
|
168
170
|
.filter(BeaconUtils.isBeaconService)
|
|
169
171
|
.map(BeaconUtils.parseBeaconServiceEndpoint);
|
|
170
172
|
|
|
173
|
+
// Check if bitcoin driver provided
|
|
174
|
+
if(!resolutionOptions?.drivers?.bitcoin) {
|
|
175
|
+
// If not, initialize default drivers
|
|
176
|
+
resolutionOptions.drivers = resolutionOptions.drivers || {};
|
|
177
|
+
// Set bitcoin driver to default BitcoinNetworkConnection
|
|
178
|
+
resolutionOptions.drivers.bitcoin = new BitcoinNetworkConnection();
|
|
179
|
+
// Set the network based on the decoded identifier
|
|
180
|
+
resolutionOptions.drivers.bitcoin.setActiveNetwork(didComponents.network);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Get the bitcoin driver from the resolution options
|
|
184
|
+
const bitcoin = resolutionOptions.drivers.bitcoin;
|
|
185
|
+
|
|
171
186
|
// Process the Beacon Signals to get the required updates
|
|
172
|
-
const unsortedUpdates = await Resolve.
|
|
187
|
+
const unsortedUpdates = await Resolve.beaconSignals(
|
|
173
188
|
beaconServices,
|
|
174
189
|
sidecarData,
|
|
175
|
-
|
|
176
|
-
resolutionOptions.fullBlockchainTraversal
|
|
190
|
+
bitcoin
|
|
177
191
|
);
|
|
178
192
|
|
|
179
193
|
// If no updates found, return the current document
|
|
180
194
|
if(!unsortedUpdates.length) {
|
|
181
|
-
// Set the
|
|
195
|
+
// Set the didDocument in didResolutionResult based on currentDocument
|
|
182
196
|
didResolutionResult.didDocument = currentDocument;
|
|
183
|
-
|
|
184
|
-
// Set the deactivated status in the didDocumentMetadata
|
|
197
|
+
// Set other required fields in the didResolutionResult
|
|
185
198
|
didResolutionResult.didDocumentMetadata.deactivated = !!currentDocument.deactivated;
|
|
199
|
+
didResolutionResult.didDocumentMetadata.versionId = versionId ?? '1';
|
|
186
200
|
|
|
187
201
|
// Return the didResolutionResult early
|
|
188
202
|
return didResolutionResult;
|
|
189
203
|
}
|
|
190
204
|
|
|
191
205
|
// Process the updates to apply updates to bring the current DID Document to its more current state
|
|
192
|
-
const result = await Resolve.
|
|
206
|
+
const result = await Resolve.updates(
|
|
193
207
|
currentDocument,
|
|
194
208
|
unsortedUpdates,
|
|
195
209
|
resolutionOptions.versionTime,
|
|
196
|
-
|
|
210
|
+
versionId
|
|
197
211
|
);
|
|
198
212
|
|
|
199
213
|
// Set all of the required fields in the didResolutionResult
|
|
200
|
-
didResolutionResult.didDocument = result.
|
|
201
|
-
didResolutionResult.didDocumentMetadata
|
|
202
|
-
didResolutionResult.didDocumentMetadata.versionId = result.versionId;
|
|
203
|
-
didResolutionResult.didDocumentMetadata.deactivated = !!result.currentDocument.deactivated;
|
|
214
|
+
didResolutionResult.didDocument = result.didDocument;
|
|
215
|
+
didResolutionResult.didDocumentMetadata = result.metadata;
|
|
204
216
|
|
|
205
217
|
// Return didResolutionResult;
|
|
206
218
|
return didResolutionResult;
|
|
@@ -221,92 +233,118 @@ export class DidBtcr2 implements DidMethod {
|
|
|
221
233
|
}
|
|
222
234
|
|
|
223
235
|
/**
|
|
224
|
-
* Entry point for section {@link https://dcdpr.github.io/did-btcr2/#
|
|
225
|
-
* See {@link
|
|
226
|
-
*
|
|
227
|
-
* An update to a did:btcr2 document is an invoked capability using the ZCAP-LD data format, signed by a
|
|
228
|
-
* verificationMethod that has the authority to make the update as specified in the previous DID document. Capability
|
|
229
|
-
* invocations for updates MUST be authorized using Data Integrity following the bip340-jcs-2025
|
|
230
|
-
* cryptosuite with a proofPurpose of capabilityInvocation.
|
|
231
|
-
*
|
|
232
|
-
* The Update algorithm takes as inputs a Identifier, sourceDocument, sourceVersionId, documentPatch, a
|
|
233
|
-
* verificationMethodId and an array of beaconIds. The sourceDocument is the DID document being updated. The
|
|
234
|
-
* documentPatch is a JSON Patch object containing a set of transformations to be applied to the sourceDocument.
|
|
235
|
-
* The result of these transformations MUST produce a DID document conformant to the DID Core specification. The
|
|
236
|
-
* verificationMethodId is an identifier for a verificationMethod within the sourceDocument. The verificationMethod
|
|
237
|
-
* identified MUST be a BIP340 Multikey. The beaconIds MUST identify service endpoints with one of the three Beacon
|
|
238
|
-
* Types SingletonBeacon, CASBeacon, and SMTBeacon.
|
|
236
|
+
* Entry point for section {@link https://dcdpr.github.io/did-btcr2/#read | 7.3 Update}.
|
|
237
|
+
* See specification for the {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#process | Resolve Process}.
|
|
238
|
+
* See {@link Update | Update (class)} for class implementation.
|
|
239
239
|
*
|
|
240
|
-
*
|
|
241
|
-
*
|
|
242
|
-
*
|
|
243
|
-
* @param
|
|
244
|
-
* @param {
|
|
245
|
-
* @param {
|
|
246
|
-
* @param {string
|
|
247
|
-
* @
|
|
248
|
-
* @
|
|
240
|
+
* BTCR2 DID documents can be updated by anchoring BTCR2 Updates to Bitcoin transactions. These transactions MAY be
|
|
241
|
+
* published to the Bitcoin network. Any property in the DID document may be updated except the id. Doing so would
|
|
242
|
+
* invalidate the DID document.
|
|
243
|
+
* @param params An object containing the parameters for the update operation.
|
|
244
|
+
* @param {Btcr2DidDocument} params.sourceDocument The DID document being updated.
|
|
245
|
+
* @param {PatchOperation[]} params.patches The array of JSON Patch operations to apply to the sourceDocument.
|
|
246
|
+
* @param {string} params.sourceVersionId The version ID before applying the update.
|
|
247
|
+
* @param {string} params.verificationMethodId The verificationMethod ID to sign the update with.
|
|
248
|
+
* @param {string} params.beaconId The beacon ID associated with the update.
|
|
249
|
+
* @param {KeyBytes | HexString} [params.signingMaterial] Optional signing material (key bytes or hex string).
|
|
250
|
+
* @param {BitcoinNetworkConnection} [params.bitcoin] Optional Bitcoin network connection for announcing the update. If not provided, a default connection will be initialized.
|
|
251
|
+
* @return {Promise<SignedBTCR2Update>} Promise resolving to the signed BTCR2 update.
|
|
252
|
+
* @throws {UpdateError} if no verificationMethod, verificationMethod type is not `Multikey` or the publicKeyMultibase
|
|
253
|
+
* header is not `zQ3s`
|
|
249
254
|
*/
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
255
|
+
static async update({
|
|
256
|
+
sourceDocument,
|
|
257
|
+
patches,
|
|
258
|
+
sourceVersionId,
|
|
259
|
+
verificationMethodId,
|
|
260
|
+
beaconId,
|
|
261
|
+
signingMaterial,
|
|
262
|
+
bitcoin,
|
|
263
|
+
}: {
|
|
264
|
+
sourceDocument: Btcr2DidDocument;
|
|
265
|
+
patches: PatchOperation[];
|
|
253
266
|
sourceVersionId: number;
|
|
254
|
-
patch: PatchOperation[];
|
|
255
267
|
verificationMethodId: string;
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
//
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
268
|
+
beaconId: string;
|
|
269
|
+
signingMaterial?: KeyBytes | HexString;
|
|
270
|
+
bitcoin?: BitcoinNetworkConnection;
|
|
271
|
+
}): Promise<SignedBTCR2Update> {
|
|
272
|
+
// TODO: provide KMS as alternative
|
|
273
|
+
// If no signingMaterial provided, throw an UpdateError with INVALID_DID_UPDATE.
|
|
274
|
+
if (!signingMaterial) {
|
|
275
|
+
throw new UpdateError(
|
|
276
|
+
'Missing signing material for update',
|
|
277
|
+
INVALID_DID_UPDATE, {signingMaterial}
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
// Convert signingMaterial to bytes if it's a hex string
|
|
282
|
+
const secretKey = typeof signingMaterial === 'string'
|
|
283
|
+
? Buffer.from(signingMaterial, 'hex')
|
|
284
|
+
: signingMaterial;
|
|
285
|
+
|
|
286
|
+
// Validate that the verificationMethodId is authorized for capabilityInvocation
|
|
287
|
+
if(!sourceDocument.capabilityInvocation?.some(vr => vr === verificationMethodId)) {
|
|
288
|
+
throw new UpdateError(
|
|
289
|
+
'Invalid verificationMethodId: not authorized for capabilityInvocation',
|
|
290
|
+
INVALID_DID_DOCUMENT, sourceDocument
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
// Get the verification method to be used for signing the update
|
|
295
|
+
const verificationMethod = this.getSigningMethod(sourceDocument, verificationMethodId);
|
|
281
296
|
|
|
282
297
|
// Validate the verificationMethod exists in the sourceDocument
|
|
283
298
|
if (!verificationMethod) {
|
|
284
|
-
throw new
|
|
299
|
+
throw new UpdateError(
|
|
300
|
+
'Invalid verificationMethod: not found in source document',
|
|
301
|
+
INVALID_DID_DOCUMENT, {sourceDocument, verificationMethodId}
|
|
302
|
+
);
|
|
285
303
|
}
|
|
286
304
|
|
|
287
|
-
//
|
|
288
|
-
// 3.1 verificationMethod.type == Multikey
|
|
305
|
+
// Validate the verificationMethod is of type 'Multikey'
|
|
289
306
|
if (verificationMethod.type !== 'Multikey') {
|
|
290
|
-
throw new
|
|
307
|
+
throw new UpdateError(
|
|
308
|
+
'Invalid verificationMethod: verificationMethod.type must be "Multikey"',
|
|
309
|
+
INVALID_DID_DOCUMENT, verificationMethod
|
|
310
|
+
);
|
|
291
311
|
}
|
|
292
312
|
|
|
293
|
-
//
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
313
|
+
// Validate the publicKeyMultibase prefix is 'zQ3s'
|
|
314
|
+
if (verificationMethod.publicKeyMultibase?.slice(0, 4) !== 'zQ3s') {
|
|
315
|
+
throw new UpdateError(
|
|
316
|
+
'Invalid verificationMethodId: publicKeyMultibase prefix must start with "zQ3s"',
|
|
317
|
+
INVALID_DID_DOCUMENT, verificationMethod
|
|
318
|
+
);
|
|
297
319
|
}
|
|
298
320
|
|
|
299
|
-
//
|
|
300
|
-
|
|
301
|
-
|
|
321
|
+
// Construct an unsigned update following the BTCR2 Update construction algorithm
|
|
322
|
+
const update = await Update.construct(sourceDocument, patches, sourceVersionId);
|
|
323
|
+
|
|
324
|
+
// Sign the unsigned update using the specified verification method
|
|
325
|
+
const signed = await Update.sign(sourceDocument.id, update, verificationMethod, secretKey);
|
|
326
|
+
|
|
327
|
+
// Filter sourceDocument services to get beaconServices matching beaconIds
|
|
328
|
+
const beaconService = sourceDocument.service
|
|
329
|
+
.filter((service: BeaconService) => service.id === beaconId)
|
|
330
|
+
.filter((service: BeaconService): service is BeaconService => !!service)
|
|
331
|
+
.shift();
|
|
332
|
+
|
|
333
|
+
// If no matching beacon service found, throw an UpdateError with INVALID_DID_UPDATE.
|
|
334
|
+
if(!beaconService) {
|
|
335
|
+
throw new UpdateError(
|
|
336
|
+
'No beacon service found for provided beaconId',
|
|
337
|
+
INVALID_DID_UPDATE, {sourceDocument, beaconId}
|
|
338
|
+
);
|
|
339
|
+
}
|
|
340
|
+
// If no bitcoin network connection provided, initialize default
|
|
341
|
+
bitcoin ??= new BitcoinNetworkConnection();
|
|
302
342
|
|
|
303
|
-
//
|
|
304
|
-
|
|
305
|
-
const signalsMetadata = await Update.announce({ sourceDocument, beaconIds, signedUpdate });
|
|
343
|
+
// Announce the signed update to the blockchain using the specified beacon(s)
|
|
344
|
+
await Update.announce(beaconService, signed, secretKey, bitcoin);
|
|
306
345
|
|
|
307
|
-
//
|
|
308
|
-
return
|
|
309
|
-
// TODO: Should we be applying the patch, producing a target did document and returning it?
|
|
346
|
+
// Return signed update if announced successfully
|
|
347
|
+
return signed;
|
|
310
348
|
}
|
|
311
349
|
|
|
312
350
|
/**
|
|
@@ -314,12 +352,12 @@ export class DidBtcr2 implements DidMethod {
|
|
|
314
352
|
* for signing messages and credentials. If given, the `methodId` parameter is used to select the
|
|
315
353
|
* verification method. If not given, the Identity Key's verification method with an ID fragment
|
|
316
354
|
* of '#initialKey' is used.
|
|
317
|
-
* @param {
|
|
355
|
+
* @param {Btcr2DidDocument} didDocument The DID Document of the `did:btcr2` identifier.
|
|
318
356
|
* @param {string} [methodId] Optional verification method ID to be used for signing.
|
|
319
357
|
* @returns {DidVerificationMethod} Promise resolving to the {@link DidVerificationMethod} object used for signing.
|
|
320
358
|
* @throws {DidError} if the parsed did method does not match `btcr2` or signing method could not be determined.
|
|
321
359
|
*/
|
|
322
|
-
|
|
360
|
+
static getSigningMethod(didDocument: Btcr2DidDocument, methodId?: string): DidVerificationMethod {
|
|
323
361
|
// Set the default methodId to the first assertionMethod if not given
|
|
324
362
|
methodId ??= '#initialKey';
|
|
325
363
|
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
export * from './core/beacon/aggregation/cohort/index.js';
|
|
2
|
+
export * from './core/beacon/aggregation/cohort/status.js';
|
|
3
|
+
|
|
2
4
|
export * from './core/beacon/aggregation/cohort/messages/base.js';
|
|
3
5
|
export * from './core/beacon/aggregation/cohort/messages/constants.js';
|
|
4
6
|
export * from './core/beacon/aggregation/cohort/messages/index.js';
|
|
@@ -12,20 +14,25 @@ export * from './core/beacon/aggregation/cohort/messages/sign/authorization-requ
|
|
|
12
14
|
export * from './core/beacon/aggregation/cohort/messages/sign/nonce-contribution.js';
|
|
13
15
|
export * from './core/beacon/aggregation/cohort/messages/sign/request-signature.js';
|
|
14
16
|
export * from './core/beacon/aggregation/cohort/messages/sign/signature-authorization.js';
|
|
15
|
-
|
|
17
|
+
|
|
16
18
|
export * from './core/beacon/aggregation/communication/adapter/did-comm.js';
|
|
17
19
|
export * from './core/beacon/aggregation/communication/adapter/nostr.js';
|
|
20
|
+
|
|
18
21
|
export * from './core/beacon/aggregation/communication/error.js';
|
|
19
22
|
export * from './core/beacon/aggregation/communication/factory.js';
|
|
20
23
|
export * from './core/beacon/aggregation/communication/service.js';
|
|
24
|
+
|
|
21
25
|
export * from './core/beacon/aggregation/coordinator.js';
|
|
22
26
|
export * from './core/beacon/aggregation/participant.js';
|
|
23
27
|
export * from './core/beacon/aggregation/session/index.js';
|
|
24
28
|
export * from './core/beacon/aggregation/session/status.js';
|
|
29
|
+
|
|
30
|
+
export * from './core/beacon/beacon.js';
|
|
25
31
|
export * from './core/beacon/cas-beacon.js';
|
|
26
32
|
export * from './core/beacon/error.js';
|
|
27
33
|
export * from './core/beacon/factory.js';
|
|
28
34
|
export * from './core/beacon/interfaces.js';
|
|
35
|
+
export * from './core/beacon/signal-discovery.js';
|
|
29
36
|
export * from './core/beacon/singleton.js';
|
|
30
37
|
export * from './core/beacon/smt-beacon.js';
|
|
31
38
|
export * from './core/beacon/utils.js';
|
package/src/utils/appendix.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HashBytes
|
|
1
|
+
import { HashBytes } from '@did-btcr2/common';
|
|
2
2
|
import { strings } from '@helia/strings';
|
|
3
3
|
import {
|
|
4
4
|
DidDocument,
|
|
@@ -109,27 +109,13 @@ export class Appendix {
|
|
|
109
109
|
* }
|
|
110
110
|
* ```
|
|
111
111
|
*/
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
// 3. Set encodedIdentifier to result of calling algorithm encodeURIComponent(identifier).
|
|
120
|
-
const encodedIdentifier = encodeURIComponent(identifier);
|
|
121
|
-
|
|
122
|
-
// 4. Set rootCapability.id to urn:zcap:root:${encodedIdentifier}.
|
|
123
|
-
rootCapability.id = `urn:zcap:root:${encodedIdentifier}`;
|
|
124
|
-
|
|
125
|
-
// 5. Set rootCapability.controller to identifier.
|
|
126
|
-
rootCapability.controller = identifier;
|
|
127
|
-
|
|
128
|
-
// 6. Set rootCapability.invocationTarget to identifier.
|
|
129
|
-
rootCapability.invocationTarget = identifier;
|
|
130
|
-
|
|
131
|
-
// 7. Return rootCapability.
|
|
132
|
-
return rootCapability;
|
|
112
|
+
static deriveRootCapability(identifier: string): RootCapability {
|
|
113
|
+
return {
|
|
114
|
+
'@context' : 'https://w3id.org/zcap/v1',
|
|
115
|
+
id : `urn:zcap:root:${encodeURIComponent(identifier)}`,
|
|
116
|
+
controller : identifier,
|
|
117
|
+
invocationTarget : identifier,
|
|
118
|
+
};
|
|
133
119
|
}
|
|
134
120
|
|
|
135
121
|
|
|
@@ -2,6 +2,11 @@ import { DidDocumentError, INVALID_DID_DOCUMENT } from '@did-btcr2/common';
|
|
|
2
2
|
import { BeaconService } from '../core/beacon/interfaces.js';
|
|
3
3
|
import { DidDocument, DidVerificationMethod } from './did-document.js';
|
|
4
4
|
|
|
5
|
+
/**
|
|
6
|
+
* A builder class for constructing DID Documents.
|
|
7
|
+
* @type {DidDocumentBuilder}
|
|
8
|
+
* @class DidDocumentBuilder
|
|
9
|
+
*/
|
|
5
10
|
export class DidDocumentBuilder {
|
|
6
11
|
private document: Partial<DidDocument> = {};
|
|
7
12
|
|
|
@@ -17,13 +22,6 @@ export class DidDocumentBuilder {
|
|
|
17
22
|
}
|
|
18
23
|
}
|
|
19
24
|
|
|
20
|
-
withController(controller?: Array<string>): this {
|
|
21
|
-
if (controller) {
|
|
22
|
-
this.document.controller = controller ?? [this.document.id!];
|
|
23
|
-
}
|
|
24
|
-
return this;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
25
|
withAuthentication(authentication: Array<string | DidVerificationMethod>): this {
|
|
28
26
|
if (authentication) {
|
|
29
27
|
this.document.authentication = authentication;
|