@did-btcr2/method 0.18.0 → 0.19.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 (262) hide show
  1. package/dist/browser.js +5240 -6079
  2. package/dist/browser.mjs +5240 -6079
  3. package/dist/cjs/core/beacon/aggregation/cohort/index.js +3 -3
  4. package/dist/cjs/core/beacon/aggregation/cohort/index.js.map +1 -1
  5. package/dist/cjs/core/beacon/aggregation/cohort/messages/base.js +1 -9
  6. package/dist/cjs/core/beacon/aggregation/cohort/messages/base.js.map +1 -1
  7. package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.js +2 -1
  8. package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.js.map +1 -1
  9. package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.js +2 -1
  10. package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.js.map +1 -1
  11. package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.js +2 -1
  12. package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.js.map +1 -1
  13. package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/opt-in.js +2 -1
  14. package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/opt-in.js.map +1 -1
  15. package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/subscribe.js +2 -1
  16. package/dist/cjs/core/beacon/aggregation/cohort/messages/keygen/subscribe.js.map +1 -1
  17. package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.js +2 -1
  18. package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.js.map +1 -1
  19. package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/authorization-request.js +2 -1
  20. package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/authorization-request.js.map +1 -1
  21. package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.js +2 -1
  22. package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.js.map +1 -1
  23. package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/request-signature.js +2 -1
  24. package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/request-signature.js.map +1 -1
  25. package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/signature-authorization.js +2 -1
  26. package/dist/cjs/core/beacon/aggregation/cohort/messages/sign/signature-authorization.js.map +1 -1
  27. package/dist/cjs/core/beacon/aggregation/communication/adapter/nostr.js +36 -18
  28. package/dist/cjs/core/beacon/aggregation/communication/adapter/nostr.js.map +1 -1
  29. package/dist/cjs/core/beacon/aggregation/coordinator.js +14 -14
  30. package/dist/cjs/core/beacon/aggregation/coordinator.js.map +1 -1
  31. package/dist/cjs/core/beacon/aggregation/participant.js +4 -3
  32. package/dist/cjs/core/beacon/aggregation/participant.js.map +1 -1
  33. package/dist/cjs/core/beacon/aggregation/session/index.js +1 -1
  34. package/dist/cjs/core/beacon/aggregation/session/index.js.map +1 -1
  35. package/dist/cjs/core/beacon/cas-beacon.js +55 -0
  36. package/dist/cjs/core/beacon/cas-beacon.js.map +1 -0
  37. package/dist/cjs/core/beacon/factory.js +11 -10
  38. package/dist/cjs/core/beacon/factory.js.map +1 -1
  39. package/dist/cjs/core/beacon/interfaces.js +32 -0
  40. package/dist/cjs/core/beacon/interfaces.js.map +1 -0
  41. package/dist/cjs/core/beacon/singleton.js +59 -135
  42. package/dist/cjs/core/beacon/singleton.js.map +1 -1
  43. package/dist/cjs/core/beacon/smt-beacon.js +56 -0
  44. package/dist/cjs/core/beacon/smt-beacon.js.map +1 -0
  45. package/dist/cjs/core/beacon/utils.js +67 -105
  46. package/dist/cjs/core/beacon/utils.js.map +1 -1
  47. package/dist/cjs/core/identifier.js +18 -21
  48. package/dist/cjs/core/identifier.js.map +1 -1
  49. package/dist/cjs/core/interfaces.js +2 -0
  50. package/dist/cjs/core/interfaces.js.map +1 -0
  51. package/dist/cjs/core/resolve.js +511 -0
  52. package/dist/cjs/core/resolve.js.map +1 -0
  53. package/dist/cjs/{utils → core}/types.js.map +1 -1
  54. package/dist/cjs/core/{crud/update.js → update.js} +62 -52
  55. package/dist/cjs/core/update.js.map +1 -0
  56. package/dist/cjs/did-btcr2.js +109 -75
  57. package/dist/cjs/did-btcr2.js.map +1 -1
  58. package/dist/cjs/index.js +14 -15
  59. package/dist/cjs/index.js.map +1 -1
  60. package/dist/cjs/utils/appendix.js +10 -18
  61. package/dist/cjs/utils/appendix.js.map +1 -1
  62. package/dist/cjs/utils/did-document.js +51 -58
  63. package/dist/cjs/utils/did-document.js.map +1 -1
  64. package/dist/cjs/utils/general.js +1 -1
  65. package/dist/cjs/utils/general.js.map +1 -1
  66. package/dist/esm/core/beacon/aggregation/cohort/index.js +3 -3
  67. package/dist/esm/core/beacon/aggregation/cohort/index.js.map +1 -1
  68. package/dist/esm/core/beacon/aggregation/cohort/messages/base.js +1 -9
  69. package/dist/esm/core/beacon/aggregation/cohort/messages/base.js.map +1 -1
  70. package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.js +2 -1
  71. package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.js.map +1 -1
  72. package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.js +2 -1
  73. package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.js.map +1 -1
  74. package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.js +2 -1
  75. package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.js.map +1 -1
  76. package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/opt-in.js +2 -1
  77. package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/opt-in.js.map +1 -1
  78. package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/subscribe.js +2 -1
  79. package/dist/esm/core/beacon/aggregation/cohort/messages/keygen/subscribe.js.map +1 -1
  80. package/dist/esm/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.js +2 -1
  81. package/dist/esm/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.js.map +1 -1
  82. package/dist/esm/core/beacon/aggregation/cohort/messages/sign/authorization-request.js +2 -1
  83. package/dist/esm/core/beacon/aggregation/cohort/messages/sign/authorization-request.js.map +1 -1
  84. package/dist/esm/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.js +2 -1
  85. package/dist/esm/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.js.map +1 -1
  86. package/dist/esm/core/beacon/aggregation/cohort/messages/sign/request-signature.js +2 -1
  87. package/dist/esm/core/beacon/aggregation/cohort/messages/sign/request-signature.js.map +1 -1
  88. package/dist/esm/core/beacon/aggregation/cohort/messages/sign/signature-authorization.js +2 -1
  89. package/dist/esm/core/beacon/aggregation/cohort/messages/sign/signature-authorization.js.map +1 -1
  90. package/dist/esm/core/beacon/aggregation/communication/adapter/nostr.js +36 -18
  91. package/dist/esm/core/beacon/aggregation/communication/adapter/nostr.js.map +1 -1
  92. package/dist/esm/core/beacon/aggregation/coordinator.js +14 -14
  93. package/dist/esm/core/beacon/aggregation/coordinator.js.map +1 -1
  94. package/dist/esm/core/beacon/aggregation/participant.js +4 -3
  95. package/dist/esm/core/beacon/aggregation/participant.js.map +1 -1
  96. package/dist/esm/core/beacon/aggregation/session/index.js +1 -1
  97. package/dist/esm/core/beacon/aggregation/session/index.js.map +1 -1
  98. package/dist/esm/core/beacon/cas-beacon.js +55 -0
  99. package/dist/esm/core/beacon/cas-beacon.js.map +1 -0
  100. package/dist/esm/core/beacon/factory.js +11 -10
  101. package/dist/esm/core/beacon/factory.js.map +1 -1
  102. package/dist/esm/core/beacon/interfaces.js +32 -0
  103. package/dist/esm/core/beacon/interfaces.js.map +1 -0
  104. package/dist/esm/core/beacon/singleton.js +59 -135
  105. package/dist/esm/core/beacon/singleton.js.map +1 -1
  106. package/dist/esm/core/beacon/smt-beacon.js +56 -0
  107. package/dist/esm/core/beacon/smt-beacon.js.map +1 -0
  108. package/dist/esm/core/beacon/utils.js +67 -105
  109. package/dist/esm/core/beacon/utils.js.map +1 -1
  110. package/dist/esm/core/identifier.js +18 -21
  111. package/dist/esm/core/identifier.js.map +1 -1
  112. package/dist/esm/core/interfaces.js +2 -0
  113. package/dist/esm/core/interfaces.js.map +1 -0
  114. package/dist/esm/core/resolve.js +511 -0
  115. package/dist/esm/core/resolve.js.map +1 -0
  116. package/dist/esm/{utils → core}/types.js.map +1 -1
  117. package/dist/esm/core/{crud/update.js → update.js} +62 -52
  118. package/dist/esm/core/update.js.map +1 -0
  119. package/dist/esm/did-btcr2.js +109 -75
  120. package/dist/esm/did-btcr2.js.map +1 -1
  121. package/dist/esm/index.js +14 -15
  122. package/dist/esm/index.js.map +1 -1
  123. package/dist/esm/utils/appendix.js +10 -18
  124. package/dist/esm/utils/appendix.js.map +1 -1
  125. package/dist/esm/utils/did-document.js +51 -58
  126. package/dist/esm/utils/did-document.js.map +1 -1
  127. package/dist/esm/utils/general.js +1 -1
  128. package/dist/esm/utils/general.js.map +1 -1
  129. package/dist/types/core/beacon/aggregation/cohort/index.d.ts +1 -1
  130. package/dist/types/core/beacon/aggregation/cohort/messages/base.d.ts +0 -7
  131. package/dist/types/core/beacon/aggregation/cohort/messages/base.d.ts.map +1 -1
  132. package/dist/types/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.d.ts.map +1 -1
  133. package/dist/types/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.d.ts.map +1 -1
  134. package/dist/types/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.d.ts.map +1 -1
  135. package/dist/types/core/beacon/aggregation/cohort/messages/keygen/opt-in.d.ts.map +1 -1
  136. package/dist/types/core/beacon/aggregation/cohort/messages/keygen/subscribe.d.ts.map +1 -1
  137. package/dist/types/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.d.ts.map +1 -1
  138. package/dist/types/core/beacon/aggregation/cohort/messages/sign/authorization-request.d.ts.map +1 -1
  139. package/dist/types/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.d.ts.map +1 -1
  140. package/dist/types/core/beacon/aggregation/cohort/messages/sign/request-signature.d.ts.map +1 -1
  141. package/dist/types/core/beacon/aggregation/cohort/messages/sign/signature-authorization.d.ts.map +1 -1
  142. package/dist/types/core/beacon/aggregation/communication/adapter/nostr.d.ts +13 -5
  143. package/dist/types/core/beacon/aggregation/communication/adapter/nostr.d.ts.map +1 -1
  144. package/dist/types/core/beacon/aggregation/coordinator.d.ts +17 -29
  145. package/dist/types/core/beacon/aggregation/coordinator.d.ts.map +1 -1
  146. package/dist/types/core/beacon/aggregation/participant.d.ts.map +1 -1
  147. package/dist/types/core/beacon/cas-beacon.d.ts +47 -0
  148. package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -0
  149. package/dist/types/core/beacon/factory.d.ts +5 -4
  150. package/dist/types/core/beacon/factory.d.ts.map +1 -1
  151. package/dist/types/core/beacon/interfaces.d.ts +98 -0
  152. package/dist/types/core/beacon/interfaces.d.ts.map +1 -0
  153. package/dist/types/core/beacon/singleton.d.ts +22 -65
  154. package/dist/types/core/beacon/singleton.d.ts.map +1 -1
  155. package/dist/types/core/beacon/smt-beacon.d.ts +48 -0
  156. package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -0
  157. package/dist/types/core/beacon/utils.d.ts +19 -97
  158. package/dist/types/core/beacon/utils.d.ts.map +1 -1
  159. package/dist/types/core/identifier.d.ts.map +1 -1
  160. package/dist/types/core/interfaces.d.ts +94 -0
  161. package/dist/types/core/interfaces.d.ts.map +1 -0
  162. package/dist/types/core/resolve.d.ts +105 -0
  163. package/dist/types/core/resolve.d.ts.map +1 -0
  164. package/dist/types/core/types.d.ts +71 -0
  165. package/dist/types/core/types.d.ts.map +1 -0
  166. package/dist/types/core/{crud/update.d.ts → update.d.ts} +21 -20
  167. package/dist/types/core/update.d.ts.map +1 -0
  168. package/dist/types/did-btcr2.d.ts +45 -57
  169. package/dist/types/did-btcr2.d.ts.map +1 -1
  170. package/dist/types/index.d.ts +14 -15
  171. package/dist/types/index.d.ts.map +1 -1
  172. package/dist/types/utils/appendix.d.ts +5 -10
  173. package/dist/types/utils/appendix.d.ts.map +1 -1
  174. package/dist/types/utils/did-document-builder.d.ts +1 -1
  175. package/dist/types/utils/did-document-builder.d.ts.map +1 -1
  176. package/dist/types/utils/did-document.d.ts +31 -29
  177. package/dist/types/utils/did-document.d.ts.map +1 -1
  178. package/package.json +5 -5
  179. package/src/core/beacon/aggregation/cohort/index.ts +3 -3
  180. package/src/core/beacon/aggregation/cohort/messages/base.ts +1 -12
  181. package/src/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.ts +2 -2
  182. package/src/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.ts +2 -2
  183. package/src/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.ts +2 -2
  184. package/src/core/beacon/aggregation/cohort/messages/keygen/opt-in.ts +2 -2
  185. package/src/core/beacon/aggregation/cohort/messages/keygen/subscribe.ts +2 -2
  186. package/src/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.ts +2 -2
  187. package/src/core/beacon/aggregation/cohort/messages/sign/authorization-request.ts +2 -2
  188. package/src/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.ts +2 -2
  189. package/src/core/beacon/aggregation/cohort/messages/sign/request-signature.ts +2 -2
  190. package/src/core/beacon/aggregation/cohort/messages/sign/signature-authorization.ts +2 -2
  191. package/src/core/beacon/aggregation/communication/adapter/nostr.ts +43 -21
  192. package/src/core/beacon/aggregation/coordinator.ts +41 -29
  193. package/src/core/beacon/aggregation/participant.ts +4 -3
  194. package/src/core/beacon/aggregation/session/index.ts +1 -1
  195. package/src/core/beacon/cas-beacon.ts +67 -0
  196. package/src/core/beacon/factory.ts +13 -15
  197. package/src/core/beacon/interfaces.ts +124 -0
  198. package/src/core/beacon/singleton.ts +75 -145
  199. package/src/core/beacon/smt-beacon.ts +70 -0
  200. package/src/core/beacon/utils.ts +80 -170
  201. package/src/core/identifier.ts +21 -24
  202. package/src/core/interfaces.ts +101 -0
  203. package/src/core/resolve.ts +707 -0
  204. package/src/core/types.ts +78 -0
  205. package/src/core/{crud/update.ts → update.ts} +75 -68
  206. package/src/did-btcr2.ts +152 -92
  207. package/src/index.ts +14 -24
  208. package/src/utils/appendix.ts +18 -22
  209. package/src/utils/did-document-builder.ts +1 -1
  210. package/src/utils/did-document.ts +67 -71
  211. package/src/utils/general.ts +1 -1
  212. package/dist/cjs/core/beacon/cid-aggregate.js +0 -116
  213. package/dist/cjs/core/beacon/cid-aggregate.js.map +0 -1
  214. package/dist/cjs/core/beacon/smt-aggregate.js +0 -126
  215. package/dist/cjs/core/beacon/smt-aggregate.js.map +0 -1
  216. package/dist/cjs/core/crud/deactivate.js +0 -14
  217. package/dist/cjs/core/crud/deactivate.js.map +0 -1
  218. package/dist/cjs/core/crud/read.js +0 -679
  219. package/dist/cjs/core/crud/read.js.map +0 -1
  220. package/dist/cjs/core/crud/update.js.map +0 -1
  221. package/dist/cjs/interfaces/beacon.js +0 -41
  222. package/dist/cjs/interfaces/beacon.js.map +0 -1
  223. package/dist/cjs/interfaces/crud.js +0 -2
  224. package/dist/cjs/interfaces/crud.js.map +0 -1
  225. package/dist/esm/core/beacon/cid-aggregate.js +0 -116
  226. package/dist/esm/core/beacon/cid-aggregate.js.map +0 -1
  227. package/dist/esm/core/beacon/smt-aggregate.js +0 -126
  228. package/dist/esm/core/beacon/smt-aggregate.js.map +0 -1
  229. package/dist/esm/core/crud/deactivate.js +0 -14
  230. package/dist/esm/core/crud/deactivate.js.map +0 -1
  231. package/dist/esm/core/crud/read.js +0 -679
  232. package/dist/esm/core/crud/read.js.map +0 -1
  233. package/dist/esm/core/crud/update.js.map +0 -1
  234. package/dist/esm/interfaces/beacon.js +0 -41
  235. package/dist/esm/interfaces/beacon.js.map +0 -1
  236. package/dist/esm/interfaces/crud.js +0 -2
  237. package/dist/esm/interfaces/crud.js.map +0 -1
  238. package/dist/types/core/beacon/cid-aggregate.d.ts +0 -102
  239. package/dist/types/core/beacon/cid-aggregate.d.ts.map +0 -1
  240. package/dist/types/core/beacon/smt-aggregate.d.ts +0 -111
  241. package/dist/types/core/beacon/smt-aggregate.d.ts.map +0 -1
  242. package/dist/types/core/crud/deactivate.d.ts +0 -13
  243. package/dist/types/core/crud/deactivate.d.ts.map +0 -1
  244. package/dist/types/core/crud/read.d.ts +0 -334
  245. package/dist/types/core/crud/read.d.ts.map +0 -1
  246. package/dist/types/core/crud/update.d.ts.map +0 -1
  247. package/dist/types/interfaces/beacon.d.ts +0 -116
  248. package/dist/types/interfaces/beacon.d.ts.map +0 -1
  249. package/dist/types/interfaces/crud.d.ts +0 -32
  250. package/dist/types/interfaces/crud.d.ts.map +0 -1
  251. package/dist/types/utils/types.d.ts +0 -38
  252. package/dist/types/utils/types.d.ts.map +0 -1
  253. package/src/canonicalize.d.ts +0 -6
  254. package/src/core/beacon/cid-aggregate.ts +0 -153
  255. package/src/core/beacon/smt-aggregate.ts +0 -135
  256. package/src/core/crud/deactivate.ts +0 -13
  257. package/src/core/crud/read.ts +0 -948
  258. package/src/interfaces/beacon.ts +0 -137
  259. package/src/interfaces/crud.ts +0 -33
  260. package/src/utils/types.ts +0 -41
  261. /package/dist/cjs/{utils → core}/types.js +0 -0
  262. /package/dist/esm/{utils → core}/types.js +0 -0
@@ -1,679 +0,0 @@
1
- import { BitcoinNetworkConnection, GENESIS_TX_ID, getNetwork, TXIN_WITNESS_COINBASE } from '@did-btcr2/bitcoin';
2
- import { ID_PLACEHOLDER_VALUE, IdentifierHrp, INVALID_DID, INVALID_DID_DOCUMENT, INVALID_DID_UPDATE, LATE_PUBLISHING_ERROR, Logger, MethodError, ResolveError } from '@did-btcr2/common';
3
- import { Cryptosuite, DataIntegrityProof, SchnorrMultikey } from '@did-btcr2/cryptosuite';
4
- import { CompressedSecp256k1PublicKey } from '@did-btcr2/keypair';
5
- import { bytesToHex } from '@noble/hashes/utils';
6
- import { DidBtcr2 } from '../../did-btcr2.js';
7
- import { Appendix } from '../../utils/appendix.js';
8
- import { DidDocument } from '../../utils/did-document.js';
9
- import { BeaconFactory } from '../beacon/factory.js';
10
- import { BeaconUtils } from '../beacon/utils.js';
11
- ;
12
- ;
13
- ;
14
- const bitcoin = new BitcoinNetworkConnection();
15
- /**
16
- * Implements {@link https://dcdpr.github.io/did-btcr2/#read | 4.2 Read}.
17
- * The read operation is executed by a resolver after a resolution request identifying a specific did:btcr2 identifier is
18
- * received from a client at Resolution Time. The request MAY contain a resolutionOptions object containing additional
19
- * information to be used in resolution. The resolver then attempts to resolve the DID document of the identifier at a
20
- * specific Target Time. The Target Time is either provided in resolutionOptions or is set to the Resolution Time of the
21
- * request.
22
- * To do so it executes the following algorithm:
23
- * 1. Let identifierComponents be the result of running the algorithm
24
- * in Parse did:btcr2 identifier, passing in the identifier.
25
- * 2. Set initialDocument to the result of running Resolve Initial Document
26
- * passing identifier, identifierComponents and resolutionOptions.
27
- * 3. Set targetDocument to the result of running the algorithm in Resolve
28
- * Target Document passing in initialDocument and resolutionOptions.
29
- * 4. Return targetDocument.
30
- *
31
- * @class Resolve
32
- * @type {Resolve}
33
- */
34
- export class Resolve {
35
- /**
36
- * Implements {@link https://dcdpr.github.io/did-btcr2/#deterministically-generate-initial-did-document | 4.2.2.1 Deterministically Generate Initial DID Document}.
37
- *
38
- * The Deterministically Generate Initial DID Document algorithm deterministically generates an initial DID
39
- * Document from a secp256k1 public key. It takes in a did:btcr2 identifier and a identifierComponents object and
40
- * returns an initialDocument.
41
- *
42
- * @param {ResolveDeterministic} params See {@link ResolveDeterministic} for details.
43
- * @param {string} params.identifier The did-btcr2 version.
44
- * @param {DidComponents} params.identifierComponents The decoded components of the identifier.
45
- * @returns {DidDocument} The resolved DID Document object.
46
- */
47
- static deterministic({ identifier, identifierComponents }) {
48
- // Deconstruct the components
49
- const { network, genesisBytes } = identifierComponents;
50
- // Construct a new CompressedSecp256k1PublicKey and deconstruct the publicKey and publicKeyMultibase
51
- const { compressed: publicKey, multibase: publicKeyMultibase } = new CompressedSecp256k1PublicKey(genesisBytes);
52
- // Generate the service field for the DID Document
53
- const service = BeaconUtils.generateBeaconServices({
54
- identifier,
55
- publicKey,
56
- network: getNetwork(network),
57
- type: 'SingletonBeacon',
58
- });
59
- return new DidDocument({
60
- id: identifier,
61
- controller: [identifier],
62
- verificationMethod: [{
63
- id: `${identifier}#initialKey`,
64
- type: 'Multikey',
65
- controller: identifier,
66
- publicKeyMultibase: publicKeyMultibase.encoded
67
- }],
68
- service
69
- });
70
- }
71
- /**
72
- * Implements {@link https://dcdpr.github.io/did-btcr2/#external-resolution | 4.2.2.2 External Resolution}.
73
- *
74
- * The External Resolution algorithm externally retrieves an intermediateDocumentRepresentation, either by retrieving
75
- * it from {@link https://dcdpr.github.io/did-btcr2/#def-content-addressable-storage | Content Addressable Storage (CAS)}
76
- * or from the {@link https://dcdpr.github.io/did-btcr2/#def-sidecar-data | Sidecar Data} provided as part of the
77
- * resolution request. It takes in a did:btcr2 identifier, a identifierComponents object and a resolutionOptions object.
78
- * It returns an initialDocument, which is a conformant DID document validated against the identifier.
79
- *
80
- * @param {ResolveExternal} params Required params for calling the external method.
81
- * @param {string} params.identifier The DID to be resolved.
82
- * @param {DidComponents} params.identifierComponents The decoded components of the identifier.
83
- * @param {DidResolutionOptions} params.resolutionsOptions The options for resolving the DID Document.
84
- * @param {DidDocument} params.resolutionsOptions.sidecarData The sidecar data for resolving the DID Document.
85
- * @param {DidDocument} params.resolutionsOptions.sidecarData.initialDocument The offline user-provided DID Document
86
- * @returns {DidDocument} The resolved DID Document object
87
- */
88
- static async external({ identifier, identifierComponents, resolutionsOptions }) {
89
- // Deconstruct the options
90
- const { initialDocument: document } = resolutionsOptions.sidecarData;
91
- // 1. If resolutionOptions.sidecarData.initialDocument is not null, set initialDocument to the result of passing
92
- // identifier, identifierComponents and resolutionOptions.sidecarData.initialDocument into algorithm Sidecar
93
- // Initial Document Validation.
94
- // 2. Else set initialDocument to the result of passing identifier and identifierComponents to the CAS Retrieval algorithm.
95
- const initialDocument = document
96
- ? await this.sidecar({ identifierComponents, initialDocument: document })
97
- : await this.cas({ identifier, identifierComponents });
98
- // 3. Validate initialDocument is a conformant DID document according to the DID Core 1.1 specification. Else MUST
99
- // raise invalidDidDocument error.
100
- DidDocument.validate(initialDocument);
101
- // 4. Return initialDocument.
102
- return initialDocument;
103
- }
104
- /**
105
- * Implements {@link https://dcdpr.github.io/did-btcr2/#sidecar-initial-document-validation | 4.2.2.2.1 Sidecar Initial Document Validation}.
106
- *
107
- * The Sidecar Initial Document Validation algorithm validates an initialDocument against its identifier, by first
108
- * constructing the intermediateDocumentRepresentation and verifying the hash of this document matches the bytes
109
- * encoded within the identifier. It takes in a did:btcr2 identifier, identifierComponents and a
110
- * initialDocument. It returns the initialDocument if validated, otherwise it throws an error.
111
- *
112
- * @param {ResolveSidecar} params Required params for calling the sidecar method
113
- * @param {string} params.identifier The DID to be resolved
114
- * @param {DidComponents} params.identifierComponents The components of the DID identifier
115
- * @param {DidDocument} params.initialDocument The initial DID Document provided by the user
116
- * @returns {DidDocument} The resolved DID Document object
117
- * @throws {DidError} InvalidDidDocument if genesisBytes !== initialDocument hashBytes
118
- */
119
- static async sidecar({ identifierComponents, initialDocument }) {
120
- // Replace the placeholder did with the identifier throughout the initialDocument.
121
- const intermediateDocument = JSON.parse(JSON.stringify(initialDocument).replaceAll(initialDocument.id, ID_PLACEHOLDER_VALUE));
122
- // Canonicalize and sha256 hash the intermediateDocument
123
- const hashBytes = await JSON.canonicalization.process(intermediateDocument, 'hex');
124
- // Compare the genesisBytes to the hashBytes
125
- const genesisBytes = bytesToHex(identifierComponents.genesisBytes);
126
- // If the genesisBytes do not match the hashBytes, throw an error
127
- if (genesisBytes !== hashBytes) {
128
- throw new MethodError(`Initial document mismatch: genesisBytes ${genesisBytes} !== hashBytes ${hashBytes}`, INVALID_DID_DOCUMENT, { genesisBytes, hashBytes });
129
- }
130
- // Return a W3C conformant DID Document
131
- return new DidDocument(initialDocument);
132
- }
133
- /**
134
- * Implements {@link https://dcdpr.github.io/did-btcr2/#cas-retrieval | 4.2.2.2.2 CAS Retrieval}.
135
- *
136
- * The CAS Retrieval algorithm attempts to retrieve an initialDocument from a Content Addressable Storage (CAS) system
137
- * by converting the bytes in the identifier into a Content Identifier (CID). It takes in an identifier and
138
- * an identifierComponents object. It returns an initialDocument.
139
- *
140
- * @param {ResolveCas} params Required params for calling the cas method
141
- * @param {string} params.identifier BTCR2 DID used to resolve the DID Document
142
- * @param {DidComponents} params.identifierComponents BTCR2 DID components used to resolve the DID Document
143
- * @returns {DidDocument} The resolved DID Document object
144
- * @throws {MethodError} if the DID Document content is invalid
145
- */
146
- static async cas({ identifier, identifierComponents }) {
147
- // 1. Set hashBytes to identifierComponents.genesisBytes.
148
- const hashBytes = identifierComponents.genesisBytes;
149
- // 3. Set intermediateDocumentRepresentation to the result of fetching the cid against a Content Addressable Storage
150
- // (CAS) system such as IPFS.
151
- const intermediateDocument = await Appendix.fetchFromCas(hashBytes);
152
- // Validate the intermediateDocument is not null and is parsable JSON
153
- if (!intermediateDocument || !JSON.parsable(intermediateDocument)) {
154
- throw new MethodError(INVALID_DID_DOCUMENT, 'Invalid DID Document content', { intermediateDocument });
155
- }
156
- // 5. Replace the placeholder did with the identifier throughout the initialDocument.
157
- const initialDocument = JSON.parse(intermediateDocument.replaceAll(ID_PLACEHOLDER_VALUE, identifier));
158
- // 6. Return initialDocument.
159
- return new DidDocument(initialDocument);
160
- }
161
- /**
162
- * Implements {@link https://dcdpr.github.io/did-btcr2/#resolve-initial-document | 4.2.2 Resolve Initial Document}.
163
- *
164
- * This algorithm resolves an initial DID document and validates it against the identifier for a specific did:btcr2.
165
- * The algorithm takes in a did:btcr2 identifier, identifier components object, resolutionsOptions object and returns
166
- * a valid initialDocument for that identifier.
167
- *
168
- * @public
169
- * @param {ResolveInitialDocument} params See {@link ResolveInitialDocument} for parameter details.
170
- * @param {string} params.identifier The DID to be resolved.
171
- * @param {DidComponents} params.identifierComponents The decoded components of the identifier.
172
- * @param {DidResolutionOptions} params.resolutionsOptions Options for resolving the DID Document. See {@link DidResolutionOptions}.
173
- * @returns {Promise<DidDocument>} The resolved DID Document object.
174
- * @throws {DidError} if the DID hrp is invalid, no sidecarData passed and hrp = "x".
175
- */
176
- static async initialDocument({ identifier, identifierComponents, resolutionsOptions }) {
177
- // Deconstruct the hrp from the components
178
- const hrp = identifierComponents.hrp;
179
- // Validate the hrp is either 'k' or 'x'
180
- if (!(hrp in IdentifierHrp)) {
181
- throw new MethodError(`Invalid DID hrp ${hrp}`, INVALID_DID, { hrp });
182
- }
183
- // Make sure options.sidecarData is not null if hrp === x
184
- if (hrp === IdentifierHrp.x && !resolutionsOptions.sidecarData) {
185
- throw new MethodError('External resolution requires sidecar data', INVALID_DID, resolutionsOptions);
186
- }
187
- return hrp === IdentifierHrp.k
188
- ? this.deterministic({ identifier, identifierComponents })
189
- : await this.external({ identifier, identifierComponents, resolutionsOptions });
190
- }
191
- /**
192
- * Implements {@link https://dcdpr.github.io/did-btcr2/#resolve-target-document | 4.2.3 Resolve Target Document}.
193
- *
194
- * The Resolve Target Document algorithm resolves a DID document from an initial document by walking the Bitcoin
195
- * blockchain to identify Beacon Signals that announce DID Update Payloads applicable to the did:btcr2 identifier being
196
- * resolved. It takes as inputs initialDocument, resolutionOptions and network. It returns a valid DID document.
197
- *
198
- * @public
199
- * @param {TargetDocumentParams} params See {@link TargetDocumentParams} for details.
200
- * @param {DidDocument} params.initialDocument The initial DID Document to resolve
201
- * @param {ResolutionOptions} params.options See {@link DidResolutionOptions} for details.
202
- * @returns {DidDocument} The resolved DID Document object with a validated single, canonical history
203
- */
204
- static async targetDocument({ initialDocument, resolutionsOptions }) {
205
- // Set the network from the options or default to mainnet
206
- const network = resolutionsOptions.network;
207
- // 1. If resolutionOptions.versionId is not null, set targetVersionId to resolutionOptions.versionId.
208
- const targetVersionId = resolutionsOptions.versionId;
209
- // 2. Else if resolutionOptions.versionTime is not null, set targetTime to resolutionOptions.versionTime.
210
- // 3. Else set targetTime to the UNIX timestamp for now at the moment of execution.
211
- const targetTime = resolutionsOptions.versionTime ?? new Date().toUnix();
212
- // 4. Set signalsMetadata to resolutionOptions.sidecarData.signalsMetadata.
213
- const signalsMetadata = resolutionsOptions.sidecarData?.signalsMetadata ?? {};
214
- // 5. Set currentVersionId to 1
215
- const currentVersionId = 1;
216
- // 6. If currentVersionId equals targetVersionId return initialDocument.
217
- if (currentVersionId === targetVersionId) {
218
- return new DidDocument(initialDocument);
219
- }
220
- // 10. Set targetDocument to the result of calling the Traverse Bitcoin Blockchain History algorithm
221
- // passing in contemporaryDIDDocument, contemporaryBlockheight, currentVersionId, targetVersionId,
222
- // targetTime, didDocumentHistory, updateHashHistory, signalsMetadata, and network.
223
- const targetDocument = this.traverseBlockchainHistory({
224
- contemporaryDidDocument: initialDocument,
225
- contemporaryBlockHeight: 0,
226
- currentVersionId,
227
- targetVersionId,
228
- targetTime,
229
- didDocumentHistory: new Array(),
230
- updateHashHistory: new Array(),
231
- signalsMetadata,
232
- network
233
- });
234
- // 11. Return targetDocument.
235
- return targetDocument;
236
- }
237
- /**
238
- * Implements {@link https://dcdpr.github.io/did-btcr2/#traverse-blockchain-history | 4.2.3.2 Traverse Blockchain History}.
239
- *
240
- * The Traverse Blockchain History algorithm traverses Bitcoin blocks, starting from the block with the
241
- * contemporaryBlockheight, to find beaconSignals emitted by Beacons within the contemporaryDidDocument. Each
242
- * beaconSignal is processed to retrieve a didUpdatePayload to the DID document. Each update is applied to the
243
- * document and duplicates are ignored. If the algorithm reaches the block with the blockheight specified by a
244
- * targetBlockheight, the contemporaryDidDocument at that blockheight is returned assuming a single canonical history
245
- * of the DID document has been constructed up to that point. It takes in contemporaryDidDocument,
246
- * contemporaryBlockHeight, currentVersionId, targetVersionId, targetBlockheight, updateHashHistory, signalsMetadata
247
- * and network. It returns the contemporaryDidDocument once either the targetBlockheight or targetVersionId have been
248
- * reached.
249
- *
250
- * @protected
251
- * @param {ReadBlockchainParams} params The parameters for the traverseBlockchainHistory operation.
252
- * @param {DidDocument} params.contemporaryDidDocument The DID document for the did:btcr2 identifier being resolved.
253
- * It should be "current" (contemporary) at the blockheight of the contemporaryBlockheight.
254
- * It should be a DID Core conformant DID document.
255
- * @param {number} params.contemporaryBlockHeight The Bitcoin blockheight signaling the "contemporary time" of the
256
- * contemporary DID Document that is being resolved and updated using the Traverse Blockchain History algorithm.
257
- * @param {number} params.currentVersionId The version of the contemporary DID document starting from 1 and
258
- * incrementing by 1 with each BTCR2 Update applied to the DID document.
259
- * @param {number} params.targetVersionId The version of the DID document where resolution will complete.
260
- * @param {UnixTimestamp} params.targetTime The timestamp used to target specific historical states of a DID document.
261
- * Only Beacon Signals included in the Bitcoin blockchain before the targetTime are processed.
262
- * @param {boolean} params.didDocumentHistory An array of DID documents ordered ascensing by version (1...N).
263
- * @param {boolean} params.updateHashHistory An array of SHA256 hashes of BTCR2 Updates ordered by version that are
264
- * applied to the DID document in order to construct the contemporaryDIDDocument.
265
- * @param {SignalsMetadata} params.signalsMetadata See {@link SignalsMetadata} for details.
266
- * @param {string} params.network The bitcoin network to connect to (mainnet, signet, testnet, regtest).
267
- * @returns {Promise<DidDocument>} The resolved DID Document object with a validated single, canonical history.
268
- */
269
- static async traverseBlockchainHistory({ contemporaryDidDocument, contemporaryBlockHeight, currentVersionId, targetVersionId, targetTime, didDocumentHistory, updateHashHistory, signalsMetadata, network }) {
270
- // 1. Set contemporaryHash to the SHA256 hash of the contemporaryDidDocument
271
- let contemporaryHash = await JSON.canonicalization.process(contemporaryDidDocument, 'base58');
272
- // 2. Find all BTCR2 Beacons in contemporaryDIDDocument.service where service.type equals one of
273
- // SingletonBeacon, CIDAggregateBeacon and SMTAggregateBeacon.
274
- // 3. For each beacon in beacons convert the beacon.serviceEndpoint to a Bitcoin address
275
- // following BIP21. Set beacon.address to the Bitcoin address.
276
- const beacons = BeaconUtils.toBeaconServiceAddress(BeaconUtils.getBeaconServices(contemporaryDidDocument));
277
- // 4. Set nextSignals to the result of calling algorithm Find Next Signals passing in contemporaryBlockheight,
278
- // beacons and network.
279
- const nextSignals = await this.findNextSignals({ contemporaryBlockHeight, beacons, network, targetTime });
280
- if (!nextSignals || nextSignals.length === 0) {
281
- // 5. If nextSignals is null or empty, return contemporaryDidDocument.
282
- return new DidDocument(contemporaryDidDocument);
283
- }
284
- // 6. If nextSignals[0].blocktime is greater than targetTime, return contemporaryDIDDocument.
285
- if (nextSignals[0].blocktime > targetTime) {
286
- return new DidDocument(contemporaryDidDocument);
287
- }
288
- // 8. Set updates to the result of calling algorithm Process Beacon Signals passing in signals and sidecarData.
289
- // 9. Set orderedUpdates to the list of updates ordered by the targetVersionId property.
290
- const orderedUpdates = (await Promise.all(nextSignals.map(async (signal) => await this.processBeaconSignal(signal, signalsMetadata)))).sort((a, b) => a.targetVersionId - b.targetVersionId);
291
- // 10. For update in orderedUpdates:
292
- for (let update of orderedUpdates) {
293
- const updateTargetVersionId = update.targetVersionId;
294
- // 10.1. If update.targetVersionId is less than or equal to currentVersionId, run Algorithm Confirm Duplicate
295
- // Update passing in update, documentHistory, and contemporaryHash.
296
- if (updateTargetVersionId <= currentVersionId) {
297
- updateHashHistory.push(contemporaryHash);
298
- await this.confirmDuplicateUpdate({ update, updateHashHistory: updateHashHistory });
299
- // 10.2. If update.targetVersionId equals currentVersionId + 1:
300
- }
301
- else if (updateTargetVersionId === currentVersionId + 1) {
302
- // Prepend `z` to the sourceHash if it does not start with it
303
- const sourceHash = update.sourceHash.startsWith('z') ? update.sourceHash : `z${update.sourceHash}`;
304
- // 10.2.1. Check that update.sourceHash equals contemporaryHash, else MUST raise latePublishing error.
305
- if (sourceHash !== contemporaryHash) {
306
- throw new ResolveError(`Hash mismatch: sourceHash ${sourceHash} !== contemporaryHash ${contemporaryHash}`, LATE_PUBLISHING_ERROR, { sourceHash: sourceHash, contemporaryHash });
307
- }
308
- // 10.2.2. Set contemporaryDidDocument to the result of calling Apply DID Update algorithm passing in
309
- // contemporaryDidDocument, update.
310
- contemporaryDidDocument = await this.applyDidUpdate({ contemporaryDidDocument, update });
311
- // 10.2.4 Push contemporaryDIDDocument onto didDocumentHistory.
312
- didDocumentHistory.push(contemporaryDidDocument);
313
- // 10.2.4. Increment currentVersionId.
314
- currentVersionId++;
315
- // 10.2.5. Set unsecuredUpdate to a copy of the update object.
316
- const unsecuredUpdate = update;
317
- // 10.2.6 Remove the proof property from the unsecuredUpdate object.
318
- delete unsecuredUpdate.proof;
319
- // 10.2.7 Set updateHash to the result of passing unsecuredUpdate into the JSON Canonicalization and Hash algorithm.
320
- const updateHash = await JSON.canonicalization.process(update, 'base58');
321
- // 10.2.8. Push updateHash onto updateHashHistory.
322
- updateHashHistory.push(updateHash);
323
- // 10.2.9. Set contemporaryHash to result of passing contemporaryDIDDocument into the JSON Canonicalization and Hash algorithm.
324
- contemporaryHash = await JSON.canonicalization.process(contemporaryDidDocument, 'base58');
325
- // 10.3. If update.targetVersionId is greater than currentVersionId + 1, MUST throw a LatePublishing error.
326
- }
327
- else if (update.targetVersionId > currentVersionId + 1) {
328
- throw new ResolveError(`Version Id Mismatch: target ${update.targetVersionId} cannot be > current+1 ${currentVersionId + 1}`, 'LATE_PUBLISHING_ERROR');
329
- }
330
- }
331
- // 13. If targetVersionId in not null, set targetDocument to the index at the targetVersionId of the didDocumentHistory array.
332
- if (targetVersionId) {
333
- return new DidDocument(didDocumentHistory[targetVersionId]);
334
- }
335
- // 14. Return contemporaryDidDocument.
336
- return new DidDocument(contemporaryDidDocument);
337
- }
338
- /**
339
- * Implements {@link https://dcdpr.github.io/did-btcr2/#find-next-signals | 4.2.3.3 Find Next Signals}.
340
- *
341
- * The Find Next Signals algorithm finds the next Bitcoin block containing Beacon Signals from one or more of the
342
- * beacons and retuns all Beacon Signals within that block.
343
- *
344
- * It takes the following inputs:
345
- * - `contemporaryBlockhieght`: The height of the block this function is looking for Beacon Signals in.
346
- * An integer greater or equal to 0.
347
- * - `targetBlockheight`: The height of the Bitcoin block that the resolution algorithm searches for Beacon Signals
348
- * up to. An integer greater or equal to 0.
349
- * - `beacons`: An array of Beacon services in the contemporary DID document. Each Beacon contains properties:
350
- * - `id`: The id of the Beacon service in the DID document. A string.
351
- * - `type`: The type of the Beacon service in the DID document. A string whose values MUST be
352
- * either SingletonBeacon, CIDAggregateBeacon or SMTAggregateBeacon.
353
- * - `serviceEndpoint`: A BIP21 URI representing a Bitcoin address.
354
- * - `address`: The Bitcoin address decoded from the `serviceEndpoint value.
355
- * - `network`: A string identifying the Bitcoin network of the did:btcr2 identifier. This algorithm MUST query the
356
- * Bitcoin blockchain identified by the network.
357
- *
358
- * It returns a nextSignals struct, containing the following properties:
359
- * - blockheight: The Bitcoin blockheight for the block containing the Beacon Signals.
360
- * - signals: An array of signals. Each signal is a struct containing the following:
361
- * - beaconId: The id for the Beacon that the signal was announced by.
362
- * - beaconType: The type of the Beacon that announced the signal.
363
- * - tx: The Bitcoin transaction that is the Beacon Signal.
364
- *
365
- * @public
366
- * @param {FindNextSignals} params The parameters for the findNextSignals operation.
367
- * @param {number} params.contemporaryBlockHeight The blockheight to start looking for beacon signals.
368
- * @param {Array<BeaconService>} params.beacons The beacons to look for in the block.
369
- * @param {Array<BeaconService>} params.network The bitcoin network to connect to (mainnet, signet, testnet, regtest).
370
- * @param {UnixTimestamp} params.targetTime The timestamp used to target specific historical states of a DID document.
371
- * Only Beacon Signals included in the Bitcoin blockchain before the targetTime are processed.
372
- * @returns {Promise<Array<BeaconSignal>>} An array of BeaconSignal objects with blockHeight and signals.
373
- */
374
- static async findNextSignals({ contemporaryBlockHeight, targetTime, network, beacons }) {
375
- let height = contemporaryBlockHeight;
376
- // Create an default beaconSignal and beaconSignals array
377
- let beaconSignals = [];
378
- // Get the bitcoin network connection
379
- bitcoin.setActiveNetwork(network);
380
- // Opt into REST connection if available
381
- if (bitcoin.network.rest) {
382
- return await this.findSignalsRest(beacons);
383
- }
384
- // If no rest and no rpc connection is available, throw an error
385
- if (!bitcoin.network.rpc) {
386
- throw new ResolveError(`No Bitcoin connection available, cannot find next signals`, 'NO_BITCOIN_CONNECTION');
387
- }
388
- // Opt into rpc connection to get the block data at the blockhash
389
- let block = await bitcoin.network.rpc.getBlock({ height });
390
- Logger.info(`Searching for signals, please wait ...`);
391
- while (block.time <= targetTime) {
392
- // Iterate over each transaction in the block
393
- for (const tx of block.tx) {
394
- // If the txid is a coinbase, continue ...
395
- if (tx.txid === GENESIS_TX_ID) {
396
- continue;
397
- }
398
- // Iterate over each input in the transaction
399
- for (const vin of tx.vin) {
400
- // If the vin is a coinbase transaction, continue ...
401
- if (vin.coinbase) {
402
- continue;
403
- }
404
- // If the vin txinwitness contains a coinbase identifier, continue ...
405
- if (vin.txinwitness && vin.txinwitness.length === 1 && vin.txinwitness[0] === TXIN_WITNESS_COINBASE) {
406
- continue;
407
- }
408
- // If the txid from the vin is undefined, continue ...
409
- if (!vin.txid) {
410
- continue;
411
- }
412
- // If the vout from the vin is undefined, continue ...
413
- if (vin.vout === undefined) {
414
- continue;
415
- }
416
- // Get the previous output transaction data
417
- const prevout = await bitcoin.network.rpc.getRawTransaction(vin.txid, 2);
418
- // If the previous output vout at the vin.vout index is undefined, continue ...
419
- if (!prevout.vout[vin.vout]) {
420
- continue;
421
- }
422
- // Get the address from the scriptPubKey from the prevvout (previous output's input at the vout index)
423
- const scriptPubKey = prevout.vout[vin.vout].scriptPubKey;
424
- // If the scriptPubKey.address is undefined, continue ...
425
- if (!scriptPubKey.address) {
426
- continue;
427
- }
428
- // If the beaconAddress from prevvout scriptPubKey is not a beacon service endpoint address, continue ...
429
- const beaconAddresses = BeaconUtils.getBeaconServiceAddressMap(beacons);
430
- const beacon = (beaconAddresses.get(scriptPubKey.address) ?? {});
431
- if (!beacon || !(beacon.id && beacon.type)) {
432
- continue;
433
- }
434
- // If the prevout.vout[vin.vout].scriptPubKey.asm does not include 'OP_RETURN', continue ...
435
- if (!prevout.vout[vin.vout].scriptPubKey.asm.includes('OP_RETURN')) {
436
- continue;
437
- }
438
- // Log the found txid and beacon
439
- Logger.info(`Tx ${tx.txid} contains beacon address ${scriptPubKey.address} and OP_RETURN!`, tx);
440
- // Push the signal object to to signals array
441
- beaconSignals.push({
442
- beaconId: beacon.id,
443
- beaconType: beacon.type,
444
- beaconAddress: beacon.address,
445
- tx,
446
- blockheight: block.height,
447
- blocktime: block.time
448
- });
449
- }
450
- ;
451
- }
452
- height += 1;
453
- const tip = await bitcoin.network.rpc.getBlockCount();
454
- if (height > tip) {
455
- Logger.info(`Chain tip reached ${height}, breaking ...`);
456
- break;
457
- }
458
- // Reset the block to the next block
459
- block = await bitcoin.network.rpc.getBlock({ height });
460
- }
461
- return beaconSignals;
462
- }
463
- /**
464
- * Helper method for the {@link findNextSignals | Find Next Signals} algorithm.
465
- * @param {Array<BeaconService>} beacons The beacons to process.
466
- * @returns {Promise<Array<BeaconSignal>>} The beacon signals found in the block.
467
- */
468
- static async findSignalsRest(beacons) {
469
- // Empty array of beaconSignals
470
- const beaconSignals = new Array();
471
- // Iterate over each beacon
472
- for (const beacon of BeaconUtils.toBeaconServiceAddress(beacons)) {
473
- // Get the transactions for the beacon address via REST
474
- const transactions = await bitcoin.network.rest.address.getTxs(beacon.address);
475
- // If no transactions are found, continue
476
- if (!transactions || transactions.length === 0) {
477
- continue;
478
- }
479
- // Iterate over each transaction and push a beaconSignal
480
- for (const tx of transactions) {
481
- for (const vout of tx.vout) {
482
- if (vout.scriptpubkey_asm.includes('OP_RETURN')) {
483
- beaconSignals.push({
484
- beaconId: beacon.id,
485
- beaconType: beacon.type,
486
- beaconAddress: beacon.address,
487
- tx,
488
- blockheight: tx.status.block_height,
489
- blocktime: tx.status.block_time,
490
- });
491
- }
492
- }
493
- }
494
- }
495
- // Return the beaconSignals
496
- return beaconSignals;
497
- }
498
- /**
499
- * Implements {@link https://dcdpr.github.io/did-btcr2/#process-beacon-signals | 4.2.3.4 Process Beacon Signals}.
500
- *
501
- * The Process Beacon Signals algorithm processes each Beacon Signal by attempting to retrieve and validate an
502
- * announce DID Update Payload for that signal according to the type of the Beacon.
503
- *
504
- * It takes as inputs
505
- * - `beaconSignals`: An array of Beacon Signals retrieved from the Find Next Signals algorithm. Each signal contains:
506
- * - `beaconId`: The id for the Beacon that the signal was announced by.
507
- * - `beaconType`: The type of the Beacon that announced the signal.
508
- * - `tx`: The Bitcoin transaction that is the Beacon Signal.
509
- * - `signalsMetadata`: Maps Beacon Signal Bitcoin transaction ids to a SignalMetadata object containing:
510
- * - `updatePayload`: A DID Update Payload which should match the update announced by the Beacon Signal.
511
- * In the case of a SMT proof of non-inclusion, no DID Update Payload may be provided.
512
- * - `proofs`: Sparse Merkle Tree proof used to verify that the `updatePayload` exists as the leaf indexed by the
513
- * did:btcr2 identifier being resolved.
514
- *
515
- * It returns an array of {@link https://dcdpr.github.io/did-btcr2/#def-did-update-payload | DID Update Payloads}.
516
- *
517
- * @public
518
- * @param {BeaconSignal} signal The beacon signals to process.
519
- * @param {SignalsMetadata} signalsMetadata The sidecar data for the DID Document.
520
- * @returns {DidUpdatePayload[]} The updated DID Document object.
521
- */
522
- static async processBeaconSignal(signal, signalsMetadata) {
523
- // 1. Set updates to an empty array.
524
- const updates = new Array();
525
- // 2. For beaconSignal in beaconSignals:
526
- // 2.1 Set type to beaconSignal.beaconType.
527
- // 2.2 Set signalTx to beaconSignal.tx.
528
- // 2.3 Set signalId to signalTx.id.
529
- const { beaconId: id, beaconType: type, beaconAddress: address, tx } = signal;
530
- const signalTx = tx;
531
- // 2.4 Set signalSidecarData to signalsMetadata[signalId]. TODO: formalize structure of sidecarData
532
- // const signalSidecarData = new Map(Object.entries(signalsMetadata)).get(id)!;
533
- // TODO: processBeaconSignal - formalize structure of sidecarData, signalSidecarData
534
- // 2.6 If type == SingletonBeacon:
535
- // 2.6.1 Set didUpdatePayload to the result of passing signalTx and signalSidecarData to Process Singleton Beacon Signal algorithm.
536
- // 2.7 If type == CIDAggregateBeacon:
537
- // 2.7.1 Set didUpdatePayload to the result of passing signalTx and signalSidecarData to the Process CIDAggregate Beacon Signal algorithm.
538
- // 2.8 If type == SMTAggregateBeacon:
539
- // 2.8.1 Set didUpdatePayload to the result of passing signalTx and signalSidecarData to the Process SMTAggregate Beacon Signal algorithm.
540
- // TODO: processBeaconSignal - where/how to convert signalsMetadata to diff sidecars
541
- const sidecar = { signalsMetadata };
542
- // switch (type) {
543
- // case 'SingletonBeacon': {
544
- // sidecar = { signalsMetadata } as SingletonSidecar;
545
- // break;
546
- // }
547
- // case 'CIDAggregateBeacon': {
548
- // sidecar = {} as CIDAggregateSidecar;
549
- // break;
550
- // }
551
- // case 'SMTAggregateBeacon': {
552
- // sidecar = {} as SMTAggregateSidecar;
553
- // break;
554
- // }
555
- // default: {
556
- // throw new MethodError('Invalid beacon type', 'INVALID_BEACON_TYPE', { type });
557
- // }
558
- // }
559
- // Construct a service object from the beaconId and type
560
- // and set the serviceEndpoint to the BIP21 URI for the Bitcoin address.
561
- const service = { id, type, serviceEndpoint: `bitcoin:${address}` };
562
- // Establish a Beacon instance using the service and sidecar
563
- const beacon = BeaconFactory.establish(service, sidecar);
564
- // 2.5 Set didUpdate to null.
565
- const didUpdate = await beacon.processSignal(signalTx, signalsMetadata) ?? null;
566
- // If the updates is null, throw an error
567
- if (!didUpdate) {
568
- throw new MethodError('No didUpdate for beacon', 'PROCESS_BEACON_SIGNALS_ERROR', { tx, signalsMetadata });
569
- }
570
- // 2.9 If didUpdate is not null, push didUpdate to updates.
571
- updates.push(didUpdate);
572
- // 3. Return updates.
573
- return didUpdate;
574
- }
575
- /**
576
- * Implements {@link https://dcdpr.github.io/did-btcr2/#confirm-duplicate-update | 7.2.2.4 Confirm Duplicate Update}.
577
- *
578
- * The Confirm Duplicate Update algorithm takes in a {@link DidUpdatePayload | DID Update Payload} and verifies that
579
- * the update is a duplicate against the hash history of previously applied updates. The algorithm takes in an update
580
- * and an array of hashes, updateHashHistory. It throws an error if the update is not a duplicate, otherwise it
581
- * returns.
582
- *
583
- * @public
584
- * @param {{ update: DidUpdatePayload; updateHashHistory: string[]; }} params Parameters for confirmDuplicateUpdate.
585
- * @param {DidUpdatePayload} params.update The DID Update Payload to confirm.
586
- * @param {Array<string>} params.updateHashHistory The history of hashes for previously applied updates.
587
- * @returns {Promise<void>} A promise that resolves if the update is a duplicate, otherwise throws an error.
588
- * @throws {ResolveError} if the update hash does not match the historical hash.
589
- */
590
- static async confirmDuplicateUpdate({ update, updateHashHistory }) {
591
- // 1. Let unsecuredUpdate be a copy of the update object.
592
- const unsecuredUpdate = update;
593
- // 2. Remove the proof property from the unsecuredUpdate object.
594
- delete unsecuredUpdate.proof;
595
- // 3. Let updateHash equal the result of passing unsecuredUpdate into the JSON Canonicalization and Hash algorithm.
596
- const updateHash = await JSON.canonicalization.process(unsecuredUpdate);
597
- // 4. Let updateHashIndex equal update.targetVersionId - 2.
598
- // const updateHashIndex = update.targetVersionId - 2;
599
- // 5. Let historicalUpdateHash equal updateHashHistory[updateHashIndex].
600
- const historicalUpdateHash = updateHashHistory[update.targetVersionId - 2];
601
- // Check if the updateHash matches the historical hash
602
- if (historicalUpdateHash !== updateHash) {
603
- throw new ResolveError(`Invalid duplicate: ${updateHash} does not match ${historicalUpdateHash}`, 'LATE_PUBLISHING_ERROR', { updateHash, updateHashHistory });
604
- }
605
- }
606
- /**
607
- * Implements {@link https://dcdpr.github.io/did-btcr2/#apply-did-update | 4.2.3.6 Apply DID Update}.
608
- *
609
- * This algorithm attempts to apply a DID Update to a DID document, it first verifies the proof on the update is a
610
- * valid capabilityInvocation of the root authority over the DID being resolved. Then it applies the JSON patch
611
- * transformation to the DID document, checks the transformed DID document matches the targetHash specified by the
612
- * update and validates it is a conformant DID document before returning it. This algorithm takes inputs
613
- * contemporaryDidDocument and an update.
614
- *
615
- * @public
616
- * @param {ApplyDidUpdateParams} params Parameters for applyDidUpdate.
617
- * @param {DidDocument} params.contemporaryDidDocument The current DID Document to update.
618
- * @param {DidUpdatePayload} params.update The DID Update Payload to apply.
619
- * @param {Bytes} params.genesisBytes The genesis bytes for the DID Document.
620
- * @returns {Promise<DidDocument>}
621
- */
622
- static async applyDidUpdate({ contemporaryDidDocument, update }) {
623
- // 1. Set capabilityId to update.proof.capability.
624
- const capabilityId = update.proof?.capability;
625
- if (!capabilityId) {
626
- throw new ResolveError('No capabilityId found in update', INVALID_DID_UPDATE);
627
- }
628
- // 2. Set rootCapability to the result of passing capabilityId to the Dereference Root Capability Identifier algorithm.
629
- const rootCapability = Appendix.derefernceRootCapabilityIdentifier(capabilityId);
630
- // 3. If rootCapability.invocationTarget does not equal contemporaryDidDocument.id
631
- // and rootCapability.controller does not equal contemporaryDidDocument.id, MUST throw an invalidDidUpdate error.
632
- const { invocationTarget, controller: rootController } = rootCapability;
633
- if (![invocationTarget, rootController].every((id) => id === contemporaryDidDocument.id)) {
634
- throw new ResolveError(`Invalid root capability: ${rootCapability}`, INVALID_DID_UPDATE);
635
- }
636
- // 4. Instantiate a bip340-jcs-2025 cryptosuite instance using the key referenced by the verificationMethod field in the update.
637
- // Get the verificationMethod field from the update.
638
- const methodId = update.proof?.verificationMethod;
639
- if (!methodId) {
640
- throw new ResolveError('No verificationMethod found in update', INVALID_DID_UPDATE, update);
641
- }
642
- // Get the verificationMethod from the DID Document using the methodId.
643
- const { id: vmId, publicKeyMultibase } = DidBtcr2.getSigningMethod({ didDocument: contemporaryDidDocument, methodId });
644
- // Split the vmId by the `#` to get the id and controller.
645
- const [controller, id] = vmId.split('#');
646
- // Construct a new Multikey.
647
- const multikey = SchnorrMultikey.fromPublicKeyMultibase({ id: `#${id}`, controller, publicKeyMultibase });
648
- const cryptosuite = new Cryptosuite({ cryptosuite: 'bip340-jcs-2025', multikey });
649
- // 7. Set documentBytes to the bytes representation of update.
650
- const documentBytes = await JSON.canonicalization.canonicalize(update);
651
- // 8. Set verificationResult to the result of passing mediaType, documentBytes, cryptosuite, and
652
- // expectedProofPurpose into the Verify Proof algorithm defined in the VC Data Integrity specification.
653
- const diProof = new DataIntegrityProof(cryptosuite);
654
- const verificationResult = await diProof.verifyProof({ document: documentBytes, expectedPurpose: 'capabilityInvocation' });
655
- // 9. If verificationResult.verified equals False, MUST raise a invalidUpdateProof exception.
656
- if (!verificationResult.verified) {
657
- throw new MethodError('Invalid update: proof not verified', INVALID_DID_UPDATE, verificationResult);
658
- }
659
- // 10. Set targetDIDDocument to a copy of contemporaryDidDocument.
660
- let targetDIDDocument = contemporaryDidDocument;
661
- // 11. Use JSON Patch to apply the update.patch to the targetDIDDOcument.
662
- targetDIDDocument = JSON.patch.apply(targetDIDDocument, update.patch);
663
- // 12. Verify that targetDIDDocument is conformant with the data model specified by the DID Core specification.
664
- DidDocument.validate(targetDIDDocument);
665
- // 13. Set targetHash to the SHA256 hash of targetDIDDocument.
666
- const targetHash = await JSON.canonicalization.process(targetDIDDocument, 'base58');
667
- // Prepend the sourceHash if it does not start with `z`
668
- const updateTargetHash = update.targetHash.startsWith('z')
669
- ? update.targetHash
670
- : `z${update.targetHash}`;
671
- // 14. Check that targetHash equals update.targetHash, else raise InvalidDIDUpdate error.
672
- if (updateTargetHash !== targetHash) {
673
- throw new MethodError(`Invalid update: updateTargetHash ${updateTargetHash} does not match targetHash ${targetHash}`, INVALID_DID_UPDATE);
674
- }
675
- // 15. Return targetDIDDocument.
676
- return targetDIDDocument;
677
- }
678
- }
679
- //# sourceMappingURL=read.js.map