@did-btcr2/method 0.24.1 → 0.25.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/browser.js +697 -554
- package/dist/browser.mjs +697 -554
- package/dist/cjs/core/beacon/beacon.js.map +1 -1
- package/dist/cjs/core/beacon/cas-beacon.js +119 -7
- package/dist/cjs/core/beacon/cas-beacon.js.map +1 -1
- package/dist/cjs/core/beacon/factory.js +1 -1
- package/dist/cjs/core/beacon/factory.js.map +1 -1
- package/dist/cjs/core/beacon/{singleton.js → singleton-beacon.js} +18 -26
- package/dist/cjs/core/beacon/singleton-beacon.js.map +1 -0
- package/dist/cjs/core/beacon/smt-beacon.js +1 -1
- package/dist/cjs/core/beacon/smt-beacon.js.map +1 -1
- package/dist/{esm/core/resolve.js → cjs/core/resolver.js} +241 -93
- package/dist/cjs/core/resolver.js.map +1 -0
- package/dist/cjs/core/update.js +5 -5
- package/dist/cjs/core/update.js.map +1 -1
- package/dist/cjs/did-btcr2.js +34 -92
- package/dist/cjs/did-btcr2.js.map +1 -1
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/esm/core/beacon/beacon.js.map +1 -1
- package/dist/esm/core/beacon/cas-beacon.js +119 -7
- 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/factory.js.map +1 -1
- package/dist/esm/core/beacon/{singleton.js → singleton-beacon.js} +18 -26
- package/dist/esm/core/beacon/singleton-beacon.js.map +1 -0
- package/dist/esm/core/beacon/smt-beacon.js +1 -1
- package/dist/esm/core/beacon/smt-beacon.js.map +1 -1
- package/dist/{cjs/core/resolve.js → esm/core/resolver.js} +241 -93
- package/dist/esm/core/resolver.js.map +1 -0
- package/dist/esm/core/update.js +5 -5
- package/dist/esm/core/update.js.map +1 -1
- package/dist/esm/did-btcr2.js +34 -92
- package/dist/esm/did-btcr2.js.map +1 -1
- package/dist/esm/index.js +2 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/types/core/beacon/beacon.d.ts +9 -4
- package/dist/types/core/beacon/beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/cas-beacon.d.ts +26 -7
- package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/{singleton.d.ts → singleton-beacon.d.ts} +7 -5
- package/dist/types/core/beacon/singleton-beacon.d.ts.map +1 -0
- package/dist/types/core/beacon/smt-beacon.d.ts +4 -3
- package/dist/types/core/beacon/smt-beacon.d.ts.map +1 -1
- package/dist/types/core/interfaces.d.ts +5 -15
- package/dist/types/core/interfaces.d.ts.map +1 -1
- package/dist/types/core/resolver.d.ts +167 -0
- package/dist/types/core/resolver.d.ts.map +1 -0
- package/dist/types/core/update.d.ts +3 -3
- package/dist/types/core/update.d.ts.map +1 -1
- package/dist/types/did-btcr2.d.ts +16 -16
- package/dist/types/did-btcr2.d.ts.map +1 -1
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/core/beacon/beacon.ts +9 -5
- package/src/core/beacon/cas-beacon.ts +156 -10
- package/src/core/beacon/factory.ts +1 -1
- package/src/core/beacon/{singleton.ts → singleton-beacon.ts} +19 -35
- package/src/core/beacon/smt-beacon.ts +4 -3
- package/src/core/interfaces.ts +5 -16
- package/src/core/{resolve.ts → resolver.ts} +355 -130
- package/src/core/update.ts +7 -7
- package/src/did-btcr2.ts +37 -128
- package/src/index.ts +2 -2
- package/dist/cjs/core/beacon/singleton.js.map +0 -1
- package/dist/cjs/core/resolve.js.map +0 -1
- package/dist/esm/core/beacon/singleton.js.map +0 -1
- package/dist/esm/core/resolve.js.map +0 -1
- package/dist/types/core/beacon/singleton.d.ts.map +0 -1
- package/dist/types/core/resolve.d.ts +0 -93
- package/dist/types/core/resolve.d.ts.map +0 -1
package/dist/cjs/did-btcr2.js
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { IdentifierHrp, INVALID_DID_DOCUMENT, INVALID_DID_UPDATE, METHOD_NOT_SUPPORTED, MethodError,
|
|
2
|
-
import { Did, DidError, DidErrorCode,
|
|
1
|
+
import { IdentifierHrp, INVALID_DID_DOCUMENT, INVALID_DID_UPDATE, METHOD_NOT_SUPPORTED, MethodError, UpdateError } from '@did-btcr2/common';
|
|
2
|
+
import { Did, DidError, DidErrorCode, } from '@web5/dids';
|
|
3
3
|
import { initEccLib } from 'bitcoinjs-lib';
|
|
4
4
|
import * as tinysecp from 'tiny-secp256k1';
|
|
5
|
-
import { BeaconUtils } from './core/beacon/utils.js';
|
|
6
5
|
import { Identifier } from './core/identifier.js';
|
|
7
|
-
import {
|
|
6
|
+
import { Resolver } from './core/resolver.js';
|
|
8
7
|
import { Update } from './core/update.js';
|
|
9
8
|
import { Appendix } from './utils/appendix.js';
|
|
10
9
|
/** Initialize tiny secp256k1 */
|
|
@@ -35,7 +34,7 @@ export class DidBtcr2 {
|
|
|
35
34
|
* @param {string} options.idType The type of identifier to create, either 'KEY' or 'EXTERNAL'. Defaults to 'KEY'.
|
|
36
35
|
* @param {number} options.version The version number of the did:btcr2 specification to use for creating the identifier. Defaults to 1.
|
|
37
36
|
* @param {string} options.network The Bitcoin network to use for the identifier, e.g. 'bitcoin', 'testnet', etc. Defaults to 'bitcoin'.
|
|
38
|
-
* @returns {Promise<
|
|
37
|
+
* @returns {Promise<string>} Promise resolving to an identifier string.
|
|
39
38
|
* @throws {MethodError} if any of the checks fail
|
|
40
39
|
* @example
|
|
41
40
|
* ```ts
|
|
@@ -54,99 +53,42 @@ export class DidBtcr2 {
|
|
|
54
53
|
}
|
|
55
54
|
/**
|
|
56
55
|
* Entry point for section {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html | 7.2 Resolve}.
|
|
57
|
-
* See specification for the {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#process | Resolve Process}.
|
|
58
|
-
* See {@link Resolve | Resolve (class)} for class implementation.
|
|
59
56
|
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* deterministically created from the DID or provided by Sidecar Data.
|
|
57
|
+
* Factory method that performs pure setup and returns a {@link Resolver} state machine.
|
|
58
|
+
* The caller drives resolution by calling `resolver.resolve()` and `resolver.provide()`.
|
|
59
|
+
* Analogous to Rust's `Document::read()`.
|
|
64
60
|
*
|
|
65
61
|
* @param {string} did The did:btcr2 identifier to be resolved.
|
|
66
62
|
* @param {ResolutionOptions} resolutionOptions Options used during the resolution process.
|
|
67
|
-
* @returns {
|
|
68
|
-
* @throws {ResolveError} If the resolution process fails at any step.
|
|
63
|
+
* @returns {Resolver} A sans-I/O state machine the caller drives to completion.
|
|
69
64
|
* @example
|
|
70
65
|
* ```ts
|
|
71
|
-
* const
|
|
72
|
-
*
|
|
73
|
-
* )
|
|
66
|
+
* const resolver = DidBtcr2.resolve(did, { sidecar });
|
|
67
|
+
* let state = resolver.resolve();
|
|
68
|
+
* while (state.status === 'action-required') {
|
|
69
|
+
* for (const need of state.needs) { ... provide data ... }
|
|
70
|
+
* state = resolver.resolve();
|
|
71
|
+
* }
|
|
72
|
+
* const { didDocument, metadata } = state.result;
|
|
74
73
|
* ```
|
|
75
74
|
*/
|
|
76
|
-
static
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
const didComponents = Identifier.decode(did);
|
|
94
|
-
// Process sidecar if provided
|
|
95
|
-
const sidecarData = Resolve.sidecarData(resolutionOptions.sidecar);
|
|
96
|
-
// Parse the genesis document from the resolution options if provided
|
|
97
|
-
const genesisDocument = resolutionOptions.sidecar?.genesisDocument;
|
|
98
|
-
// Since genesisDocument is optional, check if it exists
|
|
99
|
-
if (!genesisDocument) {
|
|
100
|
-
// If no genesisDocument and x HRP, throw MISSING_UPDATE_DATA error
|
|
101
|
-
if (didComponents.hrp === IdentifierHrp.x)
|
|
102
|
-
throw new ResolveError('External resolution requires genesisDocument', MISSING_UPDATE_DATA, resolutionOptions);
|
|
103
|
-
}
|
|
104
|
-
// Establish the current document
|
|
105
|
-
const currentDocument = await Resolve.currentDocument(didComponents, genesisDocument);
|
|
106
|
-
// Extract all Beacon services from the current DID Document
|
|
107
|
-
const beaconServices = currentDocument.service
|
|
108
|
-
.filter(BeaconUtils.isBeaconService)
|
|
109
|
-
.map(BeaconUtils.parseBeaconServiceEndpoint);
|
|
110
|
-
// Check if bitcoin driver provided
|
|
111
|
-
if (!resolutionOptions?.drivers?.bitcoin) {
|
|
112
|
-
throw new ResolveError('Bitcoin connection required for resolve. Pass a configured driver via '
|
|
113
|
-
+ 'resolutionOptions.drivers.bitcoin or use DidBtcr2Api which injects it automatically.', MISSING_RESOLUTION_OPTIONS, resolutionOptions);
|
|
114
|
-
}
|
|
115
|
-
// Get the bitcoin driver from the resolution options
|
|
116
|
-
const bitcoin = resolutionOptions.drivers.bitcoin;
|
|
117
|
-
// Process the Beacon Signals to get the required updates
|
|
118
|
-
const unsortedUpdates = await Resolve.beaconSignals(beaconServices, sidecarData, bitcoin);
|
|
119
|
-
// If no updates found, return the current document
|
|
120
|
-
if (!unsortedUpdates.length) {
|
|
121
|
-
// Set the didDocument in didResolutionResult based on currentDocument
|
|
122
|
-
didResolutionResult.didDocument = currentDocument;
|
|
123
|
-
// Set other required fields in the didResolutionResult
|
|
124
|
-
didResolutionResult.didDocumentMetadata.deactivated = !!currentDocument.deactivated;
|
|
125
|
-
didResolutionResult.didDocumentMetadata.versionId = versionId ?? '1';
|
|
126
|
-
// Return the didResolutionResult early
|
|
127
|
-
return didResolutionResult;
|
|
128
|
-
}
|
|
129
|
-
// Process the updates to apply updates to bring the current DID Document to its more current state
|
|
130
|
-
const result = await Resolve.updates(currentDocument, unsortedUpdates, resolutionOptions.versionTime, versionId);
|
|
131
|
-
// Set all of the required fields in the didResolutionResult
|
|
132
|
-
didResolutionResult.didDocument = result.didDocument;
|
|
133
|
-
didResolutionResult.didDocumentMetadata = result.metadata;
|
|
134
|
-
// Return didResolutionResult;
|
|
135
|
-
return didResolutionResult;
|
|
136
|
-
}
|
|
137
|
-
catch (error) {
|
|
138
|
-
// Rethrow any unexpected errors that are not a `ResolveError`.
|
|
139
|
-
if (!(error instanceof ResolveError))
|
|
140
|
-
throw new Error(error.message ?? error, { cause: error });
|
|
141
|
-
// Return a DID Resolution Result with the appropriate error code.
|
|
142
|
-
return {
|
|
143
|
-
...EMPTY_DID_RESOLUTION_RESULT,
|
|
144
|
-
didResolutionMetadata: {
|
|
145
|
-
error: error.type,
|
|
146
|
-
...error.message && { errorMessage: error.message }
|
|
147
|
-
}
|
|
148
|
-
};
|
|
149
|
-
}
|
|
75
|
+
static resolve(did, resolutionOptions = {}) {
|
|
76
|
+
// Decode the did to be resolved
|
|
77
|
+
const didComponents = Identifier.decode(did);
|
|
78
|
+
// Process sidecar if provided
|
|
79
|
+
const sidecarData = Resolver.sidecarData(resolutionOptions.sidecar);
|
|
80
|
+
// Establish the current document for KEY identifiers (pure, synchronous).
|
|
81
|
+
// For EXTERNAL identifiers, defer to the Resolver's GenesisDocument phase
|
|
82
|
+
// since validation (Resolve.external) is async.
|
|
83
|
+
const currentDocument = didComponents.hrp === IdentifierHrp.k
|
|
84
|
+
? Resolver.deterministic(didComponents)
|
|
85
|
+
: null;
|
|
86
|
+
// Return the sans-I/O state machine
|
|
87
|
+
return new Resolver(didComponents, sidecarData, currentDocument, {
|
|
88
|
+
versionId: resolutionOptions.versionId,
|
|
89
|
+
versionTime: resolutionOptions.versionTime,
|
|
90
|
+
genesisDocument: resolutionOptions.sidecar?.genesisDocument
|
|
91
|
+
});
|
|
150
92
|
}
|
|
151
93
|
/**
|
|
152
94
|
* Entry point for section {@link https://dcdpr.github.io/did-btcr2/#read | 7.3 Update}.
|
|
@@ -196,9 +138,9 @@ export class DidBtcr2 {
|
|
|
196
138
|
throw new UpdateError('Invalid verificationMethodId: publicKeyMultibase prefix must start with "zQ3s"', INVALID_DID_DOCUMENT, verificationMethod);
|
|
197
139
|
}
|
|
198
140
|
// Construct an unsigned update following the BTCR2 Update construction algorithm
|
|
199
|
-
const update =
|
|
141
|
+
const update = Update.construct(sourceDocument, patches, sourceVersionId);
|
|
200
142
|
// Sign the unsigned update using the specified verification method
|
|
201
|
-
const signed =
|
|
143
|
+
const signed = Update.sign(sourceDocument.id, update, verificationMethod, secretKey);
|
|
202
144
|
// Filter sourceDocument services to get beaconServices matching beaconIds
|
|
203
145
|
const beaconService = sourceDocument.service
|
|
204
146
|
.filter((service) => service.id === beaconId)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"did-btcr2.js","sourceRoot":"","sources":["../../src/did-btcr2.ts"],"names":[],"mappings":"AACA,OAAO,EAGL,aAAa,EACb,oBAAoB,EACpB,kBAAkB,EAElB,oBAAoB,EACpB,WAAW,
|
|
1
|
+
{"version":3,"file":"did-btcr2.js","sourceRoot":"","sources":["../../src/did-btcr2.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/index.js
CHANGED
|
@@ -28,12 +28,12 @@ export * from './core/beacon/error.js';
|
|
|
28
28
|
export * from './core/beacon/factory.js';
|
|
29
29
|
export * from './core/beacon/interfaces.js';
|
|
30
30
|
export * from './core/beacon/signal-discovery.js';
|
|
31
|
-
export * from './core/beacon/singleton.js';
|
|
31
|
+
export * from './core/beacon/singleton-beacon.js';
|
|
32
32
|
export * from './core/beacon/smt-beacon.js';
|
|
33
33
|
export * from './core/beacon/utils.js';
|
|
34
34
|
export * from './core/identifier.js';
|
|
35
35
|
export * from './core/interfaces.js';
|
|
36
|
-
export * from './core/
|
|
36
|
+
export * from './core/resolver.js';
|
|
37
37
|
export * from './core/types.js';
|
|
38
38
|
export * from './core/update.js';
|
|
39
39
|
export * from './utils/appendix.js';
|
package/dist/cjs/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,2CAA2C,CAAC;AAC1D,cAAc,4CAA4C,CAAC;AAE3D,cAAc,mDAAmD,CAAC;AAClE,cAAc,wDAAwD,CAAC;AACvE,cAAc,oDAAoD,CAAC;AACnE,cAAc,gEAAgE,CAAC;AAC/E,cAAc,mEAAmE,CAAC;AAClF,cAAc,kEAAkE,CAAC;AACjF,cAAc,mEAAmE,CAAC;AAClF,cAAc,4DAA4D,CAAC;AAC3E,cAAc,oEAAoE,CAAC;AACnF,cAAc,yEAAyE,CAAC;AACxF,cAAc,sEAAsE,CAAC;AACrF,cAAc,qEAAqE,CAAC;AACpF,cAAc,2EAA2E,CAAC;AAE1F,cAAc,6DAA6D,CAAC;AAC5E,cAAc,0DAA0D,CAAC;AAEzE,cAAc,kDAAkD,CAAC;AACjE,cAAc,oDAAoD,CAAC;AACnE,cAAc,oDAAoD,CAAC;AAEnE,cAAc,0CAA0C,CAAC;AACzD,cAAc,0CAA0C,CAAC;AACzD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,6CAA6C,CAAC;AAE5D,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,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,2CAA2C,CAAC;AAC1D,cAAc,4CAA4C,CAAC;AAE3D,cAAc,mDAAmD,CAAC;AAClE,cAAc,wDAAwD,CAAC;AACvE,cAAc,oDAAoD,CAAC;AACnE,cAAc,gEAAgE,CAAC;AAC/E,cAAc,mEAAmE,CAAC;AAClF,cAAc,kEAAkE,CAAC;AACjF,cAAc,mEAAmE,CAAC;AAClF,cAAc,4DAA4D,CAAC;AAC3E,cAAc,oEAAoE,CAAC;AACnF,cAAc,yEAAyE,CAAC;AACxF,cAAc,sEAAsE,CAAC;AACrF,cAAc,qEAAqE,CAAC;AACpF,cAAc,2EAA2E,CAAC;AAE1F,cAAc,6DAA6D,CAAC;AAC5E,cAAc,0DAA0D,CAAC;AAEzE,cAAc,kDAAkD,CAAC;AACjE,cAAc,oDAAoD,CAAC;AACnE,cAAc,oDAAoD,CAAC;AAEnE,cAAc,0CAA0C,CAAC;AACzD,cAAc,0CAA0C,CAAC;AACzD,cAAc,4CAA4C,CAAC;AAC3D,cAAc,6CAA6C,CAAC;AAE5D,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;AAEvC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AAEjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,iCAAiC,CAAC;AAChD,cAAc,yBAAyB,CAAC;AAExC,cAAc,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"beacon.js","sourceRoot":"","sources":["../../../../src/core/beacon/beacon.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"beacon.js","sourceRoot":"","sources":["../../../../src/core/beacon/beacon.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAgB,MAAM;IAC1B;;OAEG;IACM,OAAO,CAAgB;IAEhC,YAAY,OAAsB;QAChC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,CAAC;CA+BF"}
|
|
@@ -1,7 +1,17 @@
|
|
|
1
|
+
import { canonicalHash, canonicalize, decode, encode, hash } from '@did-btcr2/common';
|
|
2
|
+
import { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
3
|
+
import { opcodes, Psbt, script } from 'bitcoinjs-lib';
|
|
1
4
|
import { Beacon } from './beacon.js';
|
|
2
5
|
import { CASBeaconError } from './error.js';
|
|
3
6
|
/**
|
|
4
7
|
* Implements {@link https://dcdpr.github.io/did-btcr2/terminology.html#cas-beacon | CAS Beacon}.
|
|
8
|
+
*
|
|
9
|
+
* A CAS (Content-Addressed Store) Beacon aggregates updates for multiple DIDs
|
|
10
|
+
* into a single CAS Announcement — a mapping of DIDs to their update hashes.
|
|
11
|
+
* The hash of the CAS Announcement is broadcast on-chain via OP_RETURN.
|
|
12
|
+
* During resolution, the CAS Announcement is retrieved from the sidecar (or CAS)
|
|
13
|
+
* and used to look up the individual signed update for the DID being resolved.
|
|
14
|
+
*
|
|
5
15
|
* @class CASBeacon
|
|
6
16
|
* @type {CASBeacon}
|
|
7
17
|
* @extends {Beacon}
|
|
@@ -16,24 +26,126 @@ export class CASBeacon extends Beacon {
|
|
|
16
26
|
}
|
|
17
27
|
/**
|
|
18
28
|
* Implements {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#process-cas-beacon | 7.2.e.1 Process CAS Beacon}.
|
|
29
|
+
*
|
|
30
|
+
* For each signal, the signalBytes contain the hex-encoded hash of a CAS Announcement.
|
|
31
|
+
* The CAS Announcement maps DIDs to their base64url-encoded update hashes.
|
|
32
|
+
* This method looks up the CAS Announcement from the sidecar, extracts the update
|
|
33
|
+
* hash for the DID being resolved, and retrieves the corresponding signed update.
|
|
34
|
+
*
|
|
19
35
|
* @param {Array<BeaconSignal>} signals The array of Beacon Signals to process.
|
|
20
36
|
* @param {SidecarData} sidecar The sidecar data associated with the CAS Beacon.
|
|
21
|
-
* @returns {
|
|
22
|
-
* @throws {CASBeaconError} if
|
|
37
|
+
* @returns {BeaconProcessResult} Successfully resolved updates and any data needs.
|
|
38
|
+
* @throws {CASBeaconError} if hash verification fails (validation errors only).
|
|
23
39
|
*/
|
|
24
40
|
processSignals(signals, sidecar) {
|
|
25
|
-
|
|
41
|
+
const updates = new Array();
|
|
42
|
+
const needs = new Array();
|
|
43
|
+
// Extract the DID from the beacon service id (strip the #fragment)
|
|
44
|
+
const did = this.service.id.split('#')[0];
|
|
45
|
+
for (const signal of signals) {
|
|
46
|
+
// Decode signal bytes from hex and re-encode to base64url for sidecar lookup
|
|
47
|
+
const announcementHash = encode(decode(signal.signalBytes, 'hex'));
|
|
48
|
+
// Look up the CAS Announcement in sidecar casMap
|
|
49
|
+
const casAnnouncement = sidecar.casMap.get(announcementHash);
|
|
50
|
+
if (!casAnnouncement) {
|
|
51
|
+
// CAS Announcement not available — emit a need
|
|
52
|
+
needs.push({
|
|
53
|
+
kind: 'NeedCASAnnouncement',
|
|
54
|
+
announcementHash,
|
|
55
|
+
beaconServiceId: this.service.id
|
|
56
|
+
});
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
// Look up this DID's update hash in the CAS Announcement
|
|
60
|
+
const updateHash = casAnnouncement[did];
|
|
61
|
+
// If no entry for this DID, this announcement doesn't contain an update for us — skip
|
|
62
|
+
if (!updateHash) {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
// Look up the signed update in sidecar updateMap
|
|
66
|
+
const signedUpdate = sidecar.updateMap.get(updateHash);
|
|
67
|
+
if (!signedUpdate) {
|
|
68
|
+
// Signed update not available — emit a need
|
|
69
|
+
needs.push({
|
|
70
|
+
kind: 'NeedSignedUpdate',
|
|
71
|
+
updateHash,
|
|
72
|
+
beaconServiceId: this.service.id
|
|
73
|
+
});
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
updates.push([signedUpdate, signal.blockMetadata]);
|
|
77
|
+
}
|
|
78
|
+
return { updates, needs };
|
|
26
79
|
}
|
|
27
80
|
/**
|
|
28
|
-
*
|
|
81
|
+
* Broadcasts a CAS Beacon signal to the Bitcoin network.
|
|
82
|
+
*
|
|
83
|
+
* Creates a CAS Announcement mapping the DID to the update hash, then broadcasts
|
|
84
|
+
* the hash of the announcement via OP_RETURN. The CAS Announcement is distributed
|
|
85
|
+
* to resolvers via sidecar data.
|
|
86
|
+
*
|
|
29
87
|
* @param {SignedBTCR2Update} signedUpdate The signed BTCR2 update to broadcast.
|
|
30
88
|
* @param {KeyBytes} secretKey The secret key for signing the Bitcoin transaction.
|
|
31
89
|
* @param {BitcoinConnection} bitcoin The Bitcoin network connection.
|
|
32
|
-
* @
|
|
33
|
-
* @throws {CASBeaconError} if
|
|
90
|
+
* @returns {Promise<SignedBTCR2Update>} The signed update that was broadcast.
|
|
91
|
+
* @throws {CASBeaconError} if the bitcoin address is invalid or unfunded.
|
|
34
92
|
*/
|
|
35
93
|
async broadcastSignal(signedUpdate, secretKey, bitcoin) {
|
|
36
|
-
|
|
94
|
+
// Extract the DID from the beacon service id (strip the #fragment)
|
|
95
|
+
const did = this.service.id.split('#')[0];
|
|
96
|
+
// Hash the signed update (base64url for the CAS Announcement entry)
|
|
97
|
+
const updateHash = canonicalHash(signedUpdate);
|
|
98
|
+
// Create the CAS Announcement mapping this DID to its update hash
|
|
99
|
+
const casAnnouncement = { [did]: updateHash };
|
|
100
|
+
// TODO: Publish CAS Announcement to content-addressed store (e.g., IPFS via Helia)
|
|
101
|
+
// Canonicalize and hash the CAS Announcement for the OP_RETURN output
|
|
102
|
+
const announcementHash = hash(canonicalize(casAnnouncement));
|
|
103
|
+
// Convert the serviceEndpoint to a bitcoin address by removing the 'bitcoin:' prefix
|
|
104
|
+
const bitcoinAddress = this.service.serviceEndpoint.replace('bitcoin:', '');
|
|
105
|
+
// Query the Bitcoin network for UTXOs associated with the bitcoinAddress
|
|
106
|
+
const utxos = await bitcoin.rest.address.getUtxos(bitcoinAddress);
|
|
107
|
+
// If no utxos are found, throw an error indicating the address is unfunded.
|
|
108
|
+
if (!utxos.length) {
|
|
109
|
+
throw new CASBeaconError('No UTXOs found, please fund address!', 'UNFUNDED_BEACON_ADDRESS', { bitcoinAddress });
|
|
110
|
+
}
|
|
111
|
+
// Sort utxos by block height and take the most recent one
|
|
112
|
+
const utxo = utxos.sort((a, b) => b.status.block_height - a.status.block_height).shift();
|
|
113
|
+
// If no utxos are found, throw an error.
|
|
114
|
+
if (!utxo) {
|
|
115
|
+
throw new CASBeaconError('Beacon bitcoin address unfunded or utxos unconfirmed.', 'UNFUNDED_BEACON_ADDRESS', { bitcoinAddress });
|
|
116
|
+
}
|
|
117
|
+
// Get the previous tx to the utxo being spent
|
|
118
|
+
const prevTx = await bitcoin.rest.transaction.getHex(utxo.txid);
|
|
119
|
+
// Construct a spend transaction
|
|
120
|
+
const spendTx = new Psbt({ network: bitcoin.data })
|
|
121
|
+
// Spend tx contains the utxo as its input
|
|
122
|
+
.addInput({
|
|
123
|
+
hash: utxo.txid,
|
|
124
|
+
index: utxo.vout,
|
|
125
|
+
nonWitnessUtxo: Buffer.from(prevTx, 'hex')
|
|
126
|
+
})
|
|
127
|
+
// Add a change output minus a fee of 500 sats
|
|
128
|
+
// TODO: calculate fee based on transaction vsize and current fee rates
|
|
129
|
+
.addOutput({ address: bitcoinAddress, value: BigInt(utxo.value) - BigInt(500) })
|
|
130
|
+
// Add an OP_RETURN output containing the CAS Announcement hash
|
|
131
|
+
.addOutput({ script: script.compile([opcodes.OP_RETURN, announcementHash]), value: 0n });
|
|
132
|
+
// Construct a key pair and PSBT signer from the secret key
|
|
133
|
+
const keyPair = SchnorrKeyPair.fromSecret(secretKey);
|
|
134
|
+
const signer = {
|
|
135
|
+
publicKey: keyPair.publicKey.compressed,
|
|
136
|
+
sign: (hash) => keyPair.secretKey.sign(hash, { scheme: 'ecdsa' }),
|
|
137
|
+
};
|
|
138
|
+
// Sign 0th input, finalize extract to hex in prep for broadcast
|
|
139
|
+
const signedTx = spendTx.signInput(0, signer)
|
|
140
|
+
.finalizeAllInputs()
|
|
141
|
+
.extractTransaction()
|
|
142
|
+
.toHex();
|
|
143
|
+
// Broadcast spendTx to the Bitcoin network.
|
|
144
|
+
const txid = await bitcoin.rest.transaction.send(signedTx);
|
|
145
|
+
// Log the txid of the broadcasted transaction
|
|
146
|
+
console.info(`CAS Beacon Signal Broadcasted with txid: ${txid}`);
|
|
147
|
+
// Return the signed update
|
|
148
|
+
return signedUpdate;
|
|
37
149
|
}
|
|
38
150
|
}
|
|
39
151
|
//# sourceMappingURL=cas-beacon.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cas-beacon.js","sourceRoot":"","sources":["../../../../src/core/beacon/cas-beacon.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"cas-beacon.js","sourceRoot":"","sources":["../../../../src/core/beacon/cas-beacon.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { MethodError } from '@did-btcr2/common';
|
|
2
2
|
import { CASBeacon } from './cas-beacon.js';
|
|
3
|
-
import { SingletonBeacon } from './singleton.js';
|
|
3
|
+
import { SingletonBeacon } from './singleton-beacon.js';
|
|
4
4
|
import { SMTBeacon } from './smt-beacon.js';
|
|
5
5
|
/**
|
|
6
6
|
* Beacon Factory pattern to create Beacon instances.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../../src/core/beacon/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"factory.js","sourceRoot":"","sources":["../../../../src/core/beacon/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C;;;;GAIG;AACH,MAAM,OAAO,aAAa;IACxB;;;;OAIG;IACH,MAAM,CAAC,SAAS,CAAC,OAAsB;QACrC,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;YACrB,KAAK,iBAAiB;gBACpB,OAAO,IAAI,eAAe,CAAC,OAAO,CAAC,CAAC;YACtC,KAAK,WAAW;gBACd,OAAO,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC;YAChC,KAAK,WAAW;gBACd,OAAO,IAAI,SAAS,CAAC,OAAO,CAAC,CAAC;YAChC;gBACE,MAAM,IAAI,WAAW,CAAC,qBAAqB,EAAE,sBAAsB,EAAE,OAAO,CAAC,CAAC;QAClF,CAAC;IACH,CAAC;CACF"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { canonicalize, decode, encode, hash } from '@did-btcr2/common';
|
|
2
2
|
import { SchnorrKeyPair } from '@did-btcr2/keypair';
|
|
3
|
-
import { base64urlnopad } from '@scure/base';
|
|
4
3
|
import { opcodes, Psbt, script } from 'bitcoinjs-lib';
|
|
5
4
|
import { Beacon } from './beacon.js';
|
|
6
5
|
import { SingletonBeaconError } from './error.js';
|
|
@@ -20,37 +19,30 @@ export class SingletonBeacon extends Beacon {
|
|
|
20
19
|
}
|
|
21
20
|
/**
|
|
22
21
|
* Processes an array of Beacon Signals associated with a Singleton Beacon Service.
|
|
23
|
-
* @
|
|
24
|
-
* @
|
|
22
|
+
* @param {Array<BeaconSignal>} signals The beacon signals discovered on-chain.
|
|
23
|
+
* @param {SidecarData} sidecar The processed sidecar data.
|
|
24
|
+
* @returns {BeaconProcessResult} Successfully resolved updates and any data needs.
|
|
25
25
|
*/
|
|
26
|
-
|
|
27
|
-
// Initialize an empty array to hold the BTCR2 signed updates
|
|
26
|
+
processSignals(signals, sidecar) {
|
|
28
27
|
const updates = new Array();
|
|
29
|
-
|
|
28
|
+
const needs = new Array();
|
|
30
29
|
for (const signal of signals) {
|
|
31
|
-
//
|
|
32
|
-
const updateHash = signal.signalBytes;
|
|
33
|
-
//
|
|
30
|
+
// Decode signal bytes from hex and re-encode to base64url for sidecar lookup
|
|
31
|
+
const updateHash = encode(decode(signal.signalBytes, 'hex'));
|
|
32
|
+
// Look up the signed update in sidecar updateMap
|
|
34
33
|
const signedUpdate = sidecar.updateMap.get(updateHash);
|
|
35
|
-
// If no btcr2 update is found in sidecar data maps, throw missingUpdateData error.
|
|
36
34
|
if (!signedUpdate) {
|
|
37
|
-
|
|
35
|
+
// Data not available — emit a need instead of throwing
|
|
36
|
+
needs.push({
|
|
37
|
+
kind: 'NeedSignedUpdate',
|
|
38
|
+
updateHash,
|
|
39
|
+
beaconServiceId: this.service.id
|
|
40
|
+
});
|
|
41
|
+
continue;
|
|
38
42
|
}
|
|
39
|
-
// TODO: Review for simplification how we are encoding and comparing
|
|
40
|
-
// Canonicalize, hash and encode to base64url the signed update object found in sidecar or CAS
|
|
41
|
-
const encodedUpdate = canonicalHash(signedUpdate, { encoding: 'base64url' });
|
|
42
|
-
// Encode the signal bytes hex string to base64url
|
|
43
|
-
const signalBytes = base64urlnopad.encode(Buffer.from(updateHash, 'hex'));
|
|
44
|
-
// Check for mismatch between found sidecar/cas update hash and onchain beacon signal hash
|
|
45
|
-
if (encodedUpdate !== signalBytes) {
|
|
46
|
-
// If mismatch, throw invalidSidecarData error.
|
|
47
|
-
throw new SingletonBeaconError(`Hash mismatch: sidecar update ${encodedUpdate} !== signal bytes ${signalBytes}.`, INVALID_SIDECAR_DATA, { encodedUpdate, signalBytes });
|
|
48
|
-
}
|
|
49
|
-
// Push signedUpdate to updates array
|
|
50
43
|
updates.push([signedUpdate, signal.blockMetadata]);
|
|
51
44
|
}
|
|
52
|
-
|
|
53
|
-
return updates;
|
|
45
|
+
return { updates, needs };
|
|
54
46
|
}
|
|
55
47
|
/**
|
|
56
48
|
* Broadcasts a SingletonBeacon signal to the Bitcoin network.
|
|
@@ -111,4 +103,4 @@ export class SingletonBeacon extends Beacon {
|
|
|
111
103
|
return signedUpdate;
|
|
112
104
|
}
|
|
113
105
|
}
|
|
114
|
-
//# sourceMappingURL=singleton.js.map
|
|
106
|
+
//# sourceMappingURL=singleton-beacon.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"singleton-beacon.js","sourceRoot":"","sources":["../../../../src/core/beacon/singleton-beacon.ts"],"names":[],"mappings":"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"}
|
|
@@ -18,7 +18,7 @@ export class SMTBeacon extends Beacon {
|
|
|
18
18
|
* Implements {@link https://dcdpr.github.io/did-btcr2/operations/resolve.html#process-smt-beacon | 7.2.e.1 Process SMT Beacon}.
|
|
19
19
|
* @param {Array<BeaconSignal>} signals The array of Beacon Signals to process.
|
|
20
20
|
* @param {SidecarData} sidecar The sidecar data associated with the SMT Beacon.
|
|
21
|
-
* @returns {
|
|
21
|
+
* @returns {BeaconProcessResult} The processed signals.
|
|
22
22
|
* @throws {SMTBeaconError} if processing fails.
|
|
23
23
|
*/
|
|
24
24
|
processSignals(signals, sidecar) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"smt-beacon.js","sourceRoot":"","sources":["../../../../src/core/beacon/smt-beacon.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"smt-beacon.js","sourceRoot":"","sources":["../../../../src/core/beacon/smt-beacon.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAG5C;;;;;GAKG;AACH,MAAM,OAAO,SAAU,SAAQ,MAAM;IACnC;;;OAGG;IACH,YAAY,OAAsB;QAChC,KAAK,CAAC,EAAE,GAAG,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC;IAC3C,CAAC;IAED;;;;;;OAMG;IACH,cAAc,CACZ,OAA4B,EAC5B,OAAoB;QAEpB,MAAM,IAAI,cAAc,CAAC,yBAAyB,EAAE,wBAAwB,EAAE,EAAC,OAAO,EAAE,OAAO,EAAC,CAAC,CAAC;IACpG,CAAC;IAED;;;;;;;OAOG;IACH,KAAK,CAAC,eAAe,CACnB,YAA+B,EAC/B,SAAmB,EACnB,OAA0B;QAE1B,MAAM,IAAI,cAAc,CAAC,yBAAyB,EAAE,wBAAwB,EAAE,EAAC,YAAY,EAAE,SAAS,EAAE,OAAO,EAAC,CAAC,CAAC;IACpH,CAAC;CACF"}
|