@did-btcr2/method 0.27.0 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +38 -9
- package/dist/.tsbuildinfo +1 -1
- package/dist/browser.js +20181 -31588
- package/dist/browser.mjs +20110 -31517
- package/dist/cjs/index.js +1355 -422
- package/dist/esm/core/aggregation/beacon-strategy.js +62 -0
- package/dist/esm/core/aggregation/beacon-strategy.js.map +1 -0
- package/dist/esm/core/aggregation/cohort.js +31 -8
- package/dist/esm/core/aggregation/cohort.js.map +1 -1
- package/dist/esm/core/aggregation/logger.js +15 -0
- package/dist/esm/core/aggregation/logger.js.map +1 -0
- package/dist/esm/core/aggregation/messages/base.js +12 -1
- package/dist/esm/core/aggregation/messages/base.js.map +1 -1
- package/dist/esm/core/aggregation/messages/bodies.js +90 -0
- package/dist/esm/core/aggregation/messages/bodies.js.map +1 -0
- package/dist/esm/core/aggregation/messages/factories.js.map +1 -1
- package/dist/esm/core/aggregation/messages/index.js +1 -0
- package/dist/esm/core/aggregation/messages/index.js.map +1 -1
- package/dist/esm/core/aggregation/participant.js +39 -46
- package/dist/esm/core/aggregation/participant.js.map +1 -1
- package/dist/esm/core/aggregation/runner/participant-runner.js +34 -4
- package/dist/esm/core/aggregation/runner/participant-runner.js.map +1 -1
- package/dist/esm/core/aggregation/runner/service-runner.js +198 -19
- package/dist/esm/core/aggregation/runner/service-runner.js.map +1 -1
- package/dist/esm/core/aggregation/service.js +143 -15
- package/dist/esm/core/aggregation/service.js.map +1 -1
- package/dist/esm/core/aggregation/signing-session.js +44 -5
- package/dist/esm/core/aggregation/signing-session.js.map +1 -1
- package/dist/esm/core/aggregation/transport/didcomm.js +9 -0
- package/dist/esm/core/aggregation/transport/didcomm.js.map +1 -1
- package/dist/esm/core/aggregation/transport/nostr.js +245 -16
- package/dist/esm/core/aggregation/transport/nostr.js.map +1 -1
- package/dist/esm/core/beacon/beacon.js +147 -61
- package/dist/esm/core/beacon/beacon.js.map +1 -1
- package/dist/esm/core/beacon/utils.js +14 -9
- package/dist/esm/core/beacon/utils.js.map +1 -1
- package/dist/esm/core/updater.js +269 -0
- package/dist/esm/core/updater.js.map +1 -0
- package/dist/esm/did-btcr2.js +30 -46
- package/dist/esm/did-btcr2.js.map +1 -1
- package/dist/esm/index.js +4 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/utils/did-document.js +2 -2
- package/dist/esm/utils/did-document.js.map +1 -1
- package/dist/types/core/aggregation/beacon-strategy.d.ts +52 -0
- package/dist/types/core/aggregation/beacon-strategy.d.ts.map +1 -0
- package/dist/types/core/aggregation/cohort.d.ts +20 -3
- package/dist/types/core/aggregation/cohort.d.ts.map +1 -1
- package/dist/types/core/aggregation/logger.d.ts +22 -0
- package/dist/types/core/aggregation/logger.d.ts.map +1 -0
- package/dist/types/core/aggregation/messages/base.d.ts +13 -1
- package/dist/types/core/aggregation/messages/base.d.ts.map +1 -1
- package/dist/types/core/aggregation/messages/bodies.d.ts +130 -0
- package/dist/types/core/aggregation/messages/bodies.d.ts.map +1 -0
- package/dist/types/core/aggregation/messages/factories.d.ts +1 -0
- package/dist/types/core/aggregation/messages/factories.d.ts.map +1 -1
- package/dist/types/core/aggregation/messages/index.d.ts +1 -0
- package/dist/types/core/aggregation/messages/index.d.ts.map +1 -1
- package/dist/types/core/aggregation/participant.d.ts +2 -0
- package/dist/types/core/aggregation/participant.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/events.d.ts +32 -6
- package/dist/types/core/aggregation/runner/events.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/participant-runner.d.ts +8 -2
- package/dist/types/core/aggregation/runner/participant-runner.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/service-runner.d.ts +33 -3
- package/dist/types/core/aggregation/runner/service-runner.d.ts.map +1 -1
- package/dist/types/core/aggregation/service.d.ts +33 -2
- package/dist/types/core/aggregation/service.d.ts.map +1 -1
- package/dist/types/core/aggregation/signing-session.d.ts +5 -1
- package/dist/types/core/aggregation/signing-session.d.ts.map +1 -1
- package/dist/types/core/aggregation/transport/didcomm.d.ts +3 -0
- package/dist/types/core/aggregation/transport/didcomm.d.ts.map +1 -1
- package/dist/types/core/aggregation/transport/nostr.d.ts +99 -1
- package/dist/types/core/aggregation/transport/nostr.d.ts.map +1 -1
- package/dist/types/core/aggregation/transport/transport.d.ts +25 -0
- package/dist/types/core/aggregation/transport/transport.d.ts.map +1 -1
- package/dist/types/core/beacon/beacon.d.ts +85 -18
- package/dist/types/core/beacon/beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/utils.d.ts +2 -2
- package/dist/types/core/beacon/utils.d.ts.map +1 -1
- package/dist/types/core/updater.d.ts +178 -0
- package/dist/types/core/updater.d.ts.map +1 -0
- package/dist/types/did-btcr2.d.ts +23 -23
- package/dist/types/did-btcr2.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -1
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +4 -6
- package/src/core/aggregation/beacon-strategy.ts +123 -0
- package/src/core/aggregation/cohort.ts +34 -8
- package/src/core/aggregation/logger.ts +33 -0
- package/src/core/aggregation/messages/base.ts +20 -5
- package/src/core/aggregation/messages/bodies.ts +223 -0
- package/src/core/aggregation/messages/factories.ts +1 -0
- package/src/core/aggregation/messages/index.ts +1 -0
- package/src/core/aggregation/participant.ts +40 -46
- package/src/core/aggregation/runner/events.ts +27 -3
- package/src/core/aggregation/runner/participant-runner.ts +42 -4
- package/src/core/aggregation/runner/service-runner.ts +227 -19
- package/src/core/aggregation/service.ts +189 -20
- package/src/core/aggregation/signing-session.ts +65 -7
- package/src/core/aggregation/transport/didcomm.ts +17 -0
- package/src/core/aggregation/transport/nostr.ts +266 -23
- package/src/core/aggregation/transport/transport.ts +33 -0
- package/src/core/beacon/beacon.ts +217 -76
- package/src/core/beacon/utils.ts +16 -11
- package/src/core/updater.ts +415 -0
- package/src/did-btcr2.ts +36 -71
- package/src/index.ts +4 -1
- package/src/utils/did-document.ts +2 -2
- package/dist/esm/core/update.js +0 -112
- package/dist/esm/core/update.js.map +0 -1
- package/dist/types/core/update.d.ts +0 -52
- package/dist/types/core/update.d.ts.map +0 -1
- package/src/core/update.ts +0 -158
|
@@ -1,10 +1,82 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getPublicKey } from '@noble/secp256k1';
|
|
2
2
|
import { hexToBytes } from '@noble/hashes/utils';
|
|
3
|
-
import {
|
|
3
|
+
import { OP, p2tr, p2wpkh, Script, Transaction } from '@scure/btc-signer';
|
|
4
4
|
import { BeaconError } from './error.js';
|
|
5
5
|
import { StaticFeeEstimator } from './fee-estimator.js';
|
|
6
6
|
/** Default fee estimator used when none is supplied. ~5 sat/vB static rate. */
|
|
7
7
|
const DEFAULT_FEE_ESTIMATOR = new StaticFeeEstimator(5);
|
|
8
|
+
/**
|
|
9
|
+
* Conservative vsize estimate for a 1-input P2TR key-path → 1 P2TR change + 1 OP_RETURN(32) tx.
|
|
10
|
+
* Taproot key-path witness is a fixed 64-byte Schnorr signature, so vsize is predictable
|
|
11
|
+
* without having to sign. Used for fee estimation in the aggregation path where MuSig2
|
|
12
|
+
* signatures are produced externally.
|
|
13
|
+
*/
|
|
14
|
+
const P2TR_BEACON_TX_VSIZE = 140;
|
|
15
|
+
/**
|
|
16
|
+
* Build an OP_RETURN script carrying a 32-byte beacon signal.
|
|
17
|
+
* Exported as a utility so callers building txs outside Beacon (e.g., the aggregation
|
|
18
|
+
* `onProvideTxData` callback) can produce identical output.
|
|
19
|
+
*/
|
|
20
|
+
export function opReturnScript(signalBytes) {
|
|
21
|
+
return Script.encode([OP.RETURN, signalBytes]);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Fetch the most recent confirmed UTXO at `bitcoinAddress` + the raw bytes of its
|
|
25
|
+
* parent transaction (needed by PSBT inputs). Throws if unfunded.
|
|
26
|
+
*/
|
|
27
|
+
async function fetchSpendableUtxo(bitcoinAddress, bitcoin) {
|
|
28
|
+
const utxos = await bitcoin.rest.address.getUtxos(bitcoinAddress);
|
|
29
|
+
if (!utxos.length) {
|
|
30
|
+
throw new BeaconError('No UTXOs found, please fund address!', 'UNFUNDED_BEACON_ADDRESS', { bitcoinAddress });
|
|
31
|
+
}
|
|
32
|
+
const utxo = utxos.sort((a, b) => b.status.block_height - a.status.block_height).shift();
|
|
33
|
+
if (!utxo) {
|
|
34
|
+
throw new BeaconError('Beacon bitcoin address unfunded or utxos unconfirmed.', 'UNFUNDED_BEACON_ADDRESS', { bitcoinAddress });
|
|
35
|
+
}
|
|
36
|
+
const prevTxHex = await bitcoin.rest.transaction.getHex(utxo.txid);
|
|
37
|
+
return { utxo, prevTxBytes: hexToBytes(prevTxHex) };
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Build an aggregation beacon transaction (P2TR key-path spend) ready for MuSig2 signing.
|
|
41
|
+
* Returns the unsigned Transaction + prev-output metadata that an aggregation service's
|
|
42
|
+
* signing session consumes (via {@link SigningTxData}).
|
|
43
|
+
*
|
|
44
|
+
* This is the reusable counterpart to {@link Beacon.buildSignAndBroadcast}'s internal
|
|
45
|
+
* construction step — the aggregation path must produce an unsigned tx because the
|
|
46
|
+
* signature comes from a MuSig2 round, not a local secret key.
|
|
47
|
+
*
|
|
48
|
+
* @param opts Parameters including the cohort's aggregate internal pubkey.
|
|
49
|
+
* @returns A {@link BeaconTxPlan} with the unsigned tx and sighash inputs.
|
|
50
|
+
*/
|
|
51
|
+
export async function buildAggregationBeaconTx(opts) {
|
|
52
|
+
const feeEstimator = opts.feeEstimator ?? DEFAULT_FEE_ESTIMATOR;
|
|
53
|
+
const { utxo, prevTxBytes } = await fetchSpendableUtxo(opts.beaconAddress, opts.bitcoin);
|
|
54
|
+
const tapOut = p2tr(opts.internalPubkey, undefined, opts.network);
|
|
55
|
+
const witnessScript = tapOut.script;
|
|
56
|
+
// Fee cannot be probe-measured (no secret key for MuSig2 round). Use fixed P2TR vsize.
|
|
57
|
+
const feeSats = await feeEstimator.estimateFee(P2TR_BEACON_TX_VSIZE);
|
|
58
|
+
if (BigInt(utxo.value) <= feeSats) {
|
|
59
|
+
throw new BeaconError(`UTXO value (${utxo.value}) insufficient to cover fee (${feeSats}).`, 'INSUFFICIENT_FUNDS', { bitcoinAddress: opts.beaconAddress, utxoValue: utxo.value, fee: feeSats.toString() });
|
|
60
|
+
}
|
|
61
|
+
const tx = new Transaction();
|
|
62
|
+
tx.addInput({
|
|
63
|
+
txid: utxo.txid,
|
|
64
|
+
index: utxo.vout,
|
|
65
|
+
nonWitnessUtxo: prevTxBytes,
|
|
66
|
+
witnessUtxo: { amount: BigInt(utxo.value), script: witnessScript },
|
|
67
|
+
tapInternalKey: opts.internalPubkey,
|
|
68
|
+
});
|
|
69
|
+
tx.addOutputAddress(opts.beaconAddress, BigInt(utxo.value) - feeSats, opts.network);
|
|
70
|
+
tx.addOutput({ script: opReturnScript(opts.signalBytes), amount: 0n });
|
|
71
|
+
return {
|
|
72
|
+
tx,
|
|
73
|
+
prevOutScripts: [witnessScript],
|
|
74
|
+
prevOutValues: [BigInt(utxo.value)],
|
|
75
|
+
beaconAddress: opts.beaconAddress,
|
|
76
|
+
utxo,
|
|
77
|
+
feeSats,
|
|
78
|
+
};
|
|
79
|
+
}
|
|
8
80
|
/**
|
|
9
81
|
* Abstract base class for all BTCR2 Beacon types.
|
|
10
82
|
* A Beacon is a service listed in a BTCR2 DID document that informs resolvers
|
|
@@ -29,77 +101,91 @@ export class Beacon {
|
|
|
29
101
|
this.service = service;
|
|
30
102
|
}
|
|
31
103
|
/**
|
|
32
|
-
*
|
|
104
|
+
* Build + sign + broadcast a single-party beacon signal transaction (P2WPKH spend).
|
|
33
105
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* 5. Build a PSBT: input (UTXO) → change output + OP_RETURN(signalBytes).
|
|
40
|
-
* 6. Compute the fee via the supplied (or default) {@link FeeEstimator} against the tx vsize.
|
|
41
|
-
* 7. Sign input 0 with an ECDSA signer derived from `secretKey`.
|
|
42
|
-
* 8. Finalize, extract, and broadcast via the REST transaction endpoint.
|
|
43
|
-
*
|
|
44
|
-
* Fee handling: the PSBT is constructed with a placeholder change amount, signed to measure
|
|
45
|
-
* vsize, then the change is adjusted to pay the actual fee and the input re-signed. This
|
|
46
|
-
* two-pass approach avoids hardcoded fee constants and produces a tx that matches the
|
|
47
|
-
* estimator's rate.
|
|
106
|
+
* Composed from the three extracted phases ({@link buildSinglePartyTx},
|
|
107
|
+
* {@link signSinglePartyTx}, {@link broadcastRawTx}) so each piece can be exercised
|
|
108
|
+
* in isolation. Aggregation beacons use {@link buildAggregationBeaconTx} instead —
|
|
109
|
+
* the multi-party path can't share the signing phase, but the tx-construction
|
|
110
|
+
* plumbing (UTXO fetch + OP_RETURN output + change output) is shared.
|
|
48
111
|
*
|
|
49
112
|
* @param signalBytes 32-byte payload to embed in OP_RETURN.
|
|
50
113
|
* @param secretKey Secret key used to sign the spending input.
|
|
51
114
|
* @param bitcoin Bitcoin network connection.
|
|
52
115
|
* @param options Broadcast options (fee estimator, etc.).
|
|
53
116
|
* @returns The txid of the broadcast transaction.
|
|
54
|
-
* @throws {BeaconError} if the address is unfunded
|
|
117
|
+
* @throws {BeaconError} if the address is unfunded, no UTXO is available, or fee exceeds value.
|
|
55
118
|
*/
|
|
56
119
|
async buildSignAndBroadcast(signalBytes, secretKey, bitcoin, options) {
|
|
57
120
|
const feeEstimator = options?.feeEstimator ?? DEFAULT_FEE_ESTIMATOR;
|
|
58
|
-
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
const
|
|
75
|
-
|
|
76
|
-
|
|
121
|
+
const beaconAddress = this.service.serviceEndpoint.replace('bitcoin:', '');
|
|
122
|
+
const { utxo, prevTxBytes } = await fetchSpendableUtxo(beaconAddress, bitcoin);
|
|
123
|
+
const plan = await this.buildSinglePartyTx({
|
|
124
|
+
signalBytes, beaconAddress, utxo, prevTxBytes, secretKey, bitcoin, feeEstimator,
|
|
125
|
+
});
|
|
126
|
+
const signedHex = this.signSinglePartyTx(plan.tx, secretKey);
|
|
127
|
+
return this.broadcastRawTx(bitcoin, signedHex);
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Build an unsigned P2WPKH single-party beacon tx + probe-sign to determine vsize,
|
|
131
|
+
* then rebuild with the real fee. Returns the tx and prev-output metadata.
|
|
132
|
+
*
|
|
133
|
+
* The secret key is required here (not just in `signSinglePartyTx`) because the
|
|
134
|
+
* two-pass fee estimation requires an actual signature to measure vsize accurately.
|
|
135
|
+
*/
|
|
136
|
+
async buildSinglePartyTx(opts) {
|
|
137
|
+
const pubkey = this.#derivePubkey(opts.secretKey);
|
|
138
|
+
const witnessOut = p2wpkh(pubkey, opts.bitcoin.data);
|
|
139
|
+
const witnessScript = witnessOut.script;
|
|
140
|
+
const build = (feeSats) => {
|
|
141
|
+
const tx = new Transaction();
|
|
142
|
+
tx.addInput({
|
|
143
|
+
txid: opts.utxo.txid,
|
|
144
|
+
index: opts.utxo.vout,
|
|
145
|
+
nonWitnessUtxo: opts.prevTxBytes,
|
|
146
|
+
witnessUtxo: { amount: BigInt(opts.utxo.value), script: witnessScript },
|
|
147
|
+
});
|
|
148
|
+
tx.addOutputAddress(opts.beaconAddress, BigInt(opts.utxo.value) - feeSats, opts.bitcoin.data);
|
|
149
|
+
tx.addOutput({ script: opReturnScript(opts.signalBytes), amount: 0n });
|
|
150
|
+
return tx;
|
|
77
151
|
};
|
|
78
|
-
// First pass:
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
.
|
|
86
|
-
.addOutput({ script: script.compile([opcodes.OP_RETURN, signalBytes]), value: 0n });
|
|
87
|
-
const probeTx = build(0n)
|
|
88
|
-
.signInput(0, signer)
|
|
89
|
-
.finalizeAllInputs()
|
|
90
|
-
.extractTransaction();
|
|
91
|
-
const vsize = probeTx.virtualSize();
|
|
92
|
-
// Second pass: use the estimator to compute the real fee.
|
|
93
|
-
const fee = await feeEstimator.estimateFee(vsize);
|
|
94
|
-
if (BigInt(utxo.value) <= fee) {
|
|
95
|
-
throw new BeaconError(`UTXO value (${utxo.value}) insufficient to cover fee (${fee}).`, 'INSUFFICIENT_FUNDS', { bitcoinAddress, utxoValue: utxo.value, fee: fee.toString() });
|
|
152
|
+
// First pass: sign with zero fee to measure vsize.
|
|
153
|
+
const probe = build(0n);
|
|
154
|
+
probe.signIdx(opts.secretKey, 0);
|
|
155
|
+
probe.finalize();
|
|
156
|
+
const vsize = probe.vsize;
|
|
157
|
+
const feeSats = await opts.feeEstimator.estimateFee(vsize);
|
|
158
|
+
if (BigInt(opts.utxo.value) <= feeSats) {
|
|
159
|
+
throw new BeaconError(`UTXO value (${opts.utxo.value}) insufficient to cover fee (${feeSats}).`, 'INSUFFICIENT_FUNDS', { bitcoinAddress: opts.beaconAddress, utxoValue: opts.utxo.value, fee: feeSats.toString() });
|
|
96
160
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
161
|
+
// Second pass: real fee.
|
|
162
|
+
const tx = build(feeSats);
|
|
163
|
+
return {
|
|
164
|
+
tx,
|
|
165
|
+
prevOutScripts: [witnessScript],
|
|
166
|
+
prevOutValues: [BigInt(opts.utxo.value)],
|
|
167
|
+
beaconAddress: opts.beaconAddress,
|
|
168
|
+
utxo: opts.utxo,
|
|
169
|
+
feeSats,
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Sign + finalize the unsigned single-party tx and return its raw hex.
|
|
174
|
+
*/
|
|
175
|
+
signSinglePartyTx(tx, secretKey) {
|
|
176
|
+
tx.signIdx(secretKey, 0);
|
|
177
|
+
tx.finalize();
|
|
178
|
+
return tx.hex;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Broadcast raw transaction hex via the Bitcoin REST endpoint. Returns the txid.
|
|
182
|
+
*/
|
|
183
|
+
async broadcastRawTx(bitcoin, rawHex) {
|
|
184
|
+
return bitcoin.rest.transaction.send(rawHex);
|
|
185
|
+
}
|
|
186
|
+
/** Derive the compressed secp256k1 public key from a raw secret key. */
|
|
187
|
+
#derivePubkey(secretKey) {
|
|
188
|
+
return getPublicKey(secretKey, true);
|
|
103
189
|
}
|
|
104
190
|
}
|
|
105
191
|
//# sourceMappingURL=beacon.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"beacon.js","sourceRoot":"","sources":["../../../../src/core/beacon/beacon.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"beacon.js","sourceRoot":"","sources":["../../../../src/core/beacon/beacon.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getNetwork } from '@did-btcr2/bitcoin';
|
|
2
2
|
import { DidMethodError, MethodError } from '@did-btcr2/common';
|
|
3
|
-
import {
|
|
3
|
+
import { p2pkh, p2tr, p2wpkh } from '@scure/btc-signer';
|
|
4
4
|
import { Appendix } from '../../utils/appendix.js';
|
|
5
5
|
import { Identifier } from '../identifier.js';
|
|
6
6
|
import { BeaconError } from './error.js';
|
|
@@ -86,7 +86,12 @@ export class BeaconUtils {
|
|
|
86
86
|
// Build the id
|
|
87
87
|
const id = `${did}#initial${addressType.toUpperCase()}`;
|
|
88
88
|
// Generate the bitcoin address
|
|
89
|
-
const
|
|
89
|
+
const address = addressType === 'p2tr'
|
|
90
|
+
? p2tr(pubkey.slice(1, 33), undefined, network).address
|
|
91
|
+
: addressType === 'p2wpkh'
|
|
92
|
+
? p2wpkh(pubkey, network).address
|
|
93
|
+
: p2pkh(pubkey, network).address;
|
|
94
|
+
const serviceEndpoint = `bitcoin:${address}`;
|
|
90
95
|
// Return the beacon serviceD
|
|
91
96
|
return { id, type: beaconType, serviceEndpoint, };
|
|
92
97
|
}
|
|
@@ -103,11 +108,11 @@ export class BeaconUtils {
|
|
|
103
108
|
static generateBeaconServices({ id, publicKey, network, beaconType }) {
|
|
104
109
|
try {
|
|
105
110
|
// Generate the bitcoin addresses for the given public key and network
|
|
106
|
-
const
|
|
107
|
-
const
|
|
108
|
-
const
|
|
111
|
+
const p2pkhAddr = p2pkh(publicKey, network).address;
|
|
112
|
+
const p2wpkhAddr = p2wpkh(publicKey, network).address;
|
|
113
|
+
const p2trAddr = p2tr(publicKey.slice(1, 33), undefined, network).address;
|
|
109
114
|
// Check that all addresses were generated successfully
|
|
110
|
-
if (!
|
|
115
|
+
if (!p2pkhAddr || !p2wpkhAddr || !p2trAddr) {
|
|
111
116
|
throw new DidMethodError('Failed to generate bitcoin addresses');
|
|
112
117
|
}
|
|
113
118
|
// Return the beacon services with the generated addresses as service endpoints
|
|
@@ -115,17 +120,17 @@ export class BeaconUtils {
|
|
|
115
120
|
{
|
|
116
121
|
id: `${id}#initialP2PKH`,
|
|
117
122
|
type: beaconType,
|
|
118
|
-
serviceEndpoint: `bitcoin:${
|
|
123
|
+
serviceEndpoint: `bitcoin:${p2pkhAddr}`
|
|
119
124
|
},
|
|
120
125
|
{
|
|
121
126
|
id: `${id}#initialP2WPKH`,
|
|
122
127
|
type: beaconType,
|
|
123
|
-
serviceEndpoint: `bitcoin:${
|
|
128
|
+
serviceEndpoint: `bitcoin:${p2wpkhAddr}`
|
|
124
129
|
},
|
|
125
130
|
{
|
|
126
131
|
id: `${id}#initialP2TR`,
|
|
127
132
|
type: beaconType,
|
|
128
|
-
serviceEndpoint: `bitcoin:${
|
|
133
|
+
serviceEndpoint: `bitcoin:${p2trAddr}`
|
|
129
134
|
},
|
|
130
135
|
];
|
|
131
136
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/core/beacon/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../src/core/beacon/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
var _a;
|
|
2
|
+
import { canonicalHash, INVALID_DID_UPDATE, JSONPatch, UpdateError } from '@did-btcr2/common';
|
|
3
|
+
import { SchnorrMultikey } from '@did-btcr2/cryptosuite';
|
|
4
|
+
import { DidDocument } from '../utils/did-document.js';
|
|
5
|
+
import { BeaconFactory } from './beacon/factory.js';
|
|
6
|
+
/**
|
|
7
|
+
* Internal phases of the Updater state machine.
|
|
8
|
+
* @internal
|
|
9
|
+
*/
|
|
10
|
+
var UpdaterPhase;
|
|
11
|
+
(function (UpdaterPhase) {
|
|
12
|
+
UpdaterPhase["Construct"] = "Construct";
|
|
13
|
+
UpdaterPhase["Sign"] = "Sign";
|
|
14
|
+
UpdaterPhase["Fund"] = "Fund";
|
|
15
|
+
UpdaterPhase["Broadcast"] = "Broadcast";
|
|
16
|
+
UpdaterPhase["Complete"] = "Complete";
|
|
17
|
+
})(UpdaterPhase || (UpdaterPhase = {}));
|
|
18
|
+
/**
|
|
19
|
+
* Sans-I/O state machine for did:btcr2 updates — the counterpart to {@link Resolver}.
|
|
20
|
+
*
|
|
21
|
+
* Created by {@link DidBtcr2.update} (the factory). The caller drives the update by
|
|
22
|
+
* repeatedly calling {@link advance} and {@link provide}:
|
|
23
|
+
*
|
|
24
|
+
* ```typescript
|
|
25
|
+
* const updater = DidBtcr2.update({ sourceDocument, patches, ... });
|
|
26
|
+
* let state = updater.advance();
|
|
27
|
+
*
|
|
28
|
+
* while(state.status === 'action-required') {
|
|
29
|
+
* for(const need of state.needs) {
|
|
30
|
+
* switch(need.kind) {
|
|
31
|
+
* case 'NeedSigningKey':
|
|
32
|
+
* updater.provide(need, secretKeyBytes);
|
|
33
|
+
* break;
|
|
34
|
+
* case 'NeedFunding':
|
|
35
|
+
* // Check UTXOs at need.beaconAddress, fund if needed
|
|
36
|
+
* updater.provide(need);
|
|
37
|
+
* break;
|
|
38
|
+
* case 'NeedBroadcast':
|
|
39
|
+
* await Updater.announce(need.beaconService, need.signedUpdate, secretKey, bitcoin);
|
|
40
|
+
* updater.provide(need);
|
|
41
|
+
* break;
|
|
42
|
+
* }
|
|
43
|
+
* }
|
|
44
|
+
* state = updater.advance();
|
|
45
|
+
* }
|
|
46
|
+
*
|
|
47
|
+
* const { signedUpdate } = state.result;
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* The Updater performs **zero I/O**. All external work (signing with a KMS or raw
|
|
51
|
+
* key, funding checks, Bitcoin transaction construction, broadcast) flows through
|
|
52
|
+
* the advance/provide protocol. This mirrors the {@link Resolver} pattern and makes
|
|
53
|
+
* the update path transport-agnostic and KMS-ready.
|
|
54
|
+
*
|
|
55
|
+
* The class also exposes static utility methods ({@link construct}, {@link sign},
|
|
56
|
+
* {@link announce}) for callers that need direct access to individual update steps
|
|
57
|
+
* outside the state machine (e.g., test vector generation scripts).
|
|
58
|
+
*
|
|
59
|
+
* @class Updater
|
|
60
|
+
*/
|
|
61
|
+
export class Updater {
|
|
62
|
+
#phase = UpdaterPhase.Construct;
|
|
63
|
+
#sourceDocument;
|
|
64
|
+
#patches;
|
|
65
|
+
#sourceVersionId;
|
|
66
|
+
#verificationMethod;
|
|
67
|
+
#beaconService;
|
|
68
|
+
#unsignedUpdate = null;
|
|
69
|
+
#signedUpdate = null;
|
|
70
|
+
/**
|
|
71
|
+
* @internal — Use {@link DidBtcr2.update} to create instances.
|
|
72
|
+
*/
|
|
73
|
+
constructor(params) {
|
|
74
|
+
this.#sourceDocument = params.sourceDocument;
|
|
75
|
+
this.#patches = params.patches;
|
|
76
|
+
this.#sourceVersionId = params.sourceVersionId;
|
|
77
|
+
this.#verificationMethod = params.verificationMethod;
|
|
78
|
+
this.#beaconService = params.beaconService;
|
|
79
|
+
}
|
|
80
|
+
// ─── Public static utility methods ─────────────────────────────────────────
|
|
81
|
+
// Used by generate-vector.ts and other scripts that need direct access to
|
|
82
|
+
// individual update steps outside the state machine flow.
|
|
83
|
+
/**
|
|
84
|
+
* Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/update.html#construct-btcr2-unsigned-update | 7.3.b Construct BTCR2 Unsigned Update}.
|
|
85
|
+
*
|
|
86
|
+
* @param {Btcr2DidDocument} sourceDocument The source DID document to be updated.
|
|
87
|
+
* @param {PatchOperation[]} patches The JSON Patch operations to apply.
|
|
88
|
+
* @param {number} sourceVersionId The version ID of the source document.
|
|
89
|
+
* @returns {UnsignedBTCR2Update} The constructed UnsignedBTCR2Update object.
|
|
90
|
+
* @throws {UpdateError} If the target document fails DID Core validation.
|
|
91
|
+
*/
|
|
92
|
+
static construct(sourceDocument, patches, sourceVersionId) {
|
|
93
|
+
const unsignedUpdate = {
|
|
94
|
+
'@context': [
|
|
95
|
+
'https://w3id.org/security/v2',
|
|
96
|
+
'https://w3id.org/zcap/v1',
|
|
97
|
+
'https://w3id.org/json-ld-patch/v1',
|
|
98
|
+
'https://btcr2.dev/context/v1'
|
|
99
|
+
],
|
|
100
|
+
patch: patches,
|
|
101
|
+
targetHash: '',
|
|
102
|
+
targetVersionId: sourceVersionId + 1,
|
|
103
|
+
sourceHash: canonicalHash(sourceDocument),
|
|
104
|
+
};
|
|
105
|
+
const targetDocument = JSONPatch.apply(sourceDocument, patches);
|
|
106
|
+
try {
|
|
107
|
+
DidDocument.isValid(targetDocument);
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
throw new UpdateError('Error validating targetDocument: ' + (error instanceof Error ? error.message : String(error)), INVALID_DID_UPDATE, targetDocument);
|
|
111
|
+
}
|
|
112
|
+
unsignedUpdate.targetHash = canonicalHash(targetDocument);
|
|
113
|
+
return unsignedUpdate;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Implements subsection {@link http://dcdpr.github.io/did-btcr2/operations/update.html#construct-btcr2-signed-update | 7.3.c Construct BTCR2 Signed Update }.
|
|
117
|
+
*
|
|
118
|
+
* @param {string} did The did-btcr2 identifier to derive the root capability from.
|
|
119
|
+
* @param {UnsignedBTCR2Update} unsignedUpdate The unsigned update to sign.
|
|
120
|
+
* @param {DidVerificationMethod} verificationMethod The verification method for signing.
|
|
121
|
+
* @param {KeyBytes} secretKey The secret key bytes.
|
|
122
|
+
* @returns {SignedBTCR2Update} The signed update with a Data Integrity proof.
|
|
123
|
+
*/
|
|
124
|
+
static sign(did, unsignedUpdate, verificationMethod, secretKey) {
|
|
125
|
+
const controller = verificationMethod.controller;
|
|
126
|
+
const id = verificationMethod.id.slice(verificationMethod.id.indexOf('#'));
|
|
127
|
+
const multikey = SchnorrMultikey.fromSecretKey(id, controller, secretKey);
|
|
128
|
+
const config = {
|
|
129
|
+
'@context': [
|
|
130
|
+
'https://w3id.org/security/v2',
|
|
131
|
+
'https://w3id.org/zcap/v1',
|
|
132
|
+
'https://w3id.org/json-ld-patch/v1',
|
|
133
|
+
'https://btcr2.dev/context/v1'
|
|
134
|
+
],
|
|
135
|
+
cryptosuite: 'bip340-jcs-2025',
|
|
136
|
+
type: 'DataIntegrityProof',
|
|
137
|
+
verificationMethod: verificationMethod.id,
|
|
138
|
+
proofPurpose: 'capabilityInvocation',
|
|
139
|
+
capability: `urn:zcap:root:${encodeURIComponent(did)}`,
|
|
140
|
+
capabilityAction: 'Write',
|
|
141
|
+
};
|
|
142
|
+
const diproof = multikey.toCryptosuite().toDataIntegrityProof();
|
|
143
|
+
return diproof.addProof(unsignedUpdate, config);
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/update.html#announce-did-update | 7.3.d Announce DID Update}.
|
|
147
|
+
* Announces a signed update to the Bitcoin blockchain via the specified beacon.
|
|
148
|
+
*
|
|
149
|
+
* @param {BeaconService} beaconService The beacon service to broadcast through.
|
|
150
|
+
* @param {SignedBTCR2Update} update The signed update to announce.
|
|
151
|
+
* @param {KeyBytes} secretKey The secret key for signing the Bitcoin transaction.
|
|
152
|
+
* @param {BitcoinConnection} bitcoin The Bitcoin network connection.
|
|
153
|
+
* @returns {Promise<SignedBTCR2Update>} The signed update that was broadcast.
|
|
154
|
+
*/
|
|
155
|
+
static async announce(beaconService, update, secretKey, bitcoin) {
|
|
156
|
+
const beacon = BeaconFactory.establish(beaconService);
|
|
157
|
+
return beacon.broadcastSignal(update, secretKey, bitcoin);
|
|
158
|
+
}
|
|
159
|
+
// ─── Private instance wrappers ─────────────────────────────────────────────
|
|
160
|
+
// Delegate to the public statics with bound instance fields for cleaner
|
|
161
|
+
// advance/provide code.
|
|
162
|
+
#construct() {
|
|
163
|
+
return _a.construct(this.#sourceDocument, this.#patches, this.#sourceVersionId);
|
|
164
|
+
}
|
|
165
|
+
#sign(secretKey) {
|
|
166
|
+
return _a.sign(this.#sourceDocument.id, this.#unsignedUpdate, this.#verificationMethod, secretKey);
|
|
167
|
+
}
|
|
168
|
+
// ─── State machine ─────────────────────────────────────────────────────────
|
|
169
|
+
/**
|
|
170
|
+
* Advance the state machine. Returns either:
|
|
171
|
+
* - `{ status: 'action-required', needs }` — caller must provide data via {@link provide}
|
|
172
|
+
* - `{ status: 'complete', result }` — update is signed and broadcast
|
|
173
|
+
*/
|
|
174
|
+
advance() {
|
|
175
|
+
while (true) {
|
|
176
|
+
switch (this.#phase) {
|
|
177
|
+
// Phase: Construct
|
|
178
|
+
// Build the unsigned update from source doc + patches. Pure, synchronous.
|
|
179
|
+
case UpdaterPhase.Construct: {
|
|
180
|
+
this.#unsignedUpdate = this.#construct();
|
|
181
|
+
this.#phase = UpdaterPhase.Sign;
|
|
182
|
+
continue;
|
|
183
|
+
}
|
|
184
|
+
// Phase: Sign
|
|
185
|
+
// Emit NeedSigningKey — the caller supplies the secret key (or a KMS signature).
|
|
186
|
+
case UpdaterPhase.Sign: {
|
|
187
|
+
return {
|
|
188
|
+
status: 'action-required',
|
|
189
|
+
needs: [{
|
|
190
|
+
kind: 'NeedSigningKey',
|
|
191
|
+
verificationMethodId: this.#verificationMethod.id,
|
|
192
|
+
unsignedUpdate: this.#unsignedUpdate,
|
|
193
|
+
}],
|
|
194
|
+
};
|
|
195
|
+
}
|
|
196
|
+
// Phase: Fund
|
|
197
|
+
// Emit NeedFunding with the beacon address. The caller checks UTXOs,
|
|
198
|
+
// funds the address if needed, and provides to continue.
|
|
199
|
+
case UpdaterPhase.Fund: {
|
|
200
|
+
const beaconAddress = this.#beaconService.serviceEndpoint.replace('bitcoin:', '');
|
|
201
|
+
return {
|
|
202
|
+
status: 'action-required',
|
|
203
|
+
needs: [{
|
|
204
|
+
kind: 'NeedFunding',
|
|
205
|
+
beaconAddress,
|
|
206
|
+
beaconService: this.#beaconService,
|
|
207
|
+
}],
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
// Phase: Broadcast
|
|
211
|
+
// Emit NeedBroadcast with the signed update + beacon service. The caller performs
|
|
212
|
+
// the actual on-chain announcement (or hands off to the aggregation protocol).
|
|
213
|
+
case UpdaterPhase.Broadcast: {
|
|
214
|
+
return {
|
|
215
|
+
status: 'action-required',
|
|
216
|
+
needs: [{
|
|
217
|
+
kind: 'NeedBroadcast',
|
|
218
|
+
beaconService: this.#beaconService,
|
|
219
|
+
signedUpdate: this.#signedUpdate,
|
|
220
|
+
}],
|
|
221
|
+
};
|
|
222
|
+
}
|
|
223
|
+
// Phase: Complete
|
|
224
|
+
case UpdaterPhase.Complete: {
|
|
225
|
+
return {
|
|
226
|
+
status: 'complete',
|
|
227
|
+
result: { signedUpdate: this.#signedUpdate },
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
provide(need, data) {
|
|
234
|
+
switch (need.kind) {
|
|
235
|
+
case 'NeedSigningKey': {
|
|
236
|
+
if (this.#phase !== UpdaterPhase.Sign) {
|
|
237
|
+
throw new UpdateError(`Cannot provide NeedSigningKey: updater phase is ${this.#phase}, expected Sign.`, INVALID_DID_UPDATE, { phase: this.#phase });
|
|
238
|
+
}
|
|
239
|
+
if (!data) {
|
|
240
|
+
throw new UpdateError('NeedSigningKey requires secret key bytes.', INVALID_DID_UPDATE);
|
|
241
|
+
}
|
|
242
|
+
if (!this.#unsignedUpdate) {
|
|
243
|
+
throw new UpdateError('Internal error: unsigned update missing in Sign phase.', INVALID_DID_UPDATE);
|
|
244
|
+
}
|
|
245
|
+
this.#signedUpdate = this.#sign(data);
|
|
246
|
+
this.#phase = UpdaterPhase.Fund;
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
case 'NeedFunding': {
|
|
250
|
+
if (this.#phase !== UpdaterPhase.Fund) {
|
|
251
|
+
throw new UpdateError(`Cannot provide NeedFunding: updater phase is ${this.#phase}, expected Fund.`, INVALID_DID_UPDATE, { phase: this.#phase });
|
|
252
|
+
}
|
|
253
|
+
// Caller has confirmed funding (or it was already funded). Continue.
|
|
254
|
+
this.#phase = UpdaterPhase.Broadcast;
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
case 'NeedBroadcast': {
|
|
258
|
+
if (this.#phase !== UpdaterPhase.Broadcast) {
|
|
259
|
+
throw new UpdateError(`Cannot provide NeedBroadcast: updater phase is ${this.#phase}, expected Broadcast.`, INVALID_DID_UPDATE, { phase: this.#phase });
|
|
260
|
+
}
|
|
261
|
+
// Caller has broadcast externally. Transition to Complete.
|
|
262
|
+
this.#phase = UpdaterPhase.Complete;
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
_a = Updater;
|
|
269
|
+
//# sourceMappingURL=updater.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updater.js","sourceRoot":"","sources":["../../../src/core/updater.ts"],"names":[],"mappings":"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"}
|