@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,17 +1,68 @@
|
|
|
1
|
-
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
1
|
+
import type { AddressUtxo, BitcoinConnection, BTCNetwork } from '@did-btcr2/bitcoin';
|
|
2
2
|
import type { KeyBytes } from '@did-btcr2/common';
|
|
3
3
|
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
4
|
+
import { Transaction } from '@scure/btc-signer';
|
|
4
5
|
import type { BeaconProcessResult } from '../resolver.js';
|
|
5
6
|
import type { SidecarData } from '../types.js';
|
|
6
7
|
import type { FeeEstimator } from './fee-estimator.js';
|
|
7
8
|
import type { BeaconService, BeaconSignal } from './interfaces.js';
|
|
8
9
|
/**
|
|
9
|
-
* Options accepted by {@link Beacon.buildSignAndBroadcast}.
|
|
10
|
+
* Options accepted by {@link Beacon.buildSignAndBroadcast} and related helpers.
|
|
10
11
|
*/
|
|
11
12
|
export interface BroadcastOptions {
|
|
12
13
|
/** Fee estimator for computing the transaction fee. Defaults to {@link DEFAULT_FEE_ESTIMATOR}. */
|
|
13
14
|
feeEstimator?: FeeEstimator;
|
|
14
15
|
}
|
|
16
|
+
/**
|
|
17
|
+
* Unsigned beacon transaction + the prev-output metadata needed for downstream
|
|
18
|
+
* signing (single-party ECDSA or multi-party MuSig2 Taproot).
|
|
19
|
+
*/
|
|
20
|
+
export interface BeaconTxPlan {
|
|
21
|
+
/** The unsigned scure @scure/btc-signer Transaction. */
|
|
22
|
+
tx: Transaction;
|
|
23
|
+
/** Scripts of the consumed previous outputs (needed for Taproot sighash). */
|
|
24
|
+
prevOutScripts: Uint8Array[];
|
|
25
|
+
/** Amounts (sats) of the consumed previous outputs. */
|
|
26
|
+
prevOutValues: bigint[];
|
|
27
|
+
/** Address change was sent back to (same as the beacon address). */
|
|
28
|
+
beaconAddress: string;
|
|
29
|
+
/** The UTXO this tx consumes. */
|
|
30
|
+
utxo: AddressUtxo;
|
|
31
|
+
/** The fee (sats) already deducted from the change output. */
|
|
32
|
+
feeSats: bigint;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Build an OP_RETURN script carrying a 32-byte beacon signal.
|
|
36
|
+
* Exported as a utility so callers building txs outside Beacon (e.g., the aggregation
|
|
37
|
+
* `onProvideTxData` callback) can produce identical output.
|
|
38
|
+
*/
|
|
39
|
+
export declare function opReturnScript(signalBytes: Uint8Array): Uint8Array;
|
|
40
|
+
/**
|
|
41
|
+
* Build an aggregation beacon transaction (P2TR key-path spend) ready for MuSig2 signing.
|
|
42
|
+
* Returns the unsigned Transaction + prev-output metadata that an aggregation service's
|
|
43
|
+
* signing session consumes (via {@link SigningTxData}).
|
|
44
|
+
*
|
|
45
|
+
* This is the reusable counterpart to {@link Beacon.buildSignAndBroadcast}'s internal
|
|
46
|
+
* construction step — the aggregation path must produce an unsigned tx because the
|
|
47
|
+
* signature comes from a MuSig2 round, not a local secret key.
|
|
48
|
+
*
|
|
49
|
+
* @param opts Parameters including the cohort's aggregate internal pubkey.
|
|
50
|
+
* @returns A {@link BeaconTxPlan} with the unsigned tx and sighash inputs.
|
|
51
|
+
*/
|
|
52
|
+
export declare function buildAggregationBeaconTx(opts: {
|
|
53
|
+
/** The beacon (cohort) address where UTXOs live and change returns to. */
|
|
54
|
+
beaconAddress: string;
|
|
55
|
+
/** The cohort's MuSig2-aggregated x-only internal pubkey (32 bytes). */
|
|
56
|
+
internalPubkey: Uint8Array;
|
|
57
|
+
/** 32-byte beacon signal embedded in the OP_RETURN output. */
|
|
58
|
+
signalBytes: Uint8Array;
|
|
59
|
+
/** Bitcoin REST connection for UTXO / prev-tx lookup. */
|
|
60
|
+
bitcoin: BitcoinConnection;
|
|
61
|
+
/** Network params used to derive the P2TR witnessUtxo script. */
|
|
62
|
+
network: BTCNetwork;
|
|
63
|
+
/** Optional fee estimator (defaults to 5 sat/vB). */
|
|
64
|
+
feeEstimator?: FeeEstimator;
|
|
65
|
+
}): Promise<BeaconTxPlan>;
|
|
15
66
|
/**
|
|
16
67
|
* Abstract base class for all BTCR2 Beacon types.
|
|
17
68
|
* A Beacon is a service listed in a BTCR2 DID document that informs resolvers
|
|
@@ -28,6 +79,7 @@ export interface BroadcastOptions {
|
|
|
28
79
|
* @type {Beacon}
|
|
29
80
|
*/
|
|
30
81
|
export declare abstract class Beacon {
|
|
82
|
+
#private;
|
|
31
83
|
/**
|
|
32
84
|
* The Beacon service configuration parsed from the DID Document.
|
|
33
85
|
*/
|
|
@@ -56,30 +108,45 @@ export declare abstract class Beacon {
|
|
|
56
108
|
*/
|
|
57
109
|
abstract broadcastSignal(signedUpdate: SignedBTCR2Update, secretKey: KeyBytes, bitcoin: BitcoinConnection, options?: BroadcastOptions): Promise<SignedBTCR2Update>;
|
|
58
110
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* Steps:
|
|
62
|
-
* 1. Parse the beacon's `serviceEndpoint` (stripping `bitcoin:` prefix) into a Bitcoin address.
|
|
63
|
-
* 2. Query the address for unconfirmed/confirmed UTXOs.
|
|
64
|
-
* 3. Select the most recent confirmed UTXO.
|
|
65
|
-
* 4. Fetch the previous transaction hex for `nonWitnessUtxo`.
|
|
66
|
-
* 5. Build a PSBT: input (UTXO) → change output + OP_RETURN(signalBytes).
|
|
67
|
-
* 6. Compute the fee via the supplied (or default) {@link FeeEstimator} against the tx vsize.
|
|
68
|
-
* 7. Sign input 0 with an ECDSA signer derived from `secretKey`.
|
|
69
|
-
* 8. Finalize, extract, and broadcast via the REST transaction endpoint.
|
|
111
|
+
* Build + sign + broadcast a single-party beacon signal transaction (P2WPKH spend).
|
|
70
112
|
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
*
|
|
113
|
+
* Composed from the three extracted phases ({@link buildSinglePartyTx},
|
|
114
|
+
* {@link signSinglePartyTx}, {@link broadcastRawTx}) so each piece can be exercised
|
|
115
|
+
* in isolation. Aggregation beacons use {@link buildAggregationBeaconTx} instead —
|
|
116
|
+
* the multi-party path can't share the signing phase, but the tx-construction
|
|
117
|
+
* plumbing (UTXO fetch + OP_RETURN output + change output) is shared.
|
|
75
118
|
*
|
|
76
119
|
* @param signalBytes 32-byte payload to embed in OP_RETURN.
|
|
77
120
|
* @param secretKey Secret key used to sign the spending input.
|
|
78
121
|
* @param bitcoin Bitcoin network connection.
|
|
79
122
|
* @param options Broadcast options (fee estimator, etc.).
|
|
80
123
|
* @returns The txid of the broadcast transaction.
|
|
81
|
-
* @throws {BeaconError} if the address is unfunded
|
|
124
|
+
* @throws {BeaconError} if the address is unfunded, no UTXO is available, or fee exceeds value.
|
|
82
125
|
*/
|
|
83
126
|
protected buildSignAndBroadcast(signalBytes: Uint8Array, secretKey: KeyBytes, bitcoin: BitcoinConnection, options?: BroadcastOptions): Promise<string>;
|
|
127
|
+
/**
|
|
128
|
+
* Build an unsigned P2WPKH single-party beacon tx + probe-sign to determine vsize,
|
|
129
|
+
* then rebuild with the real fee. Returns the tx and prev-output metadata.
|
|
130
|
+
*
|
|
131
|
+
* The secret key is required here (not just in `signSinglePartyTx`) because the
|
|
132
|
+
* two-pass fee estimation requires an actual signature to measure vsize accurately.
|
|
133
|
+
*/
|
|
134
|
+
protected buildSinglePartyTx(opts: {
|
|
135
|
+
signalBytes: Uint8Array;
|
|
136
|
+
beaconAddress: string;
|
|
137
|
+
utxo: AddressUtxo;
|
|
138
|
+
prevTxBytes: Uint8Array;
|
|
139
|
+
secretKey: KeyBytes;
|
|
140
|
+
bitcoin: BitcoinConnection;
|
|
141
|
+
feeEstimator: FeeEstimator;
|
|
142
|
+
}): Promise<BeaconTxPlan>;
|
|
143
|
+
/**
|
|
144
|
+
* Sign + finalize the unsigned single-party tx and return its raw hex.
|
|
145
|
+
*/
|
|
146
|
+
protected signSinglePartyTx(tx: Transaction, secretKey: KeyBytes): string;
|
|
147
|
+
/**
|
|
148
|
+
* Broadcast raw transaction hex via the Bitcoin REST endpoint. Returns the txid.
|
|
149
|
+
*/
|
|
150
|
+
protected broadcastRawTx(bitcoin: BitcoinConnection, rawHex: string): Promise<string>;
|
|
84
151
|
}
|
|
85
152
|
//# sourceMappingURL=beacon.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"beacon.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/beacon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"beacon.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/beacon.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrF,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAGhE,OAAO,EAA4B,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AAC1D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAG/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAanE;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,kGAAkG;IAClG,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;GAGG;AACH,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,EAAE,EAAE,WAAW,CAAC;IAChB,6EAA6E;IAC7E,cAAc,EAAE,UAAU,EAAE,CAAC;IAC7B,uDAAuD;IACvD,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,oEAAoE;IACpE,aAAa,EAAE,MAAM,CAAC;IACtB,iCAAiC;IACjC,IAAI,EAAE,WAAW,CAAC;IAClB,8DAA8D;IAC9D,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,WAAW,EAAE,UAAU,GAAG,UAAU,CAElE;AA4BD;;;;;;;;;;;GAWG;AACH,wBAAsB,wBAAwB,CAAC,IAAI,EAAE;IACnD,0EAA0E;IAC1E,aAAa,EAAE,MAAM,CAAC;IACtB,wEAAwE;IACxE,cAAc,EAAE,UAAU,CAAC;IAC3B,8DAA8D;IAC9D,WAAW,EAAE,UAAU,CAAC;IACxB,yDAAyD;IACzD,OAAO,EAAE,iBAAiB,CAAC;IAC3B,iEAAiE;IACjE,OAAO,EAAE,UAAU,CAAC;IACpB,qDAAqD;IACrD,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,GAAG,OAAO,CAAC,YAAY,CAAC,CAoCxB;AAED;;;;;;;;;;;;;;GAcG;AACH,8BAAsB,MAAM;;IAC1B;;OAEG;IACH,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;gBAEpB,OAAO,EAAE,aAAa;IAIlC;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,cAAc,CACrB,OAAO,EAAE,KAAK,CAAC,YAAY,CAAC,EAC5B,OAAO,EAAE,WAAW,GACnB,mBAAmB;IAEtB;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CACtB,YAAY,EAAE,iBAAiB,EAC/B,SAAS,EAAE,QAAQ,EACnB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,iBAAiB,CAAC;IAE7B;;;;;;;;;;;;;;;OAeG;cACa,qBAAqB,CACnC,WAAW,EAAE,UAAU,EACvB,SAAS,EAAE,QAAQ,EACnB,OAAO,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE,gBAAgB,GACzB,OAAO,CAAC,MAAM,CAAC;IAWlB;;;;;;OAMG;cACa,kBAAkB,CAAC,IAAI,EAAE;QACvC,WAAW,EAAE,UAAU,CAAC;QACxB,aAAa,EAAE,MAAM,CAAC;QACtB,IAAI,EAAE,WAAW,CAAC;QAClB,WAAW,EAAE,UAAU,CAAC;QACxB,SAAS,EAAE,QAAQ,CAAC;QACpB,OAAO,EAAE,iBAAiB,CAAC;QAC3B,YAAY,EAAE,YAAY,CAAC;KAC5B,GAAG,OAAO,CAAC,YAAY,CAAC;IAiDzB;;OAEG;IACH,SAAS,CAAC,iBAAiB,CAAC,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,GAAG,MAAM;IAMzE;;OAEG;cACa,cAAc,CAAC,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAQ5F"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { BTCNetwork } from '@did-btcr2/bitcoin';
|
|
1
2
|
import type { KeyBytes, Maybe } from '@did-btcr2/common';
|
|
2
|
-
import type { networks } from 'bitcoinjs-lib';
|
|
3
3
|
import type { DidDocument } from '../../utils/did-document.js';
|
|
4
4
|
import type { BeaconService } from './interfaces.js';
|
|
5
5
|
/**
|
|
@@ -53,7 +53,7 @@ export declare class BeaconUtils {
|
|
|
53
53
|
static generateBeaconServices({ id, publicKey, network, beaconType }: {
|
|
54
54
|
id: string;
|
|
55
55
|
publicKey: KeyBytes;
|
|
56
|
-
network:
|
|
56
|
+
network: BTCNetwork;
|
|
57
57
|
beaconType: string;
|
|
58
58
|
}): Array<BeaconService>;
|
|
59
59
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/utils.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../src/core/beacon/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAC,MAAM,mBAAmB,CAAC;AAIxD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAC;AAE/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD;;;;GAIG;AACH,qBAAa,WAAW;IACtB;;;;;OAKG;IACH,MAAM,CAAC,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM;IAO/C;;;;OAIG;IACH,MAAM,CAAC,eAAe,CAAC,GAAG,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,OAAO;IAc1D;;;;;OAKG;IACH,MAAM,CAAC,iBAAiB,CAAC,WAAW,EAAE,WAAW,GAAG,aAAa,EAAE;IAKnE;;;;;OAKG;IACH,MAAM,CAAC,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,KAAK,CAAC,aAAa,CAAC;IAiBlF;;;;;;;OAOG;IACH,MAAM,CAAC,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,aAAa;IA2BpH;;;;;OAKG;IACH,MAAM,CAAC,sBAAsB,CAAC,EAAE,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE;QACpE,EAAE,EAAE,MAAM,CAAC;QACX,SAAS,EAAE,QAAQ,CAAC;QACpB,OAAO,EAAE,UAAU,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;KACpB,GAAG,KAAK,CAAC,aAAa,CAAC;IAoCxB;;;;OAIG;IACH,MAAM,CAAC,0BAA0B,CAAC,MAAM,EAAE,aAAa,GAAG,aAAa;IAIvE;;;;OAIG;IACH,MAAM,CAAC,oBAAoB,CAAC,OAAO,EAAE,KAAK,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC;IAQtF;;;;OAIG;IACH,MAAM,CAAC,mBAAmB,CAAC,WAAW,EAAE,WAAW,GAAG,MAAM,EAAE;CAG/D"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import type { BitcoinConnection } from '@did-btcr2/bitcoin';
|
|
2
|
+
import type { KeyBytes, PatchOperation } from '@did-btcr2/common';
|
|
3
|
+
import { type SignedBTCR2Update, type UnsignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
4
|
+
import { type Btcr2DidDocument, type DidVerificationMethod } from '../utils/did-document.js';
|
|
5
|
+
import type { BeaconService } from './beacon/interfaces.js';
|
|
6
|
+
/**
|
|
7
|
+
* The updater needs the caller to supply a signing key (or a KMS-backed signature)
|
|
8
|
+
* for the given verification method. The unsigned update is attached so the caller
|
|
9
|
+
* can inspect it before producing a signature.
|
|
10
|
+
*/
|
|
11
|
+
export interface NeedSigningKey {
|
|
12
|
+
readonly kind: 'NeedSigningKey';
|
|
13
|
+
/** The verification method ID that requires a signing key. */
|
|
14
|
+
readonly verificationMethodId: string;
|
|
15
|
+
/** The unsigned update that will be signed. */
|
|
16
|
+
readonly unsignedUpdate: UnsignedBTCR2Update;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* The updater needs the caller to ensure the beacon address is funded before
|
|
20
|
+
* broadcasting. The caller checks the beacon address for UTXOs, funds it if
|
|
21
|
+
* needed, and then calls `updater.provide(need)` to continue.
|
|
22
|
+
*
|
|
23
|
+
* If the beacon is already funded, the caller can provide immediately (no-op).
|
|
24
|
+
*/
|
|
25
|
+
export interface NeedFunding {
|
|
26
|
+
readonly kind: 'NeedFunding';
|
|
27
|
+
/** The Bitcoin address that must have a spendable UTXO for broadcast. */
|
|
28
|
+
readonly beaconAddress: string;
|
|
29
|
+
/** The beacon service this address belongs to. */
|
|
30
|
+
readonly beaconService: BeaconService;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* The updater needs the caller to broadcast the signed update via the beacon.
|
|
34
|
+
*
|
|
35
|
+
* The caller decides how: for single-party beacons, call
|
|
36
|
+
* `Updater.announce(beaconService, signedUpdate, secretKey, bitcoin)` or
|
|
37
|
+
* `BeaconFactory.establish(beaconService).broadcastSignal(...)`. For multi-party
|
|
38
|
+
* aggregate beacons, hand off to the aggregation protocol.
|
|
39
|
+
*
|
|
40
|
+
* After the broadcast succeeds, the caller calls `updater.provide(need)` (with no
|
|
41
|
+
* data) to transition the updater to Complete.
|
|
42
|
+
*/
|
|
43
|
+
export interface NeedBroadcast {
|
|
44
|
+
readonly kind: 'NeedBroadcast';
|
|
45
|
+
/** The beacon service to broadcast through. Inspect `beaconService.type` to decide the path. */
|
|
46
|
+
readonly beaconService: BeaconService;
|
|
47
|
+
/** The signed update ready for broadcast. */
|
|
48
|
+
readonly signedUpdate: SignedBTCR2Update;
|
|
49
|
+
}
|
|
50
|
+
/** Discriminated union of all data needs the updater may request from the caller. */
|
|
51
|
+
export type UpdaterDataNeed = NeedSigningKey | NeedFunding | NeedBroadcast;
|
|
52
|
+
/**
|
|
53
|
+
* The result returned by the updater when it reaches the Complete phase.
|
|
54
|
+
*/
|
|
55
|
+
export interface UpdaterResult {
|
|
56
|
+
/** The signed update that was constructed, signed, and broadcast. */
|
|
57
|
+
signedUpdate: SignedBTCR2Update;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Output of {@link Updater.advance}. Either the updater needs data from the
|
|
61
|
+
* caller, or the update is complete.
|
|
62
|
+
*/
|
|
63
|
+
export type UpdaterState = {
|
|
64
|
+
status: 'action-required';
|
|
65
|
+
needs: ReadonlyArray<UpdaterDataNeed>;
|
|
66
|
+
} | {
|
|
67
|
+
status: 'complete';
|
|
68
|
+
result: UpdaterResult;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Parameters for constructing an {@link Updater}. Built by
|
|
72
|
+
* {@link https://dcdpr.github.io/did-btcr2/operations/update.html | DidBtcr2.update}.
|
|
73
|
+
*/
|
|
74
|
+
export interface UpdaterParams {
|
|
75
|
+
sourceDocument: Btcr2DidDocument;
|
|
76
|
+
patches: PatchOperation[];
|
|
77
|
+
sourceVersionId: number;
|
|
78
|
+
verificationMethod: DidVerificationMethod;
|
|
79
|
+
beaconService: BeaconService;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Sans-I/O state machine for did:btcr2 updates — the counterpart to {@link Resolver}.
|
|
83
|
+
*
|
|
84
|
+
* Created by {@link DidBtcr2.update} (the factory). The caller drives the update by
|
|
85
|
+
* repeatedly calling {@link advance} and {@link provide}:
|
|
86
|
+
*
|
|
87
|
+
* ```typescript
|
|
88
|
+
* const updater = DidBtcr2.update({ sourceDocument, patches, ... });
|
|
89
|
+
* let state = updater.advance();
|
|
90
|
+
*
|
|
91
|
+
* while(state.status === 'action-required') {
|
|
92
|
+
* for(const need of state.needs) {
|
|
93
|
+
* switch(need.kind) {
|
|
94
|
+
* case 'NeedSigningKey':
|
|
95
|
+
* updater.provide(need, secretKeyBytes);
|
|
96
|
+
* break;
|
|
97
|
+
* case 'NeedFunding':
|
|
98
|
+
* // Check UTXOs at need.beaconAddress, fund if needed
|
|
99
|
+
* updater.provide(need);
|
|
100
|
+
* break;
|
|
101
|
+
* case 'NeedBroadcast':
|
|
102
|
+
* await Updater.announce(need.beaconService, need.signedUpdate, secretKey, bitcoin);
|
|
103
|
+
* updater.provide(need);
|
|
104
|
+
* break;
|
|
105
|
+
* }
|
|
106
|
+
* }
|
|
107
|
+
* state = updater.advance();
|
|
108
|
+
* }
|
|
109
|
+
*
|
|
110
|
+
* const { signedUpdate } = state.result;
|
|
111
|
+
* ```
|
|
112
|
+
*
|
|
113
|
+
* The Updater performs **zero I/O**. All external work (signing with a KMS or raw
|
|
114
|
+
* key, funding checks, Bitcoin transaction construction, broadcast) flows through
|
|
115
|
+
* the advance/provide protocol. This mirrors the {@link Resolver} pattern and makes
|
|
116
|
+
* the update path transport-agnostic and KMS-ready.
|
|
117
|
+
*
|
|
118
|
+
* The class also exposes static utility methods ({@link construct}, {@link sign},
|
|
119
|
+
* {@link announce}) for callers that need direct access to individual update steps
|
|
120
|
+
* outside the state machine (e.g., test vector generation scripts).
|
|
121
|
+
*
|
|
122
|
+
* @class Updater
|
|
123
|
+
*/
|
|
124
|
+
export declare class Updater {
|
|
125
|
+
#private;
|
|
126
|
+
/**
|
|
127
|
+
* @internal — Use {@link DidBtcr2.update} to create instances.
|
|
128
|
+
*/
|
|
129
|
+
constructor(params: UpdaterParams);
|
|
130
|
+
/**
|
|
131
|
+
* Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/update.html#construct-btcr2-unsigned-update | 7.3.b Construct BTCR2 Unsigned Update}.
|
|
132
|
+
*
|
|
133
|
+
* @param {Btcr2DidDocument} sourceDocument The source DID document to be updated.
|
|
134
|
+
* @param {PatchOperation[]} patches The JSON Patch operations to apply.
|
|
135
|
+
* @param {number} sourceVersionId The version ID of the source document.
|
|
136
|
+
* @returns {UnsignedBTCR2Update} The constructed UnsignedBTCR2Update object.
|
|
137
|
+
* @throws {UpdateError} If the target document fails DID Core validation.
|
|
138
|
+
*/
|
|
139
|
+
static construct(sourceDocument: Btcr2DidDocument, patches: PatchOperation[], sourceVersionId: number): UnsignedBTCR2Update;
|
|
140
|
+
/**
|
|
141
|
+
* Implements subsection {@link http://dcdpr.github.io/did-btcr2/operations/update.html#construct-btcr2-signed-update | 7.3.c Construct BTCR2 Signed Update }.
|
|
142
|
+
*
|
|
143
|
+
* @param {string} did The did-btcr2 identifier to derive the root capability from.
|
|
144
|
+
* @param {UnsignedBTCR2Update} unsignedUpdate The unsigned update to sign.
|
|
145
|
+
* @param {DidVerificationMethod} verificationMethod The verification method for signing.
|
|
146
|
+
* @param {KeyBytes} secretKey The secret key bytes.
|
|
147
|
+
* @returns {SignedBTCR2Update} The signed update with a Data Integrity proof.
|
|
148
|
+
*/
|
|
149
|
+
static sign(did: string, unsignedUpdate: UnsignedBTCR2Update, verificationMethod: DidVerificationMethod, secretKey: KeyBytes): SignedBTCR2Update;
|
|
150
|
+
/**
|
|
151
|
+
* Implements subsection {@link https://dcdpr.github.io/did-btcr2/operations/update.html#announce-did-update | 7.3.d Announce DID Update}.
|
|
152
|
+
* Announces a signed update to the Bitcoin blockchain via the specified beacon.
|
|
153
|
+
*
|
|
154
|
+
* @param {BeaconService} beaconService The beacon service to broadcast through.
|
|
155
|
+
* @param {SignedBTCR2Update} update The signed update to announce.
|
|
156
|
+
* @param {KeyBytes} secretKey The secret key for signing the Bitcoin transaction.
|
|
157
|
+
* @param {BitcoinConnection} bitcoin The Bitcoin network connection.
|
|
158
|
+
* @returns {Promise<SignedBTCR2Update>} The signed update that was broadcast.
|
|
159
|
+
*/
|
|
160
|
+
static announce(beaconService: BeaconService, update: SignedBTCR2Update, secretKey: KeyBytes, bitcoin: BitcoinConnection): Promise<SignedBTCR2Update>;
|
|
161
|
+
/**
|
|
162
|
+
* Advance the state machine. Returns either:
|
|
163
|
+
* - `{ status: 'action-required', needs }` — caller must provide data via {@link provide}
|
|
164
|
+
* - `{ status: 'complete', result }` — update is signed and broadcast
|
|
165
|
+
*/
|
|
166
|
+
advance(): UpdaterState;
|
|
167
|
+
/**
|
|
168
|
+
* Provide data the updater requested in a previous {@link advance} call.
|
|
169
|
+
* Call once per need, then call {@link advance} again to continue.
|
|
170
|
+
*
|
|
171
|
+
* @param need The DataNeed being fulfilled (from the `needs` array).
|
|
172
|
+
* @param data The data payload corresponding to the need kind (omit for NeedFunding/NeedBroadcast).
|
|
173
|
+
*/
|
|
174
|
+
provide(need: NeedSigningKey, data: KeyBytes): void;
|
|
175
|
+
provide(need: NeedFunding): void;
|
|
176
|
+
provide(need: NeedBroadcast): void;
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=updater.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updater.d.ts","sourceRoot":"","sources":["../../../src/core/updater.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import type { DocumentBytes, HexString, KeyBytes, PatchOperation } from '@did-btcr2/common';
|
|
3
|
-
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
1
|
+
import type { DocumentBytes, KeyBytes, PatchOperation } from '@did-btcr2/common';
|
|
4
2
|
import type { DidMethod } from '@web5/dids';
|
|
5
3
|
import type { ResolutionOptions } from './core/interfaces.js';
|
|
6
4
|
import { Resolver } from './core/resolver.js';
|
|
5
|
+
import { Updater } from './core/updater.js';
|
|
7
6
|
import type { Btcr2DidDocument, DidVerificationMethod } from './utils/did-document.js';
|
|
8
7
|
export interface DidCreateOptions {
|
|
9
8
|
/** Type of identifier to create (key or external) */
|
|
@@ -71,34 +70,35 @@ export declare class DidBtcr2 implements DidMethod {
|
|
|
71
70
|
*/
|
|
72
71
|
static resolve(did: string, resolutionOptions?: ResolutionOptions): Resolver;
|
|
73
72
|
/**
|
|
74
|
-
* Entry point for section {@link https://dcdpr.github.io/did-btcr2/#
|
|
75
|
-
* See specification for the {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#process | Resolve Process}.
|
|
76
|
-
* See {@link Update | Update (class)} for class implementation.
|
|
73
|
+
* Entry point for section {@link https://dcdpr.github.io/did-btcr2/#update | 7.3 Update}.
|
|
77
74
|
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
81
|
-
*
|
|
75
|
+
* Factory method that validates the update parameters and returns a sans-I/O
|
|
76
|
+
* {@link Updater} state machine. The caller drives the updater through its
|
|
77
|
+
* phases (Construct → Sign → Broadcast → Complete) by calling `advance()` and
|
|
78
|
+
* `provide()`. The method package performs **zero I/O** — signing key retrieval
|
|
79
|
+
* (or KMS delegation) and the on-chain broadcast are the caller's responsibility.
|
|
80
|
+
*
|
|
81
|
+
* For a fully-wired version with Bitcoin broadcast and key handling, see
|
|
82
|
+
* `DidMethodApi.update()` in `@did-btcr2/api`.
|
|
83
|
+
*
|
|
84
|
+
* @param params Update construction parameters.
|
|
82
85
|
* @param {Btcr2DidDocument} params.sourceDocument The DID document being updated.
|
|
83
|
-
* @param {PatchOperation[]} params.patches The
|
|
84
|
-
* @param {
|
|
85
|
-
* @param {string} params.verificationMethodId The
|
|
86
|
-
* @param {string} params.beaconId The beacon ID
|
|
87
|
-
* @
|
|
88
|
-
* @
|
|
89
|
-
*
|
|
90
|
-
*
|
|
91
|
-
* header is not `zQ3s`
|
|
86
|
+
* @param {PatchOperation[]} params.patches The JSON Patch operations to apply.
|
|
87
|
+
* @param {number} params.sourceVersionId The version ID before applying the update.
|
|
88
|
+
* @param {string} params.verificationMethodId The verification method ID to sign with.
|
|
89
|
+
* @param {string} params.beaconId The beacon service ID to broadcast through.
|
|
90
|
+
* @returns {Updater} A sans-I/O state machine for driving the update.
|
|
91
|
+
* @throws {UpdateError} If the verification method is not authorized, not found,
|
|
92
|
+
* not of type `Multikey`, or does not have a `zQ3s` publicKeyMultibase prefix.
|
|
93
|
+
* Also throws if the beacon service is not found.
|
|
92
94
|
*/
|
|
93
|
-
static update({ sourceDocument, patches, sourceVersionId, verificationMethodId, beaconId,
|
|
95
|
+
static update({ sourceDocument, patches, sourceVersionId, verificationMethodId, beaconId, }: {
|
|
94
96
|
sourceDocument: Btcr2DidDocument;
|
|
95
97
|
patches: PatchOperation[];
|
|
96
98
|
sourceVersionId: number;
|
|
97
99
|
verificationMethodId: string;
|
|
98
100
|
beaconId: string;
|
|
99
|
-
|
|
100
|
-
bitcoin?: BitcoinConnection;
|
|
101
|
-
}): Promise<SignedBTCR2Update>;
|
|
101
|
+
}): Updater;
|
|
102
102
|
/**
|
|
103
103
|
* Given the W3C DID Document of a `did:btcr2` identifier, return the signing verification method that will be used
|
|
104
104
|
* for signing messages and credentials. If given, the `methodId` parameter is used to select the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"did-btcr2.d.ts","sourceRoot":"","sources":["../../src/did-btcr2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"did-btcr2.d.ts","sourceRoot":"","sources":["../../src/did-btcr2.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,aAAa,EACb,QAAQ,EACR,cAAc,EAAC,MAAM,mBAAmB,CAAC;AAS3C,OAAO,KAAK,EACV,SAAS,EAAC,MAAM,YAAY,CAAC;AAQ/B,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAE5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAEvF,MAAM,WAAW,gBAAgB;IAC/B,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,sBAAsB;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,QAAS,YAAW,SAAS;IACxC;;OAEG;IACH,MAAM,CAAC,UAAU,EAAE,MAAM,CAAW;IAEpC;;;;;;;;;;;;;;;OAeG;IACH,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,QAAQ,GAAG,aAAa,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,MAAM;IAezF;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,MAAM,CAAC,OAAO,CACZ,GAAG,EAAE,MAAM,EACX,iBAAiB,GAAE,iBAAsB,GACxC,QAAQ;IAsBX;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,MAAM,CAAC,MAAM,CAAC,EACZ,cAAc,EACd,OAAO,EACP,eAAe,EACf,oBAAoB,EACpB,QAAQ,GACT,EAAE;QACD,cAAc,EAAE,gBAAgB,CAAC;QACjC,OAAO,EAAE,cAAc,EAAE,CAAC;QAC1B,eAAe,EAAE,MAAM,CAAC;QACxB,oBAAoB,EAAE,MAAM,CAAC;QAC7B,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,OAAO;IA2DX;;;;;;;;;OASG;IACH,MAAM,CAAC,gBAAgB,CAAC,WAAW,EAAE,gBAAgB,EAAG,QAAQ,CAAC,EAAE,MAAM,GAAG,qBAAqB;CA0BlG"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ export * from './core/aggregation/cohort.js';
|
|
|
4
4
|
export * from './core/aggregation/signing-session.js';
|
|
5
5
|
export * from './core/aggregation/phases.js';
|
|
6
6
|
export * from './core/aggregation/errors.js';
|
|
7
|
+
export * from './core/aggregation/beacon-strategy.js';
|
|
8
|
+
export * from './core/aggregation/logger.js';
|
|
7
9
|
export * from './core/aggregation/messages/index.js';
|
|
8
10
|
export * from './core/aggregation/transport/index.js';
|
|
9
11
|
export * from './core/aggregation/runner/index.js';
|
|
@@ -11,6 +13,7 @@ export * from './core/beacon/beacon.js';
|
|
|
11
13
|
export * from './core/beacon/cas-beacon.js';
|
|
12
14
|
export * from './core/beacon/error.js';
|
|
13
15
|
export * from './core/beacon/factory.js';
|
|
16
|
+
export * from './core/beacon/fee-estimator.js';
|
|
14
17
|
export * from './core/beacon/interfaces.js';
|
|
15
18
|
export * from './core/beacon/signal-discovery.js';
|
|
16
19
|
export * from './core/beacon/singleton-beacon.js';
|
|
@@ -20,7 +23,7 @@ export * from './core/identifier.js';
|
|
|
20
23
|
export * from './core/interfaces.js';
|
|
21
24
|
export * from './core/resolver.js';
|
|
22
25
|
export * from './core/types.js';
|
|
23
|
-
export * from './core/
|
|
26
|
+
export * from './core/updater.js';
|
|
24
27
|
export * from './utils/appendix.js';
|
|
25
28
|
export * from './utils/did-document-builder.js';
|
|
26
29
|
export * from './utils/did-document.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AACtD,cAAc,oCAAoC,CAAC;AAGnD,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC;AAClD,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AAGvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,cAAc,+BAA+B,CAAC;AAC9C,cAAc,mCAAmC,CAAC;AAClD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uCAAuC,CAAC;AACtD,cAAc,8BAA8B,CAAC;AAC7C,cAAc,sCAAsC,CAAC;AACrD,cAAc,uCAAuC,CAAC;AACtD,cAAc,oCAAoC,CAAC;AAGnD,cAAc,yBAAyB,CAAC;AACxC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AACvC,cAAc,0BAA0B,CAAC;AACzC,cAAc,gCAAgC,CAAC;AAC/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC;AAClD,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAC5C,cAAc,wBAAwB,CAAC;AAGvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,mBAAmB,CAAC;AAGlC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iCAAiC,CAAC;AAChD,cAAc,yBAAyB,CAAC;AAGxC,cAAc,gBAAgB,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@did-btcr2/method",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.29.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Reference implementation for the did:btcr2 DID method written in TypeScript and JavaScript. did:btcr2 is a censorship resistant DID Method using the Bitcoin blockchain as a Verifiable Data Registry to announce changes to the DID document. This is the core method implementation for the did-btcr2-js monorepo.",
|
|
6
6
|
"main": "./dist/cjs/index.js",
|
|
@@ -64,7 +64,6 @@
|
|
|
64
64
|
"bitcoin"
|
|
65
65
|
],
|
|
66
66
|
"dependencies": {
|
|
67
|
-
"@bitcoinerlab/secp256k1": "^1.2.0",
|
|
68
67
|
"@helia/strings": "^4.1.0",
|
|
69
68
|
"@noble/curves": "^1.9.7",
|
|
70
69
|
"@noble/hashes": "^1.8.0",
|
|
@@ -76,16 +75,15 @@
|
|
|
76
75
|
"@web5/common": "^1.1.0",
|
|
77
76
|
"@web5/crypto": "^1.0.6",
|
|
78
77
|
"@web5/dids": "^1.2.0",
|
|
79
|
-
"bitcoinjs-lib": "7.0.0-rc.0",
|
|
80
78
|
"canonicalize": "^2.1.0",
|
|
81
79
|
"dotenv": "^16.6.1",
|
|
82
80
|
"helia": "^5.5.1",
|
|
83
81
|
"multiformats": "^13.4.2",
|
|
84
82
|
"nostr-tools": "^2.23.3",
|
|
85
|
-
"@did-btcr2/bitcoin": "^0.5.3",
|
|
86
|
-
"@did-btcr2/common": "^9.0.0",
|
|
87
|
-
"@did-btcr2/cryptosuite": "^6.0.6",
|
|
88
83
|
"@did-btcr2/smt": "^0.2.4",
|
|
84
|
+
"@did-btcr2/cryptosuite": "^6.0.6",
|
|
85
|
+
"@did-btcr2/bitcoin": "^0.6.0",
|
|
86
|
+
"@did-btcr2/common": "^9.0.0",
|
|
89
87
|
"@did-btcr2/keypair": "^0.11.4"
|
|
90
88
|
},
|
|
91
89
|
"devDependencies": {
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { canonicalize } from '@did-btcr2/common';
|
|
2
|
+
import type { SignedBTCR2Update } from '@did-btcr2/cryptosuite';
|
|
3
|
+
import type { SerializedSMTProof } from '@did-btcr2/smt';
|
|
4
|
+
import { blockHash, didToIndex, hashToHex, hexToHash, verifySerializedProof } from '@did-btcr2/smt';
|
|
5
|
+
import type { AggregationCohort } from './cohort.js';
|
|
6
|
+
import type { BaseBody } from './messages/base.js';
|
|
7
|
+
|
|
8
|
+
/** Validation result returned to the participant for a distribute-data message. */
|
|
9
|
+
export interface BeaconValidationResult {
|
|
10
|
+
matches: boolean;
|
|
11
|
+
casAnnouncement?: Record<string, string>;
|
|
12
|
+
smtProof?: SerializedSMTProof;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Per-participant body attached to DISTRIBUTE_AGGREGATED_DATA by the service. */
|
|
16
|
+
export interface BeaconDistributePayload {
|
|
17
|
+
casAnnouncement?: Record<string, string>;
|
|
18
|
+
smtProof?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Pluggable strategy for beacon-type-specific aggregation, distribution, and
|
|
23
|
+
* participant-side validation. Lets new beacon types be added without
|
|
24
|
+
* modifying the service or participant state machines: register a new strategy
|
|
25
|
+
* via {@link registerBeaconStrategy}.
|
|
26
|
+
*/
|
|
27
|
+
export interface AggregateBeaconStrategy {
|
|
28
|
+
/** String constant used as `beaconType` on CohortConfig / BaseMessage bodies. */
|
|
29
|
+
readonly type: string;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Service: build the aggregated data on the cohort after all updates are
|
|
33
|
+
* collected. Implementation should mutate the cohort (set signalBytes,
|
|
34
|
+
* casAnnouncement, smtProofs, etc.).
|
|
35
|
+
*/
|
|
36
|
+
buildAggregatedData(cohort: AggregationCohort): void;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Service: produce the body fields to attach to DISTRIBUTE_AGGREGATED_DATA
|
|
40
|
+
* for a specific participant. Called once per cohort member.
|
|
41
|
+
*/
|
|
42
|
+
getDistributePayload(cohort: AggregationCohort, participantDid: string): BeaconDistributePayload;
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Participant: verify the aggregated data they received reflects their own
|
|
46
|
+
* submitted update. Pure function — returns matches + sidecar fields for
|
|
47
|
+
* the caller to store.
|
|
48
|
+
*/
|
|
49
|
+
validateParticipantView(params: {
|
|
50
|
+
participantDid: string;
|
|
51
|
+
submittedUpdate: SignedBTCR2Update;
|
|
52
|
+
expectedHash: string;
|
|
53
|
+
body: BaseBody;
|
|
54
|
+
}): BeaconValidationResult;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const CAS_STRATEGY: AggregateBeaconStrategy = {
|
|
58
|
+
type : 'CASBeacon',
|
|
59
|
+
|
|
60
|
+
buildAggregatedData(cohort) {
|
|
61
|
+
cohort.buildCASAnnouncement();
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
getDistributePayload(cohort) {
|
|
65
|
+
return { casAnnouncement: cohort.casAnnouncement };
|
|
66
|
+
},
|
|
67
|
+
|
|
68
|
+
validateParticipantView({ participantDid, expectedHash, body }) {
|
|
69
|
+
const casAnnouncement = body.casAnnouncement;
|
|
70
|
+
if(!casAnnouncement) return { matches: false };
|
|
71
|
+
return {
|
|
72
|
+
matches : casAnnouncement[participantDid] === expectedHash,
|
|
73
|
+
casAnnouncement,
|
|
74
|
+
};
|
|
75
|
+
},
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const SMT_STRATEGY: AggregateBeaconStrategy = {
|
|
79
|
+
type : 'SMTBeacon',
|
|
80
|
+
|
|
81
|
+
buildAggregatedData(cohort) {
|
|
82
|
+
cohort.buildSMTTree();
|
|
83
|
+
},
|
|
84
|
+
|
|
85
|
+
getDistributePayload(cohort, participantDid) {
|
|
86
|
+
const proof = cohort.smtProofs?.get(participantDid);
|
|
87
|
+
return { smtProof: proof as unknown as Record<string, unknown> | undefined };
|
|
88
|
+
},
|
|
89
|
+
|
|
90
|
+
validateParticipantView({ participantDid, submittedUpdate, body }) {
|
|
91
|
+
const smtProof = body.smtProof as unknown as SerializedSMTProof | undefined;
|
|
92
|
+
if(!smtProof?.updateId || !smtProof?.nonce) return { matches: false };
|
|
93
|
+
// Verify updateId matches the canonicalized update hash
|
|
94
|
+
const canonicalBytes = new TextEncoder().encode(canonicalize(submittedUpdate as unknown as Record<string, unknown>));
|
|
95
|
+
const expectedUpdateId = hashToHex(blockHash(canonicalBytes));
|
|
96
|
+
if(smtProof.updateId !== expectedUpdateId) {
|
|
97
|
+
return { matches: false, smtProof };
|
|
98
|
+
}
|
|
99
|
+
// Verify Merkle inclusion
|
|
100
|
+
const index = didToIndex(participantDid);
|
|
101
|
+
const candidateHash = blockHash(blockHash(hexToHash(smtProof.nonce)), hexToHash(smtProof.updateId));
|
|
102
|
+
return {
|
|
103
|
+
matches : verifySerializedProof(smtProof, index, candidateHash),
|
|
104
|
+
smtProof,
|
|
105
|
+
};
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
/** Registered strategies keyed by `beaconType` string. */
|
|
110
|
+
const STRATEGIES: Map<string, AggregateBeaconStrategy> = new Map([
|
|
111
|
+
[CAS_STRATEGY.type, CAS_STRATEGY],
|
|
112
|
+
[SMT_STRATEGY.type, SMT_STRATEGY],
|
|
113
|
+
]);
|
|
114
|
+
|
|
115
|
+
/** Register a custom beacon strategy. Overwrites any existing entry with the same type. */
|
|
116
|
+
export function registerBeaconStrategy(strategy: AggregateBeaconStrategy): void {
|
|
117
|
+
STRATEGIES.set(strategy.type, strategy);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/** Look up a registered beacon strategy by type, or undefined if not registered. */
|
|
121
|
+
export function getBeaconStrategy(type: string): AggregateBeaconStrategy | undefined {
|
|
122
|
+
return STRATEGIES.get(type);
|
|
123
|
+
}
|