@did-btcr2/method 0.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +373 -0
- package/README.md +7 -0
- package/dist/browser.js +2364 -0
- package/dist/browser.js.map +7 -0
- package/dist/browser.mjs +2364 -0
- package/dist/browser.mjs.map +7 -0
- package/dist/cjs/bitcoin/constants.js +20 -0
- package/dist/cjs/bitcoin/constants.js.map +1 -0
- package/dist/cjs/bitcoin/errors.js +11 -0
- package/dist/cjs/bitcoin/errors.js.map +1 -0
- package/dist/cjs/bitcoin/index.js +95 -0
- package/dist/cjs/bitcoin/index.js.map +1 -0
- package/dist/cjs/bitcoin/interface.js +2 -0
- package/dist/cjs/bitcoin/interface.js.map +1 -0
- package/dist/cjs/bitcoin/network.js +17 -0
- package/dist/cjs/bitcoin/network.js.map +1 -0
- package/dist/cjs/bitcoin/rest-client.js +289 -0
- package/dist/cjs/bitcoin/rest-client.js.map +1 -0
- package/dist/cjs/bitcoin/rpc-client.js +722 -0
- package/dist/cjs/bitcoin/rpc-client.js.map +1 -0
- package/dist/cjs/bitcoin/taproot.js +219 -0
- package/dist/cjs/bitcoin/taproot.js.map +1 -0
- package/dist/cjs/btcr2/beacon/aggregation/coordinator.js +120 -0
- package/dist/cjs/btcr2/beacon/aggregation/coordinator.js.map +1 -0
- package/dist/cjs/btcr2/beacon/aggregation/messages/advert.js +24 -0
- package/dist/cjs/btcr2/beacon/aggregation/messages/advert.js.map +1 -0
- package/dist/cjs/btcr2/beacon/aggregation/messages/base.js +37 -0
- package/dist/cjs/btcr2/beacon/aggregation/messages/base.js.map +1 -0
- package/dist/cjs/btcr2/beacon/aggregation/messages/cohort-set.js +25 -0
- package/dist/cjs/btcr2/beacon/aggregation/messages/cohort-set.js.map +1 -0
- package/dist/cjs/btcr2/beacon/aggregation/messages/keygen.js +8 -0
- package/dist/cjs/btcr2/beacon/aggregation/messages/keygen.js.map +1 -0
- package/dist/cjs/btcr2/beacon/aggregation/messages/opt-in.js +23 -0
- package/dist/cjs/btcr2/beacon/aggregation/messages/opt-in.js.map +1 -0
- package/dist/cjs/btcr2/beacon/aggregation/messages/sign.js +7 -0
- package/dist/cjs/btcr2/beacon/aggregation/messages/sign.js.map +1 -0
- package/dist/cjs/btcr2/beacon/aggregation/models/cohort/index.js +92 -0
- package/dist/cjs/btcr2/beacon/aggregation/models/cohort/index.js.map +1 -0
- package/dist/cjs/btcr2/beacon/aggregation/models/cohort/status.js +8 -0
- package/dist/cjs/btcr2/beacon/aggregation/models/cohort/status.js.map +1 -0
- package/dist/cjs/btcr2/beacon/aggregation/participant.js +2 -0
- package/dist/cjs/btcr2/beacon/aggregation/participant.js.map +1 -0
- package/dist/cjs/btcr2/beacon/aggregation/protocol/nostr.js +57 -0
- package/dist/cjs/btcr2/beacon/aggregation/protocol/nostr.js.map +1 -0
- package/dist/cjs/btcr2/beacon/aggregation/protocol/service.js +2 -0
- package/dist/cjs/btcr2/beacon/aggregation/protocol/service.js.map +1 -0
- package/dist/cjs/btcr2/beacon/cid-aggregate.js +116 -0
- package/dist/cjs/btcr2/beacon/cid-aggregate.js.map +1 -0
- package/dist/cjs/btcr2/beacon/factory.js +30 -0
- package/dist/cjs/btcr2/beacon/factory.js.map +1 -0
- package/dist/cjs/btcr2/beacon/singleton.js +220 -0
- package/dist/cjs/btcr2/beacon/singleton.js.map +1 -0
- package/dist/cjs/btcr2/beacon/smt-aggregate.js +126 -0
- package/dist/cjs/btcr2/beacon/smt-aggregate.js.map +1 -0
- package/dist/cjs/btcr2/crud/create.js +102 -0
- package/dist/cjs/btcr2/crud/create.js.map +1 -0
- package/dist/cjs/btcr2/crud/deactivate.js +14 -0
- package/dist/cjs/btcr2/crud/deactivate.js.map +1 -0
- package/dist/cjs/btcr2/crud/read.js +686 -0
- package/dist/cjs/btcr2/crud/read.js.map +1 -0
- package/dist/cjs/btcr2/crud/update.js +195 -0
- package/dist/cjs/btcr2/crud/update.js.map +1 -0
- package/dist/cjs/btcr2/key-manager/index.js +290 -0
- package/dist/cjs/btcr2/key-manager/index.js.map +1 -0
- package/dist/cjs/btcr2/key-manager/interface.js +2 -0
- package/dist/cjs/btcr2/key-manager/interface.js.map +1 -0
- package/dist/cjs/did-btcr2.js +222 -0
- package/dist/cjs/did-btcr2.js.map +1 -0
- package/dist/cjs/index.js +27 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/interfaces/beacon.js +41 -0
- package/dist/cjs/interfaces/beacon.js.map +1 -0
- package/dist/cjs/interfaces/crud.js +2 -0
- package/dist/cjs/interfaces/crud.js.map +1 -0
- package/dist/cjs/interfaces/ibeacon.js +2 -0
- package/dist/cjs/interfaces/ibeacon.js.map +1 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/types/bitcoin.js +62 -0
- package/dist/cjs/types/bitcoin.js.map +1 -0
- package/dist/cjs/types/crud.js +2 -0
- package/dist/cjs/types/crud.js.map +1 -0
- package/dist/cjs/utils/appendix.js +221 -0
- package/dist/cjs/utils/appendix.js.map +1 -0
- package/dist/cjs/utils/beacons.js +206 -0
- package/dist/cjs/utils/beacons.js.map +1 -0
- package/dist/cjs/utils/did-document-builder.js +61 -0
- package/dist/cjs/utils/did-document-builder.js.map +1 -0
- package/dist/cjs/utils/did-document.js +380 -0
- package/dist/cjs/utils/did-document.js.map +1 -0
- package/dist/cjs/utils/general.js +195 -0
- package/dist/cjs/utils/general.js.map +1 -0
- package/dist/cjs/utils/identifier.js +238 -0
- package/dist/cjs/utils/identifier.js.map +1 -0
- package/dist/esm/bitcoin/constants.js +20 -0
- package/dist/esm/bitcoin/constants.js.map +1 -0
- package/dist/esm/bitcoin/errors.js +11 -0
- package/dist/esm/bitcoin/errors.js.map +1 -0
- package/dist/esm/bitcoin/index.js +95 -0
- package/dist/esm/bitcoin/index.js.map +1 -0
- package/dist/esm/bitcoin/interface.js +2 -0
- package/dist/esm/bitcoin/interface.js.map +1 -0
- package/dist/esm/bitcoin/network.js +17 -0
- package/dist/esm/bitcoin/network.js.map +1 -0
- package/dist/esm/bitcoin/rest-client.js +289 -0
- package/dist/esm/bitcoin/rest-client.js.map +1 -0
- package/dist/esm/bitcoin/rpc-client.js +722 -0
- package/dist/esm/bitcoin/rpc-client.js.map +1 -0
- package/dist/esm/bitcoin/taproot.js +219 -0
- package/dist/esm/bitcoin/taproot.js.map +1 -0
- package/dist/esm/btcr2/beacon/aggregation/coordinator.js +120 -0
- package/dist/esm/btcr2/beacon/aggregation/coordinator.js.map +1 -0
- package/dist/esm/btcr2/beacon/aggregation/messages/advert.js +24 -0
- package/dist/esm/btcr2/beacon/aggregation/messages/advert.js.map +1 -0
- package/dist/esm/btcr2/beacon/aggregation/messages/base.js +37 -0
- package/dist/esm/btcr2/beacon/aggregation/messages/base.js.map +1 -0
- package/dist/esm/btcr2/beacon/aggregation/messages/cohort-set.js +25 -0
- package/dist/esm/btcr2/beacon/aggregation/messages/cohort-set.js.map +1 -0
- package/dist/esm/btcr2/beacon/aggregation/messages/keygen.js +8 -0
- package/dist/esm/btcr2/beacon/aggregation/messages/keygen.js.map +1 -0
- package/dist/esm/btcr2/beacon/aggregation/messages/opt-in.js +23 -0
- package/dist/esm/btcr2/beacon/aggregation/messages/opt-in.js.map +1 -0
- package/dist/esm/btcr2/beacon/aggregation/messages/sign.js +7 -0
- package/dist/esm/btcr2/beacon/aggregation/messages/sign.js.map +1 -0
- package/dist/esm/btcr2/beacon/aggregation/models/cohort/index.js +92 -0
- package/dist/esm/btcr2/beacon/aggregation/models/cohort/index.js.map +1 -0
- package/dist/esm/btcr2/beacon/aggregation/models/cohort/status.js +8 -0
- package/dist/esm/btcr2/beacon/aggregation/models/cohort/status.js.map +1 -0
- package/dist/esm/btcr2/beacon/aggregation/participant.js +2 -0
- package/dist/esm/btcr2/beacon/aggregation/participant.js.map +1 -0
- package/dist/esm/btcr2/beacon/aggregation/protocol/nostr.js +57 -0
- package/dist/esm/btcr2/beacon/aggregation/protocol/nostr.js.map +1 -0
- package/dist/esm/btcr2/beacon/aggregation/protocol/service.js +2 -0
- package/dist/esm/btcr2/beacon/aggregation/protocol/service.js.map +1 -0
- package/dist/esm/btcr2/beacon/cid-aggregate.js +116 -0
- package/dist/esm/btcr2/beacon/cid-aggregate.js.map +1 -0
- package/dist/esm/btcr2/beacon/factory.js +30 -0
- package/dist/esm/btcr2/beacon/factory.js.map +1 -0
- package/dist/esm/btcr2/beacon/singleton.js +220 -0
- package/dist/esm/btcr2/beacon/singleton.js.map +1 -0
- package/dist/esm/btcr2/beacon/smt-aggregate.js +126 -0
- package/dist/esm/btcr2/beacon/smt-aggregate.js.map +1 -0
- package/dist/esm/btcr2/crud/create.js +102 -0
- package/dist/esm/btcr2/crud/create.js.map +1 -0
- package/dist/esm/btcr2/crud/deactivate.js +14 -0
- package/dist/esm/btcr2/crud/deactivate.js.map +1 -0
- package/dist/esm/btcr2/crud/read.js +686 -0
- package/dist/esm/btcr2/crud/read.js.map +1 -0
- package/dist/esm/btcr2/crud/update.js +195 -0
- package/dist/esm/btcr2/crud/update.js.map +1 -0
- package/dist/esm/btcr2/key-manager/index.js +290 -0
- package/dist/esm/btcr2/key-manager/index.js.map +1 -0
- package/dist/esm/btcr2/key-manager/interface.js +2 -0
- package/dist/esm/btcr2/key-manager/interface.js.map +1 -0
- package/dist/esm/did-btcr2.js +222 -0
- package/dist/esm/did-btcr2.js.map +1 -0
- package/dist/esm/index.js +27 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/interfaces/beacon.js +41 -0
- package/dist/esm/interfaces/beacon.js.map +1 -0
- package/dist/esm/interfaces/crud.js +2 -0
- package/dist/esm/interfaces/crud.js.map +1 -0
- package/dist/esm/interfaces/ibeacon.js +2 -0
- package/dist/esm/interfaces/ibeacon.js.map +1 -0
- package/dist/esm/types/bitcoin.js +62 -0
- package/dist/esm/types/bitcoin.js.map +1 -0
- package/dist/esm/types/crud.js +2 -0
- package/dist/esm/types/crud.js.map +1 -0
- package/dist/esm/utils/appendix.js +221 -0
- package/dist/esm/utils/appendix.js.map +1 -0
- package/dist/esm/utils/beacons.js +206 -0
- package/dist/esm/utils/beacons.js.map +1 -0
- package/dist/esm/utils/did-document-builder.js +61 -0
- package/dist/esm/utils/did-document-builder.js.map +1 -0
- package/dist/esm/utils/did-document.js +380 -0
- package/dist/esm/utils/did-document.js.map +1 -0
- package/dist/esm/utils/general.js +195 -0
- package/dist/esm/utils/general.js.map +1 -0
- package/dist/esm/utils/identifier.js +238 -0
- package/dist/esm/utils/identifier.js.map +1 -0
- package/dist/types/bitcoin/constants.d.ts +19 -0
- package/dist/types/bitcoin/constants.d.ts.map +1 -0
- package/dist/types/bitcoin/errors.d.ts +5 -0
- package/dist/types/bitcoin/errors.d.ts.map +1 -0
- package/dist/types/bitcoin/index.d.ts +75 -0
- package/dist/types/bitcoin/index.d.ts.map +1 -0
- package/dist/types/bitcoin/interface.d.ts +86 -0
- package/dist/types/bitcoin/interface.d.ts.map +1 -0
- package/dist/types/bitcoin/network.d.ts +2 -0
- package/dist/types/bitcoin/network.d.ts.map +1 -0
- package/dist/types/bitcoin/rest-client.d.ts +268 -0
- package/dist/types/bitcoin/rest-client.d.ts.map +1 -0
- package/dist/types/bitcoin/rpc-client.d.ts +506 -0
- package/dist/types/bitcoin/rpc-client.d.ts.map +1 -0
- package/dist/types/bitcoin/taproot.d.ts +34 -0
- package/dist/types/bitcoin/taproot.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/aggregation/coordinator.d.ts +74 -0
- package/dist/types/btcr2/beacon/aggregation/coordinator.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/aggregation/messages/advert.d.ts +22 -0
- package/dist/types/btcr2/beacon/aggregation/messages/advert.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/aggregation/messages/base.d.ts +36 -0
- package/dist/types/btcr2/beacon/aggregation/messages/base.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/aggregation/messages/cohort-set.d.ts +23 -0
- package/dist/types/btcr2/beacon/aggregation/messages/cohort-set.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/aggregation/messages/keygen.d.ts +6 -0
- package/dist/types/btcr2/beacon/aggregation/messages/keygen.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/aggregation/messages/opt-in.d.ts +22 -0
- package/dist/types/btcr2/beacon/aggregation/messages/opt-in.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/aggregation/messages/sign.d.ts +5 -0
- package/dist/types/btcr2/beacon/aggregation/messages/sign.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/aggregation/models/cohort/index.d.ts +77 -0
- package/dist/types/btcr2/beacon/aggregation/models/cohort/index.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/aggregation/models/cohort/status.d.ts +7 -0
- package/dist/types/btcr2/beacon/aggregation/models/cohort/status.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/aggregation/participant.d.ts +1 -0
- package/dist/types/btcr2/beacon/aggregation/participant.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/aggregation/protocol/nostr.d.ts +36 -0
- package/dist/types/btcr2/beacon/aggregation/protocol/nostr.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/aggregation/protocol/service.d.ts +6 -0
- package/dist/types/btcr2/beacon/aggregation/protocol/service.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/cid-aggregate.d.ts +103 -0
- package/dist/types/btcr2/beacon/cid-aggregate.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/factory.d.ts +17 -0
- package/dist/types/btcr2/beacon/factory.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/singleton.d.ts +93 -0
- package/dist/types/btcr2/beacon/singleton.d.ts.map +1 -0
- package/dist/types/btcr2/beacon/smt-aggregate.d.ts +112 -0
- package/dist/types/btcr2/beacon/smt-aggregate.d.ts.map +1 -0
- package/dist/types/btcr2/crud/create.d.ts +92 -0
- package/dist/types/btcr2/crud/create.d.ts.map +1 -0
- package/dist/types/btcr2/crud/deactivate.d.ts +13 -0
- package/dist/types/btcr2/crud/deactivate.d.ts.map +1 -0
- package/dist/types/btcr2/crud/read.d.ts +341 -0
- package/dist/types/btcr2/crud/read.d.ts.map +1 -0
- package/dist/types/btcr2/crud/update.d.ts +83 -0
- package/dist/types/btcr2/crud/update.d.ts.map +1 -0
- package/dist/types/btcr2/key-manager/index.d.ts +145 -0
- package/dist/types/btcr2/key-manager/index.d.ts.map +1 -0
- package/dist/types/btcr2/key-manager/interface.d.ts +113 -0
- package/dist/types/btcr2/key-manager/interface.d.ts.map +1 -0
- package/dist/types/did-btcr2.d.ts +117 -0
- package/dist/types/did-btcr2.d.ts.map +1 -0
- package/dist/types/index.d.ts +26 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/interfaces/beacon.d.ts +57 -0
- package/dist/types/interfaces/beacon.d.ts.map +1 -0
- package/dist/types/interfaces/crud.d.ts +35 -0
- package/dist/types/interfaces/crud.d.ts.map +1 -0
- package/dist/types/interfaces/ibeacon.d.ts +66 -0
- package/dist/types/interfaces/ibeacon.d.ts.map +1 -0
- package/dist/types/types/bitcoin.d.ts +827 -0
- package/dist/types/types/bitcoin.d.ts.map +1 -0
- package/dist/types/types/crud.d.ts +38 -0
- package/dist/types/types/crud.d.ts.map +1 -0
- package/dist/types/utils/appendix.d.ts +118 -0
- package/dist/types/utils/appendix.d.ts.map +1 -0
- package/dist/types/utils/beacons.d.ts +156 -0
- package/dist/types/utils/beacons.d.ts.map +1 -0
- package/dist/types/utils/did-document-builder.d.ts +13 -0
- package/dist/types/utils/did-document-builder.d.ts.map +1 -0
- package/dist/types/utils/did-document.d.ts +211 -0
- package/dist/types/utils/did-document.d.ts.map +1 -0
- package/dist/types/utils/general.d.ts +85 -0
- package/dist/types/utils/general.d.ts.map +1 -0
- package/dist/types/utils/identifier.d.ts +59 -0
- package/dist/types/utils/identifier.d.ts.map +1 -0
- package/package.json +137 -0
- package/src/bitcoin/constants.ts +19 -0
- package/src/bitcoin/errors.ts +10 -0
- package/src/bitcoin/index.ts +154 -0
- package/src/bitcoin/interface.ts +160 -0
- package/src/bitcoin/network.ts +17 -0
- package/src/bitcoin/rest-client.ts +415 -0
- package/src/bitcoin/rpc-client.ts +888 -0
- package/src/bitcoin/taproot.ts +237 -0
- package/src/btcr2/beacon/aggregation/coordinator.ts +135 -0
- package/src/btcr2/beacon/aggregation/messages/advert.ts +36 -0
- package/src/btcr2/beacon/aggregation/messages/base.ts +59 -0
- package/src/btcr2/beacon/aggregation/messages/cohort-set.ts +37 -0
- package/src/btcr2/beacon/aggregation/messages/keygen.ts +8 -0
- package/src/btcr2/beacon/aggregation/messages/opt-in.ts +35 -0
- package/src/btcr2/beacon/aggregation/messages/sign.ts +7 -0
- package/src/btcr2/beacon/aggregation/models/cohort/index.ts +112 -0
- package/src/btcr2/beacon/aggregation/models/cohort/status.ts +7 -0
- package/src/btcr2/beacon/aggregation/participant.ts +0 -0
- package/src/btcr2/beacon/aggregation/protocol/nostr.ts +81 -0
- package/src/btcr2/beacon/aggregation/protocol/service.ts +6 -0
- package/src/btcr2/beacon/cid-aggregate.ts +154 -0
- package/src/btcr2/beacon/factory.ts +36 -0
- package/src/btcr2/beacon/singleton.ts +257 -0
- package/src/btcr2/beacon/smt-aggregate.ts +136 -0
- package/src/btcr2/crud/create.ts +160 -0
- package/src/btcr2/crud/deactivate.ts +13 -0
- package/src/btcr2/crud/read.ts +946 -0
- package/src/btcr2/crud/update.ts +277 -0
- package/src/btcr2/key-manager/index.ts +364 -0
- package/src/btcr2/key-manager/interface.ts +129 -0
- package/src/canonicalize.d.ts +6 -0
- package/src/did-btcr2.ts +288 -0
- package/src/index.ts +34 -0
- package/src/interfaces/beacon.ts +68 -0
- package/src/interfaces/crud.ts +36 -0
- package/src/interfaces/ibeacon.ts +76 -0
- package/src/types/bitcoin.ts +1028 -0
- package/src/types/crud.ts +41 -0
- package/src/utils/appendix.ts +257 -0
- package/src/utils/beacons.ts +276 -0
- package/src/utils/did-document-builder.ts +73 -0
- package/src/utils/did-document.ts +474 -0
- package/src/utils/general.ts +204 -0
- package/src/utils/identifier.ts +276 -0
|
@@ -0,0 +1,686 @@
|
|
|
1
|
+
import { BitcoinNetworkNames, Btcr2Error, Btcr2IdentifierHrp, Btcr2ReadError, ID_PLACEHOLDER_VALUE, INVALID_DID, INVALID_DID_DOCUMENT, INVALID_DID_UPDATE, LATE_PUBLISHING_ERROR, Logger } from '@did-btcr2/common';
|
|
2
|
+
import { Cryptosuite, DataIntegrityProof, SchnorrMultikey } from '@did-btcr2/cryptosuite';
|
|
3
|
+
import { PublicKey } from '@did-btcr2/keypair';
|
|
4
|
+
import { bytesToHex } from '@noble/hashes/utils';
|
|
5
|
+
import { GENESIS_TX_ID, TXIN_WITNESS_COINBASE } from '../../bitcoin/constants.js';
|
|
6
|
+
import bitcoinNetwork, { Bitcoin } from '../../bitcoin/index.js';
|
|
7
|
+
import { getNetwork } from '../../bitcoin/network.js';
|
|
8
|
+
import { DidBtc1 } from '../../did-btcr2.js';
|
|
9
|
+
import { Btc1Appendix } from '../../utils/appendix.js';
|
|
10
|
+
import { BeaconUtils } from '../../utils/beacons.js';
|
|
11
|
+
import { Btc1DidDocument } from '../../utils/did-document.js';
|
|
12
|
+
import { BeaconFactory } from '../beacon/factory.js';
|
|
13
|
+
;
|
|
14
|
+
;
|
|
15
|
+
;
|
|
16
|
+
/**
|
|
17
|
+
* Implements {@link https://dcdpr.github.io/did-btcr2/#read | 4.2 Read}.
|
|
18
|
+
* The read operation is executed by a resolver after a resolution request identifying a specific did:btcr2 identifier is
|
|
19
|
+
* received from a client at Resolution Time. The request MAY contain a resolutionOptions object containing additional
|
|
20
|
+
* information to be used in resolution. The resolver then attempts to resolve the DID document of the identifier at a
|
|
21
|
+
* specific Target Time. The Target Time is either provided in resolutionOptions or is set to the Resolution Time of the
|
|
22
|
+
* request.
|
|
23
|
+
* To do so it executes the following algorithm:
|
|
24
|
+
* 1. Let identifierComponents be the result of running the algorithm
|
|
25
|
+
* in Parse did:btcr2 identifier, passing in the identifier.
|
|
26
|
+
* 2. Set initialDocument to the result of running Resolve Initial Document
|
|
27
|
+
* passing identifier, identifierComponents and resolutionOptions.
|
|
28
|
+
* 3. Set targetDocument to the result of running the algorithm in Resolve
|
|
29
|
+
* Target Document passing in initialDocument and resolutionOptions.
|
|
30
|
+
* 4. Return targetDocument.
|
|
31
|
+
*
|
|
32
|
+
* @class Btc1Read
|
|
33
|
+
* @type {Btc1Read}
|
|
34
|
+
*/
|
|
35
|
+
export class Btc1Read {
|
|
36
|
+
/**
|
|
37
|
+
* Implements {@link https://dcdpr.github.io/did-btcr2/#deterministically-generate-initial-did-document | 4.2.2.1 Deterministically Generate Initial DID Document}.
|
|
38
|
+
*
|
|
39
|
+
* The Deterministically Generate Initial DID Document algorithm deterministically generates an initial DID
|
|
40
|
+
* Document from a secp256k1 public key. It takes in a did:btcr2 identifier and a identifierComponents object and
|
|
41
|
+
* returns an initialDocument.
|
|
42
|
+
*
|
|
43
|
+
* @param {Btc1ReadDeterministic} params See {@link Btc1ReadDeterministic} for details.
|
|
44
|
+
* @param {string} params.identifier The did-btcr2 version.
|
|
45
|
+
* @param {DidComponents} params.identifierComponents The decoded components of the identifier.
|
|
46
|
+
* @returns {Btc1DidDocument} The resolved DID Document object.
|
|
47
|
+
*/
|
|
48
|
+
static deterministic({ identifier, identifierComponents }) {
|
|
49
|
+
// Deconstruct the components
|
|
50
|
+
const { network, genesisBytes } = identifierComponents;
|
|
51
|
+
// Construct a new PublicKey and deconstruct the publicKey and publicKeyMultibase
|
|
52
|
+
const { compressed: publicKey, multibase: publicKeyMultibase } = new PublicKey(genesisBytes);
|
|
53
|
+
// Generate the service field for the DID Document
|
|
54
|
+
const service = BeaconUtils.generateBeaconServices({
|
|
55
|
+
identifier,
|
|
56
|
+
publicKey,
|
|
57
|
+
network: getNetwork(network),
|
|
58
|
+
type: 'SingletonBeacon',
|
|
59
|
+
});
|
|
60
|
+
return new Btc1DidDocument({
|
|
61
|
+
id: identifier,
|
|
62
|
+
controller: [identifier],
|
|
63
|
+
verificationMethod: [{
|
|
64
|
+
id: `${identifier}#initialKey`,
|
|
65
|
+
type: 'Multikey',
|
|
66
|
+
controller: identifier,
|
|
67
|
+
publicKeyMultibase: publicKeyMultibase.address
|
|
68
|
+
}],
|
|
69
|
+
service
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Implements {@link https://dcdpr.github.io/did-btcr2/#external-resolution | 4.2.2.2 External Resolution}.
|
|
74
|
+
*
|
|
75
|
+
* The External Resolution algorithm externally retrieves an intermediateDocumentRepresentation, either by retrieving
|
|
76
|
+
* it from {@link https://dcdpr.github.io/did-btcr2/#def-content-addressable-storage | Content Addressable Storage (CAS)}
|
|
77
|
+
* or from the {@link https://dcdpr.github.io/did-btcr2/#def-sidecar-data | Sidecar Data} provided as part of the
|
|
78
|
+
* resolution request. It takes in a did:btcr2 identifier, a identifierComponents object and a resolutionOptions object.
|
|
79
|
+
* It returns an initialDocument, which is a conformant DID document validated against the identifier.
|
|
80
|
+
*
|
|
81
|
+
* @param {Btc1ReadExternal} params Required params for calling the external method.
|
|
82
|
+
* @param {string} params.identifier The DID to be resolved.
|
|
83
|
+
* @param {DidComponents} params.identifierComponents The decoded components of the identifier.
|
|
84
|
+
* @param {DidResolutionOptions} params.resolutionsOptions The options for resolving the DID Document.
|
|
85
|
+
* @param {Btc1DidDocument} params.resolutionsOptions.sidecarData The sidecar data for resolving the DID Document.
|
|
86
|
+
* @param {Btc1DidDocument} params.resolutionsOptions.sidecarData.initialDocument The offline user-provided DID Document
|
|
87
|
+
* @returns {Btc1DidDocument} The resolved DID Document object
|
|
88
|
+
*/
|
|
89
|
+
static async external({ identifier, identifierComponents, resolutionsOptions }) {
|
|
90
|
+
// Deconstruct the options
|
|
91
|
+
const { initialDocument: document } = resolutionsOptions.sidecarData;
|
|
92
|
+
// 1. If resolutionOptions.sidecarData.initialDocument is not null, set initialDocument to the result of passing
|
|
93
|
+
// identifier, identifierComponents and resolutionOptions.sidecarData.initialDocument into algorithm Sidecar
|
|
94
|
+
// Initial Document Validation.
|
|
95
|
+
// 2. Else set initialDocument to the result of passing identifier and identifierComponents to the CAS Retrieval algorithm.
|
|
96
|
+
const initialDocument = document
|
|
97
|
+
? await this.sidecar({ identifierComponents, initialDocument: document })
|
|
98
|
+
: await this.cas({ identifier, identifierComponents });
|
|
99
|
+
// 3. Validate initialDocument is a conformant DID document according to the DID Core 1.1 specification. Else MUST
|
|
100
|
+
// raise invalidDidDocument error.
|
|
101
|
+
Btc1DidDocument.validate(initialDocument);
|
|
102
|
+
// 4. Return initialDocument.
|
|
103
|
+
return initialDocument;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Implements {@link https://dcdpr.github.io/did-btcr2/#sidecar-initial-document-validation | 4.2.2.2.1 Sidecar Initial Document Validation}.
|
|
107
|
+
*
|
|
108
|
+
* The Sidecar Initial Document Validation algorithm validates an initialDocument against its identifier, by first
|
|
109
|
+
* constructing the intermediateDocumentRepresentation and verifying the hash of this document matches the bytes
|
|
110
|
+
* encoded within the identifier. It takes in a did:btcr2 identifier, identifierComponents and a
|
|
111
|
+
* initialDocument. It returns the initialDocument if validated, otherwise it throws an error.
|
|
112
|
+
*
|
|
113
|
+
* @param {Btc1ReadSidecar} params Required params for calling the sidecar method
|
|
114
|
+
* @param {string} params.identifier The DID to be resolved
|
|
115
|
+
* @param {DidComponents} params.identifierComponents The components of the DID identifier
|
|
116
|
+
* @param {Btc1DidDocument} params.initialDocument The initial DID Document provided by the user
|
|
117
|
+
* @returns {Btc1DidDocument} The resolved DID Document object
|
|
118
|
+
* @throws {DidError} InvalidDidDocument if genesisBytes !== initialDocument hashBytes
|
|
119
|
+
*/
|
|
120
|
+
static async sidecar({ identifierComponents, initialDocument }) {
|
|
121
|
+
// Replace the placeholder did with the identifier throughout the initialDocument.
|
|
122
|
+
const intermediateDocument = JSON.parse(JSON.stringify(initialDocument).replaceAll(initialDocument.id, ID_PLACEHOLDER_VALUE));
|
|
123
|
+
// Canonicalize and sha256 hash the intermediateDocument
|
|
124
|
+
const hashBytes = await JSON.canonicalization.process(intermediateDocument, 'hex');
|
|
125
|
+
// Compare the genesisBytes to the hashBytes
|
|
126
|
+
const genesisBytes = bytesToHex(identifierComponents.genesisBytes);
|
|
127
|
+
// If the genesisBytes do not match the hashBytes, throw an error
|
|
128
|
+
if (genesisBytes !== hashBytes) {
|
|
129
|
+
throw new Btcr2Error(`Initial document mismatch: genesisBytes ${genesisBytes} !== hashBytes ${hashBytes}`, INVALID_DID_DOCUMENT, { genesisBytes, hashBytes });
|
|
130
|
+
}
|
|
131
|
+
// Return a W3C conformant DID Document
|
|
132
|
+
return new Btc1DidDocument(initialDocument);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Implements {@link https://dcdpr.github.io/did-btcr2/#cas-retrieval | 4.2.2.2.2 CAS Retrieval}.
|
|
136
|
+
*
|
|
137
|
+
* The CAS Retrieval algorithm attempts to retrieve an initialDocument from a Content Addressable Storage (CAS) system
|
|
138
|
+
* by converting the bytes in the identifier into a Content Identifier (CID). It takes in an identifier and
|
|
139
|
+
* an identifierComponents object. It returns an initialDocument.
|
|
140
|
+
*
|
|
141
|
+
* @param {DidReadCas} params Required params for calling the cas method
|
|
142
|
+
* @param {string} params.identifier BTCR2 DID used to resolve the DID Document
|
|
143
|
+
* @param {DidComponents} params.identifierComponents BTCR2 DID components used to resolve the DID Document
|
|
144
|
+
* @returns {Btc1DidDocument} The resolved DID Document object
|
|
145
|
+
* @throws {Btcr2Error} if the DID Document content is invalid
|
|
146
|
+
*/
|
|
147
|
+
static async cas({ identifier, identifierComponents }) {
|
|
148
|
+
// 1. Set hashBytes to identifierComponents.genesisBytes.
|
|
149
|
+
const hashBytes = identifierComponents.genesisBytes;
|
|
150
|
+
// 3. Set intermediateDocumentRepresentation to the result of fetching the cid against a Content Addressable Storage
|
|
151
|
+
// (CAS) system such as IPFS.
|
|
152
|
+
const intermediateDocument = await Btc1Appendix.fetchFromCas(hashBytes);
|
|
153
|
+
// Validate the intermediateDocument is not null and is parsable JSON
|
|
154
|
+
if (!intermediateDocument || !JSON.parsable(intermediateDocument)) {
|
|
155
|
+
throw new Btcr2Error(INVALID_DID_DOCUMENT, 'Invalid DID Document content', { intermediateDocument });
|
|
156
|
+
}
|
|
157
|
+
// 5. Replace the placeholder did with the identifier throughout the initialDocument.
|
|
158
|
+
const initialDocument = JSON.parse(intermediateDocument.replaceAll(ID_PLACEHOLDER_VALUE, identifier));
|
|
159
|
+
// 6. Return initialDocument.
|
|
160
|
+
return new Btc1DidDocument(initialDocument);
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Implements {@link https://dcdpr.github.io/did-btcr2/#resolve-initial-document | 4.2.2 Resolve Initial Document}.
|
|
164
|
+
*
|
|
165
|
+
* This algorithm resolves an initial DID document and validates it against the identifier for a specific did:btcr2.
|
|
166
|
+
* The algorithm takes in a did:btcr2 identifier, identifier components object, resolutionsOptions object and returns
|
|
167
|
+
* a valid initialDocument for that identifier.
|
|
168
|
+
*
|
|
169
|
+
* @public
|
|
170
|
+
* @param {ResolveInitialDocument} params See {@link ResolveInitialDocument} for parameter details.
|
|
171
|
+
* @param {string} params.identifier The DID to be resolved.
|
|
172
|
+
* @param {DidComponents} params.identifierComponents The decoded components of the identifier.
|
|
173
|
+
* @param {DidResolutionOptions} params.resolutionsOptions Options for resolving the DID Document. See {@link DidResolutionOptions}.
|
|
174
|
+
* @returns {Promise<Btc1DidDocument>} The resolved DID Document object.
|
|
175
|
+
* @throws {DidError} if the DID hrp is invalid, no sidecarData passed and hrp = "x".
|
|
176
|
+
*/
|
|
177
|
+
static async initialDocument({ identifier, identifierComponents, resolutionsOptions }) {
|
|
178
|
+
// Deconstruct the hrp from the components
|
|
179
|
+
const hrp = identifierComponents.hrp;
|
|
180
|
+
// Validate the hrp is either 'k' or 'x'
|
|
181
|
+
if (!(hrp in Btcr2IdentifierHrp)) {
|
|
182
|
+
throw new Btcr2Error(`Invalid DID hrp ${hrp}`, INVALID_DID, { hrp });
|
|
183
|
+
}
|
|
184
|
+
// Make sure options.sidecarData is not null if hrp === x
|
|
185
|
+
if (hrp === Btcr2IdentifierHrp.x && !resolutionsOptions.sidecarData) {
|
|
186
|
+
throw new Btcr2Error('External resolution requires sidecar data', INVALID_DID, resolutionsOptions);
|
|
187
|
+
}
|
|
188
|
+
return hrp === Btcr2IdentifierHrp.k
|
|
189
|
+
? this.deterministic({ identifier, identifierComponents })
|
|
190
|
+
: await this.external({ identifier, identifierComponents, resolutionsOptions });
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Implements {@link https://dcdpr.github.io/did-btcr2/#resolve-target-document | 4.2.3 Resolve Target Document}.
|
|
194
|
+
*
|
|
195
|
+
* The Resolve Target Document algorithm resolves a DID document from an initial document by walking the Bitcoin
|
|
196
|
+
* blockchain to identify Beacon Signals that announce DID Update Payloads applicable to the did:btcr2 identifier being
|
|
197
|
+
* resolved. It takes as inputs initialDocument, resolutionOptions and network. It returns a valid DID document.
|
|
198
|
+
*
|
|
199
|
+
* @public
|
|
200
|
+
* @param {TargetDocumentParams} params See {@link TargetDocumentParams} for details.
|
|
201
|
+
* @param {Btc1DidDocument} params.initialDocument The initial DID Document to resolve
|
|
202
|
+
* @param {ResolutionOptions} params.options See {@link DidResolutionOptions} for details.
|
|
203
|
+
* @returns {Btc1DidDocument} The resolved DID Document object with a validated single, canonical history
|
|
204
|
+
*/
|
|
205
|
+
static async targetDocument({ initialDocument, resolutionsOptions }) {
|
|
206
|
+
// Set the network from the options or default to mainnet
|
|
207
|
+
const network = resolutionsOptions.network ?? BitcoinNetworkNames.bitcoin;
|
|
208
|
+
// 1. If resolutionOptions.versionId is not null, set targetVersionId to resolutionOptions.versionId.
|
|
209
|
+
const targetVersionId = resolutionsOptions.versionId;
|
|
210
|
+
// 2. Else if resolutionOptions.versionTime is not null, set targetTime to resolutionOptions.versionTime.
|
|
211
|
+
// 3. Else set targetTime to the UNIX timestamp for now at the moment of execution.
|
|
212
|
+
const targetTime = resolutionsOptions.versionTime ?? new Date().toUnix();
|
|
213
|
+
// 4. Set signalsMetadata to resolutionOptions.sidecarData.signalsMetadata.
|
|
214
|
+
const signalsMetadata = resolutionsOptions.sidecarData.signalsMetadata;
|
|
215
|
+
// 5. Set currentVersionId to 1
|
|
216
|
+
const currentVersionId = 1;
|
|
217
|
+
// 6. If currentVersionId equals targetVersionId return initialDocument.
|
|
218
|
+
if (currentVersionId === targetVersionId) {
|
|
219
|
+
return new Btc1DidDocument(initialDocument);
|
|
220
|
+
}
|
|
221
|
+
// 10. Set targetDocument to the result of calling the Traverse Bitcoin Blockchain History algorithm
|
|
222
|
+
// passing in contemporaryDIDDocument, contemporaryBlockheight, currentVersionId, targetVersionId,
|
|
223
|
+
// targetTime, didDocumentHistory, btc1UpdateHashHistory, signalsMetadata, and network.
|
|
224
|
+
const targetDocument = this.traverseBlockchainHistory({
|
|
225
|
+
contemporaryDidDocument: initialDocument,
|
|
226
|
+
contemporaryBlockHeight: 0,
|
|
227
|
+
currentVersionId,
|
|
228
|
+
targetVersionId,
|
|
229
|
+
targetTime,
|
|
230
|
+
didDocumentHistory: new Array(),
|
|
231
|
+
btc1UpdateHashHistory: new Array(),
|
|
232
|
+
signalsMetadata,
|
|
233
|
+
network
|
|
234
|
+
});
|
|
235
|
+
// 11. Return targetDocument.
|
|
236
|
+
return targetDocument;
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Implements {@link https://dcdpr.github.io/did-btcr2/#traverse-blockchain-history | 4.2.3.2 Traverse Blockchain History}.
|
|
240
|
+
*
|
|
241
|
+
* The Traverse Blockchain History algorithm traverses Bitcoin blocks, starting from the block with the
|
|
242
|
+
* contemporaryBlockheight, to find beaconSignals emitted by Beacons within the contemporaryDidDocument. Each
|
|
243
|
+
* beaconSignal is processed to retrieve a didUpdatePayload to the DID document. Each update is applied to the
|
|
244
|
+
* document and duplicates are ignored. If the algorithm reaches the block with the blockheight specified by a
|
|
245
|
+
* targetBlockheight, the contemporaryDidDocument at that blockheight is returned assuming a single canonical history
|
|
246
|
+
* of the DID document has been constructed up to that point. It takes in contemporaryDidDocument,
|
|
247
|
+
* contemporaryBlockHeight, currentVersionId, targetVersionId, targetBlockheight, updateHashHistory, signalsMetadata
|
|
248
|
+
* and network. It returns the contemporaryDidDocument once either the targetBlockheight or targetVersionId have been
|
|
249
|
+
* reached.
|
|
250
|
+
*
|
|
251
|
+
* @protected
|
|
252
|
+
* @param {ReadBlockchainParams} params The parameters for the traverseBlockchainHistory operation.
|
|
253
|
+
* @param {Btc1DidDocument} params.contemporaryDidDocument The DID document for the did:btcr2 identifier being resolved.
|
|
254
|
+
* It should be "current" (contemporary) at the blockheight of the contemporaryBlockheight.
|
|
255
|
+
* It should be a DID Core conformant DID document.
|
|
256
|
+
* @param {number} params.contemporaryBlockHeight The Bitcoin blockheight signaling the "contemporary time" of the
|
|
257
|
+
* contemporary DID Document that is being resolved and updated using the Traverse Blockchain History algorithm.
|
|
258
|
+
* @param {number} params.currentVersionId The version of the contemporary DID document starting from 1 and
|
|
259
|
+
* incrementing by 1 with each BTCR2 Update applied to the DID document.
|
|
260
|
+
* @param {number} params.targetVersionId The version of the DID document where resolution will complete.
|
|
261
|
+
* @param {UnixTimestamp} params.targetTime The timestamp used to target specific historical states of a DID document.
|
|
262
|
+
* Only Beacon Signals included in the Bitcoin blockchain before the targetTime are processed.
|
|
263
|
+
* @param {boolean} params.didDocumentHistory An array of DID documents ordered ascensing by version (1...N).
|
|
264
|
+
* @param {boolean} params.btc1UpdateHashHistory An array of SHA256 hashes of BTCR2 Updates ordered by version that are
|
|
265
|
+
* applied to the DID document in order to construct the contemporaryDIDDocument.
|
|
266
|
+
* @param {SignalsMetadata} params.signalsMetadata See {@link SignalsMetadata} for details.
|
|
267
|
+
* @param {BitcoinNetworkNames} params.network The bitcoin network to connect to (mainnet, signet, testnet, regtest).
|
|
268
|
+
* @returns {Promise<Btc1DidDocument>} The resolved DID Document object with a validated single, canonical history.
|
|
269
|
+
*/
|
|
270
|
+
static async traverseBlockchainHistory({ contemporaryDidDocument, contemporaryBlockHeight, currentVersionId, targetVersionId, targetTime, didDocumentHistory, btc1UpdateHashHistory, signalsMetadata, network }) {
|
|
271
|
+
// 1. Set contemporaryHash to the SHA256 hash of the contemporaryDidDocument
|
|
272
|
+
let contemporaryHash = await JSON.canonicalization.process(contemporaryDidDocument, 'base58');
|
|
273
|
+
// 2. Find all BTCR2 Beacons in contemporaryDIDDocument.service where service.type equals one of
|
|
274
|
+
// SingletonBeacon, CIDAggregateBeacon and SMTAggregateBeacon.
|
|
275
|
+
// 3. For each beacon in beacons convert the beacon.serviceEndpoint to a Bitcoin address
|
|
276
|
+
// following BIP21. Set beacon.address to the Bitcoin address.
|
|
277
|
+
const beacons = BeaconUtils.toBeaconServiceAddress(BeaconUtils.getBeaconServices(contemporaryDidDocument));
|
|
278
|
+
// 4. Set nextSignals to the result of calling algorithm Find Next Signals passing in contemporaryBlockheight,
|
|
279
|
+
// beacons and network.
|
|
280
|
+
const nextSignals = await this.findNextSignals({ contemporaryBlockHeight, beacons, network, targetTime });
|
|
281
|
+
if (!nextSignals || nextSignals.length === 0) {
|
|
282
|
+
// 5. If nextSignals is null or empty, return contemporaryDidDocument.
|
|
283
|
+
return new Btc1DidDocument(contemporaryDidDocument);
|
|
284
|
+
}
|
|
285
|
+
// 6. If nextSignals[0].blocktime is greater than targetTime, return contemporaryDIDDocument.
|
|
286
|
+
if (nextSignals[0].blocktime > targetTime) {
|
|
287
|
+
return new Btc1DidDocument(contemporaryDidDocument);
|
|
288
|
+
}
|
|
289
|
+
// 8. Set updates to the result of calling algorithm Process Beacon Signals passing in signals and sidecarData.
|
|
290
|
+
// 9. Set orderedUpdates to the list of updates ordered by the targetVersionId property.
|
|
291
|
+
const orderedUpdates = (await Promise.all(nextSignals.map(async (signal) => await this.processBeaconSignal(signal, signalsMetadata)))).sort((a, b) => a.targetVersionId - b.targetVersionId);
|
|
292
|
+
// 10. For update in orderedUpdates:
|
|
293
|
+
for (let update of orderedUpdates) {
|
|
294
|
+
const updateTargetVersionId = update.targetVersionId;
|
|
295
|
+
// 10.1. If update.targetVersionId is less than or equal to currentVersionId, run Algorithm Confirm Duplicate
|
|
296
|
+
// Update passing in update, documentHistory, and contemporaryHash.
|
|
297
|
+
if (updateTargetVersionId <= currentVersionId) {
|
|
298
|
+
btc1UpdateHashHistory.push(contemporaryHash);
|
|
299
|
+
await this.confirmDuplicateUpdate({ update, updateHashHistory: btc1UpdateHashHistory });
|
|
300
|
+
// 10.2. If update.targetVersionId equals currentVersionId + 1:
|
|
301
|
+
}
|
|
302
|
+
else if (updateTargetVersionId === currentVersionId + 1) {
|
|
303
|
+
// Prepend `z` to the sourceHash if it does not start with it
|
|
304
|
+
const sourceHash = update.sourceHash.startsWith('z') ? update.sourceHash : `z${update.sourceHash}`;
|
|
305
|
+
// 10.2.1. Check that update.sourceHash equals contemporaryHash, else MUST raise latePublishing error.
|
|
306
|
+
if (sourceHash !== contemporaryHash) {
|
|
307
|
+
throw new Btcr2ReadError(`Hash mismatch: sourceHash ${sourceHash} !== contemporaryHash ${contemporaryHash}`, LATE_PUBLISHING_ERROR, { sourceHash: sourceHash, contemporaryHash });
|
|
308
|
+
}
|
|
309
|
+
// 10.2.2. Set contemporaryDidDocument to the result of calling Apply DID Update algorithm passing in
|
|
310
|
+
// contemporaryDidDocument, update.
|
|
311
|
+
contemporaryDidDocument = await this.applyDidUpdate({ contemporaryDidDocument, update });
|
|
312
|
+
// 10.2.4 Push contemporaryDIDDocument onto didDocumentHistory.
|
|
313
|
+
didDocumentHistory.push(contemporaryDidDocument);
|
|
314
|
+
// 10.2.4. Increment currentVersionId.
|
|
315
|
+
currentVersionId++;
|
|
316
|
+
// 10.2.5. Set unsecuredUpdate to a copy of the update object.
|
|
317
|
+
const unsecuredUpdate = update;
|
|
318
|
+
// 10.2.6 Remove the proof property from the unsecuredUpdate object.
|
|
319
|
+
delete unsecuredUpdate.proof;
|
|
320
|
+
// 10.2.7 Set updateHash to the result of passing unsecuredUpdate into the JSON Canonicalization and Hash algorithm.
|
|
321
|
+
const updateHash = await JSON.canonicalization.process(update, 'base58');
|
|
322
|
+
// 10.2.8. Push updateHash onto btc1UpdateHashHistory.
|
|
323
|
+
btc1UpdateHashHistory.push(updateHash);
|
|
324
|
+
// 10.2.9. Set contemporaryHash to result of passing contemporaryDIDDocument into the JSON Canonicalization and Hash algorithm.
|
|
325
|
+
contemporaryHash = await JSON.canonicalization.process(contemporaryDidDocument, 'base58');
|
|
326
|
+
// 10.3. If update.targetVersionId is greater than currentVersionId + 1, MUST throw a LatePublishing error.
|
|
327
|
+
}
|
|
328
|
+
else if (update.targetVersionId > currentVersionId + 1) {
|
|
329
|
+
throw new Btcr2ReadError(`Version Id Mismatch: target ${update.targetVersionId} cannot be > current+1 ${currentVersionId + 1}`, 'LATE_PUBLISHING_ERROR');
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// 13. If targetVersionId in not null, set targetDocument to the index at the targetVersionId of the didDocumentHistory array.
|
|
333
|
+
if (targetVersionId) {
|
|
334
|
+
return new Btc1DidDocument(didDocumentHistory[targetVersionId]);
|
|
335
|
+
}
|
|
336
|
+
// 14. Return contemporaryDidDocument.
|
|
337
|
+
return new Btc1DidDocument(contemporaryDidDocument);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Implements {@link https://dcdpr.github.io/did-btcr2/#find-next-signals | 4.2.3.3 Find Next Signals}.
|
|
341
|
+
*
|
|
342
|
+
* The Find Next Signals algorithm finds the next Bitcoin block containing Beacon Signals from one or more of the
|
|
343
|
+
* beacons and retuns all Beacon Signals within that block.
|
|
344
|
+
*
|
|
345
|
+
* It takes the following inputs:
|
|
346
|
+
* - `contemporaryBlockhieght`: The height of the block this function is looking for Beacon Signals in.
|
|
347
|
+
* An integer greater or equal to 0.
|
|
348
|
+
* - `targetBlockheight`: The height of the Bitcoin block that the resolution algorithm searches for Beacon Signals
|
|
349
|
+
* up to. An integer greater or equal to 0.
|
|
350
|
+
* - `beacons`: An array of Beacon services in the contemporary DID document. Each Beacon contains properties:
|
|
351
|
+
* - `id`: The id of the Beacon service in the DID document. A string.
|
|
352
|
+
* - `type`: The type of the Beacon service in the DID document. A string whose values MUST be
|
|
353
|
+
* either SingletonBeacon, CIDAggregateBeacon or SMTAggregateBeacon.
|
|
354
|
+
* - `serviceEndpoint`: A BIP21 URI representing a Bitcoin address.
|
|
355
|
+
* - `address`: The Bitcoin address decoded from the `serviceEndpoint value.
|
|
356
|
+
* - `network`: A string identifying the Bitcoin network of the did:btcr2 identifier. This algorithm MUST query the
|
|
357
|
+
* Bitcoin blockchain identified by the network.
|
|
358
|
+
*
|
|
359
|
+
* It returns a nextSignals struct, containing the following properties:
|
|
360
|
+
* - blockheight: The Bitcoin blockheight for the block containing the Beacon Signals.
|
|
361
|
+
* - signals: An array of signals. Each signal is a struct containing the following:
|
|
362
|
+
* - beaconId: The id for the Beacon that the signal was announced by.
|
|
363
|
+
* - beaconType: The type of the Beacon that announced the signal.
|
|
364
|
+
* - tx: The Bitcoin transaction that is the Beacon Signal.
|
|
365
|
+
*
|
|
366
|
+
* @public
|
|
367
|
+
* @param {FindNextSignals} params The parameters for the findNextSignals operation.
|
|
368
|
+
* @param {number} params.blockheight The blockheight to start looking for beacon signals.
|
|
369
|
+
* @param {Array<BeaconService>} params.target The target blockheight at which to stop finding signals.
|
|
370
|
+
* @param {Array<BeaconService>} params.beacons The beacons to look for in the block.
|
|
371
|
+
* @returns {Promise<Array<BeaconSignal>>} An array of BeaconSignal objects with blockHeight and signals.
|
|
372
|
+
*/
|
|
373
|
+
static async findNextSignals({ contemporaryBlockHeight, targetTime, beacons }) {
|
|
374
|
+
let height = contemporaryBlockHeight;
|
|
375
|
+
// Toggle RPC or REST connection based on the connection type
|
|
376
|
+
const bitcoin = bitcoinNetwork ?? new Bitcoin();
|
|
377
|
+
// Create an default beaconSignal and beaconSignals array
|
|
378
|
+
let beaconSignals = [];
|
|
379
|
+
if (bitcoin.network.rest) {
|
|
380
|
+
return await this.findSignalsRest({ beacons });
|
|
381
|
+
}
|
|
382
|
+
// Use connection to get the block data at the blockhash
|
|
383
|
+
let block = await bitcoin.network.rpc.getBlock({ height });
|
|
384
|
+
Logger.info(`Searching for signals, please wait ...`);
|
|
385
|
+
while (block.time <= targetTime) {
|
|
386
|
+
// Iterate over each transaction in the block
|
|
387
|
+
for (const tx of block.tx) {
|
|
388
|
+
// If the txid is a coinbase, continue ...
|
|
389
|
+
if (tx.txid === GENESIS_TX_ID) {
|
|
390
|
+
continue;
|
|
391
|
+
}
|
|
392
|
+
// Iterate over each input in the transaction
|
|
393
|
+
for (const vin of tx.vin) {
|
|
394
|
+
// If the vin is a coinbase transaction, continue ...
|
|
395
|
+
if (vin.coinbase) {
|
|
396
|
+
continue;
|
|
397
|
+
}
|
|
398
|
+
// If the vin txinwitness contains a coinbase identifier, continue ...
|
|
399
|
+
if (vin.txinwitness && vin.txinwitness.length === 1 && vin.txinwitness[0] === TXIN_WITNESS_COINBASE) {
|
|
400
|
+
continue;
|
|
401
|
+
}
|
|
402
|
+
// If the txid from the vin is undefined, continue ...
|
|
403
|
+
if (!vin.txid) {
|
|
404
|
+
continue;
|
|
405
|
+
}
|
|
406
|
+
// If the vout from the vin is undefined, continue ...
|
|
407
|
+
if (vin.vout === undefined) {
|
|
408
|
+
continue;
|
|
409
|
+
}
|
|
410
|
+
// Get the previous output transaction data
|
|
411
|
+
const prevout = await bitcoin.network.rpc.getRawTransaction(vin.txid, 2);
|
|
412
|
+
// If the previous output vout at the vin.vout index is undefined, continue ...
|
|
413
|
+
if (!prevout.vout[vin.vout]) {
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
// Get the address from the scriptPubKey from the prevvout (previous output's input at the vout index)
|
|
417
|
+
const scriptPubKey = prevout.vout[vin.vout].scriptPubKey;
|
|
418
|
+
// If the scriptPubKey.address is undefined, continue ...
|
|
419
|
+
if (!scriptPubKey.address) {
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
// If the beaconAddress from prevvout scriptPubKey is not a beacon service endpoint address, continue ...
|
|
423
|
+
const beaconAddresses = BeaconUtils.getBeaconServiceAddressMap(beacons);
|
|
424
|
+
const beacon = (beaconAddresses.get(scriptPubKey.address) ?? {});
|
|
425
|
+
if (!beacon || !(beacon.id && beacon.type)) {
|
|
426
|
+
continue;
|
|
427
|
+
}
|
|
428
|
+
// If the prevout.vout[vin.vout].scriptPubKey.asm does not include 'OP_RETURN', continue ...
|
|
429
|
+
if (!prevout.vout[vin.vout].scriptPubKey.asm.includes('OP_RETURN')) {
|
|
430
|
+
continue;
|
|
431
|
+
}
|
|
432
|
+
// Log the found txid and beacon
|
|
433
|
+
Logger.info(`Tx ${tx.txid} contains beacon address ${scriptPubKey.address} and OP_RETURN!`, tx);
|
|
434
|
+
// Push the signal object to to signals array
|
|
435
|
+
beaconSignals.push({
|
|
436
|
+
beaconId: beacon.id,
|
|
437
|
+
beaconType: beacon.type,
|
|
438
|
+
beaconAddress: beacon.address,
|
|
439
|
+
tx,
|
|
440
|
+
blockheight: block.height,
|
|
441
|
+
blocktime: block.time
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
;
|
|
445
|
+
}
|
|
446
|
+
height += 1;
|
|
447
|
+
const tip = await bitcoin.network.rpc.getBlockCount();
|
|
448
|
+
if (height > tip) {
|
|
449
|
+
Logger.info(`Chain tip reached ${height}, breaking ...`);
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
// Reset the block to the next block
|
|
453
|
+
block = await bitcoin.network.rpc.getBlock({ height });
|
|
454
|
+
}
|
|
455
|
+
return beaconSignals;
|
|
456
|
+
}
|
|
457
|
+
/**
|
|
458
|
+
* Helper method for the {@link findNextSignals | Find Next Signals} algorithm.
|
|
459
|
+
*
|
|
460
|
+
* @param params See {@link FindNextSignalsRestParams} for details.
|
|
461
|
+
* @param {BitcoinClient} params.connection The bitcoin connection to use.
|
|
462
|
+
* @param {Array<BeaconSignal>} params.beaconSignals The beacon signals to process.
|
|
463
|
+
* @param {BlockV3} params.block The block to process.
|
|
464
|
+
* @param {Array<BeaconService>} params.beacons The beacons to process.
|
|
465
|
+
* @returns {Promise<Array<BeaconSignal>>} The beacon signals found in the block.
|
|
466
|
+
*/
|
|
467
|
+
static async findSignalsRest({ beacons }) {
|
|
468
|
+
const bitcoin = bitcoinNetwork ?? new Bitcoin();
|
|
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.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 Btcr2Error('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 btc1Update to null.
|
|
565
|
+
const btc1Update = await beacon.processSignal(signalTx, signalsMetadata) ?? null;
|
|
566
|
+
// If the updates is null, throw an error
|
|
567
|
+
if (!btc1Update) {
|
|
568
|
+
throw new Btcr2Error('No btc1Update for beacon', 'PROCESS_BEACON_SIGNALS_ERROR', { tx, signalsMetadata });
|
|
569
|
+
}
|
|
570
|
+
// 2.9 If btc1Update is not null, push btc1Update to updates.
|
|
571
|
+
updates.push(btc1Update);
|
|
572
|
+
// 3. Return updates.
|
|
573
|
+
return btc1Update;
|
|
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 {DidBtc1Error} 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 Btcr2ReadError(`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 {Btc1DidDocument} 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<Btc1DidDocument>}
|
|
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 Btcr2ReadError('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 = Btc1Appendix.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 Btcr2ReadError(`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 Btcr2ReadError('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 } = DidBtc1.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
|
+
// Logger.warn('// TODO: applyDidUpdate - Refactor Multikey to accept pub/priv bytes => Pub/PrivKey => KeyPair.');
|
|
649
|
+
const cryptosuite = new Cryptosuite({ cryptosuite: 'bip340-jcs-2025', multikey });
|
|
650
|
+
// Logger.warn('// TODO: applyDidUpdate - Refactor Cryptosuite to default to RDFC.');
|
|
651
|
+
// 5. Set expectedProofPurpose to capabilityInvocation.
|
|
652
|
+
const expectedPurpose = 'capabilityInvocation';
|
|
653
|
+
// 6. Set mediaType to ????
|
|
654
|
+
// const mediaType = 'application/json';
|
|
655
|
+
// Logger.warn('// TODO: applyDidUpdate - is this just application/json?');
|
|
656
|
+
// 7. Set documentBytes to the bytes representation of update.
|
|
657
|
+
const documentBytes = await JSON.canonicalization.canonicalize(update);
|
|
658
|
+
// 8. Set verificationResult to the result of passing mediaType, documentBytes, cryptosuite, and
|
|
659
|
+
// expectedProofPurpose into the Verify Proof algorithm defined in the VC Data Integrity specification.
|
|
660
|
+
const diProof = new DataIntegrityProof(cryptosuite);
|
|
661
|
+
const verificationResult = await diProof.verifyProof({ document: documentBytes, expectedPurpose });
|
|
662
|
+
// 9. If verificationResult.verified equals False, MUST raise a invalidUpdateProof exception.
|
|
663
|
+
if (!verificationResult.verified) {
|
|
664
|
+
throw new Btcr2Error('Invalid update: proof not verified', INVALID_DID_UPDATE, verificationResult);
|
|
665
|
+
}
|
|
666
|
+
// 10. Set targetDIDDocument to a copy of contemporaryDidDocument.
|
|
667
|
+
let targetDIDDocument = contemporaryDidDocument;
|
|
668
|
+
// 11. Use JSON Patch to apply the update.patch to the targetDIDDOcument.
|
|
669
|
+
targetDIDDocument = JSON.patch.apply(targetDIDDocument, update.patch);
|
|
670
|
+
// 12. Verify that targetDIDDocument is conformant with the data model specified by the DID Core specification.
|
|
671
|
+
Btc1DidDocument.validate(targetDIDDocument);
|
|
672
|
+
// 13. Set targetHash to the SHA256 hash of targetDIDDocument.
|
|
673
|
+
const targetHash = await JSON.canonicalization.process(targetDIDDocument, 'base58');
|
|
674
|
+
// Prepend the sourceHash if it does not start with `z`
|
|
675
|
+
const updateTargetHash = update.targetHash.startsWith('z')
|
|
676
|
+
? update.targetHash
|
|
677
|
+
: `z${update.targetHash}`;
|
|
678
|
+
// 14. Check that targetHash equals update.targetHash, else raise InvalidDIDUpdate error.
|
|
679
|
+
if (updateTargetHash !== targetHash) {
|
|
680
|
+
throw new Btcr2Error(`Invalid update: updateTargetHash ${updateTargetHash} does not match targetHash ${targetHash}`, INVALID_DID_UPDATE);
|
|
681
|
+
}
|
|
682
|
+
// 15. Return targetDIDDocument.
|
|
683
|
+
return targetDIDDocument;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
//# sourceMappingURL=read.js.map
|