@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.
Files changed (120) hide show
  1. package/README.md +223 -1
  2. package/dist/browser.js +3496 -4202
  3. package/dist/browser.mjs +3496 -4202
  4. package/dist/cjs/core/beacon/beacon.js +25 -0
  5. package/dist/cjs/core/beacon/beacon.js.map +1 -0
  6. package/dist/cjs/core/beacon/cas-beacon.js +20 -36
  7. package/dist/cjs/core/beacon/cas-beacon.js.map +1 -1
  8. package/dist/cjs/core/beacon/error.js +4 -4
  9. package/dist/cjs/core/beacon/error.js.map +1 -1
  10. package/dist/cjs/core/beacon/factory.js +5 -7
  11. package/dist/cjs/core/beacon/factory.js.map +1 -1
  12. package/dist/cjs/core/beacon/interfaces.js +1 -31
  13. package/dist/cjs/core/beacon/interfaces.js.map +1 -1
  14. package/dist/cjs/core/beacon/signal-discovery.js +183 -0
  15. package/dist/cjs/core/beacon/signal-discovery.js.map +1 -0
  16. package/dist/cjs/core/beacon/singleton.js +56 -86
  17. package/dist/cjs/core/beacon/singleton.js.map +1 -1
  18. package/dist/cjs/core/beacon/smt-beacon.js +22 -39
  19. package/dist/cjs/core/beacon/smt-beacon.js.map +1 -1
  20. package/dist/cjs/core/beacon/utils.js +4 -9
  21. package/dist/cjs/core/beacon/utils.js.map +1 -1
  22. package/dist/cjs/core/resolve.js +121 -307
  23. package/dist/cjs/core/resolve.js.map +1 -1
  24. package/dist/cjs/core/update.js +62 -154
  25. package/dist/cjs/core/update.js.map +1 -1
  26. package/dist/cjs/did-btcr2.js +100 -91
  27. package/dist/cjs/did-btcr2.js.map +1 -1
  28. package/dist/cjs/index.js +3 -1
  29. package/dist/cjs/index.js.map +1 -1
  30. package/dist/cjs/utils/appendix.js +6 -15
  31. package/dist/cjs/utils/appendix.js.map +1 -1
  32. package/dist/cjs/utils/did-document-builder.js +5 -6
  33. package/dist/cjs/utils/did-document-builder.js.map +1 -1
  34. package/dist/cjs/utils/did-document.js +42 -38
  35. package/dist/cjs/utils/did-document.js.map +1 -1
  36. package/dist/esm/core/beacon/beacon.js +25 -0
  37. package/dist/esm/core/beacon/beacon.js.map +1 -0
  38. package/dist/esm/core/beacon/cas-beacon.js +20 -36
  39. package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
  40. package/dist/esm/core/beacon/error.js +4 -4
  41. package/dist/esm/core/beacon/error.js.map +1 -1
  42. package/dist/esm/core/beacon/factory.js +5 -7
  43. package/dist/esm/core/beacon/factory.js.map +1 -1
  44. package/dist/esm/core/beacon/interfaces.js +1 -31
  45. package/dist/esm/core/beacon/interfaces.js.map +1 -1
  46. package/dist/esm/core/beacon/signal-discovery.js +183 -0
  47. package/dist/esm/core/beacon/signal-discovery.js.map +1 -0
  48. package/dist/esm/core/beacon/singleton.js +56 -86
  49. package/dist/esm/core/beacon/singleton.js.map +1 -1
  50. package/dist/esm/core/beacon/smt-beacon.js +22 -39
  51. package/dist/esm/core/beacon/smt-beacon.js.map +1 -1
  52. package/dist/esm/core/beacon/utils.js +4 -9
  53. package/dist/esm/core/beacon/utils.js.map +1 -1
  54. package/dist/esm/core/resolve.js +121 -307
  55. package/dist/esm/core/resolve.js.map +1 -1
  56. package/dist/esm/core/update.js +62 -154
  57. package/dist/esm/core/update.js.map +1 -1
  58. package/dist/esm/did-btcr2.js +100 -91
  59. package/dist/esm/did-btcr2.js.map +1 -1
  60. package/dist/esm/index.js +3 -1
  61. package/dist/esm/index.js.map +1 -1
  62. package/dist/esm/utils/appendix.js +6 -15
  63. package/dist/esm/utils/appendix.js.map +1 -1
  64. package/dist/esm/utils/did-document-builder.js +5 -6
  65. package/dist/esm/utils/did-document-builder.js.map +1 -1
  66. package/dist/esm/utils/did-document.js +42 -38
  67. package/dist/esm/utils/did-document.js.map +1 -1
  68. package/dist/types/core/beacon/beacon.d.ts +44 -0
  69. package/dist/types/core/beacon/beacon.d.ts.map +1 -0
  70. package/dist/types/core/beacon/cas-beacon.d.ts +19 -30
  71. package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
  72. package/dist/types/core/beacon/error.d.ts +2 -2
  73. package/dist/types/core/beacon/error.d.ts.map +1 -1
  74. package/dist/types/core/beacon/factory.d.ts +4 -6
  75. package/dist/types/core/beacon/factory.d.ts.map +1 -1
  76. package/dist/types/core/beacon/interfaces.d.ts +7 -46
  77. package/dist/types/core/beacon/interfaces.d.ts.map +1 -1
  78. package/dist/types/core/beacon/signal-discovery.d.ts +25 -0
  79. package/dist/types/core/beacon/signal-discovery.d.ts.map +1 -0
  80. package/dist/types/core/beacon/singleton.d.ts +17 -30
  81. package/dist/types/core/beacon/singleton.d.ts.map +1 -1
  82. package/dist/types/core/beacon/smt-beacon.d.ts +21 -33
  83. package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -1
  84. package/dist/types/core/beacon/utils.d.ts.map +1 -1
  85. package/dist/types/core/interfaces.d.ts +1 -8
  86. package/dist/types/core/interfaces.d.ts.map +1 -1
  87. package/dist/types/core/resolve.d.ts +34 -47
  88. package/dist/types/core/resolve.d.ts.map +1 -1
  89. package/dist/types/core/types.d.ts +21 -8
  90. package/dist/types/core/types.d.ts.map +1 -1
  91. package/dist/types/core/update.d.ts +30 -73
  92. package/dist/types/core/update.d.ts.map +1 -1
  93. package/dist/types/did-btcr2.d.ts +44 -47
  94. package/dist/types/did-btcr2.d.ts.map +1 -1
  95. package/dist/types/index.d.ts +3 -1
  96. package/dist/types/index.d.ts.map +1 -1
  97. package/dist/types/utils/appendix.d.ts.map +1 -1
  98. package/dist/types/utils/did-document-builder.d.ts +5 -1
  99. package/dist/types/utils/did-document-builder.d.ts.map +1 -1
  100. package/dist/types/utils/did-document.d.ts +26 -21
  101. package/dist/types/utils/did-document.d.ts.map +1 -1
  102. package/package.json +8 -7
  103. package/src/core/beacon/beacon.ts +58 -0
  104. package/src/core/beacon/cas-beacon.ts +30 -44
  105. package/src/core/beacon/error.ts +5 -6
  106. package/src/core/beacon/factory.ts +7 -9
  107. package/src/core/beacon/interfaces.ts +7 -64
  108. package/src/core/beacon/signal-discovery.ts +237 -0
  109. package/src/core/beacon/singleton.ts +78 -100
  110. package/src/core/beacon/smt-beacon.ts +32 -49
  111. package/src/core/beacon/utils.ts +16 -13
  112. package/src/core/interfaces.ts +1 -9
  113. package/src/core/resolve.ts +163 -395
  114. package/src/core/types.ts +25 -8
  115. package/src/core/update.ts +91 -236
  116. package/src/did-btcr2.ts +154 -116
  117. package/src/index.ts +8 -1
  118. package/src/utils/appendix.ts +8 -22
  119. package/src/utils/did-document-builder.ts +5 -7
  120. package/src/utils/did-document.ts +80 -73
@@ -1,13 +1,9 @@
1
- import { INVALID_DID_DOCUMENT, INVALID_DID_UPDATE, INVALID_PUBLIC_KEY_TYPE, JSONPatch, MethodError, NOT_FOUND, UpdateError } from '@did-btcr2/common';
1
+ import { Canonicalization, INVALID_DID_UPDATE, JSONPatch, UpdateError } from '@did-btcr2/common';
2
2
  import { SchnorrMultikey } from '@did-btcr2/cryptosuite';
3
- import { CompressedSecp256k1PublicKey, SchnorrKeyPair, Secp256k1SecretKey } from '@did-btcr2/keypair';
4
- import { Kms } from '@did-btcr2/kms';
5
- import { canonicalization } from '../did-btcr2.js';
6
- import { Appendix } from '../utils/appendix.js';
7
3
  import { DidDocument } from '../utils/did-document.js';
8
- import { Identifier } from './identifier.js';
4
+ import { BeaconFactory } from './beacon/factory.js';
9
5
  /**
10
- * Implements {@link https://dcdpr.github.io/did-btcr2/#update | 4.3 Update}.
6
+ * Implements {@link https://dcdpr.github.io/did-btcr2/operations/update.html | 7.3 Update}.
11
7
  *
12
8
  * An update to a did:btcr2 document is an invoked capability using the ZCAP-LD
13
9
  * data format, signed by a verificationMethod that has the authority to make
@@ -20,109 +16,62 @@ import { Identifier } from './identifier.js';
20
16
  */
21
17
  export class Update {
22
18
  /**
23
- * Implements {@link https://dcdpr.github.io/did-btcr2/#construct-did-update-payload | 4.3.1 Construct DID Update Payload}.
19
+ * Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/update.html#construct-btcr2-unsigned-update | 7.3.b Construct BTCR2 Unsigned Update}.
20
+ * This process constructs a BTCR2 Unsigned Update conformant to the spec template.
24
21
  *
25
- * The Construct DID Update Payload algorithm applies the documentPatch to the sourceDocument and verifies the
26
- * resulting targetDocument is a conformant DID document. It takes in a Identifier, sourceDocument,
27
- * sourceVersionId, and documentPatch objects. It returns an unsigned DID Update Payload.
28
- *
29
- * @param {ConstructPayloadParams} params See {@link ConstructPayloadParams} for more details.
30
- * @param {string} params.identifier The did-btcr2 identifier to use for verification.
31
- * @param {DidDocument} params.sourceDocument The source document to be updated.
32
- * @param {string} params.sourceVersionId The versionId of the source document.
33
- * @param {DidDocumentPatch} params.patch The JSON patch to be applied to the source document.
34
- * @returns {Promise<BTCR2SignedUpdate>} The constructed BTCR2SignedUpdate object.
35
- * @throws {MethodError} InvalidDid if sourceDocument.id does not match identifier.
22
+ * @param {Btcr2DidDocument} sourceDocument The source DID document to be updated.
23
+ * @param {PatchOperation[]} patches The array of JSON Patch operations to apply to the sourceDocument.
24
+ * @param {number} sourceVersionId The version ID of the source document.
25
+ * @returns {Promise<SignedBTCR2Update>} The constructed SignedBTCR2Update object.
26
+ * @throws {UpdateError} InvalidDid if sourceDocument.id does not match identifier.
36
27
  */
37
- static async construct({ identifier, sourceDocument, sourceVersionId, patch, }) {
38
- // 1. Check that sourceDocument.id equals identifier else MUST raise invalidDIDUpdate error.
39
- if (sourceDocument.id !== identifier) {
40
- throw new UpdateError('Identifier mismatch: sourceDocument.id !== identifier', INVALID_DID_UPDATE, { sourceDocument, identifier });
41
- }
42
- // 2. Initialize an unsigned update.
28
+ static async construct(sourceDocument, patches, sourceVersionId) {
29
+ // Initialize an unsigned update conformant to btcr2 spec.
43
30
  const unsignedUpdate = {
44
- // 3. Set BTCR2SignedUpdate.@context to the following list
45
31
  '@context': [
46
32
  'https://w3id.org/security/v2',
47
33
  'https://w3id.org/zcap/v1',
48
34
  'https://w3id.org/json-ld-patch/v1',
49
35
  'https://btcr2.dev/context/v1'
50
36
  ],
51
- // 4. Set BTCR2SignedUpdate.patch to documentPatch.
52
- patch,
37
+ patch: patches,
53
38
  targetHash: '',
54
- targetVersionId: 0,
55
- sourceHash: '',
39
+ targetVersionId: sourceVersionId + 1,
40
+ sourceHash: Canonicalization.process(sourceDocument, { encoding: 'base58' }),
56
41
  };
57
- // 5. Set targetDocument to the result of applying the documentPatch to the sourceDocument, following the JSON Patch
58
- // specification.
59
- const targetDocument = JSONPatch.apply(sourceDocument, patch);
60
- // 6. Validate targetDocument is a conformant DID document, else MUST raise invalidDIDUpdate error.
61
- DidDocument.validate(targetDocument);
62
- // 7. Set sourceHashBytes to the result of passing sourceDocument into the JSON Canonicalization and Hash algorithm.
63
- // 8. Set BTCR2SignedUpdate.sourceHash to the base58-btc Multibase encoding of sourceHashBytes.
64
- unsignedUpdate.sourceHash = (canonicalization.process(sourceDocument, { encoding: 'base58' })).slice(1);
65
- // TODO: Question - is base58btc the correct encoding scheme?
66
- // 9. Set targetHashBytes to the result of passing targetDocument into the JSON Canonicalization and Hash algorithm.
67
- // 10. Set BTCR2SignedUpdate.targetHash to the base58-btc Multibase encoding of targetHashBytes.
68
- unsignedUpdate.targetHash = (canonicalization.process(targetDocument, { encoding: 'base58' })).slice(1);
69
- // 11. Set BTCR2SignedUpdate.targetVersionId to sourceVersionId + 1.
70
- unsignedUpdate.targetVersionId = sourceVersionId + 1;
71
- // 12. Return updatePayload.
42
+ // Apply all JSON patches to sourceDocument.
43
+ const targetDocument = JSONPatch.apply(sourceDocument, patches);
44
+ try {
45
+ // Ensure the targetDocument is conformant to DID Core v1.1.
46
+ DidDocument.isValid(targetDocument);
47
+ }
48
+ catch (error) {
49
+ // If validation fails, throw an UpdateError with INVALID_DID_UPDATE.
50
+ throw new UpdateError('Error validating targetDocument: ' + (error instanceof Error ? error.message : String(error)), INVALID_DID_UPDATE, targetDocument);
51
+ }
52
+ // Set the targetHash by canonicalizing the targetDocument and encoding it in base58.
53
+ unsignedUpdate.targetHash = Canonicalization.process(targetDocument, { encoding: 'base58' });
54
+ // Return unsignedUpdate.
72
55
  return unsignedUpdate;
73
56
  }
74
57
  /**
75
- * {@link https://dcdpr.github.io/did-btcr2/#invoke-did-update-payload | 4.3.2 Invoke DID Update Payload}.
58
+ * Implements subsection {@link http://dcdpr.github.io/did-btcr2/operations/update.html#construct-btcr2-signed-update | 7.3.c Construct BTCR2 Signed Update }.
59
+ * This process constructs a BTCR2 Signed Update from a BTCR2 Unsigned Update.
76
60
  *
77
- * The Invoke DID Update Payload algorithm takes in a Identifier, an unsigned BTCR2SignedUpdate, and a
78
- * verificationMethod. It retrieves the privateKeyBytes for the verificationMethod and adds a capability invocation in
79
- * the form of a Data Integrity proof following the Authorization Capabilities (ZCAP-LD) and VC Data Integrity
80
- * specifications. It returns the invoked DID Update Payload.
81
- *
82
- * @param {InvokePayloadParams} params Required params for calling the invokePayload method
83
- * @param {string} params.identifier The did-btcr2 identifier to derive the root capability from
84
- * @param {BTCR2SignedUpdate} params.BTCR2SignedUpdate The updatePayload object to be signed
85
- * @param {DidVerificationMethod} params.verificationMethod The verificationMethod object to be used for signing
86
- * @returns {BTCR2SignedUpdate} Did update payload secured with a proof => BTCR2SignedUpdate
87
- * @throws {MethodError} if the privateKeyBytes are invalid
61
+ * @param {string} did The did-btcr2 identifier to derive the root capability from
62
+ * @param {UnsignedBTCR2Update} unsignedUpdate The updatePayload object to be signed
63
+ * @param {DidVerificationMethod} verificationMethod The verificationMethod object to be used for signing
64
+ * @returns {SignedBTCR2Update} Did update payload secured with a proof => SignedBTCR2Update
65
+ * @throws {UpdateError} if the privateKeyBytes are invalid
88
66
  */
89
- static async invoke({ identifier, unsignedUpdate, verificationMethod }) {
90
- // Deconstruct the verificationMethod
91
- const { id: fullId, controller, publicKeyMultibase, secretKeyMultibase } = verificationMethod;
92
- // Validate the verificationMethod
93
- if (!publicKeyMultibase) {
94
- throw new MethodError('Invalid publicKeyMultibase: cannot be undefined', INVALID_PUBLIC_KEY_TYPE, verificationMethod);
95
- }
96
- // 1. Set privateKeyBytes to the result of retrieving the private key bytes
97
- // associated with the verificationMethod value.
98
- // 1.1 Let id be the fragment portion of verificationMethod.id.
99
- const id = fullId.slice(fullId.indexOf('#'));
100
- // 1.2 Retrieve the key pair from the KMS or from the secretKeyMultibase
101
- const components = Identifier.decode(id);
102
- const keyUri = new CompressedSecp256k1PublicKey(components.genesisBytes).hex;
103
- const keys = secretKeyMultibase
104
- ? new SchnorrKeyPair({ secretKey: Secp256k1SecretKey.decode(secretKeyMultibase) })
105
- : Kms.getKey(keyUri);
106
- if (!keys) {
107
- throw new MethodError('No privateKey found in kms or vm', NOT_FOUND, verificationMethod);
108
- }
109
- // 1.3 Set multikey to the result of passing verificationMethod and privateKeyBytes into the Multikey Creation algorithm.
110
- const multikey = SchnorrMultikey.create({ id, controller, keys });
111
- // 1.4 If the privateKey is not found, throw an error
112
- if (!multikey) {
113
- throw new MethodError('Failed to create multikey from verification method', 'MULTKEY_CREATE_FAILED', verificationMethod);
114
- }
115
- // 2. Set rootCapability to the result of passing Identifier into the Derive Root Capability from did:btcr2
116
- // Identifier algorithm.
117
- const rootCapability = Appendix.deriveRootCapability(identifier);
118
- const cryptosuite = 'bip340-jcs-2025';
119
- // 3. Initialize proofOptions to an empty object.
120
- // 4. Set proofOptions.type to DataIntegrityProof.
121
- // 5. Set proofOptions.cryptosuite to schnorr-secp256k1-jcs-2025.
122
- // 6. Set proofOptions.verificationMethod to verificationMethod.id.
123
- // 7. Set proofOptions.proofPurpose to capabilityInvocation.
124
- // 8. Set proofOptions.capability to rootCapability.id.
125
- // 9. Set proofOptions.capabilityAction to Write.
67
+ static async sign(did, unsignedUpdate, verificationMethod, secretKey) {
68
+ // Parse the controller from the verificationMethod
69
+ const controller = verificationMethod.controller;
70
+ // Parse the fragment from the vmId
71
+ const id = verificationMethod.id.slice(verificationMethod.id.indexOf('#'));
72
+ // Construct a Schnorr Multikey
73
+ const multikey = SchnorrMultikey.fromSecretKey(id, controller, secretKey);
74
+ // Define the Data Integrity proof config
126
75
  const config = {
127
76
  '@context': [
128
77
  'https://w3id.org/security/v2',
@@ -130,75 +79,34 @@ export class Update {
130
79
  'https://w3id.org/json-ld-patch/v1',
131
80
  'https://btcr2.dev/context/v1'
132
81
  ],
133
- cryptosuite,
82
+ cryptosuite: 'bip340-jcs-2025',
134
83
  type: 'DataIntegrityProof',
135
- verificationMethod: fullId,
84
+ verificationMethod: verificationMethod.id,
136
85
  proofPurpose: 'capabilityInvocation',
137
- capability: rootCapability.id,
86
+ capability: `urn:zcap:root:${encodeURIComponent(did)}`,
138
87
  capabilityAction: 'Write',
139
88
  };
140
- // 10. Set cryptosuite to the result of executing the Cryptosuite Instantiation algorithm from the BIP340 Data
141
- // Integrity specification passing in proofOptions.
89
+ // Go from multikey => cryptosuite => diproof
142
90
  const diproof = multikey.toCryptosuite().toDataIntegrityProof();
143
- // 12. Set BTCR2SignedUpdate to the result of executing the Add Proof algorithm from VC Data Integrity passing
144
- // BTCR2SignedUpdate as the input document, cryptosuite, and the set of proofOptions.
145
- // 13. Return BTCR2SignedUpdate.
146
- return await diproof.addProof(unsignedUpdate, config);
91
+ // Use the config to add a proof to the unsigned update
92
+ return diproof.addProof(unsignedUpdate, config);
147
93
  }
148
94
  /**
149
- * Implements {@link https://dcdpr.github.io/did-btcr2/#announce-did-update | 4.3.3 Announce DID Update}.
150
- *
151
- * The Announce DID Update algorithm retrieves beaconServices from the sourceDocument and calls the Broadcast DID
152
- * Update algorithm corresponding to the type of the Beacon. It takes in a Identifier, sourceDocument, an array of
153
- * beaconIds, and a BTCR2SignedUpdate. It returns an array of signalsMetadata, containing the necessary
154
- * data to validate the Beacon Signal against the BTCR2SignedUpdate.
155
- *
156
- * @param {AnnounceUpdatePayloadParams} params Required params for calling the announcePayload method
157
- * @param {DidDocument} params.sourceDocument The did-btcr2 did document to derive the root capability from
158
- * @param {string[]} params.beaconIds The BTCR2SignedUpdate object to be signed
159
- * @param {BTCR2SignedUpdate} params.BTCR2SignedUpdate The verificationMethod object to be used for signing
160
- * @returns {BTCR2SignedUpdate} The BTCR2SignedUpdate object containing data to validate the Beacon Signal
161
- * @throws {MethodError} if the beaconService type is invalid
95
+ * Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/update.html#announce-did-update | 7.3.d Announce DID Update}.
96
+ * BTCR2 Signed Updates are announced to the Bitcoin blockchain depending on the Beacon Type.
97
+ * @param {BeaconService} beaconService The BeaconService object representing the funded beacon to announce the update to.
98
+ * @param {SignedBTCR2Update} update The signed update object to be announced.
99
+ * @param {KeyBytes} secretKey The private key used to sign the update for announcement.
100
+ * @returns {SignedBTCR2Update} The SignedBTCR2Update object containing data to validate the Beacon Signal
101
+ * @throws {UpdateError} if the beaconService type is invalid
162
102
  */
163
- static async announce({ sourceDocument, beaconIds, signedUpdate }) {
164
- // 1. Set beaconServices to an empty array.
165
- const beaconServices = [];
166
- // 2. sidecarData to an empty array.
167
- let sidecarData;
168
- // 3. For beaconId in beaconIds:
169
- for (const beaconId of beaconIds) {
170
- // 3.1 Find the beacon services in the sourceDocument
171
- const beaconService = sourceDocument.service.find((s) => s.id === beaconId);
172
- // 3.2 If no beaconService MUST throw beaconNotFound error.
173
- if (!beaconService) {
174
- throw new MethodError('Not found: sourceDocument does not contain beaconId', INVALID_DID_DOCUMENT, { beaconId });
175
- }
176
- // 3.3 Push beaconService to beaconServices.
177
- beaconServices.push(beaconService);
178
- }
179
- // 4. For beaconService in beaconServices:
180
- for (const beaconService of beaconServices) {
181
- // 4.1 Set signalMetadata to null.
182
- // 4.2 If beaconService.type == SingletonBeacon:
183
- // 4.2.1 Set signalMetadata to the result of passing beaconService and BTCR2SignedUpdate to the Broadcast
184
- // Singleton Beacon Signal algorithm.
185
- // 4.3 Else If beaconService.type == CASBeacon:
186
- // 4.3.1 Set signalMetadata to the result of passing Identifier, beaconService and BTCR2SignedUpdate to
187
- // the Broadcast CIDAggregate Beacon Signal algorithm.
188
- // 4.4 Else If beaconService.type == SMTBeacon:
189
- // 4.4.1 Set signalMetadata to the result of passing Identifier, beaconService and BTCR2SignedUpdate to
190
- // the Broadcast SMTAggregate Beacon Signal algorithm.
191
- // 4.5 Else:
192
- // 4.5.1 MUST throw invalidBeacon error.
193
- // const beacon = BeaconFactory.establish(beaconService);
194
- // sidecarData = await beacon.broadcastSignal(signedUpdate);
195
- console.log('TODO: refactor this code', signedUpdate, beaconService);
196
- }
197
- if (!sidecarData) {
198
- throw new MethodError('Invalid beacon: no sidecarData found', INVALID_DID_DOCUMENT, { beaconServices });
199
- }
103
+ static async announce(beaconService, update, secretKey, bitcoin) {
104
+ // Establish a beacon object
105
+ const beacon = BeaconFactory.establish(beaconService);
106
+ // Broadcast the update
107
+ const result = await beacon.broadcastSignal(update, secretKey, bitcoin);
200
108
  // Return the sidecarData
201
- return sidecarData;
109
+ return result;
202
110
  }
203
111
  }
204
112
  //# sourceMappingURL=update.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"update.js","sourceRoot":"","sources":["../../../src/core/update.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"update.js","sourceRoot":"","sources":["../../../src/core/update.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { BitcoinNetworkConnection } from '@did-btcr2/bitcoin';
2
- import { Canonicalization, IdentifierHrp, INVALID_DID_DOCUMENT, METHOD_NOT_SUPPORTED, MethodError, MISSING_UPDATE_DATA, ResolveError } from '@did-btcr2/common';
2
+ import { IdentifierHrp, INVALID_DID_DOCUMENT, INVALID_DID_UPDATE, METHOD_NOT_SUPPORTED, MethodError, MISSING_UPDATE_DATA, ResolveError, UpdateError } from '@did-btcr2/common';
3
3
  import { Did, DidError, DidErrorCode, EMPTY_DID_RESOLUTION_RESULT } from '@web5/dids';
4
4
  import { initEccLib } from 'bitcoinjs-lib';
5
5
  import * as tinysecp from 'tiny-secp256k1';
@@ -8,9 +8,7 @@ import { Identifier } from './core/identifier.js';
8
8
  import { Resolve } from './core/resolve.js';
9
9
  import { Update } from './core/update.js';
10
10
  import { Appendix } from './utils/appendix.js';
11
- // TODO: convert to API driver
12
- export const canonicalization = new Canonicalization();
13
- // TODO: convert to API driver
11
+ // TODO: convert to API driver?
14
12
  /** Initialize tiny secp256k1 */
15
13
  initEccLib(tinysecp);
16
14
  /**
@@ -27,7 +25,9 @@ initEccLib(tinysecp);
27
25
  * @implements {DidMethod}
28
26
  */
29
27
  export class DidBtcr2 {
30
- /** @type {string} Name of the DID method, as defined in the DID BTCR2 specification */
28
+ /**
29
+ * Name of the DID method, as defined in the DID BTCR2 specification
30
+ */
31
31
  static methodName = 'btcr2';
32
32
  /**
33
33
  * Implements section {@link https://dcdpr.github.io/did-btcr2/operations/create.html | 7.1 Create}.
@@ -39,8 +39,13 @@ export class DidBtcr2 {
39
39
  * @param {string} options.network The Bitcoin network to use for the identifier, e.g. 'bitcoin', 'testnet', etc. Defaults to 'bitcoin'.
40
40
  * @returns {Promise<Btcr2Identifier>} Promise resolving to a Btcr2Identifier string.
41
41
  * @throws {MethodError} if any of the checks fail
42
+ * @example
43
+ * ```ts
44
+ * const genesisBytes = SchnorrKeyPair.generate().publicKey.compressed;
45
+ * const did = DidBtcr2.create(genesisBytes, { idType: 'KEY', network: 'regtest' });
46
+ * ```
42
47
  */
43
- static async create(genesisBytes, options) {
48
+ static create(genesisBytes, options) {
44
49
  // Deconstruct the idType, version and network from the options, setting defaults if not given
45
50
  const { idType, version = 1, network = 'bitcoin' } = options || {};
46
51
  if (!idType) {
@@ -50,7 +55,7 @@ export class DidBtcr2 {
50
55
  return Identifier.encode({ idType, genesisBytes, version, network });
51
56
  }
52
57
  /**
53
- * Entry point for section {@link https://dcdpr.github.io/did-btcr2/#read | 7.2 Resolve}.
58
+ * Entry point for section {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html | 7.2 Resolve}.
54
59
  * See specification for the {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#process | Resolve Process}.
55
60
  * See {@link Resolve | Resolve (class)} for class implementation.
56
61
  *
@@ -59,31 +64,29 @@ export class DidBtcr2 {
59
64
  * blockchain by Authorized Beacon Signals. The Initial DID Document is either
60
65
  * deterministically created from the DID or provided by Sidecar Data.
61
66
  *
62
- * @param {string} did a valid did:btcr2 identifier to be resolved
63
- * @param {ResolutionOptions} resolutionOptions see {@link https://www.w3.org/TR/did-1.0/#did-resolution-options | ResolutionOptions}
64
- * @param {number} resolutionOptions.versionId optional version of the identifier and/or DID document
65
- * @param {number} resolutionOptions.versionTime optional timestamp used during resolution as a bound for when to stop resolving
66
- * @param {DidDocument} resolutionOptions.sidecar optional data necessary for resolving a DID
67
+ * @param {string} did The did:btcr2 identifier to be resolved.
68
+ * @param {ResolutionOptions} resolutionOptions Options used during the resolution process.
67
69
  * @returns {Promise<DidResolutionResult>} Promise resolving to a DID Resolution Result containing the `targetDocument`
68
- * @throws {Error} if the resolution fails for any reason
69
- * @throws {DidError} InvalidDid if the identifier is invalid
70
+ * @throws {ResolveError} If the resolution process fails at any step.
70
71
  * @example
71
72
  * ```ts
72
73
  * const resolution = await DidBtcr2.resolve(
73
- * 'did:btcr2:k1q0dygyp3gz969tp46dychzy4q78c2k3js68kvyr0shanzg67jnuez2cfplh'
74
+ * 'did:btcr2:k1qgpr45cheptyjekl3cex80xfnkwhxnlclecwwf92gvdjrszm2uwhzlcxu5xte'
74
75
  * )
75
76
  * ```
76
77
  */
77
- static async resolve(did, resolutionOptions = { drivers: {} }) {
78
+ static async resolve(did, resolutionOptions = {}) {
78
79
  try {
80
+ // Set versionId from resolutionOptions
81
+ const versionId = resolutionOptions.versionId;
79
82
  // Initialize an empty DID Resolution Result
80
83
  const didResolutionResult = {
81
84
  '@context': 'https://w3id.org/did-resolution/v1',
82
85
  didResolutionMetadata: { contentType: 'application/ld+json' },
83
86
  didDocumentMetadata: {
87
+ versionId,
84
88
  deactivated: false,
85
89
  updated: undefined,
86
- versionId: resolutionOptions.versionId,
87
90
  confirmations: undefined,
88
91
  },
89
92
  didDocument: null,
@@ -91,45 +94,49 @@ export class DidBtcr2 {
91
94
  // Decode the did to be resolved
92
95
  const didComponents = Identifier.decode(did);
93
96
  // Process sidecar if provided
94
- const sidecarData = Resolve.processSidecarData(resolutionOptions.sidecar);
95
- // Establish a connection to a bitcoin network
96
- if (!resolutionOptions.drivers.bitcoin) {
97
- resolutionOptions.drivers.bitcoin = new BitcoinNetworkConnection();
98
- // Set the network based on the decoded identifier
99
- resolutionOptions.drivers.bitcoin.setActiveNetwork(didComponents.network);
100
- }
97
+ const sidecarData = Resolve.sidecarData(resolutionOptions.sidecar);
101
98
  // Parse the genesis document from the resolution options if provided
102
99
  const genesisDocument = resolutionOptions.sidecar?.genesisDocument;
103
100
  // Since genesisDocument is optional, check if it exists
104
101
  if (!genesisDocument) {
105
102
  // If no genesisDocument and x HRP, throw MISSING_UPDATE_DATA error
106
103
  if (didComponents.hrp === IdentifierHrp.x)
107
- throw new ResolveError('External resolution requires genesisDocument', MISSING_UPDATE_DATA, { resolutionOptions });
104
+ throw new ResolveError('External resolution requires genesisDocument', MISSING_UPDATE_DATA, resolutionOptions);
108
105
  }
109
106
  // Establish the current document
110
- const currentDocument = await Resolve.establishCurrentDocument(didComponents, genesisDocument);
107
+ const currentDocument = await Resolve.currentDocument(didComponents, genesisDocument);
111
108
  // Extract all Beacon services from the current DID Document
112
109
  const beaconServices = currentDocument.service
113
110
  .filter(BeaconUtils.isBeaconService)
114
111
  .map(BeaconUtils.parseBeaconServiceEndpoint);
112
+ // Check if bitcoin driver provided
113
+ if (!resolutionOptions?.drivers?.bitcoin) {
114
+ // If not, initialize default drivers
115
+ resolutionOptions.drivers = resolutionOptions.drivers || {};
116
+ // Set bitcoin driver to default BitcoinNetworkConnection
117
+ resolutionOptions.drivers.bitcoin = new BitcoinNetworkConnection();
118
+ // Set the network based on the decoded identifier
119
+ resolutionOptions.drivers.bitcoin.setActiveNetwork(didComponents.network);
120
+ }
121
+ // Get the bitcoin driver from the resolution options
122
+ const bitcoin = resolutionOptions.drivers.bitcoin;
115
123
  // Process the Beacon Signals to get the required updates
116
- const unsortedUpdates = await Resolve.processBeaconSignals(beaconServices, sidecarData, resolutionOptions.drivers.bitcoin, resolutionOptions.fullBlockchainTraversal);
124
+ const unsortedUpdates = await Resolve.beaconSignals(beaconServices, sidecarData, bitcoin);
117
125
  // If no updates found, return the current document
118
126
  if (!unsortedUpdates.length) {
119
- // Set the current document in the didResolutionResult
127
+ // Set the didDocument in didResolutionResult based on currentDocument
120
128
  didResolutionResult.didDocument = currentDocument;
121
- // Set the deactivated status in the didDocumentMetadata
129
+ // Set other required fields in the didResolutionResult
122
130
  didResolutionResult.didDocumentMetadata.deactivated = !!currentDocument.deactivated;
131
+ didResolutionResult.didDocumentMetadata.versionId = versionId ?? '1';
123
132
  // Return the didResolutionResult early
124
133
  return didResolutionResult;
125
134
  }
126
135
  // Process the updates to apply updates to bring the current DID Document to its more current state
127
- const result = await Resolve.processUpdatesArray(currentDocument, unsortedUpdates, resolutionOptions.versionTime, resolutionOptions.versionId);
136
+ const result = await Resolve.updates(currentDocument, unsortedUpdates, resolutionOptions.versionTime, versionId);
128
137
  // Set all of the required fields in the didResolutionResult
129
- didResolutionResult.didDocument = result.currentDocument;
130
- didResolutionResult.didDocumentMetadata.confirmations = result.confirmations;
131
- didResolutionResult.didDocumentMetadata.versionId = result.versionId;
132
- didResolutionResult.didDocumentMetadata.deactivated = !!result.currentDocument.deactivated;
138
+ didResolutionResult.didDocument = result.didDocument;
139
+ didResolutionResult.didDocumentMetadata = result.metadata;
133
140
  // Return didResolutionResult;
134
141
  return didResolutionResult;
135
142
  }
@@ -149,77 +156,79 @@ export class DidBtcr2 {
149
156
  }
150
157
  }
151
158
  /**
152
- * Entry point for section {@link https://dcdpr.github.io/did-btcr2/#update | 4.3 Update}.
153
- * See {@link Update} for implementation details.
154
- *
155
- * An update to a did:btcr2 document is an invoked capability using the ZCAP-LD data format, signed by a
156
- * verificationMethod that has the authority to make the update as specified in the previous DID document. Capability
157
- * invocations for updates MUST be authorized using Data Integrity following the bip340-jcs-2025
158
- * cryptosuite with a proofPurpose of capabilityInvocation.
159
- *
160
- * The Update algorithm takes as inputs a Identifier, sourceDocument, sourceVersionId, documentPatch, a
161
- * verificationMethodId and an array of beaconIds. The sourceDocument is the DID document being updated. The
162
- * documentPatch is a JSON Patch object containing a set of transformations to be applied to the sourceDocument.
163
- * The result of these transformations MUST produce a DID document conformant to the DID Core specification. The
164
- * verificationMethodId is an identifier for a verificationMethod within the sourceDocument. The verificationMethod
165
- * identified MUST be a BIP340 Multikey. The beaconIds MUST identify service endpoints with one of the three Beacon
166
- * Types SingletonBeacon, CASBeacon, and SMTBeacon.
159
+ * Entry point for section {@link https://dcdpr.github.io/did-btcr2/#read | 7.3 Update}.
160
+ * See specification for the {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#process | Resolve Process}.
161
+ * See {@link Update | Update (class)} for class implementation.
167
162
  *
168
- * @param {UpdateParams} params Required parameters for the update operation.
169
- * @param {string} params.identifier The btcr2 identifier to be updated.
170
- * @param {DidDocument} params.sourceDocument The DID document being updated.
171
- * @param {string} params.sourceVersionId The versionId of the source document.
172
- * @param {PatchOperation} params.documentPatch The JSON patch to be applied to the source document.
173
- * @param {string} params.verificationMethodId The verificationMethod ID to sign the update
174
- * @param {string[]} params.beaconIds The beacon IDs to announce the update
175
- * @returns {Promise<void>} Promise resolving to void
176
- * @throws {MethodError} if the verificationMethod type is not `Multikey` or the publicKeyMultibase header is not `zQ3s`
163
+ * BTCR2 DID documents can be updated by anchoring BTCR2 Updates to Bitcoin transactions. These transactions MAY be
164
+ * published to the Bitcoin network. Any property in the DID document may be updated except the id. Doing so would
165
+ * invalidate the DID document.
166
+ * @param params An object containing the parameters for the update operation.
167
+ * @param {Btcr2DidDocument} params.sourceDocument The DID document being updated.
168
+ * @param {PatchOperation[]} params.patches The array of JSON Patch operations to apply to the sourceDocument.
169
+ * @param {string} params.sourceVersionId The version ID before applying the update.
170
+ * @param {string} params.verificationMethodId The verificationMethod ID to sign the update with.
171
+ * @param {string} params.beaconId The beacon ID associated with the update.
172
+ * @param {KeyBytes | HexString} [params.signingMaterial] Optional signing material (key bytes or hex string).
173
+ * @param {BitcoinNetworkConnection} [params.bitcoin] Optional Bitcoin network connection for announcing the update. If not provided, a default connection will be initialized.
174
+ * @return {Promise<SignedBTCR2Update>} Promise resolving to the signed BTCR2 update.
175
+ * @throws {UpdateError} if no verificationMethod, verificationMethod type is not `Multikey` or the publicKeyMultibase
176
+ * header is not `zQ3s`
177
177
  */
178
- static async update(params) {
179
- // Deconstruct the params
180
- const { identifier, sourceDocument, sourceVersionId, patch, verificationMethodId: methodId, beaconIds, } = params;
181
- // 1. Set unsignedUpdate to the result of passing Identifier, sourceDocument,
182
- // sourceVersionId, and documentPatch into the Construct DID Update
183
- // Payload algorithm.
184
- const unsignedUpdate = await Update.construct({
185
- identifier,
186
- sourceDocument,
187
- sourceVersionId,
188
- patch,
189
- });
190
- // 2. Set verificationMethod to the result of retrieving the verificationMethod
191
- // from sourceDocument using the verificationMethodId.
192
- const verificationMethod = this.getSigningMethod(sourceDocument, methodId);
178
+ static async update({ sourceDocument, patches, sourceVersionId, verificationMethodId, beaconId, signingMaterial, bitcoin, }) {
179
+ // TODO: provide KMS as alternative
180
+ // If no signingMaterial provided, throw an UpdateError with INVALID_DID_UPDATE.
181
+ if (!signingMaterial) {
182
+ throw new UpdateError('Missing signing material for update', INVALID_DID_UPDATE, { signingMaterial });
183
+ }
184
+ // Convert signingMaterial to bytes if it's a hex string
185
+ const secretKey = typeof signingMaterial === 'string'
186
+ ? Buffer.from(signingMaterial, 'hex')
187
+ : signingMaterial;
188
+ // Validate that the verificationMethodId is authorized for capabilityInvocation
189
+ if (!sourceDocument.capabilityInvocation?.some(vr => vr === verificationMethodId)) {
190
+ throw new UpdateError('Invalid verificationMethodId: not authorized for capabilityInvocation', INVALID_DID_DOCUMENT, sourceDocument);
191
+ }
192
+ // Get the verification method to be used for signing the update
193
+ const verificationMethod = this.getSigningMethod(sourceDocument, verificationMethodId);
193
194
  // Validate the verificationMethod exists in the sourceDocument
194
195
  if (!verificationMethod) {
195
- throw new MethodError('Verification method not found in did document', INVALID_DID_DOCUMENT, sourceDocument);
196
+ throw new UpdateError('Invalid verificationMethod: not found in source document', INVALID_DID_DOCUMENT, { sourceDocument, verificationMethodId });
196
197
  }
197
- // 3. Validate the verificationMethod is a BIP340 Multikey:
198
- // 3.1 verificationMethod.type == Multikey
198
+ // Validate the verificationMethod is of type 'Multikey'
199
199
  if (verificationMethod.type !== 'Multikey') {
200
- throw new MethodError('Invalid type: must be type "Multikey"', INVALID_DID_DOCUMENT, verificationMethod);
200
+ throw new UpdateError('Invalid verificationMethod: verificationMethod.type must be "Multikey"', INVALID_DID_DOCUMENT, verificationMethod);
201
+ }
202
+ // Validate the publicKeyMultibase prefix is 'zQ3s'
203
+ if (verificationMethod.publicKeyMultibase?.slice(0, 4) !== 'zQ3s') {
204
+ throw new UpdateError('Invalid verificationMethodId: publicKeyMultibase prefix must start with "zQ3s"', INVALID_DID_DOCUMENT, verificationMethod);
201
205
  }
202
- // 3.2 verificationMethod.publicKeyMultibase[4] == zQ3s
203
- const mbasePrefix = verificationMethod.publicKeyMultibase?.slice(0, 4);
204
- if (mbasePrefix !== 'zQ3s') {
205
- throw new MethodError(`Invalid publicKeyMultibase prefix ${mbasePrefix}`, INVALID_DID_DOCUMENT, verificationMethod);
206
+ // Construct an unsigned update following the BTCR2 Update construction algorithm
207
+ const update = await Update.construct(sourceDocument, patches, sourceVersionId);
208
+ // Sign the unsigned update using the specified verification method
209
+ const signed = await Update.sign(sourceDocument.id, update, verificationMethod, secretKey);
210
+ // Filter sourceDocument services to get beaconServices matching beaconIds
211
+ const beaconService = sourceDocument.service
212
+ .filter((service) => service.id === beaconId)
213
+ .filter((service) => !!service)
214
+ .shift();
215
+ // If no matching beacon service found, throw an UpdateError with INVALID_DID_UPDATE.
216
+ if (!beaconService) {
217
+ throw new UpdateError('No beacon service found for provided beaconId', INVALID_DID_UPDATE, { sourceDocument, beaconId });
206
218
  }
207
- // 4. Set didUpdateInvocation to the result of passing Identifier, unsignedUpdate as didUpdatePayload, and
208
- // verificationMethod to the Invoke DID Update Payload algorithm.
209
- const signedUpdate = await Update.invoke({ identifier, verificationMethod, unsignedUpdate });
210
- // 5. Set signalsMetadata to the result of passing Identifier, sourceDocument, beaconIds and didUpdateInvocation
211
- // to the Announce DID Update algorithm.
212
- const signalsMetadata = await Update.announce({ sourceDocument, beaconIds, signedUpdate });
213
- // 6. Return signalsMetadata. It is up to implementations to ensure that the signalsMetadata is persisted.
214
- return signalsMetadata;
215
- // TODO: Should we be applying the patch, producing a target did document and returning it?
219
+ // If no bitcoin network connection provided, initialize default
220
+ bitcoin ??= new BitcoinNetworkConnection();
221
+ // Announce the signed update to the blockchain using the specified beacon(s)
222
+ await Update.announce(beaconService, signed, secretKey, bitcoin);
223
+ // Return signed update if announced successfully
224
+ return signed;
216
225
  }
217
226
  /**
218
227
  * Given the W3C DID Document of a `did:btcr2` identifier, return the signing verification method that will be used
219
228
  * for signing messages and credentials. If given, the `methodId` parameter is used to select the
220
229
  * verification method. If not given, the Identity Key's verification method with an ID fragment
221
230
  * of '#initialKey' is used.
222
- * @param {DidDocument} didDocument The DID Document of the `did:btcr2` identifier.
231
+ * @param {Btcr2DidDocument} didDocument The DID Document of the `did:btcr2` identifier.
223
232
  * @param {string} [methodId] Optional verification method ID to be used for signing.
224
233
  * @returns {DidVerificationMethod} Promise resolving to the {@link DidVerificationMethod} object used for signing.
225
234
  * @throws {DidError} if the parsed did method does not match `btcr2` or signing method could not be determined.