@did-btcr2/method 0.22.0 → 0.24.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/README.md +96 -50
- package/dist/browser.js +35708 -37764
- package/dist/browser.mjs +35707 -37763
- package/dist/cjs/core/beacon/aggregation/cohort/index.js +13 -2
- package/dist/cjs/core/beacon/aggregation/cohort/index.js.map +1 -1
- package/dist/cjs/core/beacon/aggregation/cohort/messages/base.js +7 -2
- package/dist/cjs/core/beacon/aggregation/cohort/messages/base.js.map +1 -1
- package/dist/cjs/core/beacon/aggregation/communication/adapter/did-comm.js +6 -11
- package/dist/cjs/core/beacon/aggregation/communication/adapter/did-comm.js.map +1 -1
- package/dist/cjs/core/beacon/aggregation/communication/adapter/nostr.js +5 -8
- package/dist/cjs/core/beacon/aggregation/communication/adapter/nostr.js.map +1 -1
- package/dist/cjs/core/beacon/aggregation/coordinator.js +40 -44
- package/dist/cjs/core/beacon/aggregation/coordinator.js.map +1 -1
- package/dist/cjs/core/beacon/aggregation/participant.js +35 -38
- package/dist/cjs/core/beacon/aggregation/participant.js.map +1 -1
- package/dist/cjs/core/beacon/aggregation/session/index.js +18 -7
- package/dist/cjs/core/beacon/aggregation/session/index.js.map +1 -1
- package/dist/cjs/core/beacon/cas-beacon.js +1 -1
- package/dist/cjs/core/beacon/cas-beacon.js.map +1 -1
- package/dist/cjs/core/beacon/signal-discovery.js +6 -6
- package/dist/cjs/core/beacon/signal-discovery.js.map +1 -1
- package/dist/cjs/core/beacon/singleton.js +18 -17
- package/dist/cjs/core/beacon/singleton.js.map +1 -1
- package/dist/cjs/core/beacon/smt-beacon.js +1 -1
- package/dist/cjs/core/beacon/smt-beacon.js.map +1 -1
- package/dist/cjs/core/identifier.js +11 -13
- package/dist/cjs/core/identifier.js.map +1 -1
- package/dist/cjs/core/resolve.js +25 -22
- package/dist/cjs/core/resolve.js.map +1 -1
- package/dist/cjs/core/update.js +4 -4
- package/dist/cjs/core/update.js.map +1 -1
- package/dist/cjs/did-btcr2.js +11 -16
- package/dist/cjs/did-btcr2.js.map +1 -1
- package/dist/cjs/index.js +0 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/utils/did-document.js +22 -21
- package/dist/cjs/utils/did-document.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/cohort/index.js +13 -2
- package/dist/esm/core/beacon/aggregation/cohort/index.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/cohort/messages/base.js +7 -2
- package/dist/esm/core/beacon/aggregation/cohort/messages/base.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/communication/adapter/did-comm.js +6 -11
- package/dist/esm/core/beacon/aggregation/communication/adapter/did-comm.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/communication/adapter/nostr.js +5 -8
- package/dist/esm/core/beacon/aggregation/communication/adapter/nostr.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/coordinator.js +40 -44
- package/dist/esm/core/beacon/aggregation/coordinator.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/participant.js +35 -38
- package/dist/esm/core/beacon/aggregation/participant.js.map +1 -1
- package/dist/esm/core/beacon/aggregation/session/index.js +18 -7
- package/dist/esm/core/beacon/aggregation/session/index.js.map +1 -1
- package/dist/esm/core/beacon/cas-beacon.js +1 -1
- package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
- package/dist/esm/core/beacon/signal-discovery.js +6 -6
- package/dist/esm/core/beacon/signal-discovery.js.map +1 -1
- package/dist/esm/core/beacon/singleton.js +18 -17
- package/dist/esm/core/beacon/singleton.js.map +1 -1
- package/dist/esm/core/beacon/smt-beacon.js +1 -1
- package/dist/esm/core/beacon/smt-beacon.js.map +1 -1
- package/dist/esm/core/identifier.js +11 -13
- package/dist/esm/core/identifier.js.map +1 -1
- package/dist/esm/core/resolve.js +25 -22
- package/dist/esm/core/resolve.js.map +1 -1
- package/dist/esm/core/update.js +4 -4
- package/dist/esm/core/update.js.map +1 -1
- package/dist/esm/did-btcr2.js +11 -16
- package/dist/esm/did-btcr2.js.map +1 -1
- package/dist/esm/index.js +0 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/utils/did-document.js +22 -21
- package/dist/esm/utils/did-document.js.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/index.d.ts +2 -1
- package/dist/types/core/beacon/aggregation/cohort/index.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/base.d.ts +2 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/base.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/constants.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/cohort/messages/index.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/cohort-advert.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.d.ts +2 -2
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/opt-in-accept.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/opt-in.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/cohort/messages/keygen/subscribe.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/aggregated-nonce.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/authorization-request.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/nonce-contribution.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/request-signature.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/cohort/messages/sign/signature-authorization.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/cohort/status.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/communication/adapter/did-comm.d.ts +4 -3
- package/dist/types/core/beacon/aggregation/communication/adapter/did-comm.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/communication/adapter/nostr.d.ts +5 -3
- package/dist/types/core/beacon/aggregation/communication/adapter/nostr.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/communication/error.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/communication/factory.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/communication/service.d.ts +3 -2
- package/dist/types/core/beacon/aggregation/communication/service.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/coordinator.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/coordinator.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/participant.d.ts +1 -0
- package/dist/types/core/beacon/aggregation/participant.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/session/index.d.ts +2 -1
- package/dist/types/core/beacon/aggregation/session/index.d.ts.map +1 -1
- package/dist/types/core/beacon/aggregation/session/status.d.ts +1 -0
- package/dist/types/core/beacon/beacon.d.ts +4 -3
- package/dist/types/core/beacon/beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/cas-beacon.d.ts +4 -3
- package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/error.d.ts +1 -0
- package/dist/types/core/beacon/factory.d.ts +1 -0
- package/dist/types/core/beacon/interfaces.d.ts +1 -0
- package/dist/types/core/beacon/signal-discovery.d.ts +6 -5
- package/dist/types/core/beacon/signal-discovery.d.ts.map +1 -1
- package/dist/types/core/beacon/singleton.d.ts +4 -4
- package/dist/types/core/beacon/singleton.d.ts.map +1 -1
- package/dist/types/core/beacon/smt-beacon.d.ts +4 -3
- package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/utils.d.ts +1 -0
- package/dist/types/core/identifier.d.ts +18 -21
- package/dist/types/core/identifier.d.ts.map +1 -1
- package/dist/types/core/interfaces.d.ts +3 -2
- package/dist/types/core/interfaces.d.ts.map +1 -1
- package/dist/types/core/resolve.d.ts +4 -3
- package/dist/types/core/resolve.d.ts.map +1 -1
- package/dist/types/core/types.d.ts +1 -0
- package/dist/types/core/update.d.ts +3 -2
- package/dist/types/core/update.d.ts.map +1 -1
- package/dist/types/did-btcr2.d.ts +5 -4
- package/dist/types/did-btcr2.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/utils/appendix.d.ts +1 -0
- package/dist/types/utils/did-document-builder.d.ts +1 -0
- package/dist/types/utils/did-document.d.ts +5 -7
- package/dist/types/utils/did-document.d.ts.map +1 -1
- package/package.json +5 -6
- package/src/core/beacon/aggregation/cohort/index.ts +13 -2
- package/src/core/beacon/aggregation/cohort/messages/base.ts +7 -2
- package/src/core/beacon/aggregation/cohort/messages/keygen/cohort-ready.ts +1 -1
- package/src/core/beacon/aggregation/communication/adapter/did-comm.ts +9 -15
- package/src/core/beacon/aggregation/communication/adapter/nostr.ts +9 -11
- package/src/core/beacon/aggregation/communication/service.ts +2 -2
- package/src/core/beacon/aggregation/coordinator.ts +40 -44
- package/src/core/beacon/aggregation/participant.ts +38 -40
- package/src/core/beacon/aggregation/session/index.ts +18 -7
- package/src/core/beacon/beacon.ts +3 -3
- package/src/core/beacon/cas-beacon.ts +3 -3
- package/src/core/beacon/signal-discovery.ts +9 -9
- package/src/core/beacon/singleton.ts +20 -20
- package/src/core/beacon/smt-beacon.ts +3 -3
- package/src/core/identifier.ts +31 -28
- package/src/core/interfaces.ts +2 -2
- package/src/core/resolve.ts +32 -26
- package/src/core/update.ts +6 -6
- package/src/did-btcr2.ts +21 -21
- package/src/index.ts +0 -1
- package/src/utils/did-document.ts +24 -20
- package/dist/cjs/utils/general.js +0 -195
- package/dist/cjs/utils/general.js.map +0 -1
- package/dist/esm/utils/general.js +0 -195
- package/dist/esm/utils/general.js.map +0 -1
- package/dist/types/utils/general.d.ts +0 -85
- package/dist/types/utils/general.d.ts.map +0 -1
- package/src/utils/general.ts +0 -204
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
BitcoinConnection,
|
|
3
3
|
BlockV3,
|
|
4
4
|
GENESIS_TX_ID,
|
|
5
5
|
RawTransactionV2,
|
|
@@ -21,23 +21,23 @@ export class BeaconSignalDiscovery {
|
|
|
21
21
|
* Retrieves the beacon signals for the given array of BeaconService objects
|
|
22
22
|
* using an esplora/electrs REST API connection via a bitcoin I/O driver.
|
|
23
23
|
* @param {Array<BeaconService>} beaconServices Array of BeaconService objects to retrieve signals for
|
|
24
|
-
* @param {
|
|
24
|
+
* @param {BitcoinConnection} bitcoin Bitcoin network connection to use for REST calls
|
|
25
25
|
* @returns {Promise<Map<BeaconService, Array<BeaconSignal>>>} Map of beacon service to its discovered signals
|
|
26
26
|
*/
|
|
27
27
|
static async indexer(
|
|
28
28
|
beaconServices: Array<BeaconService>,
|
|
29
|
-
bitcoin:
|
|
29
|
+
bitcoin: BitcoinConnection
|
|
30
30
|
): Promise<Map<BeaconService, Array<BeaconSignal>>> {
|
|
31
31
|
const beaconServiceSignals = new Map<BeaconService, Array<BeaconSignal>>();
|
|
32
32
|
|
|
33
33
|
// Fetch the current block count once before the loop
|
|
34
|
-
const currentBlockCount = await bitcoin.
|
|
34
|
+
const currentBlockCount = await bitcoin.rest.block.count();
|
|
35
35
|
|
|
36
36
|
// Iterate over each beacon
|
|
37
37
|
for (const beaconService of beaconServices) {
|
|
38
38
|
beaconServiceSignals.set(beaconService, []);
|
|
39
39
|
// Get the transactions for the beacon address via REST
|
|
40
|
-
const beaconSignals = await bitcoin.
|
|
40
|
+
const beaconSignals = await bitcoin.rest.address.getTxs(
|
|
41
41
|
beaconService.serviceEndpoint as string
|
|
42
42
|
);
|
|
43
43
|
|
|
@@ -104,12 +104,12 @@ export class BeaconSignalDiscovery {
|
|
|
104
104
|
/**
|
|
105
105
|
* Traverse the full blockchain from genesis to chain top looking for beacon signals.
|
|
106
106
|
* @param {Array<BeaconService>} beaconServices Array of BeaconService objects to search for signals.
|
|
107
|
-
* @param {
|
|
107
|
+
* @param {BitcoinConnection} bitcoin Bitcoin network connection to use for RPC calls.
|
|
108
108
|
* @returns {Promise<Map<BeaconService, Array<BeaconSignal>>>} Map of beacon service to its discovered signals.
|
|
109
109
|
*/
|
|
110
110
|
static async fullnode(
|
|
111
111
|
beaconServices: Array<BeaconService>,
|
|
112
|
-
bitcoin:
|
|
112
|
+
bitcoin: BitcoinConnection
|
|
113
113
|
): Promise<Map<BeaconService, Array<BeaconSignal>>> {
|
|
114
114
|
const beaconServiceSignals = new Map<BeaconService, Array<BeaconSignal>>();
|
|
115
115
|
|
|
@@ -118,7 +118,7 @@ export class BeaconSignalDiscovery {
|
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
// Get the RPC connection from the bitcoin network
|
|
121
|
-
const rpc = bitcoin.
|
|
121
|
+
const rpc = bitcoin.rpc;
|
|
122
122
|
|
|
123
123
|
// Ensure that the RPC connection is available
|
|
124
124
|
if(!rpc) {
|
|
@@ -135,7 +135,7 @@ export class BeaconSignalDiscovery {
|
|
|
135
135
|
let height = 0;
|
|
136
136
|
|
|
137
137
|
// Opt into rpc connection to get the block data at the blockhash
|
|
138
|
-
let block = await bitcoin.
|
|
138
|
+
let block = await bitcoin.rpc!.getBlock({ height }) as BlockV3;
|
|
139
139
|
|
|
140
140
|
console.info(`Searching for beacon signals, please wait ...`);
|
|
141
141
|
while (block.height <= targetHeight) {
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { AddressUtxo,
|
|
2
|
-
import {
|
|
1
|
+
import { AddressUtxo, BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
|
+
import { canonicalHash, canonicalize, hash, INVALID_SIDECAR_DATA, KeyBytes, MISSING_UPDATE_DATA } from '@did-btcr2/common';
|
|
3
3
|
import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
4
4
|
import { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
5
|
-
import {
|
|
5
|
+
import { base64urlnopad } from '@scure/base';
|
|
6
6
|
import { opcodes, Psbt, script } from 'bitcoinjs-lib';
|
|
7
|
-
import { base58btc } from 'multiformats/bases/base58';
|
|
8
7
|
import { SidecarData } from '../types.js';
|
|
9
8
|
import { Beacon } from './beacon.js';
|
|
10
9
|
import { SingletonBeaconError } from './error.js';
|
|
@@ -21,7 +20,6 @@ export class SingletonBeacon extends Beacon {
|
|
|
21
20
|
/**
|
|
22
21
|
* Creates an instance of SingletonBeacon.
|
|
23
22
|
* @param {BeaconService} service The BeaconService object representing the funded beacon to announce the update to.
|
|
24
|
-
*
|
|
25
23
|
*/
|
|
26
24
|
constructor(service: BeaconService) {
|
|
27
25
|
super({ ...service, type: 'SingletonBeacon' });
|
|
@@ -55,11 +53,12 @@ export class SingletonBeacon extends Beacon {
|
|
|
55
53
|
);
|
|
56
54
|
}
|
|
57
55
|
|
|
58
|
-
//
|
|
59
|
-
|
|
56
|
+
// TODO: Review for simplification how we are encoding and comparing
|
|
57
|
+
// Canonicalize, hash and encode to base64url the signed update object found in sidecar or CAS
|
|
58
|
+
const encodedUpdate = canonicalHash(signedUpdate, { encoding: 'base64url' });
|
|
60
59
|
|
|
61
|
-
// Encode the signal bytes hex string to
|
|
62
|
-
const signalBytes =
|
|
60
|
+
// Encode the signal bytes hex string to base64url
|
|
61
|
+
const signalBytes = base64urlnopad.encode(Buffer.from(updateHash, 'hex'));
|
|
63
62
|
|
|
64
63
|
// Check for mismatch between found sidecar/cas update hash and onchain beacon signal hash
|
|
65
64
|
if (encodedUpdate !== signalBytes) {
|
|
@@ -81,20 +80,20 @@ export class SingletonBeacon extends Beacon {
|
|
|
81
80
|
* Broadcasts a SingletonBeacon signal to the Bitcoin network.
|
|
82
81
|
* @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
|
|
83
82
|
* @param {KeyBytes} secretKey The secret key for signing the Bitcoin transaction.
|
|
84
|
-
* @param {
|
|
83
|
+
* @param {BitcoinConnection} bitcoin The Bitcoin network connection.
|
|
85
84
|
* @returns {Promise<SignedBTCR2Update>} The signed update that was broadcast.
|
|
86
85
|
* @throws {SingletonBeaconError} if the bitcoin address is invalid or unfunded.
|
|
87
86
|
*/
|
|
88
87
|
async broadcastSignal(
|
|
89
88
|
signedUpdate: SignedBTCR2Update,
|
|
90
89
|
secretKey: KeyBytes,
|
|
91
|
-
bitcoin:
|
|
90
|
+
bitcoin: BitcoinConnection
|
|
92
91
|
): Promise<SignedBTCR2Update> {
|
|
93
92
|
// Convert the serviceEndpoint to a bitcoin address by removing the 'bitcoin:' prefix
|
|
94
93
|
const bitcoinAddress = this.service.serviceEndpoint.replace('bitcoin:', '');
|
|
95
94
|
|
|
96
95
|
// Query the Bitcoin network for UTXOs associated with the bitcoinAddress
|
|
97
|
-
const utxos = await bitcoin.
|
|
96
|
+
const utxos = await bitcoin.rest.address.getUtxos(bitcoinAddress);
|
|
98
97
|
|
|
99
98
|
// If no utxos are found, throw an error indicating the address is unfunded.
|
|
100
99
|
if(!utxos.length) {
|
|
@@ -118,13 +117,13 @@ export class SingletonBeacon extends Beacon {
|
|
|
118
117
|
}
|
|
119
118
|
|
|
120
119
|
// Get the previous tx to the utxo being spent
|
|
121
|
-
const prevTx = await bitcoin.
|
|
120
|
+
const prevTx = await bitcoin.rest.transaction.getHex(utxo.txid);
|
|
122
121
|
|
|
123
122
|
// Canonicalize and hash the signed update for OP_RETURN output
|
|
124
|
-
const updateHash =
|
|
123
|
+
const updateHash = hash(canonicalize(signedUpdate));
|
|
125
124
|
|
|
126
125
|
// Construct a spend transaction
|
|
127
|
-
const spendTx = new Psbt({ network: bitcoin.
|
|
126
|
+
const spendTx = new Psbt({ network: bitcoin.data })
|
|
128
127
|
// Spend tx contains the utxo as its input
|
|
129
128
|
.addInput({
|
|
130
129
|
hash : utxo.txid,
|
|
@@ -137,11 +136,12 @@ export class SingletonBeacon extends Beacon {
|
|
|
137
136
|
// Add an OP_RETURN output containing the update hash
|
|
138
137
|
.addOutput({ script: script.compile([opcodes.OP_RETURN, updateHash]), value: 0n });
|
|
139
138
|
|
|
140
|
-
// Construct a
|
|
139
|
+
// Construct a key pair and PSBT signer from the secret key
|
|
141
140
|
const keyPair = SchnorrKeyPair.fromSecret(secretKey);
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
141
|
+
const signer = {
|
|
142
|
+
publicKey : keyPair.publicKey.compressed,
|
|
143
|
+
sign : (hash: Uint8Array) => keyPair.secretKey.sign(hash, { scheme: 'ecdsa' }),
|
|
144
|
+
};
|
|
145
145
|
|
|
146
146
|
// Sign 0th input, finalize extract to hex in prep for broadcast
|
|
147
147
|
const signedTx = spendTx.signInput(0, signer)
|
|
@@ -150,7 +150,7 @@ export class SingletonBeacon extends Beacon {
|
|
|
150
150
|
.toHex();
|
|
151
151
|
|
|
152
152
|
// Broadcast spendTx to the Bitcoin network.
|
|
153
|
-
const txid = await bitcoin.
|
|
153
|
+
const txid = await bitcoin.rest.transaction.send(signedTx);
|
|
154
154
|
|
|
155
155
|
// Log the txid of the broadcasted transaction
|
|
156
156
|
console.info(`Singleton Beacon Signal Broadcasted with txid: ${txid}`);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
2
|
import { KeyBytes } from '@did-btcr2/common';
|
|
3
3
|
import { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
4
4
|
import { SidecarData } from '../types.js';
|
|
@@ -39,14 +39,14 @@ export class SMTBeacon extends Beacon {
|
|
|
39
39
|
* Broadcast CAS Beacon signal to the Bitcoin network.
|
|
40
40
|
* @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
|
|
41
41
|
* @param {KeyBytes} secretKey The secret key for signing the Bitcoin transaction.
|
|
42
|
-
* @param {
|
|
42
|
+
* @param {BitcoinConnection} bitcoin The Bitcoin network connection.
|
|
43
43
|
* @return {Promise<SignedBTCR2Update>} The signed update that was broadcasted.
|
|
44
44
|
* @throws {SMTBeaconError} if broadcasting fails.
|
|
45
45
|
*/
|
|
46
46
|
async broadcastSignal(
|
|
47
47
|
signedUpdate: SignedBTCR2Update,
|
|
48
48
|
secretKey: KeyBytes,
|
|
49
|
-
bitcoin:
|
|
49
|
+
bitcoin: BitcoinConnection
|
|
50
50
|
): Promise<SignedBTCR2Update> {
|
|
51
51
|
throw new SMTBeaconError('Method not implemented.', `METHOD_NOT_IMPLEMENTED`, {signedUpdate, secretKey, bitcoin});
|
|
52
52
|
}
|
package/src/core/identifier.ts
CHANGED
|
@@ -1,24 +1,32 @@
|
|
|
1
|
-
import { BitcoinNetworkNames, Bytes, IdentifierError, IdentifierTypes, INVALID_DID, METHOD_NOT_SUPPORTED } from '@did-btcr2/common';
|
|
1
|
+
import { BitcoinNetworkNames, Bytes, DocumentBytes, IdentifierError, IdentifierTypes, INVALID_DID, KeyBytes, METHOD_NOT_SUPPORTED, SchnorrKeyPairObject } from '@did-btcr2/common';
|
|
2
2
|
import { CompressedSecp256k1PublicKey, SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
3
3
|
import { bech32m } from '@scure/base';
|
|
4
|
+
import { DidCreateOptions } from '../did-btcr2.js';
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Components of a did:btcr2 identifier.
|
|
7
8
|
* @interface DidComponents
|
|
9
|
+
* @extends {IdentifierComponents}
|
|
8
10
|
* @property {string} hrp The human-readable part of the Bech32m encoding.
|
|
11
|
+
*/
|
|
12
|
+
export interface DidComponents extends IdentifierComponents {
|
|
13
|
+
hrp: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Components of a did:btcr2 identifier.
|
|
18
|
+
* @interface IdentifierComponents
|
|
9
19
|
* @property {string} idType Identifier type (key or external).
|
|
10
20
|
* @property {number} version Identifier version.
|
|
11
|
-
* @property {string
|
|
21
|
+
* @property {string} network Bitcoin network name or number.
|
|
12
22
|
* @property {Bytes} genesisBytes Public key or an intermediate document bytes.
|
|
13
23
|
*/
|
|
14
|
-
export interface
|
|
15
|
-
hrp: string;
|
|
24
|
+
export interface IdentifierComponents {
|
|
16
25
|
idType: string;
|
|
17
26
|
version: number;
|
|
18
27
|
network: string;
|
|
19
28
|
genesisBytes: Bytes;
|
|
20
|
-
}
|
|
21
|
-
|
|
29
|
+
}
|
|
22
30
|
/**
|
|
23
31
|
* Implements {@link https://dcdpr.github.io/did-btcr2/#syntax | 3 Syntax}.
|
|
24
32
|
* A did:btcr2 DID consists of a did:btcr2 prefix, followed by an id-bech32 value, which is a Bech32m encoding of:
|
|
@@ -41,20 +49,15 @@ export class Identifier {
|
|
|
41
49
|
* - a key-value representing a secp256k1 public key; or
|
|
42
50
|
* - a hash-value representing the hash of an initiating external DID document.
|
|
43
51
|
*
|
|
44
|
-
* @param {
|
|
45
|
-
* @param {
|
|
46
|
-
* @param {string} params.network Bitcoin network name.
|
|
47
|
-
* @param {number} params.version Identifier version.
|
|
48
|
-
* @param {KeyBytes | DocumentBytes} params.genesisBytes Public key or an intermediate document bytes.
|
|
52
|
+
* @param {KeyBytes | DocumentBytes} genesisBytes The genesis bytes (public key or document bytes).
|
|
53
|
+
* @param {DidCreateOptions} options The DID creation options.
|
|
49
54
|
* @returns {string} The new did:btcr2 identifier.
|
|
50
55
|
*/
|
|
51
|
-
static encode(
|
|
52
|
-
|
|
53
|
-
version
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}): string {
|
|
57
|
-
// 1. If idType is not a valid value per above, raise invalidDid error.
|
|
56
|
+
static encode(genesisBytes: KeyBytes | DocumentBytes, options: DidCreateOptions): string {
|
|
57
|
+
// Deconstruct the options
|
|
58
|
+
const { idType, version = 1, network } = options;
|
|
59
|
+
|
|
60
|
+
// If idType is not a valid value per above, raise invalidDid error.
|
|
58
61
|
if (!(idType in IdentifierTypes)) {
|
|
59
62
|
throw new IdentifierError('Expected "idType" to be "KEY" or "EXTERNAL"', INVALID_DID, {idType});
|
|
60
63
|
}
|
|
@@ -275,16 +278,16 @@ export class Identifier {
|
|
|
275
278
|
* Generates a new did:btcr2 identifier based on a newly generated key pair.
|
|
276
279
|
* @returns {string} The new did:btcr2 identifier.
|
|
277
280
|
*/
|
|
278
|
-
static generate(): {
|
|
279
|
-
const
|
|
280
|
-
const did = this.encode(
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
return {
|
|
281
|
+
static generate(): { keyPair: SchnorrKeyPairObject; did: string } {
|
|
282
|
+
const keyPair = SchnorrKeyPair.generate();
|
|
283
|
+
const did = this.encode(keyPair.publicKey.compressed,
|
|
284
|
+
{
|
|
285
|
+
idType : 'KEY',
|
|
286
|
+
version : 1,
|
|
287
|
+
network : 'regtest'
|
|
288
|
+
}
|
|
289
|
+
);
|
|
290
|
+
return { keyPair: keyPair.exportJSON(), did };
|
|
288
291
|
}
|
|
289
292
|
|
|
290
293
|
/**
|
package/src/core/interfaces.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
2
|
import { DidResolutionOptions } from '@web5/dids';
|
|
3
3
|
import { Sidecar } from './types.js';
|
|
4
4
|
|
|
@@ -44,7 +44,7 @@ export interface ResolutionOptions extends ResolutionOptionsCore {
|
|
|
44
44
|
* Drivers for interacting with external systems, such as the Bitcoin network.
|
|
45
45
|
*/
|
|
46
46
|
drivers?: {
|
|
47
|
-
bitcoin?:
|
|
47
|
+
bitcoin?: BitcoinConnection;
|
|
48
48
|
};
|
|
49
49
|
}
|
|
50
50
|
|
package/src/core/resolve.ts
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
BitcoinConnection,
|
|
3
3
|
getNetwork
|
|
4
4
|
} from '@did-btcr2/bitcoin';
|
|
5
5
|
import {
|
|
6
|
-
|
|
6
|
+
canonicalHash,
|
|
7
|
+
canonicalize,
|
|
7
8
|
DateUtils,
|
|
8
9
|
IdentifierHrp,
|
|
9
10
|
INVALID_DID,
|
|
@@ -23,7 +24,7 @@ import {
|
|
|
23
24
|
UnsignedBTCR2Update
|
|
24
25
|
} from '@did-btcr2/cryptosuite';
|
|
25
26
|
import { CompressedSecp256k1PublicKey } from '@did-btcr2/keypair';
|
|
26
|
-
import {
|
|
27
|
+
import { hex } from '@scure/base';
|
|
27
28
|
import { DidBtcr2 } from '../did-btcr2.js';
|
|
28
29
|
import { Appendix } from '../utils/appendix.js';
|
|
29
30
|
import { DidDocument, ID_PLACEHOLDER_VALUE } from '../utils/did-document.js';
|
|
@@ -64,12 +65,12 @@ export class Resolve {
|
|
|
64
65
|
* @returns {DidDocument} The resolved DID Document object.
|
|
65
66
|
*/
|
|
66
67
|
static deterministic(didComponents: DidComponents): DidDocument {
|
|
67
|
-
// Encode the did from the didComponents
|
|
68
|
-
const did = Identifier.encode(didComponents);
|
|
69
|
-
|
|
70
68
|
// Deconstruct the bytes from the given components
|
|
71
69
|
const { genesisBytes } = didComponents;
|
|
72
70
|
|
|
71
|
+
// Encode the did from the didComponents
|
|
72
|
+
const did = Identifier.encode(genesisBytes, didComponents);
|
|
73
|
+
|
|
73
74
|
// Construct a new CompressedSecp256k1PublicKey and deconstruct the publicKey and publicKeyMultibase
|
|
74
75
|
const { multibase: publicKeyMultibase } = new CompressedSecp256k1PublicKey(genesisBytes);
|
|
75
76
|
|
|
@@ -104,22 +105,25 @@ export class Resolve {
|
|
|
104
105
|
didComponents: DidComponents,
|
|
105
106
|
genesisDocument: object,
|
|
106
107
|
): Promise<DidDocument> {
|
|
107
|
-
//
|
|
108
|
-
const
|
|
108
|
+
// Get the genesis bytes from the did components
|
|
109
|
+
const { genesisBytes } = didComponents;
|
|
110
|
+
|
|
111
|
+
// Convert the genesis bytes to a hex string
|
|
112
|
+
const genesisHex = hex.encode(genesisBytes);
|
|
109
113
|
|
|
110
|
-
//
|
|
111
|
-
const
|
|
114
|
+
// Canonicalize and sha256 hash the currentDocument
|
|
115
|
+
const hashBytes = canonicalHash(genesisDocument);
|
|
112
116
|
|
|
113
117
|
// If the genesisBytes do not match the hashBytes, throw an error
|
|
114
|
-
if (
|
|
118
|
+
if (genesisHex !== hashBytes) {
|
|
115
119
|
throw new ResolveError(
|
|
116
|
-
`Initial document mismatch: genesisBytes ${
|
|
120
|
+
`Initial document mismatch: genesisBytes ${genesisHex} !== hashBytes ${hashBytes}`,
|
|
117
121
|
INVALID_DID_DOCUMENT, { genesisBytes, hashBytes }
|
|
118
122
|
);
|
|
119
123
|
}
|
|
120
124
|
|
|
121
125
|
// Encode the did from the didComponents
|
|
122
|
-
const did = Identifier.encode(didComponents);
|
|
126
|
+
const did = Identifier.encode(genesisBytes, didComponents);
|
|
123
127
|
|
|
124
128
|
// Replace the placeholder did with the did throughout the currentDocument.
|
|
125
129
|
const currentDocument = JSON.parse(
|
|
@@ -140,14 +144,14 @@ export class Resolve {
|
|
|
140
144
|
const updateMap = new Map<string, SignedBTCR2Update>();
|
|
141
145
|
if(sidecar.updates?.length)
|
|
142
146
|
for(const update of sidecar.updates) {
|
|
143
|
-
updateMap.set(
|
|
147
|
+
updateMap.set(canonicalHash(update, { encoding: 'hex' }), update);
|
|
144
148
|
}
|
|
145
149
|
|
|
146
150
|
// CAS Announcements map
|
|
147
151
|
const casMap = new Map<string, CASAnnouncement>();
|
|
148
152
|
if(sidecar.casUpdates?.length)
|
|
149
153
|
for(const update of sidecar.casUpdates) {
|
|
150
|
-
casMap.set(
|
|
154
|
+
casMap.set(canonicalHash(update, { encoding: 'hex' }), update);
|
|
151
155
|
}
|
|
152
156
|
|
|
153
157
|
// SMT Proofs map
|
|
@@ -209,16 +213,16 @@ export class Resolve {
|
|
|
209
213
|
* Signal Bytes (last output in OP_RETURN transaction).
|
|
210
214
|
* @param {Array<BeaconService>} beaconServices The array of BeaconService objects to search for signals.
|
|
211
215
|
* @param {SidecarData} sidecarData The sidecar data containing maps of updates, CAS announcements, and SMT proofs.
|
|
212
|
-
* @param {
|
|
216
|
+
* @param {BitcoinConnection} bitcoin The bitcoin network connection used to fetch beacon signals
|
|
213
217
|
* @returns {Promise<Array<[SignedBTCR2Update, BlockMetadata]>>} The array of BTCR2 Signed Updates announced by the Beacon Signals.
|
|
214
218
|
*/
|
|
215
219
|
static async beaconSignals(
|
|
216
220
|
beaconServices: Array<BeaconService>,
|
|
217
221
|
sidecarData: SidecarData,
|
|
218
|
-
bitcoin:
|
|
222
|
+
bitcoin: BitcoinConnection
|
|
219
223
|
): Promise<Array<[SignedBTCR2Update, BlockMetadata]>> {
|
|
220
224
|
// Discover Beacon Signals via indexer server (esplora/electrs) or full node
|
|
221
|
-
const beaconServicesSignals = bitcoin.
|
|
225
|
+
const beaconServicesSignals = bitcoin.rest
|
|
222
226
|
? await BeaconSignalDiscovery.indexer(beaconServices, bitcoin)
|
|
223
227
|
: await BeaconSignalDiscovery.fullnode(beaconServices, bitcoin);
|
|
224
228
|
|
|
@@ -276,11 +280,13 @@ export class Resolve {
|
|
|
276
280
|
// Iterate over each (update block) pair
|
|
277
281
|
for(const [update, block] of updates) {
|
|
278
282
|
// Get the hash of the current document
|
|
279
|
-
const currentDocumentHash =
|
|
283
|
+
const currentDocumentHash = canonicalHash(response.didDocument, { encoding: 'base64url' });
|
|
280
284
|
|
|
281
285
|
// Safely convert block.time to timestamp
|
|
282
286
|
const blocktime = DateUtils.blocktimeToTimestamp(block.time);
|
|
283
287
|
|
|
288
|
+
// TODO: How to detect if block is unconfirmed and exit gracefully or return without it
|
|
289
|
+
|
|
284
290
|
// Set the updated field to the blocktime of the current update
|
|
285
291
|
response.metadata.updated = DateUtils.toISOStringNonFractional(blocktime);
|
|
286
292
|
|
|
@@ -318,7 +324,7 @@ export class Resolve {
|
|
|
318
324
|
// Create unsigned_update by removing the proof property from update.
|
|
319
325
|
const unsignedUpdate = JSONUtils.deleteKeys(update, ['proof']) as UnsignedBTCR2Update;
|
|
320
326
|
// Push the canonicalized unsigned update hash to the updateHashHistory
|
|
321
|
-
updateHashHistory.push(
|
|
327
|
+
updateHashHistory.push(canonicalHash(unsignedUpdate, { encoding: 'base64url' }));
|
|
322
328
|
}
|
|
323
329
|
|
|
324
330
|
// If update.targetVersionId > currentVersionId + 1, throw LATE_PUBLISHING error
|
|
@@ -367,7 +373,7 @@ export class Resolve {
|
|
|
367
373
|
const { proof: _, ...unsignedUpdate } = update;
|
|
368
374
|
|
|
369
375
|
// Hash unsignedUpdate with JSON Document Hashing algorithm
|
|
370
|
-
const unsignedUpdateHash =
|
|
376
|
+
const unsignedUpdateHash = canonicalHash(unsignedUpdate);
|
|
371
377
|
|
|
372
378
|
// Let historicalUpdateHash equal updateHashHistory[updateHashIndex].
|
|
373
379
|
const historicalUpdateHash = updateHashHistory[update.targetVersionId - 2];
|
|
@@ -432,7 +438,7 @@ export class Resolve {
|
|
|
432
438
|
const cryptosuite = new BIP340Cryptosuite(multikey);
|
|
433
439
|
|
|
434
440
|
// Canonicalize the update
|
|
435
|
-
const canonicalUpdate =
|
|
441
|
+
const canonicalUpdate = canonicalize(update);
|
|
436
442
|
|
|
437
443
|
// Construct a DataIntegrityProof with the cryptosuite
|
|
438
444
|
const diProof = new BIP340DataIntegrityProof(cryptosuite);
|
|
@@ -455,16 +461,16 @@ export class Resolve {
|
|
|
455
461
|
DidDocument.validate(updatedDocument);
|
|
456
462
|
|
|
457
463
|
// Canonicalize and hash the updatedDocument to get the currentDocumentHash.
|
|
458
|
-
const currentDocumentHash =
|
|
464
|
+
const currentDocumentHash = canonicalHash(updatedDocument, { encoding: 'base64url' });
|
|
459
465
|
|
|
460
466
|
// Prepare the update targetHash for comparison with currentDocumentHash.
|
|
461
|
-
const updateTargetHash = update.targetHash
|
|
467
|
+
const updateTargetHash = update.targetHash;
|
|
462
468
|
|
|
463
469
|
// Make sure the update.targetHash equals currentDocumentHash.
|
|
464
|
-
if (
|
|
470
|
+
if (update.targetHash !== currentDocumentHash) {
|
|
465
471
|
// If they do not match, throw INVALID_DID_UPDATE error.
|
|
466
472
|
throw new ResolveError(
|
|
467
|
-
`Invalid update:
|
|
473
|
+
`Invalid update: update.targetHash !== currentDocumentHash`,
|
|
468
474
|
INVALID_DID_UPDATE, { updateTargetHash, currentDocumentHash }
|
|
469
475
|
);
|
|
470
476
|
}
|
package/src/core/update.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
2
|
+
canonicalHash,
|
|
3
3
|
INVALID_DID_UPDATE,
|
|
4
4
|
JSONPatch,
|
|
5
5
|
KeyBytes,
|
|
@@ -15,7 +15,7 @@ import {
|
|
|
15
15
|
import { Btcr2DidDocument, DidDocument, DidVerificationMethod } from '../utils/did-document.js';
|
|
16
16
|
import { BeaconFactory } from './beacon/factory.js';
|
|
17
17
|
import { BeaconService } from './beacon/interfaces.js';
|
|
18
|
-
import {
|
|
18
|
+
import { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
19
19
|
|
|
20
20
|
/**
|
|
21
21
|
* Implements {@link https://dcdpr.github.io/did-btcr2/operations/update.html | 7.3 Update}.
|
|
@@ -56,7 +56,7 @@ export class Update {
|
|
|
56
56
|
patch : patches,
|
|
57
57
|
targetHash : '',
|
|
58
58
|
targetVersionId : sourceVersionId + 1,
|
|
59
|
-
sourceHash :
|
|
59
|
+
sourceHash : canonicalHash(sourceDocument, { encoding: 'base64url' }),
|
|
60
60
|
};
|
|
61
61
|
|
|
62
62
|
// Apply all JSON patches to sourceDocument.
|
|
@@ -73,8 +73,8 @@ export class Update {
|
|
|
73
73
|
);
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
// Set the targetHash by canonicalizing the targetDocument and encoding it in
|
|
77
|
-
unsignedUpdate.targetHash =
|
|
76
|
+
// Set the targetHash by canonicalizing the targetDocument and encoding it in base64url.
|
|
77
|
+
unsignedUpdate.targetHash = canonicalHash(targetDocument, { encoding: 'base64url' });
|
|
78
78
|
|
|
79
79
|
// Return unsignedUpdate.
|
|
80
80
|
return unsignedUpdate;
|
|
@@ -140,7 +140,7 @@ export class Update {
|
|
|
140
140
|
beaconService: BeaconService,
|
|
141
141
|
update: SignedBTCR2Update,
|
|
142
142
|
secretKey: KeyBytes,
|
|
143
|
-
bitcoin:
|
|
143
|
+
bitcoin: BitcoinConnection
|
|
144
144
|
): Promise<SignedBTCR2Update> {
|
|
145
145
|
// Establish a beacon object
|
|
146
146
|
const beacon = BeaconFactory.establish(beaconService);
|
package/src/did-btcr2.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
2
|
import {
|
|
3
3
|
DocumentBytes,
|
|
4
4
|
HexString,
|
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
KeyBytes,
|
|
9
9
|
METHOD_NOT_SUPPORTED,
|
|
10
10
|
MethodError,
|
|
11
|
+
MISSING_RESOLUTION_OPTIONS,
|
|
11
12
|
MISSING_UPDATE_DATA,
|
|
12
13
|
PatchOperation,
|
|
13
14
|
ResolveError,
|
|
@@ -37,14 +38,13 @@ export type Btcr2Identifier = string;
|
|
|
37
38
|
|
|
38
39
|
export interface DidCreateOptions {
|
|
39
40
|
/** Type of identifier to create (key or external) */
|
|
40
|
-
idType:
|
|
41
|
+
idType: string;
|
|
41
42
|
/** DID BTCR2 Version Number */
|
|
42
43
|
version?: number;
|
|
43
44
|
/** Bitcoin Network */
|
|
44
45
|
network?: string;
|
|
45
46
|
}
|
|
46
47
|
|
|
47
|
-
// TODO: convert to API driver?
|
|
48
48
|
/** Initialize tiny secp256k1 */
|
|
49
49
|
initEccLib(tinysecp);
|
|
50
50
|
|
|
@@ -83,10 +83,7 @@ export class DidBtcr2 implements DidMethod {
|
|
|
83
83
|
* const did = DidBtcr2.create(genesisBytes, { idType: 'KEY', network: 'regtest' });
|
|
84
84
|
* ```
|
|
85
85
|
*/
|
|
86
|
-
static create(
|
|
87
|
-
genesisBytes: KeyBytes | DocumentBytes,
|
|
88
|
-
options?: DidCreateOptions
|
|
89
|
-
): Btcr2Identifier {
|
|
86
|
+
static create(genesisBytes: KeyBytes | DocumentBytes, options?: DidCreateOptions): Btcr2Identifier {
|
|
90
87
|
// Deconstruct the idType, version and network from the options, setting defaults if not given
|
|
91
88
|
const { idType, version = 1, network = 'bitcoin' } = options || {};
|
|
92
89
|
|
|
@@ -98,7 +95,7 @@ export class DidBtcr2 implements DidMethod {
|
|
|
98
95
|
}
|
|
99
96
|
|
|
100
97
|
// Call identifier encoding algorithm
|
|
101
|
-
return Identifier.encode({ idType,
|
|
98
|
+
return Identifier.encode(genesisBytes, { idType, version, network });
|
|
102
99
|
}
|
|
103
100
|
|
|
104
101
|
/**
|
|
@@ -172,12 +169,11 @@ export class DidBtcr2 implements DidMethod {
|
|
|
172
169
|
|
|
173
170
|
// Check if bitcoin driver provided
|
|
174
171
|
if(!resolutionOptions?.drivers?.bitcoin) {
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
resolutionOptions.drivers.bitcoin.setActiveNetwork(didComponents.network);
|
|
172
|
+
throw new ResolveError(
|
|
173
|
+
'Bitcoin connection required for resolve. Pass a configured driver via '
|
|
174
|
+
+ 'resolutionOptions.drivers.bitcoin or use DidBtcr2Api which injects it automatically.',
|
|
175
|
+
MISSING_RESOLUTION_OPTIONS, resolutionOptions
|
|
176
|
+
);
|
|
181
177
|
}
|
|
182
178
|
|
|
183
179
|
// Get the bitcoin driver from the resolution options
|
|
@@ -217,9 +213,8 @@ export class DidBtcr2 implements DidMethod {
|
|
|
217
213
|
// Return didResolutionResult;
|
|
218
214
|
return didResolutionResult;
|
|
219
215
|
} catch (error: any) {
|
|
220
|
-
console.error(error);
|
|
221
216
|
// Rethrow any unexpected errors that are not a `ResolveError`.
|
|
222
|
-
if (!(error instanceof ResolveError)) throw new Error(error);
|
|
217
|
+
if (!(error instanceof ResolveError)) throw new Error(error.message ?? error, { cause: error });
|
|
223
218
|
|
|
224
219
|
// Return a DID Resolution Result with the appropriate error code.
|
|
225
220
|
return {
|
|
@@ -247,7 +242,7 @@ export class DidBtcr2 implements DidMethod {
|
|
|
247
242
|
* @param {string} params.verificationMethodId The verificationMethod ID to sign the update with.
|
|
248
243
|
* @param {string} params.beaconId The beacon ID associated with the update.
|
|
249
244
|
* @param {KeyBytes | HexString} [params.signingMaterial] Optional signing material (key bytes or hex string).
|
|
250
|
-
* @param {
|
|
245
|
+
* @param {BitcoinConnection} [params.bitcoin] Optional Bitcoin network connection for announcing the update. If not provided, a default connection will be initialized.
|
|
251
246
|
* @return {Promise<SignedBTCR2Update>} Promise resolving to the signed BTCR2 update.
|
|
252
247
|
* @throws {UpdateError} if no verificationMethod, verificationMethod type is not `Multikey` or the publicKeyMultibase
|
|
253
248
|
* header is not `zQ3s`
|
|
@@ -267,9 +262,8 @@ export class DidBtcr2 implements DidMethod {
|
|
|
267
262
|
verificationMethodId: string;
|
|
268
263
|
beaconId: string;
|
|
269
264
|
signingMaterial?: KeyBytes | HexString;
|
|
270
|
-
bitcoin?:
|
|
265
|
+
bitcoin?: BitcoinConnection;
|
|
271
266
|
}): Promise<SignedBTCR2Update> {
|
|
272
|
-
// TODO: provide KMS as alternative
|
|
273
267
|
// If no signingMaterial provided, throw an UpdateError with INVALID_DID_UPDATE.
|
|
274
268
|
if (!signingMaterial) {
|
|
275
269
|
throw new UpdateError(
|
|
@@ -337,8 +331,14 @@ export class DidBtcr2 implements DidMethod {
|
|
|
337
331
|
INVALID_DID_UPDATE, {sourceDocument, beaconId}
|
|
338
332
|
);
|
|
339
333
|
}
|
|
340
|
-
//
|
|
341
|
-
|
|
334
|
+
// Require an explicit bitcoin connection — no silent env-var fallback
|
|
335
|
+
if (!bitcoin) {
|
|
336
|
+
throw new UpdateError(
|
|
337
|
+
'Bitcoin connection required for update. Pass a configured `bitcoin` parameter '
|
|
338
|
+
+ 'or use DidBtcr2Api which injects it automatically.',
|
|
339
|
+
INVALID_DID_UPDATE, { beaconId }
|
|
340
|
+
);
|
|
341
|
+
}
|
|
342
342
|
|
|
343
343
|
// Announce the signed update to the blockchain using the specified beacon(s)
|
|
344
344
|
await Update.announce(beaconService, signed, secretKey, bitcoin);
|
package/src/index.ts
CHANGED