@did-btcr2/method 0.36.1 → 0.37.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/dist/.tsbuildinfo +1 -1
- package/dist/browser.js +1060 -96
- package/dist/browser.mjs +1060 -96
- package/dist/cjs/index.js +1153 -179
- package/dist/esm/core/aggregation/beacon-strategy.js +19 -6
- package/dist/esm/core/aggregation/beacon-strategy.js.map +1 -1
- package/dist/esm/core/aggregation/cohort.js +142 -33
- package/dist/esm/core/aggregation/cohort.js.map +1 -1
- package/dist/esm/core/aggregation/conditions.js +27 -0
- package/dist/esm/core/aggregation/conditions.js.map +1 -1
- package/dist/esm/core/aggregation/fallback-spend.js +132 -0
- package/dist/esm/core/aggregation/fallback-spend.js.map +1 -0
- package/dist/esm/core/aggregation/messages/base.js.map +1 -1
- package/dist/esm/core/aggregation/messages/bodies.js +46 -1
- package/dist/esm/core/aggregation/messages/bodies.js.map +1 -1
- package/dist/esm/core/aggregation/messages/constants.js +11 -0
- package/dist/esm/core/aggregation/messages/constants.js.map +1 -1
- package/dist/esm/core/aggregation/messages/factories.js +27 -1
- package/dist/esm/core/aggregation/messages/factories.js.map +1 -1
- package/dist/esm/core/aggregation/messages/guards.js +4 -1
- package/dist/esm/core/aggregation/messages/guards.js.map +1 -1
- package/dist/esm/core/aggregation/participant.js +210 -21
- package/dist/esm/core/aggregation/participant.js.map +1 -1
- package/dist/esm/core/aggregation/phases.js +6 -0
- package/dist/esm/core/aggregation/phases.js.map +1 -1
- package/dist/esm/core/aggregation/recovery-policy.js +156 -0
- package/dist/esm/core/aggregation/recovery-policy.js.map +1 -0
- package/dist/esm/core/aggregation/recovery-spend.js +106 -0
- package/dist/esm/core/aggregation/recovery-spend.js.map +1 -0
- package/dist/esm/core/aggregation/runner/aggregation-runner.js +11 -3
- package/dist/esm/core/aggregation/runner/aggregation-runner.js.map +1 -1
- package/dist/esm/core/aggregation/runner/participant-runner.js +74 -22
- package/dist/esm/core/aggregation/runner/participant-runner.js.map +1 -1
- package/dist/esm/core/aggregation/runner/service-runner.js +97 -9
- package/dist/esm/core/aggregation/runner/service-runner.js.map +1 -1
- package/dist/esm/core/aggregation/service.js +221 -11
- package/dist/esm/core/aggregation/service.js.map +1 -1
- package/dist/esm/core/aggregation/signing-session.js +3 -3
- package/dist/esm/core/aggregation/signing-session.js.map +1 -1
- package/dist/esm/core/aggregation/transport/http/envelope.js +3 -3
- package/dist/esm/core/aggregation/transport/http/inbox-buffer.js +1 -1
- package/dist/esm/core/aggregation/transport/http/nonce-cache.js +1 -1
- package/dist/esm/core/aggregation/transport/http/rate-limiter.js +1 -1
- package/dist/esm/core/aggregation/transport/http/request-auth.js +1 -1
- package/dist/esm/core/aggregation/transport/http/server.js +1 -1
- package/dist/esm/core/aggregation/transport/http/sse-stream.js +1 -1
- package/dist/esm/core/aggregation/transport/http/sse-writer.js +1 -1
- package/dist/esm/core/aggregation/transport/in-memory.js +1 -1
- package/dist/esm/core/aggregation/transport/nostr.js +6 -6
- package/dist/esm/core/beacon/beacon.js +15 -10
- package/dist/esm/core/beacon/beacon.js.map +1 -1
- package/dist/esm/core/beacon/cas-beacon.js +6 -6
- package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
- package/dist/esm/core/beacon/singleton-beacon.js +2 -2
- package/dist/esm/core/beacon/singleton-beacon.js.map +1 -1
- package/dist/esm/core/beacon/smt-beacon.js +3 -3
- package/dist/esm/core/beacon/smt-beacon.js.map +1 -1
- package/dist/esm/core/resolver.js +8 -8
- package/dist/esm/core/resolver.js.map +1 -1
- package/dist/esm/core/updater.js +6 -6
- package/dist/esm/core/updater.js.map +1 -1
- package/dist/esm/did-btcr2.js +2 -2
- package/dist/esm/index.js +3 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/types/core/aggregation/beacon-strategy.d.ts +8 -4
- package/dist/types/core/aggregation/beacon-strategy.d.ts.map +1 -1
- package/dist/types/core/aggregation/cohort.d.ts +88 -17
- package/dist/types/core/aggregation/cohort.d.ts.map +1 -1
- package/dist/types/core/aggregation/conditions.d.ts +28 -0
- package/dist/types/core/aggregation/conditions.d.ts.map +1 -1
- package/dist/types/core/aggregation/fallback-spend.d.ts +94 -0
- package/dist/types/core/aggregation/fallback-spend.d.ts.map +1 -0
- package/dist/types/core/aggregation/logger.d.ts +1 -1
- package/dist/types/core/aggregation/messages/base.d.ts +6 -0
- package/dist/types/core/aggregation/messages/base.d.ts.map +1 -1
- package/dist/types/core/aggregation/messages/bodies.d.ts +50 -2
- package/dist/types/core/aggregation/messages/bodies.d.ts.map +1 -1
- package/dist/types/core/aggregation/messages/constants.d.ts +8 -0
- package/dist/types/core/aggregation/messages/constants.d.ts.map +1 -1
- package/dist/types/core/aggregation/messages/factories.d.ts +40 -0
- package/dist/types/core/aggregation/messages/factories.d.ts.map +1 -1
- package/dist/types/core/aggregation/messages/guards.d.ts.map +1 -1
- package/dist/types/core/aggregation/participant.d.ts +41 -7
- package/dist/types/core/aggregation/participant.d.ts.map +1 -1
- package/dist/types/core/aggregation/phases.d.ts +8 -2
- package/dist/types/core/aggregation/phases.d.ts.map +1 -1
- package/dist/types/core/aggregation/recovery-policy.d.ts +132 -0
- package/dist/types/core/aggregation/recovery-policy.d.ts.map +1 -0
- package/dist/types/core/aggregation/recovery-spend.d.ts +94 -0
- package/dist/types/core/aggregation/recovery-spend.d.ts.map +1 -0
- package/dist/types/core/aggregation/runner/aggregation-runner.d.ts +13 -3
- package/dist/types/core/aggregation/runner/aggregation-runner.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/events.d.ts +28 -7
- package/dist/types/core/aggregation/runner/events.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/participant-runner.d.ts +3 -3
- package/dist/types/core/aggregation/runner/participant-runner.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/service-runner.d.ts +28 -3
- package/dist/types/core/aggregation/runner/service-runner.d.ts.map +1 -1
- package/dist/types/core/aggregation/service.d.ts +26 -2
- package/dist/types/core/aggregation/service.d.ts.map +1 -1
- package/dist/types/core/aggregation/signing-session.d.ts +2 -2
- package/dist/types/core/aggregation/signing-session.d.ts.map +1 -1
- package/dist/types/core/aggregation/transport/http/envelope.d.ts +3 -3
- package/dist/types/core/aggregation/transport/http/inbox-buffer.d.ts +1 -1
- package/dist/types/core/aggregation/transport/http/nonce-cache.d.ts +1 -1
- package/dist/types/core/aggregation/transport/http/rate-limiter.d.ts +1 -1
- package/dist/types/core/aggregation/transport/http/request-auth.d.ts +1 -1
- package/dist/types/core/aggregation/transport/http/server.d.ts +1 -1
- package/dist/types/core/aggregation/transport/http/sse-stream.d.ts +2 -2
- package/dist/types/core/aggregation/transport/http/sse-writer.d.ts +1 -1
- package/dist/types/core/aggregation/transport/in-memory.d.ts +1 -1
- package/dist/types/core/aggregation/transport/nostr.d.ts +4 -4
- package/dist/types/core/aggregation/transport/transport.d.ts +4 -4
- package/dist/types/core/aggregation/transport/transport.d.ts.map +1 -1
- package/dist/types/core/beacon/beacon.d.ts +7 -7
- package/dist/types/core/beacon/beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/cas-beacon.d.ts +2 -2
- package/dist/types/core/beacon/interfaces.d.ts +1 -1
- package/dist/types/core/resolver.d.ts +3 -3
- package/dist/types/core/updater.d.ts +4 -4
- package/dist/types/did-btcr2.d.ts +2 -2
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/core/aggregation/beacon-strategy.ts +27 -9
- package/src/core/aggregation/cohort.ts +171 -35
- package/src/core/aggregation/conditions.ts +56 -0
- package/src/core/aggregation/fallback-spend.ts +223 -0
- package/src/core/aggregation/logger.ts +1 -1
- package/src/core/aggregation/messages/base.ts +6 -0
- package/src/core/aggregation/messages/bodies.ts +94 -1
- package/src/core/aggregation/messages/constants.ts +12 -0
- package/src/core/aggregation/messages/factories.ts +57 -0
- package/src/core/aggregation/messages/guards.ts +6 -0
- package/src/core/aggregation/participant.ts +255 -23
- package/src/core/aggregation/phases.ts +9 -0
- package/src/core/aggregation/recovery-policy.ts +237 -0
- package/src/core/aggregation/recovery-spend.ts +192 -0
- package/src/core/aggregation/runner/aggregation-runner.ts +27 -5
- package/src/core/aggregation/runner/events.ts +26 -7
- package/src/core/aggregation/runner/participant-runner.ts +75 -23
- package/src/core/aggregation/runner/service-runner.ts +120 -10
- package/src/core/aggregation/service.ts +260 -14
- package/src/core/aggregation/signing-session.ts +3 -3
- package/src/core/aggregation/transport/http/envelope.ts +3 -3
- package/src/core/aggregation/transport/http/inbox-buffer.ts +1 -1
- package/src/core/aggregation/transport/http/nonce-cache.ts +1 -1
- package/src/core/aggregation/transport/http/rate-limiter.ts +1 -1
- package/src/core/aggregation/transport/http/request-auth.ts +1 -1
- package/src/core/aggregation/transport/http/server.ts +1 -1
- package/src/core/aggregation/transport/http/sse-stream.ts +2 -2
- package/src/core/aggregation/transport/http/sse-writer.ts +1 -1
- package/src/core/aggregation/transport/in-memory.ts +1 -1
- package/src/core/aggregation/transport/nostr.ts +6 -6
- package/src/core/aggregation/transport/transport.ts +4 -4
- package/src/core/beacon/beacon.ts +16 -11
- package/src/core/beacon/cas-beacon.ts +7 -7
- package/src/core/beacon/interfaces.ts +1 -1
- package/src/core/beacon/singleton-beacon.ts +2 -2
- package/src/core/beacon/smt-beacon.ts +3 -3
- package/src/core/resolver.ts +8 -8
- package/src/core/updater.ts +6 -6
- package/src/did-btcr2.ts +2 -2
- package/src/index.ts +3 -0
|
@@ -16,28 +16,28 @@ const DEFAULT_FEE_ESTIMATOR: FeeEstimator = new StaticFeeEstimator(5);
|
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
18
|
* Singleton beacon script kinds. Per the did:btcr2 spec, deterministic DID documents
|
|
19
|
-
* include three beacon services: P2PKH, P2WPKH, and P2TR (taproot key-path)
|
|
19
|
+
* include three beacon services: P2PKH, P2WPKH, and P2TR (taproot key-path), all
|
|
20
20
|
* derived from the genesis secp256k1 public key. The singleton broadcast path must
|
|
21
21
|
* support signing for all three.
|
|
22
22
|
*/
|
|
23
23
|
export type SingletonScriptKind = 'p2pkh' | 'p2wpkh' | 'p2tr';
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
* Conservative vsize estimate for a 1-input P2TR key-path
|
|
26
|
+
* Conservative vsize estimate for a 1-input P2TR key-path to 1 P2TR change + 1 OP_RETURN(32) tx.
|
|
27
27
|
* Stripped 137 + witness ≈ 68 (marker + flag + stack-count + sig-len + 64 BIP-340 sig).
|
|
28
28
|
* Weight = 137*4 + 68 = 616, vsize ≈ 154, rounded to 160 for headroom.
|
|
29
29
|
*/
|
|
30
30
|
export const P2TR_BEACON_TX_VSIZE = 160;
|
|
31
31
|
|
|
32
32
|
/**
|
|
33
|
-
* Conservative vsize estimate for a 1-input P2WPKH
|
|
33
|
+
* Conservative vsize estimate for a 1-input P2WPKH to 1 P2WPKH change + 1 OP_RETURN(32) tx.
|
|
34
34
|
* Stripped 125 + witness ≈ 110 (worst-case DER ECDSA sig 72 + sighash byte + 33 pubkey + framing).
|
|
35
35
|
* vsize = ceil((125*4 + 110) / 4) ≈ 153, rounded to 155.
|
|
36
36
|
*/
|
|
37
37
|
export const P2WPKH_BEACON_TX_VSIZE = 155;
|
|
38
38
|
|
|
39
39
|
/**
|
|
40
|
-
* Conservative vsize estimate for a 1-input P2PKH
|
|
40
|
+
* Conservative vsize estimate for a 1-input P2PKH to 1 P2PKH change + 1 OP_RETURN(32) tx.
|
|
41
41
|
* Legacy (non-segwit): scriptSig carries the full sig+pubkey (~108 bytes), no witness
|
|
42
42
|
* discount. Stripped ≈ 4 nVer + 1 vin-count + (32+4+1+108+4) input + 1 vout-count +
|
|
43
43
|
* 34 P2PKH-change + 43 OP_RETURN + 4 nLockTime ≈ 236 bytes. vsize = 236, rounded to 240.
|
|
@@ -169,7 +169,7 @@ async function fetchSpendableUtxo(
|
|
|
169
169
|
* signing session consumes (via {@link SigningTxData}).
|
|
170
170
|
*
|
|
171
171
|
* This is the reusable counterpart to {@link SinglePartyBeacon.buildSignAndBroadcast}'s internal
|
|
172
|
-
* construction step
|
|
172
|
+
* construction step: the aggregation path must produce an unsigned tx because the
|
|
173
173
|
* signature comes from a MuSig2 round, not a local secret key.
|
|
174
174
|
*
|
|
175
175
|
* @param opts Parameters including the cohort's aggregate internal pubkey.
|
|
@@ -192,8 +192,13 @@ export async function buildAggregationBeaconTx(opts: {
|
|
|
192
192
|
const feeEstimator = opts.feeEstimator ?? DEFAULT_FEE_ESTIMATOR;
|
|
193
193
|
const { utxo, prevTxBytes } = await fetchSpendableUtxo(opts.beaconAddress, opts.bitcoin);
|
|
194
194
|
|
|
195
|
-
|
|
196
|
-
|
|
195
|
+
// The funded beacon output is a Taproot script-tree output: key path is the
|
|
196
|
+
// MuSig2 aggregate, script path is the k-of-n fallback + CSV recovery leaves
|
|
197
|
+
// (see cohort.ts and ADR 042). Derive the witnessUtxo scriptPubKey from the
|
|
198
|
+
// funded address itself; recomputing a key-path-only p2tr(internalPubkey) here
|
|
199
|
+
// would not match the script-tree UTXO on chain and would invalidate both the
|
|
200
|
+
// key-path sighash and the fallback script-path sighash.
|
|
201
|
+
const witnessScript = OutScript.encode(Address(opts.network).decode(opts.beaconAddress));
|
|
197
202
|
|
|
198
203
|
// Fee cannot be probe-measured (no secret key for MuSig2 round). Use fixed P2TR vsize.
|
|
199
204
|
const feeSats = await feeEstimator.estimateFee(P2TR_BEACON_TX_VSIZE);
|
|
@@ -258,7 +263,7 @@ async function signSingletonInput(
|
|
|
258
263
|
// directly. We need only the sighash bytes so an external Signer can produce
|
|
259
264
|
// the signature, so we reach through the type system here. If scure ever
|
|
260
265
|
// renames this method, the P2PKH path tests fail loudly.
|
|
261
|
-
// TODO: track https://github.com/paulmillr/scure-btc-signer/issues/142
|
|
266
|
+
// TODO: track https://github.com/paulmillr/scure-btc-signer/issues/142 -
|
|
262
267
|
// drop the cast once a public preimage (e.g. `preimageP2PKH`) lands upstream.
|
|
263
268
|
const sighashType = SigHash.ALL;
|
|
264
269
|
const sighash = (tx as unknown as {
|
|
@@ -302,7 +307,7 @@ async function signSingletonInput(
|
|
|
302
307
|
// `d' = taprootTweakPrivKey(d, merkleRoot)`; the verifier checks against the
|
|
303
308
|
// tweaked output internal key `Q = P + tG`. The tweak lives inside the Signer
|
|
304
309
|
// (it needs the secret key), so we use scheme 'bip341' rather than the raw
|
|
305
|
-
// 'bip340' scheme. No script tree on singleton beacons
|
|
310
|
+
// 'bip340' scheme. No script tree on singleton beacons, no merkleRoot.
|
|
306
311
|
const sighash = tx.preimageWitnessV1(inputIdx, [prevOutScript], SigHash.DEFAULT, [amount]);
|
|
307
312
|
const sig = signer.sign(sighash, 'bip341');
|
|
308
313
|
tx.updateInput(inputIdx, { tapKeySig: sig });
|
|
@@ -377,7 +382,7 @@ export abstract class SinglePartyBeacon {
|
|
|
377
382
|
*
|
|
378
383
|
* Composed from the three extracted phases ({@link buildSinglePartyTx},
|
|
379
384
|
* {@link signSinglePartyTx}, {@link broadcastRawTx}) so each piece can be exercised
|
|
380
|
-
* in isolation. Aggregation beacons use {@link buildAggregationBeaconTx} instead
|
|
385
|
+
* in isolation. Aggregation beacons use {@link buildAggregationBeaconTx} instead:
|
|
381
386
|
* the multi-party path can't share the signing phase, but the tx-construction
|
|
382
387
|
* plumbing (UTXO fetch + OP_RETURN output + change output) is shared.
|
|
383
388
|
*
|
|
@@ -409,7 +414,7 @@ export abstract class SinglePartyBeacon {
|
|
|
409
414
|
*
|
|
410
415
|
* Detects the beacon address script kind (P2PKH / P2WPKH / P2TR) and configures
|
|
411
416
|
* the input accordingly. Validates that the signer's pubkey produces the beacon
|
|
412
|
-
* address under that script kind
|
|
417
|
+
* address under that script kind: without this check, a misconfigured caller
|
|
413
418
|
* would burn a real UTXO on a tx that fails at broadcast. Fees are computed from
|
|
414
419
|
* the per-kind {@link SINGLETON_BEACON_TX_VSIZE} constant, avoiding any probe-sign
|
|
415
420
|
* round-trip.
|
|
@@ -9,7 +9,7 @@ import { SinglePartyBeacon } from './beacon.js';
|
|
|
9
9
|
import type { BeaconService, BeaconSignal, BlockMetadata, CasPublishFn } from './interfaces.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
|
-
* CAS-specific broadcast options
|
|
12
|
+
* CAS-specific broadcast options: extends {@link BroadcastOptions} with an optional
|
|
13
13
|
* `casPublish` callback used to publish the CAS Announcement off-chain after the
|
|
14
14
|
* OP_RETURN signal is broadcast.
|
|
15
15
|
*/
|
|
@@ -21,7 +21,7 @@ export interface CASBroadcastOptions extends BroadcastOptions {
|
|
|
21
21
|
* Implements {@link https://dcdpr.github.io/did-btcr2/terminology.html#cas-beacon | CAS Beacon}.
|
|
22
22
|
*
|
|
23
23
|
* A CAS (Content-Addressed Store) Beacon aggregates updates for multiple DIDs
|
|
24
|
-
* into a single CAS Announcement
|
|
24
|
+
* into a single CAS Announcement: a mapping of DIDs to their update hashes.
|
|
25
25
|
* The hash of the CAS Announcement is broadcast on-chain via OP_RETURN.
|
|
26
26
|
* During resolution, the CAS Announcement is retrieved from the sidecar (or CAS)
|
|
27
27
|
* and used to look up the individual signed update for the DID being resolved.
|
|
@@ -63,14 +63,14 @@ export class CASBeacon extends SinglePartyBeacon {
|
|
|
63
63
|
const did = this.service.id.split('#')[0];
|
|
64
64
|
|
|
65
65
|
for(const signal of signals) {
|
|
66
|
-
// Signal bytes are hex
|
|
66
|
+
// Signal bytes are hex, matches hex-keyed sidecar maps directly
|
|
67
67
|
const announcementHash = signal.signalBytes;
|
|
68
68
|
|
|
69
69
|
// Look up the CAS Announcement in sidecar casMap
|
|
70
70
|
const casAnnouncement = sidecar.casMap.get(announcementHash);
|
|
71
71
|
|
|
72
72
|
if(!casAnnouncement) {
|
|
73
|
-
// CAS Announcement not available
|
|
73
|
+
// CAS Announcement not available, emit a need
|
|
74
74
|
needs.push({
|
|
75
75
|
kind : 'NeedCASAnnouncement',
|
|
76
76
|
announcementHash,
|
|
@@ -80,10 +80,10 @@ export class CASBeacon extends SinglePartyBeacon {
|
|
|
80
80
|
}
|
|
81
81
|
|
|
82
82
|
// Look up this DID's update hash in the CAS Announcement
|
|
83
|
-
// Announcement values are base64urlnopad per spec
|
|
83
|
+
// Announcement values are base64urlnopad per spec, convert to hex for map lookup
|
|
84
84
|
const updateHashEncoded = casAnnouncement[did];
|
|
85
85
|
|
|
86
|
-
// If no entry for this DID, this announcement doesn't contain an update for us
|
|
86
|
+
// If no entry for this DID, this announcement doesn't contain an update for us, skip
|
|
87
87
|
if(!updateHashEncoded) {
|
|
88
88
|
continue;
|
|
89
89
|
}
|
|
@@ -94,7 +94,7 @@ export class CASBeacon extends SinglePartyBeacon {
|
|
|
94
94
|
const signedUpdate = sidecar.updateMap.get(updateHash);
|
|
95
95
|
|
|
96
96
|
if(!signedUpdate) {
|
|
97
|
-
// Signed update not available
|
|
97
|
+
// Signed update not available, emit a need
|
|
98
98
|
needs.push({
|
|
99
99
|
kind : 'NeedSignedUpdate',
|
|
100
100
|
updateHash,
|
|
@@ -71,6 +71,6 @@ export interface BeaconSignal {
|
|
|
71
71
|
* The method package defines this type; the api layer provides the implementation
|
|
72
72
|
* (e.g., via CasApi.publish backed by IPFS/Helia).
|
|
73
73
|
*
|
|
74
|
-
* @param announcement The CAS Announcement object (DID
|
|
74
|
+
* @param announcement The CAS Announcement object (DID to update hash mapping).
|
|
75
75
|
*/
|
|
76
76
|
export type CasPublishFn = (announcement: Record<string, string>) => Promise<void>;
|
|
@@ -38,14 +38,14 @@ export class SingletonBeacon extends SinglePartyBeacon {
|
|
|
38
38
|
const needs = new Array<DataNeed>();
|
|
39
39
|
|
|
40
40
|
for(const signal of signals) {
|
|
41
|
-
// Signal bytes are hex
|
|
41
|
+
// Signal bytes are hex, matches hex-keyed sidecar maps directly
|
|
42
42
|
const updateHash = signal.signalBytes;
|
|
43
43
|
|
|
44
44
|
// Look up the signed update in sidecar updateMap
|
|
45
45
|
const signedUpdate = sidecar.updateMap.get(updateHash);
|
|
46
46
|
|
|
47
47
|
if(!signedUpdate) {
|
|
48
|
-
// Data not available
|
|
48
|
+
// Data not available, emit a need instead of throwing
|
|
49
49
|
needs.push({
|
|
50
50
|
kind : 'NeedSignedUpdate',
|
|
51
51
|
updateHash,
|
|
@@ -60,7 +60,7 @@ export class SMTBeacon extends SinglePartyBeacon {
|
|
|
60
60
|
const smtProof = sidecar.smtMap.get(signal.signalBytes);
|
|
61
61
|
|
|
62
62
|
if(!smtProof) {
|
|
63
|
-
// SMT Proof not available
|
|
63
|
+
// SMT Proof not available, emit a need
|
|
64
64
|
needs.push({
|
|
65
65
|
kind : 'NeedSMTProof',
|
|
66
66
|
smtRootHash : signal.signalBytes,
|
|
@@ -95,7 +95,7 @@ export class SMTBeacon extends SinglePartyBeacon {
|
|
|
95
95
|
);
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
-
// Non-inclusion proof verified
|
|
98
|
+
// Non-inclusion proof verified: no update for this DID this epoch, skip.
|
|
99
99
|
if(!smtProof.updateId) {
|
|
100
100
|
continue;
|
|
101
101
|
}
|
|
@@ -106,7 +106,7 @@ export class SMTBeacon extends SinglePartyBeacon {
|
|
|
106
106
|
const signedUpdate = sidecar.updateMap.get(updateHashHex);
|
|
107
107
|
|
|
108
108
|
if(!signedUpdate) {
|
|
109
|
-
// Signed update not available
|
|
109
|
+
// Signed update not available, emit a need
|
|
110
110
|
needs.push({
|
|
111
111
|
kind : 'NeedSignedUpdate',
|
|
112
112
|
updateHash : updateHashHex,
|
package/src/core/resolver.ts
CHANGED
|
@@ -164,7 +164,7 @@ export class Resolver {
|
|
|
164
164
|
#resolvedResponse: DidResolutionResponse | null = null;
|
|
165
165
|
|
|
166
166
|
/**
|
|
167
|
-
* @internal
|
|
167
|
+
* @internal Use {@link DidBtcr2.resolve} to create instances.
|
|
168
168
|
*/
|
|
169
169
|
constructor(
|
|
170
170
|
didComponents: DidComponents,
|
|
@@ -540,13 +540,13 @@ export class Resolver {
|
|
|
540
540
|
|
|
541
541
|
/**
|
|
542
542
|
* Advance the state machine. Returns either:
|
|
543
|
-
* - `{ status: 'action-required', needs }`
|
|
544
|
-
* - `{ status: 'resolved', result }`
|
|
543
|
+
* - `{ status: 'action-required', needs }` - caller must provide data via {@link provide}
|
|
544
|
+
* - `{ status: 'resolved', result }` - resolution complete
|
|
545
545
|
*
|
|
546
546
|
* Analogous to Rust's `Resolver::resolve()`.
|
|
547
547
|
*/
|
|
548
548
|
resolve(): ResolverState {
|
|
549
|
-
// Internal loop
|
|
549
|
+
// Internal loop: keeps advancing through phases until data is needed or done
|
|
550
550
|
while(true) {
|
|
551
551
|
switch(this.#phase) {
|
|
552
552
|
|
|
@@ -554,7 +554,7 @@ export class Resolver {
|
|
|
554
554
|
// Only entered for EXTERNAL (x HRP) identifiers when genesis doc was not in sidecar.
|
|
555
555
|
case ResolverPhase.GenesisDocument: {
|
|
556
556
|
if(this.#providedGenesisDocument) {
|
|
557
|
-
// Genesis doc was provided
|
|
557
|
+
// Genesis doc was provided, establish the current document
|
|
558
558
|
this.#currentDocument = Resolver.external(
|
|
559
559
|
this.#didComponents, this.#providedGenesisDocument
|
|
560
560
|
);
|
|
@@ -595,7 +595,7 @@ export class Resolver {
|
|
|
595
595
|
};
|
|
596
596
|
}
|
|
597
597
|
|
|
598
|
-
// No new beacon services to query
|
|
598
|
+
// No new beacon services to query, move to processing
|
|
599
599
|
this.#phase = ResolverPhase.BeaconProcess;
|
|
600
600
|
continue;
|
|
601
601
|
}
|
|
@@ -614,10 +614,10 @@ export class Resolver {
|
|
|
614
614
|
const result = beacon.processSignals(signals, this.#sidecarData);
|
|
615
615
|
|
|
616
616
|
if(result.needs.length > 0) {
|
|
617
|
-
// This service has unmet data needs
|
|
617
|
+
// This service has unmet data needs, collect them
|
|
618
618
|
allNeeds.push(...result.needs);
|
|
619
619
|
} else {
|
|
620
|
-
// All signals for this service resolved
|
|
620
|
+
// All signals for this service resolved, collect updates, mark processed
|
|
621
621
|
this.#unsortedUpdates.push(...result.updates);
|
|
622
622
|
this.#processedServices.add(service.id);
|
|
623
623
|
}
|
package/src/core/updater.ts
CHANGED
|
@@ -116,7 +116,7 @@ export interface UpdaterParams {
|
|
|
116
116
|
}
|
|
117
117
|
|
|
118
118
|
/**
|
|
119
|
-
* Sans-I/O state machine for did:btcr2 updates
|
|
119
|
+
* Sans-I/O state machine for did:btcr2 updates: the counterpart to {@link Resolver}.
|
|
120
120
|
*
|
|
121
121
|
* Created by {@link DidBtcr2.update} (the factory). The caller drives the update by
|
|
122
122
|
* repeatedly calling {@link advance} and {@link provide}:
|
|
@@ -168,7 +168,7 @@ export class Updater {
|
|
|
168
168
|
readonly #beaconService: BeaconService;
|
|
169
169
|
|
|
170
170
|
/**
|
|
171
|
-
* @internal
|
|
171
|
+
* @internal Use {@link DidBtcr2.update} to create instances.
|
|
172
172
|
*/
|
|
173
173
|
constructor(params: UpdaterParams) {
|
|
174
174
|
this.#sourceDocument = params.sourceDocument;
|
|
@@ -216,7 +216,7 @@ export class Updater {
|
|
|
216
216
|
// checks W3C conformance but not this equality, so it's enforced explicitly here.
|
|
217
217
|
if(targetDocument.id !== sourceDocument.id) {
|
|
218
218
|
throw new UpdateError(
|
|
219
|
-
`Patches must not change the DID document id (source "${sourceDocument.id}"
|
|
219
|
+
`Patches must not change the DID document id (source "${sourceDocument.id}" to target "${targetDocument.id}").`,
|
|
220
220
|
INVALID_DID_UPDATE, { sourceId: sourceDocument.id, targetId: targetDocument.id }
|
|
221
221
|
);
|
|
222
222
|
}
|
|
@@ -315,8 +315,8 @@ export class Updater {
|
|
|
315
315
|
|
|
316
316
|
/**
|
|
317
317
|
* Advance the state machine. Returns either:
|
|
318
|
-
* - `{ status: 'action-required', needs }`
|
|
319
|
-
* - `{ status: 'complete', result }`
|
|
318
|
+
* - `{ status: 'action-required', needs }` caller must provide data via {@link provide}
|
|
319
|
+
* - `{ status: 'complete', result }` update is signed and broadcast
|
|
320
320
|
*/
|
|
321
321
|
advance(): UpdaterState {
|
|
322
322
|
while(true) {
|
|
@@ -331,7 +331,7 @@ export class Updater {
|
|
|
331
331
|
}
|
|
332
332
|
|
|
333
333
|
// Phase: Sign
|
|
334
|
-
// Emit NeedSigningKey
|
|
334
|
+
// Emit NeedSigningKey: the caller supplies the secret key (or a KMS signature).
|
|
335
335
|
case 'Sign': {
|
|
336
336
|
return {
|
|
337
337
|
status : 'action-required',
|
package/src/did-btcr2.ts
CHANGED
|
@@ -135,8 +135,8 @@ export class DidBtcr2 implements DidMethod {
|
|
|
135
135
|
*
|
|
136
136
|
* Factory method that validates the update parameters and returns a sans-I/O
|
|
137
137
|
* {@link Updater} state machine. The caller drives the updater through its
|
|
138
|
-
* phases (Construct
|
|
139
|
-
* `provide()`. The method package performs **zero I/O
|
|
138
|
+
* phases (Construct -> Sign -> Broadcast -> Complete) by calling `advance()` and
|
|
139
|
+
* `provide()`. The method package performs **zero I/O**: signing key retrieval
|
|
140
140
|
* (or KMS delegation) and the on-chain broadcast are the caller's responsibility.
|
|
141
141
|
*
|
|
142
142
|
* For a fully-wired version with Bitcoin broadcast and key handling, see
|
package/src/index.ts
CHANGED
|
@@ -3,6 +3,9 @@ export * from './core/aggregation/service.js';
|
|
|
3
3
|
export * from './core/aggregation/participant.js';
|
|
4
4
|
export * from './core/aggregation/signer.js';
|
|
5
5
|
export * from './core/aggregation/conditions.js';
|
|
6
|
+
export * from './core/aggregation/recovery-policy.js';
|
|
7
|
+
export * from './core/aggregation/recovery-spend.js';
|
|
8
|
+
export * from './core/aggregation/fallback-spend.js';
|
|
6
9
|
export * from './core/aggregation/cohort.js';
|
|
7
10
|
export * from './core/aggregation/signing-session.js';
|
|
8
11
|
export * from './core/aggregation/phases.js';
|