@did-btcr2/method 0.42.0 → 0.44.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 +52 -21
- package/dist/browser.mjs +52 -21
- package/dist/cjs/index.js +56 -21
- package/dist/esm/core/beacon/cas-beacon.js +22 -0
- package/dist/esm/core/beacon/cas-beacon.js.map +1 -1
- package/dist/esm/core/beacon/signal-discovery.js +40 -18
- package/dist/esm/core/beacon/signal-discovery.js.map +1 -1
- package/dist/esm/did-btcr2.js +5 -4
- package/dist/esm/did-btcr2.js.map +1 -1
- package/dist/esm/utils/did-document.js +49 -7
- package/dist/esm/utils/did-document.js.map +1 -1
- package/dist/types/core/beacon/cas-beacon.d.ts +22 -0
- package/dist/types/core/beacon/cas-beacon.d.ts.map +1 -1
- package/dist/types/core/beacon/signal-discovery.d.ts +14 -0
- package/dist/types/core/beacon/signal-discovery.d.ts.map +1 -1
- package/dist/types/did-btcr2.d.ts.map +1 -1
- package/dist/types/utils/did-document.d.ts +23 -0
- package/dist/types/utils/did-document.d.ts.map +1 -1
- package/package.json +5 -5
- package/src/core/beacon/cas-beacon.ts +22 -0
- package/src/core/beacon/signal-discovery.ts +44 -22
- package/src/did-btcr2.ts +8 -4
- package/src/utils/did-document.ts +58 -5
package/dist/browser.js
CHANGED
|
@@ -93170,6 +93170,8 @@ a=end-of-candidates
|
|
|
93170
93170
|
GenesisDocument: () => GenesisDocument,
|
|
93171
93171
|
ID_PLACEHOLDER_VALUE: () => ID_PLACEHOLDER_VALUE,
|
|
93172
93172
|
Identifier: () => Identifier,
|
|
93173
|
+
MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX: () => MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX,
|
|
93174
|
+
MULTIKEY_VERIFICATION_METHOD_TYPE: () => MULTIKEY_VERIFICATION_METHOD_TYPE,
|
|
93173
93175
|
P2PKH_BEACON_TX_VSIZE: () => P2PKH_BEACON_TX_VSIZE,
|
|
93174
93176
|
P2TR_BEACON_TX_VSIZE: () => P2TR_BEACON_TX_VSIZE,
|
|
93175
93177
|
P2WPKH_BEACON_TX_VSIZE: () => P2WPKH_BEACON_TX_VSIZE,
|
|
@@ -93186,6 +93188,8 @@ a=end-of-candidates
|
|
|
93186
93188
|
buildAggregationBeaconTx: () => buildAggregationBeaconTx,
|
|
93187
93189
|
deriveSingletonAddress: () => deriveSingletonAddress,
|
|
93188
93190
|
detectSingletonScriptKind: () => detectSingletonScriptKind,
|
|
93191
|
+
extractOpReturnSignal: () => extractOpReturnSignal,
|
|
93192
|
+
isMultikeyVerificationMethod: () => isMultikeyVerificationMethod,
|
|
93189
93193
|
opReturnScript: () => opReturnScript,
|
|
93190
93194
|
resolveBtcr2SenderPk: () => resolveBtcr2SenderPk,
|
|
93191
93195
|
resolveChangeAddress: () => resolveChangeAddress
|
|
@@ -117694,6 +117698,20 @@ a=end-of-candidates
|
|
|
117694
117698
|
};
|
|
117695
117699
|
|
|
117696
117700
|
// src/core/beacon/signal-discovery.ts
|
|
117701
|
+
function extractOpReturnSignal(asm) {
|
|
117702
|
+
if (!asm) {
|
|
117703
|
+
return null;
|
|
117704
|
+
}
|
|
117705
|
+
const tokens = asm.trim().split(/\s+/);
|
|
117706
|
+
if (tokens.length !== 3 || tokens[0] !== "OP_RETURN" || tokens[1] !== "OP_PUSHBYTES_32") {
|
|
117707
|
+
return null;
|
|
117708
|
+
}
|
|
117709
|
+
const signalHash = tokens[2];
|
|
117710
|
+
if (!/^[0-9a-fA-F]{64}$/.test(signalHash)) {
|
|
117711
|
+
return null;
|
|
117712
|
+
}
|
|
117713
|
+
return signalHash.toLowerCase();
|
|
117714
|
+
}
|
|
117697
117715
|
var BeaconSignalDiscovery = class {
|
|
117698
117716
|
/**
|
|
117699
117717
|
* Retrieves the beacon signals for the given array of BeaconService objects
|
|
@@ -117715,15 +117733,10 @@ a=end-of-candidates
|
|
|
117715
117733
|
}
|
|
117716
117734
|
for (const beaconSignal of beaconSignals) {
|
|
117717
117735
|
const signalVout = beaconSignal.vout.slice(-1)[0];
|
|
117718
|
-
if (!signalVout
|
|
117719
|
-
continue;
|
|
117720
|
-
}
|
|
117721
|
-
const outputMap = new Map(Object.entries(signalVout));
|
|
117722
|
-
const signalVoutScriptPubkey = outputMap.get("scriptpubkey_asm");
|
|
117723
|
-
if (!signalVoutScriptPubkey) {
|
|
117736
|
+
if (!signalVout) {
|
|
117724
117737
|
continue;
|
|
117725
117738
|
}
|
|
117726
|
-
const updateHash =
|
|
117739
|
+
const updateHash = extractOpReturnSignal(signalVout.scriptpubkey_asm);
|
|
117727
117740
|
if (!updateHash) {
|
|
117728
117741
|
continue;
|
|
117729
117742
|
}
|
|
@@ -117792,14 +117805,11 @@ a=end-of-candidates
|
|
|
117792
117805
|
continue;
|
|
117793
117806
|
}
|
|
117794
117807
|
const txVoutScriptPubkeyAsm = prevout.vout[vin.vout].scriptPubKey.asm;
|
|
117795
|
-
|
|
117796
|
-
continue;
|
|
117797
|
-
}
|
|
117798
|
-
console.info(`Tx ${tx.txid} contains beacon service address ${scriptPubKey.address} and OP_RETURN!`, tx);
|
|
117799
|
-
const updateHash = txVoutScriptPubkeyAsm.split(" ").slice(-1)[0];
|
|
117808
|
+
const updateHash = extractOpReturnSignal(txVoutScriptPubkeyAsm);
|
|
117800
117809
|
if (!updateHash) {
|
|
117801
117810
|
continue;
|
|
117802
117811
|
}
|
|
117812
|
+
console.info(`Tx ${tx.txid} contains beacon service address ${scriptPubKey.address} and OP_RETURN!`, tx);
|
|
117803
117813
|
beaconServiceSignals.get(beaconService)?.push({
|
|
117804
117814
|
tx,
|
|
117805
117815
|
signalBytes: updateHash,
|
|
@@ -118602,9 +118612,18 @@ a=end-of-candidates
|
|
|
118602
118612
|
"https://www.w3.org/ns/did/v1.1",
|
|
118603
118613
|
"https://btcr2.dev/context/v1"
|
|
118604
118614
|
];
|
|
118615
|
+
var MULTIKEY_VERIFICATION_METHOD_TYPE = "Multikey";
|
|
118616
|
+
var MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX = "zQ3s";
|
|
118605
118617
|
var ID_PLACEHOLDER_VALUE = "did:btcr2:_";
|
|
118606
118618
|
var BECH32M_CHARS = "";
|
|
118607
118619
|
var DID_REGEX = /did:btcr2:(x1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]*)/g;
|
|
118620
|
+
function isMultikeyVerificationMethod(vm) {
|
|
118621
|
+
if (!Appendix.isDidVerificationMethod(vm)) {
|
|
118622
|
+
return false;
|
|
118623
|
+
}
|
|
118624
|
+
const { type, publicKeyMultibase } = vm;
|
|
118625
|
+
return type === MULTIKEY_VERIFICATION_METHOD_TYPE && typeof publicKeyMultibase === "string" && publicKeyMultibase.startsWith(MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX);
|
|
118626
|
+
}
|
|
118608
118627
|
var DidVerificationMethod = class {
|
|
118609
118628
|
id;
|
|
118610
118629
|
type;
|
|
@@ -118612,6 +118631,20 @@ a=end-of-candidates
|
|
|
118612
118631
|
publicKeyMultibase;
|
|
118613
118632
|
secretKeyMultibase;
|
|
118614
118633
|
constructor({ id, type, controller, publicKeyMultibase, secretKeyMultibase }) {
|
|
118634
|
+
if (type !== MULTIKEY_VERIFICATION_METHOD_TYPE) {
|
|
118635
|
+
throw new DidDocumentError(
|
|
118636
|
+
`Invalid verification method: type must be "${MULTIKEY_VERIFICATION_METHOD_TYPE}"`,
|
|
118637
|
+
INVALID_DID_DOCUMENT,
|
|
118638
|
+
{ id, type }
|
|
118639
|
+
);
|
|
118640
|
+
}
|
|
118641
|
+
if (typeof publicKeyMultibase !== "string" || !publicKeyMultibase.startsWith(MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX)) {
|
|
118642
|
+
throw new DidDocumentError(
|
|
118643
|
+
`Invalid verification method: publicKeyMultibase must start with "${MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX}"`,
|
|
118644
|
+
INVALID_DID_DOCUMENT,
|
|
118645
|
+
{ id, publicKeyMultibase }
|
|
118646
|
+
);
|
|
118647
|
+
}
|
|
118615
118648
|
this.id = id;
|
|
118616
118649
|
this.type = type;
|
|
118617
118650
|
this.controller = controller;
|
|
@@ -118770,10 +118803,8 @@ a=end-of-candidates
|
|
|
118770
118803
|
* @returns {boolean} True if the context is valid.
|
|
118771
118804
|
*/
|
|
118772
118805
|
static isValidContext(context) {
|
|
118773
|
-
if (!context) return false;
|
|
118774
|
-
|
|
118775
|
-
if (!context.every((ctx) => typeof ctx === "string" && BTCR2_DID_DOCUMENT_CONTEXT.includes(ctx))) return false;
|
|
118776
|
-
return true;
|
|
118806
|
+
if (!Array.isArray(context) || context.length === 0) return false;
|
|
118807
|
+
return BTCR2_DID_DOCUMENT_CONTEXT.every((required) => context.includes(required));
|
|
118777
118808
|
}
|
|
118778
118809
|
/**
|
|
118779
118810
|
* Validates that the DID Document has a valid id.
|
|
@@ -118797,7 +118828,7 @@ a=end-of-candidates
|
|
|
118797
118828
|
* @returns {boolean} True if the verification methods are valid.
|
|
118798
118829
|
*/
|
|
118799
118830
|
static isValidVerificationMethods(verificationMethod) {
|
|
118800
|
-
return Array.isArray(verificationMethod) && verificationMethod.every(
|
|
118831
|
+
return Array.isArray(verificationMethod) && verificationMethod.every(isMultikeyVerificationMethod);
|
|
118801
118832
|
}
|
|
118802
118833
|
/**
|
|
118803
118834
|
* Validates that the DID Document has valid services.
|
|
@@ -119339,16 +119370,16 @@ a=end-of-candidates
|
|
|
119339
119370
|
{ sourceDocument, verificationMethodId }
|
|
119340
119371
|
);
|
|
119341
119372
|
}
|
|
119342
|
-
if (verificationMethod.type !==
|
|
119373
|
+
if (verificationMethod.type !== MULTIKEY_VERIFICATION_METHOD_TYPE) {
|
|
119343
119374
|
throw new UpdateError(
|
|
119344
|
-
|
|
119375
|
+
`Invalid verificationMethod: verificationMethod.type must be "${MULTIKEY_VERIFICATION_METHOD_TYPE}"`,
|
|
119345
119376
|
INVALID_DID_DOCUMENT,
|
|
119346
119377
|
verificationMethod
|
|
119347
119378
|
);
|
|
119348
119379
|
}
|
|
119349
|
-
if (verificationMethod.publicKeyMultibase?.
|
|
119380
|
+
if (!verificationMethod.publicKeyMultibase?.startsWith(MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX)) {
|
|
119350
119381
|
throw new UpdateError(
|
|
119351
|
-
|
|
119382
|
+
`Invalid verificationMethodId: publicKeyMultibase prefix must start with "${MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX}"`,
|
|
119352
119383
|
INVALID_DID_DOCUMENT,
|
|
119353
119384
|
verificationMethod
|
|
119354
119385
|
);
|
package/dist/browser.mjs
CHANGED
|
@@ -117646,6 +117646,20 @@ var BeaconUtils = class {
|
|
|
117646
117646
|
};
|
|
117647
117647
|
|
|
117648
117648
|
// src/core/beacon/signal-discovery.ts
|
|
117649
|
+
function extractOpReturnSignal(asm) {
|
|
117650
|
+
if (!asm) {
|
|
117651
|
+
return null;
|
|
117652
|
+
}
|
|
117653
|
+
const tokens = asm.trim().split(/\s+/);
|
|
117654
|
+
if (tokens.length !== 3 || tokens[0] !== "OP_RETURN" || tokens[1] !== "OP_PUSHBYTES_32") {
|
|
117655
|
+
return null;
|
|
117656
|
+
}
|
|
117657
|
+
const signalHash = tokens[2];
|
|
117658
|
+
if (!/^[0-9a-fA-F]{64}$/.test(signalHash)) {
|
|
117659
|
+
return null;
|
|
117660
|
+
}
|
|
117661
|
+
return signalHash.toLowerCase();
|
|
117662
|
+
}
|
|
117649
117663
|
var BeaconSignalDiscovery = class {
|
|
117650
117664
|
/**
|
|
117651
117665
|
* Retrieves the beacon signals for the given array of BeaconService objects
|
|
@@ -117667,15 +117681,10 @@ var BeaconSignalDiscovery = class {
|
|
|
117667
117681
|
}
|
|
117668
117682
|
for (const beaconSignal of beaconSignals) {
|
|
117669
117683
|
const signalVout = beaconSignal.vout.slice(-1)[0];
|
|
117670
|
-
if (!signalVout
|
|
117671
|
-
continue;
|
|
117672
|
-
}
|
|
117673
|
-
const outputMap = new Map(Object.entries(signalVout));
|
|
117674
|
-
const signalVoutScriptPubkey = outputMap.get("scriptpubkey_asm");
|
|
117675
|
-
if (!signalVoutScriptPubkey) {
|
|
117684
|
+
if (!signalVout) {
|
|
117676
117685
|
continue;
|
|
117677
117686
|
}
|
|
117678
|
-
const updateHash =
|
|
117687
|
+
const updateHash = extractOpReturnSignal(signalVout.scriptpubkey_asm);
|
|
117679
117688
|
if (!updateHash) {
|
|
117680
117689
|
continue;
|
|
117681
117690
|
}
|
|
@@ -117744,14 +117753,11 @@ var BeaconSignalDiscovery = class {
|
|
|
117744
117753
|
continue;
|
|
117745
117754
|
}
|
|
117746
117755
|
const txVoutScriptPubkeyAsm = prevout.vout[vin.vout].scriptPubKey.asm;
|
|
117747
|
-
|
|
117748
|
-
continue;
|
|
117749
|
-
}
|
|
117750
|
-
console.info(`Tx ${tx.txid} contains beacon service address ${scriptPubKey.address} and OP_RETURN!`, tx);
|
|
117751
|
-
const updateHash = txVoutScriptPubkeyAsm.split(" ").slice(-1)[0];
|
|
117756
|
+
const updateHash = extractOpReturnSignal(txVoutScriptPubkeyAsm);
|
|
117752
117757
|
if (!updateHash) {
|
|
117753
117758
|
continue;
|
|
117754
117759
|
}
|
|
117760
|
+
console.info(`Tx ${tx.txid} contains beacon service address ${scriptPubKey.address} and OP_RETURN!`, tx);
|
|
117755
117761
|
beaconServiceSignals.get(beaconService)?.push({
|
|
117756
117762
|
tx,
|
|
117757
117763
|
signalBytes: updateHash,
|
|
@@ -118554,9 +118560,18 @@ var BTCR2_DID_DOCUMENT_CONTEXT = [
|
|
|
118554
118560
|
"https://www.w3.org/ns/did/v1.1",
|
|
118555
118561
|
"https://btcr2.dev/context/v1"
|
|
118556
118562
|
];
|
|
118563
|
+
var MULTIKEY_VERIFICATION_METHOD_TYPE = "Multikey";
|
|
118564
|
+
var MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX = "zQ3s";
|
|
118557
118565
|
var ID_PLACEHOLDER_VALUE = "did:btcr2:_";
|
|
118558
118566
|
var BECH32M_CHARS = "";
|
|
118559
118567
|
var DID_REGEX = /did:btcr2:(x1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]*)/g;
|
|
118568
|
+
function isMultikeyVerificationMethod(vm) {
|
|
118569
|
+
if (!Appendix.isDidVerificationMethod(vm)) {
|
|
118570
|
+
return false;
|
|
118571
|
+
}
|
|
118572
|
+
const { type, publicKeyMultibase } = vm;
|
|
118573
|
+
return type === MULTIKEY_VERIFICATION_METHOD_TYPE && typeof publicKeyMultibase === "string" && publicKeyMultibase.startsWith(MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX);
|
|
118574
|
+
}
|
|
118560
118575
|
var DidVerificationMethod = class {
|
|
118561
118576
|
id;
|
|
118562
118577
|
type;
|
|
@@ -118564,6 +118579,20 @@ var DidVerificationMethod = class {
|
|
|
118564
118579
|
publicKeyMultibase;
|
|
118565
118580
|
secretKeyMultibase;
|
|
118566
118581
|
constructor({ id, type, controller, publicKeyMultibase, secretKeyMultibase }) {
|
|
118582
|
+
if (type !== MULTIKEY_VERIFICATION_METHOD_TYPE) {
|
|
118583
|
+
throw new DidDocumentError(
|
|
118584
|
+
`Invalid verification method: type must be "${MULTIKEY_VERIFICATION_METHOD_TYPE}"`,
|
|
118585
|
+
INVALID_DID_DOCUMENT,
|
|
118586
|
+
{ id, type }
|
|
118587
|
+
);
|
|
118588
|
+
}
|
|
118589
|
+
if (typeof publicKeyMultibase !== "string" || !publicKeyMultibase.startsWith(MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX)) {
|
|
118590
|
+
throw new DidDocumentError(
|
|
118591
|
+
`Invalid verification method: publicKeyMultibase must start with "${MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX}"`,
|
|
118592
|
+
INVALID_DID_DOCUMENT,
|
|
118593
|
+
{ id, publicKeyMultibase }
|
|
118594
|
+
);
|
|
118595
|
+
}
|
|
118567
118596
|
this.id = id;
|
|
118568
118597
|
this.type = type;
|
|
118569
118598
|
this.controller = controller;
|
|
@@ -118722,10 +118751,8 @@ var DidDocument = class _DidDocument {
|
|
|
118722
118751
|
* @returns {boolean} True if the context is valid.
|
|
118723
118752
|
*/
|
|
118724
118753
|
static isValidContext(context) {
|
|
118725
|
-
if (!context) return false;
|
|
118726
|
-
|
|
118727
|
-
if (!context.every((ctx) => typeof ctx === "string" && BTCR2_DID_DOCUMENT_CONTEXT.includes(ctx))) return false;
|
|
118728
|
-
return true;
|
|
118754
|
+
if (!Array.isArray(context) || context.length === 0) return false;
|
|
118755
|
+
return BTCR2_DID_DOCUMENT_CONTEXT.every((required) => context.includes(required));
|
|
118729
118756
|
}
|
|
118730
118757
|
/**
|
|
118731
118758
|
* Validates that the DID Document has a valid id.
|
|
@@ -118749,7 +118776,7 @@ var DidDocument = class _DidDocument {
|
|
|
118749
118776
|
* @returns {boolean} True if the verification methods are valid.
|
|
118750
118777
|
*/
|
|
118751
118778
|
static isValidVerificationMethods(verificationMethod) {
|
|
118752
|
-
return Array.isArray(verificationMethod) && verificationMethod.every(
|
|
118779
|
+
return Array.isArray(verificationMethod) && verificationMethod.every(isMultikeyVerificationMethod);
|
|
118753
118780
|
}
|
|
118754
118781
|
/**
|
|
118755
118782
|
* Validates that the DID Document has valid services.
|
|
@@ -119291,16 +119318,16 @@ var DidBtcr2 = class {
|
|
|
119291
119318
|
{ sourceDocument, verificationMethodId }
|
|
119292
119319
|
);
|
|
119293
119320
|
}
|
|
119294
|
-
if (verificationMethod.type !==
|
|
119321
|
+
if (verificationMethod.type !== MULTIKEY_VERIFICATION_METHOD_TYPE) {
|
|
119295
119322
|
throw new UpdateError(
|
|
119296
|
-
|
|
119323
|
+
`Invalid verificationMethod: verificationMethod.type must be "${MULTIKEY_VERIFICATION_METHOD_TYPE}"`,
|
|
119297
119324
|
INVALID_DID_DOCUMENT,
|
|
119298
119325
|
verificationMethod
|
|
119299
119326
|
);
|
|
119300
119327
|
}
|
|
119301
|
-
if (verificationMethod.publicKeyMultibase?.
|
|
119328
|
+
if (!verificationMethod.publicKeyMultibase?.startsWith(MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX)) {
|
|
119302
119329
|
throw new UpdateError(
|
|
119303
|
-
|
|
119330
|
+
`Invalid verificationMethodId: publicKeyMultibase prefix must start with "${MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX}"`,
|
|
119304
119331
|
INVALID_DID_DOCUMENT,
|
|
119305
119332
|
verificationMethod
|
|
119306
119333
|
);
|
|
@@ -119910,6 +119937,8 @@ export {
|
|
|
119910
119937
|
GenesisDocument,
|
|
119911
119938
|
ID_PLACEHOLDER_VALUE,
|
|
119912
119939
|
Identifier,
|
|
119940
|
+
MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX,
|
|
119941
|
+
MULTIKEY_VERIFICATION_METHOD_TYPE,
|
|
119913
119942
|
P2PKH_BEACON_TX_VSIZE,
|
|
119914
119943
|
P2TR_BEACON_TX_VSIZE,
|
|
119915
119944
|
P2WPKH_BEACON_TX_VSIZE,
|
|
@@ -119926,6 +119955,8 @@ export {
|
|
|
119926
119955
|
buildAggregationBeaconTx,
|
|
119927
119956
|
deriveSingletonAddress,
|
|
119928
119957
|
detectSingletonScriptKind,
|
|
119958
|
+
extractOpReturnSignal,
|
|
119959
|
+
isMultikeyVerificationMethod,
|
|
119929
119960
|
opReturnScript,
|
|
119930
119961
|
resolveBtcr2SenderPk,
|
|
119931
119962
|
resolveChangeAddress
|
package/dist/cjs/index.js
CHANGED
|
@@ -53,6 +53,8 @@ __export(index_exports, {
|
|
|
53
53
|
GenesisDocument: () => GenesisDocument,
|
|
54
54
|
ID_PLACEHOLDER_VALUE: () => ID_PLACEHOLDER_VALUE,
|
|
55
55
|
Identifier: () => Identifier,
|
|
56
|
+
MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX: () => MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX,
|
|
57
|
+
MULTIKEY_VERIFICATION_METHOD_TYPE: () => MULTIKEY_VERIFICATION_METHOD_TYPE,
|
|
56
58
|
P2PKH_BEACON_TX_VSIZE: () => P2PKH_BEACON_TX_VSIZE,
|
|
57
59
|
P2TR_BEACON_TX_VSIZE: () => P2TR_BEACON_TX_VSIZE,
|
|
58
60
|
P2WPKH_BEACON_TX_VSIZE: () => P2WPKH_BEACON_TX_VSIZE,
|
|
@@ -69,6 +71,8 @@ __export(index_exports, {
|
|
|
69
71
|
buildAggregationBeaconTx: () => buildAggregationBeaconTx,
|
|
70
72
|
deriveSingletonAddress: () => deriveSingletonAddress,
|
|
71
73
|
detectSingletonScriptKind: () => detectSingletonScriptKind,
|
|
74
|
+
extractOpReturnSignal: () => extractOpReturnSignal,
|
|
75
|
+
isMultikeyVerificationMethod: () => isMultikeyVerificationMethod,
|
|
72
76
|
opReturnScript: () => opReturnScript,
|
|
73
77
|
resolveBtcr2SenderPk: () => resolveBtcr2SenderPk,
|
|
74
78
|
resolveChangeAddress: () => resolveChangeAddress
|
|
@@ -2060,6 +2064,20 @@ var BeaconUtils = class {
|
|
|
2060
2064
|
};
|
|
2061
2065
|
|
|
2062
2066
|
// src/core/beacon/signal-discovery.ts
|
|
2067
|
+
function extractOpReturnSignal(asm) {
|
|
2068
|
+
if (!asm) {
|
|
2069
|
+
return null;
|
|
2070
|
+
}
|
|
2071
|
+
const tokens = asm.trim().split(/\s+/);
|
|
2072
|
+
if (tokens.length !== 3 || tokens[0] !== "OP_RETURN" || tokens[1] !== "OP_PUSHBYTES_32") {
|
|
2073
|
+
return null;
|
|
2074
|
+
}
|
|
2075
|
+
const signalHash = tokens[2];
|
|
2076
|
+
if (!/^[0-9a-fA-F]{64}$/.test(signalHash)) {
|
|
2077
|
+
return null;
|
|
2078
|
+
}
|
|
2079
|
+
return signalHash.toLowerCase();
|
|
2080
|
+
}
|
|
2063
2081
|
var BeaconSignalDiscovery = class {
|
|
2064
2082
|
/**
|
|
2065
2083
|
* Retrieves the beacon signals for the given array of BeaconService objects
|
|
@@ -2081,15 +2099,10 @@ var BeaconSignalDiscovery = class {
|
|
|
2081
2099
|
}
|
|
2082
2100
|
for (const beaconSignal of beaconSignals) {
|
|
2083
2101
|
const signalVout = beaconSignal.vout.slice(-1)[0];
|
|
2084
|
-
if (!signalVout
|
|
2102
|
+
if (!signalVout) {
|
|
2085
2103
|
continue;
|
|
2086
2104
|
}
|
|
2087
|
-
const
|
|
2088
|
-
const signalVoutScriptPubkey = outputMap.get("scriptpubkey_asm");
|
|
2089
|
-
if (!signalVoutScriptPubkey) {
|
|
2090
|
-
continue;
|
|
2091
|
-
}
|
|
2092
|
-
const updateHash = signalVoutScriptPubkey.split(" ").slice(-1)[0];
|
|
2105
|
+
const updateHash = extractOpReturnSignal(signalVout.scriptpubkey_asm);
|
|
2093
2106
|
if (!updateHash) {
|
|
2094
2107
|
continue;
|
|
2095
2108
|
}
|
|
@@ -2158,14 +2171,11 @@ var BeaconSignalDiscovery = class {
|
|
|
2158
2171
|
continue;
|
|
2159
2172
|
}
|
|
2160
2173
|
const txVoutScriptPubkeyAsm = prevout.vout[vin.vout].scriptPubKey.asm;
|
|
2161
|
-
|
|
2162
|
-
continue;
|
|
2163
|
-
}
|
|
2164
|
-
console.info(`Tx ${tx.txid} contains beacon service address ${scriptPubKey.address} and OP_RETURN!`, tx);
|
|
2165
|
-
const updateHash = txVoutScriptPubkeyAsm.split(" ").slice(-1)[0];
|
|
2174
|
+
const updateHash = extractOpReturnSignal(txVoutScriptPubkeyAsm);
|
|
2166
2175
|
if (!updateHash) {
|
|
2167
2176
|
continue;
|
|
2168
2177
|
}
|
|
2178
|
+
console.info(`Tx ${tx.txid} contains beacon service address ${scriptPubKey.address} and OP_RETURN!`, tx);
|
|
2169
2179
|
beaconServiceSignals.get(beaconService)?.push({
|
|
2170
2180
|
tx,
|
|
2171
2181
|
signalBytes: updateHash,
|
|
@@ -2226,9 +2236,18 @@ var BTCR2_DID_DOCUMENT_CONTEXT = [
|
|
|
2226
2236
|
"https://www.w3.org/ns/did/v1.1",
|
|
2227
2237
|
"https://btcr2.dev/context/v1"
|
|
2228
2238
|
];
|
|
2239
|
+
var MULTIKEY_VERIFICATION_METHOD_TYPE = "Multikey";
|
|
2240
|
+
var MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX = "zQ3s";
|
|
2229
2241
|
var ID_PLACEHOLDER_VALUE = "did:btcr2:_";
|
|
2230
2242
|
var BECH32M_CHARS = "";
|
|
2231
2243
|
var DID_REGEX = /did:btcr2:(x1[qpzry9x8gf2tvdw0s3jn54khce6mua7l]*)/g;
|
|
2244
|
+
function isMultikeyVerificationMethod(vm) {
|
|
2245
|
+
if (!Appendix.isDidVerificationMethod(vm)) {
|
|
2246
|
+
return false;
|
|
2247
|
+
}
|
|
2248
|
+
const { type, publicKeyMultibase } = vm;
|
|
2249
|
+
return type === MULTIKEY_VERIFICATION_METHOD_TYPE && typeof publicKeyMultibase === "string" && publicKeyMultibase.startsWith(MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX);
|
|
2250
|
+
}
|
|
2232
2251
|
var DidVerificationMethod = class {
|
|
2233
2252
|
id;
|
|
2234
2253
|
type;
|
|
@@ -2236,6 +2255,20 @@ var DidVerificationMethod = class {
|
|
|
2236
2255
|
publicKeyMultibase;
|
|
2237
2256
|
secretKeyMultibase;
|
|
2238
2257
|
constructor({ id, type, controller, publicKeyMultibase, secretKeyMultibase }) {
|
|
2258
|
+
if (type !== MULTIKEY_VERIFICATION_METHOD_TYPE) {
|
|
2259
|
+
throw new import_common9.DidDocumentError(
|
|
2260
|
+
`Invalid verification method: type must be "${MULTIKEY_VERIFICATION_METHOD_TYPE}"`,
|
|
2261
|
+
import_common9.INVALID_DID_DOCUMENT,
|
|
2262
|
+
{ id, type }
|
|
2263
|
+
);
|
|
2264
|
+
}
|
|
2265
|
+
if (typeof publicKeyMultibase !== "string" || !publicKeyMultibase.startsWith(MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX)) {
|
|
2266
|
+
throw new import_common9.DidDocumentError(
|
|
2267
|
+
`Invalid verification method: publicKeyMultibase must start with "${MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX}"`,
|
|
2268
|
+
import_common9.INVALID_DID_DOCUMENT,
|
|
2269
|
+
{ id, publicKeyMultibase }
|
|
2270
|
+
);
|
|
2271
|
+
}
|
|
2239
2272
|
this.id = id;
|
|
2240
2273
|
this.type = type;
|
|
2241
2274
|
this.controller = controller;
|
|
@@ -2394,10 +2427,8 @@ var DidDocument = class _DidDocument {
|
|
|
2394
2427
|
* @returns {boolean} True if the context is valid.
|
|
2395
2428
|
*/
|
|
2396
2429
|
static isValidContext(context) {
|
|
2397
|
-
if (!context) return false;
|
|
2398
|
-
|
|
2399
|
-
if (!context.every((ctx) => typeof ctx === "string" && BTCR2_DID_DOCUMENT_CONTEXT.includes(ctx))) return false;
|
|
2400
|
-
return true;
|
|
2430
|
+
if (!Array.isArray(context) || context.length === 0) return false;
|
|
2431
|
+
return BTCR2_DID_DOCUMENT_CONTEXT.every((required) => context.includes(required));
|
|
2401
2432
|
}
|
|
2402
2433
|
/**
|
|
2403
2434
|
* Validates that the DID Document has a valid id.
|
|
@@ -2421,7 +2452,7 @@ var DidDocument = class _DidDocument {
|
|
|
2421
2452
|
* @returns {boolean} True if the verification methods are valid.
|
|
2422
2453
|
*/
|
|
2423
2454
|
static isValidVerificationMethods(verificationMethod) {
|
|
2424
|
-
return Array.isArray(verificationMethod) && verificationMethod.every(
|
|
2455
|
+
return Array.isArray(verificationMethod) && verificationMethod.every(isMultikeyVerificationMethod);
|
|
2425
2456
|
}
|
|
2426
2457
|
/**
|
|
2427
2458
|
* Validates that the DID Document has valid services.
|
|
@@ -2963,16 +2994,16 @@ var DidBtcr2 = class {
|
|
|
2963
2994
|
{ sourceDocument, verificationMethodId }
|
|
2964
2995
|
);
|
|
2965
2996
|
}
|
|
2966
|
-
if (verificationMethod.type !==
|
|
2997
|
+
if (verificationMethod.type !== MULTIKEY_VERIFICATION_METHOD_TYPE) {
|
|
2967
2998
|
throw new import_common11.UpdateError(
|
|
2968
|
-
|
|
2999
|
+
`Invalid verificationMethod: verificationMethod.type must be "${MULTIKEY_VERIFICATION_METHOD_TYPE}"`,
|
|
2969
3000
|
import_common11.INVALID_DID_DOCUMENT,
|
|
2970
3001
|
verificationMethod
|
|
2971
3002
|
);
|
|
2972
3003
|
}
|
|
2973
|
-
if (verificationMethod.publicKeyMultibase?.
|
|
3004
|
+
if (!verificationMethod.publicKeyMultibase?.startsWith(MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX)) {
|
|
2974
3005
|
throw new import_common11.UpdateError(
|
|
2975
|
-
|
|
3006
|
+
`Invalid verificationMethodId: publicKeyMultibase prefix must start with "${MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX}"`,
|
|
2976
3007
|
import_common11.INVALID_DID_DOCUMENT,
|
|
2977
3008
|
verificationMethod
|
|
2978
3009
|
);
|
|
@@ -3580,6 +3611,8 @@ var DidDocumentBuilder = class {
|
|
|
3580
3611
|
GenesisDocument,
|
|
3581
3612
|
ID_PLACEHOLDER_VALUE,
|
|
3582
3613
|
Identifier,
|
|
3614
|
+
MULTIKEY_PUBLIC_KEY_MULTIBASE_PREFIX,
|
|
3615
|
+
MULTIKEY_VERIFICATION_METHOD_TYPE,
|
|
3583
3616
|
P2PKH_BEACON_TX_VSIZE,
|
|
3584
3617
|
P2TR_BEACON_TX_VSIZE,
|
|
3585
3618
|
P2WPKH_BEACON_TX_VSIZE,
|
|
@@ -3596,6 +3629,8 @@ var DidDocumentBuilder = class {
|
|
|
3596
3629
|
buildAggregationBeaconTx,
|
|
3597
3630
|
deriveSingletonAddress,
|
|
3598
3631
|
detectSingletonScriptKind,
|
|
3632
|
+
extractOpReturnSignal,
|
|
3633
|
+
isMultikeyVerificationMethod,
|
|
3599
3634
|
opReturnScript,
|
|
3600
3635
|
resolveBtcr2SenderPk,
|
|
3601
3636
|
resolveChangeAddress
|
|
@@ -9,6 +9,28 @@ import { SinglePartyBeacon } from './beacon.js';
|
|
|
9
9
|
* During resolution, the CAS Announcement is retrieved from the sidecar (or CAS)
|
|
10
10
|
* and used to look up the individual signed update for the DID being resolved.
|
|
11
11
|
*
|
|
12
|
+
* ## CAS announcement hash chain
|
|
13
|
+
*
|
|
14
|
+
* Resolution links an on-chain signal to a signed update through two hashes, with
|
|
15
|
+
* an encoding transition at each hop. The write path ({@link broadcastSignal})
|
|
16
|
+
* produces both hashes; the read path ({@link processSignals}) re-derives them:
|
|
17
|
+
*
|
|
18
|
+
* 1. **Signal hop.** The OP_RETURN payload is `canonicalHash(announcement)` in
|
|
19
|
+
* **hex**: this is `signal.signalBytes` and the lookup key into `sidecar.casMap`.
|
|
20
|
+
* Broadcast emits `hash(canonicalize(announcement))`; the resolver keys `casMap`
|
|
21
|
+
* by `canonicalHash(announcement, { encoding: 'hex' })`. These are the same bytes,
|
|
22
|
+
* so `signalBytes === canonicalHash(announcement, hex)`.
|
|
23
|
+
* 2. **Update hop.** Each `announcement[did]` is `canonicalHash(signedUpdate)` in
|
|
24
|
+
* **base64urlnopad** (per spec). It is decoded back to **hex** to key
|
|
25
|
+
* `sidecar.updateMap`, so `hex(decode(announcement[did])) === canonicalHash(signedUpdate, hex)`.
|
|
26
|
+
*
|
|
27
|
+
* Both links are enforced when sidecar data is supplied via `Resolver.provide()`
|
|
28
|
+
* (which validates the provided announcement and update against the need's hash),
|
|
29
|
+
* and structurally when sidecar maps are pre-loaded (they are keyed by
|
|
30
|
+
* `canonicalHash`, so a mismatched entry simply misses the lookup). The two
|
|
31
|
+
* encoding transitions (hex for on-chain and map keys, base64urlnopad for
|
|
32
|
+
* announcement values) are the subtle part: a regression test pins them.
|
|
33
|
+
*
|
|
12
34
|
* @class CASBeacon
|
|
13
35
|
* @type {CASBeacon}
|
|
14
36
|
* @extends {SinglePartyBeacon}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cas-beacon.js","sourceRoot":"","sources":["../../../../src/core/beacon/cas-beacon.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAMtF,OAAO,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAYhD
|
|
1
|
+
{"version":3,"file":"cas-beacon.js","sourceRoot":"","sources":["../../../../src/core/beacon/cas-beacon.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,36 @@
|
|
|
1
1
|
import { GENESIS_TX_ID, TXIN_WITNESS_COINBASE } from '@did-btcr2/bitcoin';
|
|
2
2
|
import { ResolveError } from '@did-btcr2/common';
|
|
3
3
|
import { BeaconUtils } from './utils.js';
|
|
4
|
+
/**
|
|
5
|
+
* Parses a scriptPubKey asm string and returns the beacon signal hash if and only
|
|
6
|
+
* if the output is exactly `OP_RETURN OP_PUSHBYTES_32 <32-byte hex>`.
|
|
7
|
+
*
|
|
8
|
+
* Beacon signals encode a single 32-byte update or announcement hash in an
|
|
9
|
+
* OP_RETURN data push. Any other shape (a bare `OP_RETURN`, a push of the wrong
|
|
10
|
+
* size, or a non-hex payload) is not a valid signal and returns `null`, so a
|
|
11
|
+
* malformed or adversarial on-chain output cannot be mistaken for a real signal
|
|
12
|
+
* downstream.
|
|
13
|
+
*
|
|
14
|
+
* @param {string | undefined} asm The scriptPubKey asm string to parse.
|
|
15
|
+
* @returns {string | null} The lowercased 32-byte hex hash, or `null` if not a valid signal.
|
|
16
|
+
*/
|
|
17
|
+
export function extractOpReturnSignal(asm) {
|
|
18
|
+
if (!asm) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
// A standard NULL_DATA beacon output is exactly three asm tokens: the OP_RETURN
|
|
22
|
+
// opcode, the 32-byte push opcode, and the 64-character hex payload.
|
|
23
|
+
const tokens = asm.trim().split(/\s+/);
|
|
24
|
+
if (tokens.length !== 3 || tokens[0] !== 'OP_RETURN' || tokens[1] !== 'OP_PUSHBYTES_32') {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
// The payload must be exactly 32 bytes of hex (64 hex characters).
|
|
28
|
+
const signalHash = tokens[2];
|
|
29
|
+
if (!/^[0-9a-fA-F]{64}$/.test(signalHash)) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
return signalHash.toLowerCase();
|
|
33
|
+
}
|
|
4
34
|
/**
|
|
5
35
|
* Static utility class for discovering Beacon Signals on the Bitcoin blockchain.
|
|
6
36
|
* Extracted from `Resolver` for single-responsibility and independent testability.
|
|
@@ -42,19 +72,13 @@ export class BeaconSignalDiscovery {
|
|
|
42
72
|
* value: 0
|
|
43
73
|
* }
|
|
44
74
|
*/
|
|
45
|
-
if (!signalVout
|
|
46
|
-
continue;
|
|
47
|
-
}
|
|
48
|
-
// Construct output map for easier access
|
|
49
|
-
const outputMap = new Map(Object.entries(signalVout));
|
|
50
|
-
// Grab the signal vout scriptpubkey
|
|
51
|
-
const signalVoutScriptPubkey = outputMap.get('scriptpubkey_asm');
|
|
52
|
-
// If the signal vout scriptpubkey does not exist, continue to next signal
|
|
53
|
-
if (!signalVoutScriptPubkey) {
|
|
75
|
+
if (!signalVout) {
|
|
54
76
|
continue;
|
|
55
77
|
}
|
|
56
|
-
//
|
|
57
|
-
|
|
78
|
+
// A beacon signal output must be exactly `OP_RETURN OP_PUSHBYTES_32 <32-byte hash>`.
|
|
79
|
+
// Reject any other shape (bare OP_RETURN, wrong push size, non-hex payload) so a
|
|
80
|
+
// malformed on-chain output cannot masquerade as a phantom signal downstream.
|
|
81
|
+
const updateHash = extractOpReturnSignal(signalVout.scriptpubkey_asm);
|
|
58
82
|
if (!updateHash) {
|
|
59
83
|
continue;
|
|
60
84
|
}
|
|
@@ -142,18 +166,16 @@ export class BeaconSignalDiscovery {
|
|
|
142
166
|
if (!beaconService) {
|
|
143
167
|
continue;
|
|
144
168
|
}
|
|
145
|
-
//
|
|
169
|
+
// A beacon signal output must be exactly `OP_RETURN OP_PUSHBYTES_32 <32-byte hash>`.
|
|
170
|
+
// Reject any other shape so a malformed on-chain output cannot masquerade as a
|
|
171
|
+
// phantom signal downstream.
|
|
146
172
|
const txVoutScriptPubkeyAsm = prevout.vout[vin.vout].scriptPubKey.asm;
|
|
147
|
-
|
|
173
|
+
const updateHash = extractOpReturnSignal(txVoutScriptPubkeyAsm);
|
|
174
|
+
if (!updateHash) {
|
|
148
175
|
continue;
|
|
149
176
|
}
|
|
150
177
|
// Log the found txid and beacon
|
|
151
178
|
console.info(`Tx ${tx.txid} contains beacon service address ${scriptPubKey.address} and OP_RETURN!`, tx);
|
|
152
|
-
// Extract hex string hash of the signal bytes from the scriptpubkey
|
|
153
|
-
const updateHash = txVoutScriptPubkeyAsm.split(' ').slice(-1)[0];
|
|
154
|
-
if (!updateHash) {
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
179
|
// Push the beacon signal object to the beacon signals array for that beacon service
|
|
158
180
|
beaconServiceSignals.get(beaconService)?.push({
|
|
159
181
|
tx,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"signal-discovery.js","sourceRoot":"","sources":["../../../../src/core/beacon/signal-discovery.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,aAAa,EACb,qBAAqB,EACtB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzC;;;;;GAKG;AACH,MAAM,OAAO,qBAAqB;IAEhC;;;;;;OAMG;IACH,MAAM,CAAC,KAAK,CAAC,OAAO,CAClB,cAAoC,EACpC,OAA0B;QAE1B,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAsC,CAAC;QAE3E,qDAAqD;QACrD,MAAM,iBAAiB,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAE3D,2BAA2B;QAC3B,KAAK,MAAM,aAAa,IAAI,cAAc,EAAE,CAAC;YAC3C,oBAAoB,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;YAC5C,uDAAuD;YACvD,MAAM,aAAa,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,CACrD,WAAW,CAAC,mBAAmB,CAAC,aAAa,CAAC,eAAyB,CAAC,CACzE,CAAC;YAEF,oCAAoC;YACpC,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC;gBAC5C,SAAS;YACX,CAAC;YAED,2BAA2B;YAC3B,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;gBACzC,uCAAuC;gBACvC,MAAM,UAAU,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;gBAElD;;;;;;;;;mBASG;gBACH,IAAG,CAAC,UAAU,
|
|
1
|
+
{"version":3,"file":"signal-discovery.js","sourceRoot":"","sources":["../../../../src/core/beacon/signal-discovery.ts"],"names":[],"mappings":"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"}
|