@did-btcr2/method 0.33.0 → 0.34.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 +183 -9
- package/dist/browser.mjs +183 -9
- package/dist/cjs/index.js +198 -23
- package/dist/esm/core/aggregation/runner/aggregation-runner.js +66 -0
- package/dist/esm/core/aggregation/runner/aggregation-runner.js.map +1 -0
- package/dist/esm/core/aggregation/runner/index.js +1 -0
- package/dist/esm/core/aggregation/runner/index.js.map +1 -1
- package/dist/esm/core/aggregation/transport/in-memory.js +146 -0
- package/dist/esm/core/aggregation/transport/in-memory.js.map +1 -0
- package/dist/esm/core/aggregation/transport/index.js +1 -0
- package/dist/esm/core/aggregation/transport/index.js.map +1 -1
- package/dist/esm/core/beacon/beacon.js +10 -8
- package/dist/esm/core/beacon/beacon.js.map +1 -1
- package/dist/esm/core/beacon/cas-beacon.js +4 -4
- package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
- package/dist/esm/core/beacon/factory.js +1 -1
- package/dist/esm/core/beacon/singleton-beacon.js +4 -4
- package/dist/esm/core/beacon/singleton-beacon.js.map +1 -1
- package/dist/esm/core/beacon/smt-beacon.js +4 -4
- package/dist/esm/core/beacon/smt-beacon.js.map +1 -1
- package/dist/types/core/aggregation/runner/aggregation-runner.d.ts +56 -0
- package/dist/types/core/aggregation/runner/aggregation-runner.d.ts.map +1 -0
- package/dist/types/core/aggregation/runner/index.d.ts +1 -0
- package/dist/types/core/aggregation/runner/index.d.ts.map +1 -1
- package/dist/types/core/aggregation/transport/in-memory.d.ts +64 -0
- package/dist/types/core/aggregation/transport/in-memory.d.ts.map +1 -0
- package/dist/types/core/aggregation/transport/index.d.ts +1 -0
- package/dist/types/core/aggregation/transport/index.d.ts.map +1 -1
- package/dist/types/core/beacon/beacon.d.ts +12 -10
- package/dist/types/core/beacon/beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/cas-beacon.d.ts +4 -4
- package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/factory.d.ts +3 -3
- package/dist/types/core/beacon/factory.d.ts.map +1 -1
- package/dist/types/core/beacon/singleton-beacon.d.ts +4 -4
- package/dist/types/core/beacon/singleton-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/smt-beacon.d.ts +4 -4
- package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -1
- package/dist/types/core/resolver.d.ts +1 -1
- package/package.json +4 -4
- package/src/core/aggregation/runner/aggregation-runner.ts +96 -0
- package/src/core/aggregation/runner/index.ts +1 -0
- package/src/core/aggregation/transport/in-memory.ts +174 -0
- package/src/core/aggregation/transport/index.ts +1 -0
- package/src/core/beacon/beacon.ts +12 -10
- package/src/core/beacon/cas-beacon.ts +4 -4
- package/src/core/beacon/factory.ts +3 -3
- package/src/core/beacon/singleton-beacon.ts +4 -4
- package/src/core/beacon/smt-beacon.ts +4 -4
- package/src/core/resolver.ts +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@did-btcr2/method",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.34.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",
|
|
@@ -81,10 +81,10 @@
|
|
|
81
81
|
"multiformats": "^13.4.2",
|
|
82
82
|
"nostr-tools": "^2.23.3",
|
|
83
83
|
"@did-btcr2/smt": "^0.3.0",
|
|
84
|
-
"@did-btcr2/
|
|
85
|
-
"@did-btcr2/cryptosuite": "^8.0.0",
|
|
84
|
+
"@did-btcr2/common": "^9.1.0",
|
|
86
85
|
"@did-btcr2/bitcoin": "^0.6.0",
|
|
87
|
-
"@did-btcr2/
|
|
86
|
+
"@did-btcr2/keypair": "^0.13.0",
|
|
87
|
+
"@did-btcr2/cryptosuite": "^8.0.0"
|
|
88
88
|
},
|
|
89
89
|
"devDependencies": {
|
|
90
90
|
"@eslint/js": "^9.39.4",
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
import type { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
2
|
+
import type { AggregationResult } from '../service.js';
|
|
3
|
+
import { InMemoryBus, InMemoryTransport } from '../transport/in-memory.js';
|
|
4
|
+
import { AggregationParticipantRunner } from './participant-runner.js';
|
|
5
|
+
import type { OnProvideUpdate } from './participant-runner.js';
|
|
6
|
+
import { AggregationServiceRunner } from './service-runner.js';
|
|
7
|
+
import type { OnProvideTxData } from './service-runner.js';
|
|
8
|
+
|
|
9
|
+
/** Identity (DID + keys) for one actor in an {@link AggregationRunner.solo} run. */
|
|
10
|
+
export interface SoloActor {
|
|
11
|
+
did: string;
|
|
12
|
+
keys: SchnorrKeyPair;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Options for {@link AggregationRunner.solo}. */
|
|
16
|
+
export interface SoloCohortOptions {
|
|
17
|
+
/** The coordinating service identity. */
|
|
18
|
+
service: SoloActor;
|
|
19
|
+
/** The single participant identity (the lone signer of the cohort). */
|
|
20
|
+
participant: SoloActor;
|
|
21
|
+
/** Bitcoin network and beacon type (`'CASBeacon'` | `'SMTBeacon'`) for the cohort. */
|
|
22
|
+
config: { network: string; beaconType: string };
|
|
23
|
+
/** Provide the participant's signed BTCR2 update for the cohort. */
|
|
24
|
+
onProvideUpdate: OnProvideUpdate;
|
|
25
|
+
/** Provide the Bitcoin transaction data the cohort signs. */
|
|
26
|
+
onProvideTxData: OnProvideTxData;
|
|
27
|
+
/** Optional overall wall-clock budget for the run (ms). */
|
|
28
|
+
cohortTtlMs?: number;
|
|
29
|
+
/** Optional per-phase stall timeout (ms). */
|
|
30
|
+
phaseTimeoutMs?: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* High-level facades for driving an aggregation cohort to completion.
|
|
35
|
+
*
|
|
36
|
+
* @class AggregationRunner
|
|
37
|
+
*/
|
|
38
|
+
export class AggregationRunner {
|
|
39
|
+
/**
|
|
40
|
+
* Run a cohort of ONE participant entirely in-process and return the
|
|
41
|
+
* aggregated MuSig2 result.
|
|
42
|
+
*
|
|
43
|
+
* One party plays both the coordinating service and the lone participant,
|
|
44
|
+
* connected over an {@link InMemoryTransport} (no relay or HTTP server). This
|
|
45
|
+
* makes the single-participant aggregate-beacon path — the N=1 corner of the
|
|
46
|
+
* two-axis beacon matrix (see ADR 037) — first-class, useful for generating
|
|
47
|
+
* and reproducing single-participant aggregate test vectors.
|
|
48
|
+
*
|
|
49
|
+
* The service advertises a cohort with `minParticipants: 1`; the participant
|
|
50
|
+
* joins, submits its update, and the two complete keygen, data distribution,
|
|
51
|
+
* validation, and a one-signer MuSig2 P2TR key-path signing round.
|
|
52
|
+
*
|
|
53
|
+
* @param options Service + participant identities, cohort config, and the
|
|
54
|
+
* update / tx-data callbacks.
|
|
55
|
+
* @returns The {@link AggregationResult} (cohort id, aggregated signature, signed tx).
|
|
56
|
+
*/
|
|
57
|
+
static async solo(options: SoloCohortOptions): Promise<AggregationResult> {
|
|
58
|
+
const transport = new InMemoryTransport(new InMemoryBus());
|
|
59
|
+
transport.registerActor(options.service.did, options.service.keys);
|
|
60
|
+
transport.registerActor(options.participant.did, options.participant.keys);
|
|
61
|
+
// Pre-register communication keys both ways. Production exchanges these via
|
|
62
|
+
// the protocol handshake; in-process we wire them directly.
|
|
63
|
+
transport.registerPeer(options.participant.did, options.participant.keys.publicKey.compressed);
|
|
64
|
+
transport.registerPeer(options.service.did, options.service.keys.publicKey.compressed);
|
|
65
|
+
transport.start();
|
|
66
|
+
|
|
67
|
+
const service = new AggregationServiceRunner({
|
|
68
|
+
transport,
|
|
69
|
+
did : options.service.did,
|
|
70
|
+
keys : options.service.keys,
|
|
71
|
+
config : { minParticipants: 1, network: options.config.network, beaconType: options.config.beaconType },
|
|
72
|
+
onProvideTxData : options.onProvideTxData,
|
|
73
|
+
cohortTtlMs : options.cohortTtlMs,
|
|
74
|
+
phaseTimeoutMs : options.phaseTimeoutMs,
|
|
75
|
+
// In-process bus with the participant already listening: a single advert
|
|
76
|
+
// suffices, so disable the republish loop (no dangling interval).
|
|
77
|
+
advertRepeatIntervalMs : 0,
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
const participant = new AggregationParticipantRunner({
|
|
81
|
+
transport,
|
|
82
|
+
did : options.participant.did,
|
|
83
|
+
keys : options.participant.keys,
|
|
84
|
+
shouldJoin : async () => true,
|
|
85
|
+
onProvideUpdate : options.onProvideUpdate,
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
await participant.start();
|
|
89
|
+
try {
|
|
90
|
+
return await service.run();
|
|
91
|
+
} finally {
|
|
92
|
+
participant.stop();
|
|
93
|
+
service.stop();
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import type { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
2
|
+
import { bytesToHex, hexToBytes } from '@noble/hashes/utils';
|
|
3
|
+
import type { BaseMessage } from '../messages/base.js';
|
|
4
|
+
import type { MessageHandler, Transport } from './transport.js';
|
|
5
|
+
|
|
6
|
+
/** Internal registration for a single actor sharing an {@link InMemoryTransport}. */
|
|
7
|
+
interface ActorEntry {
|
|
8
|
+
keys: SchnorrKeyPair;
|
|
9
|
+
handlers: Map<string, MessageHandler>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* In-process message bus connecting one or more {@link InMemoryTransport}
|
|
14
|
+
* instances. Routes broadcasts to every registered actor and directed messages
|
|
15
|
+
* to the actor that owns the recipient DID — with no relay, server, or network.
|
|
16
|
+
*
|
|
17
|
+
* Each delivery does a JSON round-trip (Uint8Array preserved as `__bytes` hex)
|
|
18
|
+
* so handlers receive an isolated, serialization-faithful copy, exactly as a
|
|
19
|
+
* real transport would. The message `body` is merged to the top level to match
|
|
20
|
+
* the shape the {@link NostrTransport} dispatch produces.
|
|
21
|
+
*
|
|
22
|
+
* @class InMemoryBus
|
|
23
|
+
*/
|
|
24
|
+
export class InMemoryBus {
|
|
25
|
+
#transports: Set<InMemoryTransport> = new Set();
|
|
26
|
+
|
|
27
|
+
/** Attach a transport to this bus. Called by the transport's constructor. */
|
|
28
|
+
register(transport: InMemoryTransport): void {
|
|
29
|
+
this.#transports.add(transport);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/** Detach a transport from this bus. */
|
|
33
|
+
unregister(transport: InMemoryTransport): void {
|
|
34
|
+
this.#transports.delete(transport);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Deliver a message. With no `recipient` the message is broadcast to every
|
|
39
|
+
* actor on the bus; otherwise it is routed to the single transport that owns
|
|
40
|
+
* the recipient DID.
|
|
41
|
+
*/
|
|
42
|
+
async deliver(message: BaseMessage, _sender: string, recipient?: string): Promise<void> {
|
|
43
|
+
const type = (message as { type?: string }).type;
|
|
44
|
+
if(!type) return;
|
|
45
|
+
|
|
46
|
+
// JSON round-trip to mimic transport serialization, preserving Uint8Array.
|
|
47
|
+
const replacer = (_k: string, v: unknown): unknown => v instanceof Uint8Array ? { __bytes: bytesToHex(v) } : v;
|
|
48
|
+
const reviver = (_k: string, v: unknown): unknown =>
|
|
49
|
+
v && typeof v === 'object' && '__bytes' in (v as Record<string, unknown>)
|
|
50
|
+
? hexToBytes((v as { __bytes: string }).__bytes)
|
|
51
|
+
: v;
|
|
52
|
+
const raw = JSON.parse(JSON.stringify(message, replacer), reviver) as Record<string, unknown>;
|
|
53
|
+
const serialized = { ...raw, ...((raw.body as Record<string, unknown> | undefined) ?? {}) };
|
|
54
|
+
|
|
55
|
+
if(!recipient) {
|
|
56
|
+
for(const t of this.#transports) {
|
|
57
|
+
await t.dispatchBroadcast(type, serialized);
|
|
58
|
+
}
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
for(const t of this.#transports) {
|
|
62
|
+
if(t.hasActor(recipient)) {
|
|
63
|
+
await t.dispatchDirected(recipient, type, serialized);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* In-process {@link Transport} that routes aggregation messages through an
|
|
72
|
+
* {@link InMemoryBus} instead of a relay or HTTP server. Supports multiple
|
|
73
|
+
* actors per instance, so a single transport can host both a service and its
|
|
74
|
+
* participants (e.g. a cohort-of-one via {@link AggregationRunner.solo}).
|
|
75
|
+
*
|
|
76
|
+
* Encryption is a no-op (in-process, same trust domain); `registerPeer` /
|
|
77
|
+
* `getPeerPk` keep a registry so the contract matches the wire transports.
|
|
78
|
+
*
|
|
79
|
+
* @class InMemoryTransport
|
|
80
|
+
* @implements {Transport}
|
|
81
|
+
*/
|
|
82
|
+
export class InMemoryTransport implements Transport {
|
|
83
|
+
name: string = 'in-memory';
|
|
84
|
+
readonly bus: InMemoryBus;
|
|
85
|
+
|
|
86
|
+
#actors: Map<string, ActorEntry> = new Map();
|
|
87
|
+
#peers: Map<string, Uint8Array> = new Map();
|
|
88
|
+
|
|
89
|
+
/** @param bus Shared bus. Pass the same bus to connect multiple transports. */
|
|
90
|
+
constructor(bus: InMemoryBus = new InMemoryBus()) {
|
|
91
|
+
this.bus = bus;
|
|
92
|
+
this.bus.register(this);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
start(): void {
|
|
96
|
+
// No-op: there is no underlying connection to open.
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
registerActor(did: string, keys: SchnorrKeyPair): void {
|
|
100
|
+
this.#actors.set(did, { keys, handlers: new Map() });
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
getActorPk(did: string): Uint8Array | undefined {
|
|
104
|
+
return this.#actors.get(did)?.keys.publicKey.compressed;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
/** True if `did` is registered on this transport. Used by the bus for routing. */
|
|
108
|
+
hasActor(did: string): boolean {
|
|
109
|
+
return this.#actors.has(did);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
registerPeer(did: string, communicationPk: Uint8Array): void {
|
|
113
|
+
this.#peers.set(did, communicationPk);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
getPeerPk(did: string): Uint8Array | undefined {
|
|
117
|
+
return this.#peers.get(did);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
registerMessageHandler(actorDid: string, messageType: string, handler: MessageHandler): void {
|
|
121
|
+
const actor = this.#actors.get(actorDid);
|
|
122
|
+
if(actor) actor.handlers.set(messageType, handler);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
unregisterMessageHandler(actorDid: string, messageType: string): void {
|
|
126
|
+
const actor = this.#actors.get(actorDid);
|
|
127
|
+
if(actor) actor.handlers.delete(messageType);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
unregisterActor(did: string): void {
|
|
131
|
+
const actor = this.#actors.get(did);
|
|
132
|
+
if(!actor) return;
|
|
133
|
+
actor.handlers.clear();
|
|
134
|
+
this.#actors.delete(did);
|
|
135
|
+
this.#peers.delete(did);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
async sendMessage(message: BaseMessage, sender: string, recipient?: string): Promise<void> {
|
|
139
|
+
await this.bus.deliver(message, sender, recipient);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
publishRepeating(
|
|
143
|
+
message: BaseMessage,
|
|
144
|
+
sender: string,
|
|
145
|
+
intervalMs: number,
|
|
146
|
+
recipient?: string,
|
|
147
|
+
): () => void {
|
|
148
|
+
let stopped = false;
|
|
149
|
+
void this.sendMessage(message, sender, recipient).catch(() => { /* in-process: no relay to reject */ });
|
|
150
|
+
const timer = setInterval(() => {
|
|
151
|
+
if(stopped) return;
|
|
152
|
+
void this.sendMessage(message, sender, recipient).catch(() => { /* ignore */ });
|
|
153
|
+
}, intervalMs);
|
|
154
|
+
return () => {
|
|
155
|
+
if(stopped) return;
|
|
156
|
+
stopped = true;
|
|
157
|
+
clearInterval(timer);
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/** Deliver a broadcast message to every actor on this transport that handles `type`. */
|
|
162
|
+
async dispatchBroadcast(type: string, message: unknown): Promise<void> {
|
|
163
|
+
for(const actor of this.#actors.values()) {
|
|
164
|
+
const handler = actor.handlers.get(type);
|
|
165
|
+
if(handler) await handler(message);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** Deliver a directed message to the recipient actor's handler for `type`. */
|
|
170
|
+
async dispatchDirected(recipientDid: string, type: string, message: unknown): Promise<void> {
|
|
171
|
+
const handler = this.#actors.get(recipientDid)?.handlers.get(type);
|
|
172
|
+
if(handler) await handler(message);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
@@ -89,7 +89,7 @@ export function deriveSingletonAddress(
|
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
/**
|
|
92
|
-
* Options accepted by {@link
|
|
92
|
+
* Options accepted by {@link SinglePartyBeacon.buildSignAndBroadcast} and related helpers.
|
|
93
93
|
*/
|
|
94
94
|
export interface BroadcastOptions {
|
|
95
95
|
/** Fee estimator for computing the transaction fee. Defaults to {@link DEFAULT_FEE_ESTIMATOR}. */
|
|
@@ -115,14 +115,14 @@ export interface BeaconTxPlan {
|
|
|
115
115
|
feeSats: bigint;
|
|
116
116
|
/**
|
|
117
117
|
* Singleton beacon script kind, when applicable. Drives the signing dispatch
|
|
118
|
-
* in {@link
|
|
118
|
+
* in {@link SinglePartyBeacon.signSinglePartyTx}. Aggregation plans set this to `'p2tr'`.
|
|
119
119
|
*/
|
|
120
120
|
scriptKind: SingletonScriptKind;
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
/**
|
|
124
124
|
* Build an OP_RETURN script carrying a 32-byte beacon signal.
|
|
125
|
-
* Exported as a utility so callers building txs outside
|
|
125
|
+
* Exported as a utility so callers building txs outside SinglePartyBeacon (e.g., the aggregation
|
|
126
126
|
* `onProvideTxData` callback) can produce identical output.
|
|
127
127
|
*
|
|
128
128
|
* Uses the opcode *string* `'RETURN'` rather than the numeric `OP.RETURN`
|
|
@@ -168,7 +168,7 @@ async function fetchSpendableUtxo(
|
|
|
168
168
|
* Returns the unsigned Transaction + prev-output metadata that an aggregation service's
|
|
169
169
|
* signing session consumes (via {@link SigningTxData}).
|
|
170
170
|
*
|
|
171
|
-
* This is the reusable counterpart to {@link
|
|
171
|
+
* This is the reusable counterpart to {@link SinglePartyBeacon.buildSignAndBroadcast}'s internal
|
|
172
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
|
*
|
|
@@ -311,9 +311,11 @@ async function signSingletonInput(
|
|
|
311
311
|
}
|
|
312
312
|
|
|
313
313
|
/**
|
|
314
|
-
* Abstract base class
|
|
315
|
-
*
|
|
316
|
-
*
|
|
314
|
+
* Abstract base class providing the single-party broadcast machinery shared by
|
|
315
|
+
* all BTCR2 beacon types: one party holds one key and broadcasts one 32-byte
|
|
316
|
+
* signal (P2PKH / P2WPKH / P2TR key-path). The aggregation (cohort of N >= 1)
|
|
317
|
+
* broadcast mode is the orthogonal axis, handled by the AggregationService and
|
|
318
|
+
* {@link buildAggregationBeaconTx}, not by this class hierarchy. See ADR 037.
|
|
317
319
|
*
|
|
318
320
|
* Beacons are lightweight typed wrappers around a {@link BeaconService} configuration.
|
|
319
321
|
* Dependencies (signals, sidecar data, bitcoin connection) are passed as method
|
|
@@ -322,10 +324,10 @@ async function signSingletonInput(
|
|
|
322
324
|
* Use {@link BeaconFactory.establish} to create typed instances from service config.
|
|
323
325
|
*
|
|
324
326
|
* @abstract
|
|
325
|
-
* @class
|
|
326
|
-
* @type {
|
|
327
|
+
* @class SinglePartyBeacon
|
|
328
|
+
* @type {SinglePartyBeacon}
|
|
327
329
|
*/
|
|
328
|
-
export abstract class
|
|
330
|
+
export abstract class SinglePartyBeacon {
|
|
329
331
|
/**
|
|
330
332
|
* The Beacon service configuration parsed from the DID Document.
|
|
331
333
|
*/
|
|
@@ -5,7 +5,7 @@ import type { Signer } from '@did-btcr2/keypair';
|
|
|
5
5
|
import type { BeaconProcessResult, DataNeed } from '../resolver.js';
|
|
6
6
|
import type { SidecarData } from '../types.js';
|
|
7
7
|
import type { BroadcastOptions } from './beacon.js';
|
|
8
|
-
import {
|
|
8
|
+
import { SinglePartyBeacon } from './beacon.js';
|
|
9
9
|
import type { BeaconService, BeaconSignal, BlockMetadata, CasPublishFn } from './interfaces.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -28,9 +28,9 @@ export interface CASBroadcastOptions extends BroadcastOptions {
|
|
|
28
28
|
*
|
|
29
29
|
* @class CASBeacon
|
|
30
30
|
* @type {CASBeacon}
|
|
31
|
-
* @extends {
|
|
31
|
+
* @extends {SinglePartyBeacon}
|
|
32
32
|
*/
|
|
33
|
-
export class CASBeacon extends
|
|
33
|
+
export class CASBeacon extends SinglePartyBeacon {
|
|
34
34
|
/**
|
|
35
35
|
* Creates an instance of CASBeacon.
|
|
36
36
|
* @param {BeaconService} service The service of the Beacon.
|
|
@@ -115,7 +115,7 @@ export class CASBeacon extends Beacon {
|
|
|
115
115
|
* Creates a CAS Announcement mapping the DID to the update hash, broadcasts the hash of the
|
|
116
116
|
* announcement via OP_RETURN, and optionally publishes the announcement off-chain via the
|
|
117
117
|
* supplied `casPublish` callback. UTXO selection, PSBT construction, fee estimation, signing,
|
|
118
|
-
* and broadcast are delegated to {@link
|
|
118
|
+
* and broadcast are delegated to {@link SinglePartyBeacon.buildSignAndBroadcast}.
|
|
119
119
|
*
|
|
120
120
|
* @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
|
|
121
121
|
* @param {Signer} signer Signer that produces the ECDSA signature for the Bitcoin transaction.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MethodError } from '@did-btcr2/common';
|
|
2
|
-
import type {
|
|
2
|
+
import type { SinglePartyBeacon } from './beacon.js';
|
|
3
3
|
import { CASBeacon } from './cas-beacon.js';
|
|
4
4
|
import type { BeaconService } from './interfaces.js';
|
|
5
5
|
import { SingletonBeacon } from './singleton-beacon.js';
|
|
@@ -14,9 +14,9 @@ export class BeaconFactory {
|
|
|
14
14
|
/**
|
|
15
15
|
* Establish a Beacon instance based on the provided service and optional sidecar data.
|
|
16
16
|
* @param {BeaconService} service The beacon service configuration.
|
|
17
|
-
* @returns {
|
|
17
|
+
* @returns {SinglePartyBeacon} The established Beacon instance.
|
|
18
18
|
*/
|
|
19
|
-
static establish(service: BeaconService):
|
|
19
|
+
static establish(service: BeaconService): SinglePartyBeacon {
|
|
20
20
|
switch (service.type) {
|
|
21
21
|
case 'SingletonBeacon':
|
|
22
22
|
return new SingletonBeacon(service);
|
|
@@ -5,16 +5,16 @@ import type { Signer } from '@did-btcr2/keypair';
|
|
|
5
5
|
import type { BeaconProcessResult, DataNeed } from '../resolver.js';
|
|
6
6
|
import type { SidecarData } from '../types.js';
|
|
7
7
|
import type { BroadcastOptions } from './beacon.js';
|
|
8
|
-
import {
|
|
8
|
+
import { SinglePartyBeacon } from './beacon.js';
|
|
9
9
|
import type { BeaconService, BeaconSignal, BlockMetadata } from './interfaces.js';
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Implements {@link https://dcdpr.github.io/did-btcr2/terminology.html#singleton-beacon | Singleton Beacon}.
|
|
13
13
|
* @class SingletonBeacon
|
|
14
14
|
* @type {SingletonBeacon}
|
|
15
|
-
* @extends {
|
|
15
|
+
* @extends {SinglePartyBeacon}
|
|
16
16
|
*/
|
|
17
|
-
export class SingletonBeacon extends
|
|
17
|
+
export class SingletonBeacon extends SinglePartyBeacon {
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Creates an instance of SingletonBeacon.
|
|
@@ -64,7 +64,7 @@ export class SingletonBeacon extends Beacon {
|
|
|
64
64
|
*
|
|
65
65
|
* The signal bytes embedded in OP_RETURN are the SHA-256 canonical hash of the signed update.
|
|
66
66
|
* UTXO selection, PSBT construction, fee estimation, signing, and broadcast are delegated to
|
|
67
|
-
* {@link
|
|
67
|
+
* {@link SinglePartyBeacon.buildSignAndBroadcast}.
|
|
68
68
|
*
|
|
69
69
|
* @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
|
|
70
70
|
* @param {Signer} signer Signer that produces the ECDSA signature for the Bitcoin transaction.
|
|
@@ -7,7 +7,7 @@ import { randomBytes } from '@noble/hashes/utils';
|
|
|
7
7
|
import type { BeaconProcessResult, DataNeed } from '../resolver.js';
|
|
8
8
|
import type { SidecarData } from '../types.js';
|
|
9
9
|
import type { BroadcastOptions } from './beacon.js';
|
|
10
|
-
import {
|
|
10
|
+
import { SinglePartyBeacon } from './beacon.js';
|
|
11
11
|
import { SMTBeaconError } from './error.js';
|
|
12
12
|
import type { BeaconService, BeaconSignal, BlockMetadata } from './interfaces.js';
|
|
13
13
|
|
|
@@ -21,9 +21,9 @@ import type { BeaconService, BeaconSignal, BlockMetadata } from './interfaces.js
|
|
|
21
21
|
*
|
|
22
22
|
* @class SMTBeacon
|
|
23
23
|
* @type {SMTBeacon}
|
|
24
|
-
* @extends {
|
|
24
|
+
* @extends {SinglePartyBeacon}
|
|
25
25
|
*/
|
|
26
|
-
export class SMTBeacon extends
|
|
26
|
+
export class SMTBeacon extends SinglePartyBeacon {
|
|
27
27
|
/**
|
|
28
28
|
* Creates an instance of SMTBeacon.
|
|
29
29
|
* @param {BeaconService} service The Beacon service.
|
|
@@ -127,7 +127,7 @@ export class SMTBeacon extends Beacon {
|
|
|
127
127
|
* Builds a single-entry Sparse Merkle Tree from the signed update, then broadcasts the tree's
|
|
128
128
|
* root hash via OP_RETURN. For multi-party aggregation, use the {@link AggregationService}
|
|
129
129
|
* subsystem directly instead of this method. UTXO selection, PSBT construction, fee estimation,
|
|
130
|
-
* signing, and broadcast are delegated to {@link
|
|
130
|
+
* signing, and broadcast are delegated to {@link SinglePartyBeacon.buildSignAndBroadcast}.
|
|
131
131
|
*
|
|
132
132
|
* @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
|
|
133
133
|
* @param {Signer} signer Signer that produces the ECDSA signature for the Bitcoin transaction.
|
package/src/core/resolver.ts
CHANGED
|
@@ -102,7 +102,7 @@ export type ResolverState =
|
|
|
102
102
|
| { status: 'resolved'; result: DidResolutionResponse };
|
|
103
103
|
|
|
104
104
|
/**
|
|
105
|
-
* Return type from {@link
|
|
105
|
+
* Return type from {@link SinglePartyBeacon.processSignals}.
|
|
106
106
|
* Contains successfully resolved updates and any data needs that must be
|
|
107
107
|
* satisfied before the remaining signals can be processed.
|
|
108
108
|
*/
|