@did-btcr2/method 0.34.0 → 0.35.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 +190 -112
- package/dist/browser.mjs +190 -112
- package/dist/cjs/index.js +130 -60
- package/dist/esm/core/aggregation/cohort.js +5 -1
- package/dist/esm/core/aggregation/cohort.js.map +1 -1
- package/dist/esm/core/aggregation/participant.js +25 -8
- package/dist/esm/core/aggregation/participant.js.map +1 -1
- package/dist/esm/core/aggregation/runner/participant-runner.js +9 -1
- package/dist/esm/core/aggregation/runner/participant-runner.js.map +1 -1
- package/dist/esm/core/aggregation/runner/service-runner.js +4 -1
- package/dist/esm/core/aggregation/runner/service-runner.js.map +1 -1
- package/dist/esm/core/aggregation/service.js +4 -4
- package/dist/esm/core/aggregation/service.js.map +1 -1
- package/dist/esm/core/aggregation/signer.js +33 -0
- package/dist/esm/core/aggregation/signer.js.map +1 -0
- package/dist/esm/core/aggregation/signing-session.js +34 -11
- package/dist/esm/core/aggregation/signing-session.js.map +1 -1
- package/dist/esm/core/aggregation/transport/in-memory.js +5 -2
- package/dist/esm/core/aggregation/transport/in-memory.js.map +1 -1
- package/dist/esm/index.js +1 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/types/core/aggregation/cohort.d.ts.map +1 -1
- package/dist/types/core/aggregation/participant.d.ts +17 -4
- package/dist/types/core/aggregation/participant.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/participant-runner.d.ts.map +1 -1
- package/dist/types/core/aggregation/runner/service-runner.d.ts.map +1 -1
- package/dist/types/core/aggregation/service.d.ts +10 -4
- package/dist/types/core/aggregation/service.d.ts.map +1 -1
- package/dist/types/core/aggregation/signer.d.ts +50 -0
- package/dist/types/core/aggregation/signer.d.ts.map +1 -0
- package/dist/types/core/aggregation/signing-session.d.ts +13 -5
- package/dist/types/core/aggregation/signing-session.d.ts.map +1 -1
- package/dist/types/core/aggregation/transport/in-memory.d.ts.map +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/core/aggregation/cohort.ts +5 -1
- package/src/core/aggregation/participant.ts +38 -12
- package/src/core/aggregation/runner/participant-runner.ts +9 -1
- package/src/core/aggregation/runner/service-runner.ts +4 -1
- package/src/core/aggregation/service.ts +12 -6
- package/src/core/aggregation/signer.ts +67 -0
- package/src/core/aggregation/signing-session.ts +34 -11
- package/src/core/aggregation/transport/in-memory.ts +7 -3
- package/src/index.ts +1 -0
package/dist/cjs/index.js
CHANGED
|
@@ -86,6 +86,7 @@ __export(index_exports, {
|
|
|
86
86
|
InMemoryRateLimitStore: () => InMemoryRateLimitStore,
|
|
87
87
|
InMemoryTransport: () => InMemoryTransport,
|
|
88
88
|
InboxBuffer: () => InboxBuffer,
|
|
89
|
+
KeyPairAggregationSigner: () => KeyPairAggregationSigner,
|
|
89
90
|
NONCE_CONTRIBUTION: () => NONCE_CONTRIBUTION,
|
|
90
91
|
NonceCache: () => NonceCache,
|
|
91
92
|
NostrTransport: () => NostrTransport,
|
|
@@ -224,6 +225,7 @@ function getBeaconStrategy(type) {
|
|
|
224
225
|
}
|
|
225
226
|
|
|
226
227
|
// src/core/aggregation/cohort.ts
|
|
228
|
+
var import_bitcoin = require("@did-btcr2/bitcoin");
|
|
227
229
|
var import_common3 = require("@did-btcr2/common");
|
|
228
230
|
var import_smt2 = require("@did-btcr2/smt");
|
|
229
231
|
var import_secp256k1 = require("@noble/curves/secp256k1.js");
|
|
@@ -325,7 +327,7 @@ var AggregationCohort = class {
|
|
|
325
327
|
}
|
|
326
328
|
const keyAggContext = (0, import_musig2.keyAggregate)(this.#cohortKeys);
|
|
327
329
|
const aggPubkey = (0, import_musig2.keyAggExport)(keyAggContext);
|
|
328
|
-
const payment = (0, import_btc_signer.p2tr)(aggPubkey);
|
|
330
|
+
const payment = (0, import_btc_signer.p2tr)(aggPubkey, void 0, (0, import_bitcoin.getNetwork)(this.network));
|
|
329
331
|
this.tapTweak = import_secp256k1.schnorr.utils.taggedHash("TapTweak", aggPubkey);
|
|
330
332
|
if (!payment.address) {
|
|
331
333
|
throw new AggregationCohortError(
|
|
@@ -596,6 +598,7 @@ var SigningSessionPhase = /* @__PURE__ */ ((SigningSessionPhase2) => {
|
|
|
596
598
|
})(SigningSessionPhase || {});
|
|
597
599
|
|
|
598
600
|
// src/core/aggregation/signing-session.ts
|
|
601
|
+
var import_keypair = require("@did-btcr2/keypair");
|
|
599
602
|
var import_btc_signer2 = require("@scure/btc-signer");
|
|
600
603
|
var musig2 = __toESM(require("@scure/btc-signer/musig2"), 1);
|
|
601
604
|
var BeaconSigningSession = class {
|
|
@@ -619,8 +622,14 @@ var BeaconSigningSession = class {
|
|
|
619
622
|
signature;
|
|
620
623
|
/** Current signing session phase. */
|
|
621
624
|
phase;
|
|
622
|
-
/**
|
|
623
|
-
|
|
625
|
+
/**
|
|
626
|
+
* Participant's MuSig2 secret nonce, held only on the participant side
|
|
627
|
+
* between {@link generateNonceContribution} and {@link generatePartialSignature}.
|
|
628
|
+
* Private and cleared on every terminal path (success, failure, or teardown
|
|
629
|
+
* via {@link clearSecrets}) so a spent or abandoned nonce cannot be reused or
|
|
630
|
+
* serialized.
|
|
631
|
+
*/
|
|
632
|
+
#secretNonce;
|
|
624
633
|
constructor({ id, cohort, pendingTx, prevOutScripts, prevOutValues }) {
|
|
625
634
|
this.id = id || crypto.randomUUID();
|
|
626
635
|
this.cohort = cohort;
|
|
@@ -772,22 +781,24 @@ var BeaconSigningSession = class {
|
|
|
772
781
|
generateNonceContribution(participantPublicKey, participantSecretKey) {
|
|
773
782
|
const aggPublicKey = musig2.keyAggExport(musig2.keyAggregate(this.cohort.cohortKeys));
|
|
774
783
|
const nonces = musig2.nonceGen(participantPublicKey, participantSecretKey, aggPublicKey);
|
|
775
|
-
this
|
|
784
|
+
this.#secretNonce = nonces.secret;
|
|
776
785
|
return nonces.public;
|
|
777
786
|
}
|
|
778
787
|
/**
|
|
779
788
|
* Generates a partial signature using the participant's secret key + secret nonce.
|
|
780
789
|
* Requires the aggregated nonce to have been set first (via the service).
|
|
781
790
|
*
|
|
782
|
-
*
|
|
783
|
-
*
|
|
784
|
-
*
|
|
791
|
+
* Clears the stored secret nonce after use on every path (success or throw)
|
|
792
|
+
* via {@link clearSecrets}. JS cannot truly erase memory (GC may relocate
|
|
793
|
+
* buffers), but overwriting the bytes shortens the exposure window and
|
|
794
|
+
* prevents accidental reuse or serialization of a spent nonce - reuse of a
|
|
795
|
+
* MuSig2 nonce leaks the secret key.
|
|
785
796
|
*/
|
|
786
797
|
generatePartialSignature(participantSecretKey) {
|
|
787
798
|
if (!this.aggregatedNonce) {
|
|
788
799
|
throw new SigningSessionError("Aggregated nonce not available.", "MISSING_AGGREGATED_NONCE");
|
|
789
800
|
}
|
|
790
|
-
if (!this
|
|
801
|
+
if (!this.#secretNonce) {
|
|
791
802
|
throw new SigningSessionError("Secret nonce not available \u2014 generateNonceContribution() must be called first.", "MISSING_SECRET_NONCE");
|
|
792
803
|
}
|
|
793
804
|
const session = new musig2.Session(
|
|
@@ -797,10 +808,23 @@ var BeaconSigningSession = class {
|
|
|
797
808
|
[this.cohort.tapTweak],
|
|
798
809
|
[true]
|
|
799
810
|
);
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
811
|
+
try {
|
|
812
|
+
return session.sign(this.#secretNonce, participantSecretKey);
|
|
813
|
+
} finally {
|
|
814
|
+
this.clearSecrets();
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Zeroize any retained secret nonce. Safe to call repeatedly and on any path
|
|
819
|
+
* (completion, failure, or teardown of an abandoned session). Callers that
|
|
820
|
+
* drop a session before it reaches a partial signature should invoke this so
|
|
821
|
+
* the secret nonce does not linger on the live object.
|
|
822
|
+
*/
|
|
823
|
+
clearSecrets() {
|
|
824
|
+
if (this.#secretNonce) {
|
|
825
|
+
(0, import_keypair.wipe)(this.#secretNonce);
|
|
826
|
+
this.#secretNonce = void 0;
|
|
827
|
+
}
|
|
804
828
|
}
|
|
805
829
|
isComplete() {
|
|
806
830
|
return this.phase === "Complete" /* Complete */;
|
|
@@ -814,13 +838,13 @@ var BeaconSigningSession = class {
|
|
|
814
838
|
var DEFAULT_MAX_UPDATE_SIZE_BYTES = 256 * 1024;
|
|
815
839
|
var AggregationService = class {
|
|
816
840
|
did;
|
|
817
|
-
|
|
841
|
+
publicKey;
|
|
818
842
|
maxUpdateSizeBytes;
|
|
819
843
|
/** Per-cohort state, keyed by cohortId. */
|
|
820
844
|
#cohortStates = /* @__PURE__ */ new Map();
|
|
821
|
-
constructor({ did,
|
|
845
|
+
constructor({ did, publicKey, maxUpdateSizeBytes }) {
|
|
822
846
|
this.did = did;
|
|
823
|
-
this.
|
|
847
|
+
this.publicKey = publicKey;
|
|
824
848
|
this.maxUpdateSizeBytes = maxUpdateSizeBytes ?? DEFAULT_MAX_UPDATE_SIZE_BYTES;
|
|
825
849
|
}
|
|
826
850
|
receive(message) {
|
|
@@ -913,7 +937,7 @@ var AggregationService = class {
|
|
|
913
937
|
cohortSize: state.config.minParticipants,
|
|
914
938
|
beaconType: state.config.beaconType,
|
|
915
939
|
network: state.config.network,
|
|
916
|
-
communicationPk: this.
|
|
940
|
+
communicationPk: this.publicKey.compressed
|
|
917
941
|
});
|
|
918
942
|
state.phase = "Advertised" /* Advertised */;
|
|
919
943
|
return [message];
|
|
@@ -1325,12 +1349,17 @@ var import_utils3 = require("@noble/hashes/utils");
|
|
|
1325
1349
|
var import_btc_signer3 = require("@scure/btc-signer");
|
|
1326
1350
|
var AggregationParticipant = class {
|
|
1327
1351
|
did;
|
|
1328
|
-
|
|
1352
|
+
/** MuSig2 signing capability. The raw secret never lives as a field here. */
|
|
1353
|
+
#signer;
|
|
1329
1354
|
/** Per-cohort state, keyed by cohortId. */
|
|
1330
1355
|
#cohortStates = /* @__PURE__ */ new Map();
|
|
1331
|
-
constructor({ did,
|
|
1356
|
+
constructor({ did, signer }) {
|
|
1332
1357
|
this.did = did;
|
|
1333
|
-
this
|
|
1358
|
+
this.#signer = signer;
|
|
1359
|
+
}
|
|
1360
|
+
/** The participant's compressed (33-byte) MuSig2 public key. Not secret. */
|
|
1361
|
+
get publicKey() {
|
|
1362
|
+
return this.#signer.publicKey;
|
|
1334
1363
|
}
|
|
1335
1364
|
/**
|
|
1336
1365
|
* Process an incoming message. Updates internal state but never produces
|
|
@@ -1419,8 +1448,8 @@ var AggregationParticipant = class {
|
|
|
1419
1448
|
from: this.did,
|
|
1420
1449
|
to: state.serviceDid,
|
|
1421
1450
|
cohortId,
|
|
1422
|
-
participantPk: this.
|
|
1423
|
-
communicationPk: this.
|
|
1451
|
+
participantPk: this.publicKey,
|
|
1452
|
+
communicationPk: this.publicKey
|
|
1424
1453
|
});
|
|
1425
1454
|
return [optInMessage];
|
|
1426
1455
|
}
|
|
@@ -1451,7 +1480,7 @@ var AggregationParticipant = class {
|
|
|
1451
1480
|
const beaconAddress = message.body?.beaconAddress;
|
|
1452
1481
|
const cohortKeys = message.body?.cohortKeys;
|
|
1453
1482
|
if (!beaconAddress || !cohortKeys) return;
|
|
1454
|
-
const participantPkHex = (0, import_utils3.bytesToHex)(this.
|
|
1483
|
+
const participantPkHex = (0, import_utils3.bytesToHex)(this.publicKey);
|
|
1455
1484
|
const cohortKeysHex = cohortKeys.map((k) => (0, import_utils3.bytesToHex)(new Uint8Array(k)));
|
|
1456
1485
|
state.cohort.validateMembership(participantPkHex, cohortKeysHex, beaconAddress);
|
|
1457
1486
|
state.phase = "CohortReady" /* CohortReady */;
|
|
@@ -1618,9 +1647,8 @@ var AggregationParticipant = class {
|
|
|
1618
1647
|
prevOutValues
|
|
1619
1648
|
});
|
|
1620
1649
|
state.signingSession = session;
|
|
1621
|
-
const nonceContribution =
|
|
1622
|
-
this.
|
|
1623
|
-
this.keys.secretKey.bytes
|
|
1650
|
+
const nonceContribution = this.#signer.withSecret(
|
|
1651
|
+
(secretKey) => session.generateNonceContribution(this.publicKey, secretKey)
|
|
1624
1652
|
);
|
|
1625
1653
|
state.phase = "NonceSent" /* NonceSent */;
|
|
1626
1654
|
return [createNonceContributionMessage({
|
|
@@ -1663,7 +1691,10 @@ var AggregationParticipant = class {
|
|
|
1663
1691
|
{ cohortId }
|
|
1664
1692
|
);
|
|
1665
1693
|
}
|
|
1666
|
-
const
|
|
1694
|
+
const signingSession = state.signingSession;
|
|
1695
|
+
const partialSig = this.#signer.withSecret(
|
|
1696
|
+
(secretKey) => signingSession.generatePartialSignature(secretKey)
|
|
1697
|
+
);
|
|
1667
1698
|
state.phase = "Complete" /* Complete */;
|
|
1668
1699
|
return [createSignatureAuthorizationMessage({
|
|
1669
1700
|
from: this.did,
|
|
@@ -1676,6 +1707,37 @@ var AggregationParticipant = class {
|
|
|
1676
1707
|
getCohortPhase(cohortId) {
|
|
1677
1708
|
return this.#cohortStates.get(cohortId)?.phase;
|
|
1678
1709
|
}
|
|
1710
|
+
/**
|
|
1711
|
+
* Zeroize any retained MuSig2 secret nonces across all cohorts. The raw
|
|
1712
|
+
* signing key is never held here (it lives behind the {@link AggregationSigner}
|
|
1713
|
+
* and is wiped per-operation), but an abandoned signing session can still hold
|
|
1714
|
+
* a secret nonce; call this on teardown to clear it deterministically.
|
|
1715
|
+
*/
|
|
1716
|
+
clearSecrets() {
|
|
1717
|
+
for (const state of this.#cohortStates.values()) {
|
|
1718
|
+
state.signingSession?.clearSecrets();
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
};
|
|
1722
|
+
|
|
1723
|
+
// src/core/aggregation/signer.ts
|
|
1724
|
+
var import_keypair2 = require("@did-btcr2/keypair");
|
|
1725
|
+
var KeyPairAggregationSigner = class {
|
|
1726
|
+
publicKey;
|
|
1727
|
+
#keys;
|
|
1728
|
+
/** @param {SchnorrKeyPair} keys The keypair whose secret backs this signer. */
|
|
1729
|
+
constructor(keys) {
|
|
1730
|
+
this.#keys = keys;
|
|
1731
|
+
this.publicKey = keys.publicKey.compressed;
|
|
1732
|
+
}
|
|
1733
|
+
withSecret(fn) {
|
|
1734
|
+
const secretKey = this.#keys.secretKey.bytes;
|
|
1735
|
+
try {
|
|
1736
|
+
return fn(secretKey);
|
|
1737
|
+
} finally {
|
|
1738
|
+
(0, import_keypair2.wipe)(secretKey);
|
|
1739
|
+
}
|
|
1740
|
+
}
|
|
1679
1741
|
};
|
|
1680
1742
|
|
|
1681
1743
|
// src/core/aggregation/logger.ts
|
|
@@ -1787,11 +1849,11 @@ var TransportAdapterError = class extends import_common6.MethodError {
|
|
|
1787
1849
|
var import_common10 = require("@did-btcr2/common");
|
|
1788
1850
|
|
|
1789
1851
|
// src/core/aggregation/transport/http/client.ts
|
|
1790
|
-
var
|
|
1852
|
+
var import_keypair4 = require("@did-btcr2/keypair");
|
|
1791
1853
|
|
|
1792
1854
|
// src/core/identifier.ts
|
|
1793
1855
|
var import_common7 = require("@did-btcr2/common");
|
|
1794
|
-
var
|
|
1856
|
+
var import_keypair3 = require("@did-btcr2/keypair");
|
|
1795
1857
|
var import_base4 = require("@scure/base");
|
|
1796
1858
|
var Identifier = class _Identifier {
|
|
1797
1859
|
/**
|
|
@@ -1824,7 +1886,7 @@ var Identifier = class _Identifier {
|
|
|
1824
1886
|
}
|
|
1825
1887
|
if (idType === "KEY") {
|
|
1826
1888
|
try {
|
|
1827
|
-
new
|
|
1889
|
+
new import_keypair3.CompressedSecp256k1PublicKey(genesisBytes);
|
|
1828
1890
|
} catch {
|
|
1829
1891
|
throw new import_common7.IdentifierError(
|
|
1830
1892
|
'Expected "genesisBytes" to be a valid compressed secp256k1 public key',
|
|
@@ -1926,7 +1988,7 @@ var Identifier = class _Identifier {
|
|
|
1926
1988
|
const genesisBytes = dataBytes.slice(byteIndex + 1);
|
|
1927
1989
|
if (idType === "KEY") {
|
|
1928
1990
|
try {
|
|
1929
|
-
new
|
|
1991
|
+
new import_keypair3.CompressedSecp256k1PublicKey(genesisBytes);
|
|
1930
1992
|
} catch {
|
|
1931
1993
|
throw new import_common7.IdentifierError(`Invalid genesisBytes: ${genesisBytes}`, import_common7.INVALID_DID, { identifier });
|
|
1932
1994
|
}
|
|
@@ -1938,7 +2000,7 @@ var Identifier = class _Identifier {
|
|
|
1938
2000
|
* @returns {string} The new did:btcr2 identifier.
|
|
1939
2001
|
*/
|
|
1940
2002
|
static generate() {
|
|
1941
|
-
const keyPair =
|
|
2003
|
+
const keyPair = import_keypair3.SchnorrKeyPair.generate();
|
|
1942
2004
|
const did = this.encode(
|
|
1943
2005
|
keyPair.publicKey.compressed,
|
|
1944
2006
|
{
|
|
@@ -1964,7 +2026,7 @@ var Identifier = class _Identifier {
|
|
|
1964
2026
|
{ did, idType }
|
|
1965
2027
|
);
|
|
1966
2028
|
}
|
|
1967
|
-
return new
|
|
2029
|
+
return new import_keypair3.CompressedSecp256k1PublicKey(genesisBytes);
|
|
1968
2030
|
}
|
|
1969
2031
|
/**
|
|
1970
2032
|
* Validates a did:btcr2 identifier.
|
|
@@ -2371,7 +2433,7 @@ var HttpClientTransport = class {
|
|
|
2371
2433
|
}
|
|
2372
2434
|
registerPeer(did, communicationPk) {
|
|
2373
2435
|
try {
|
|
2374
|
-
new
|
|
2436
|
+
new import_keypair4.CompressedSecp256k1PublicKey(communicationPk);
|
|
2375
2437
|
} catch {
|
|
2376
2438
|
throw new HttpTransportError(
|
|
2377
2439
|
`Invalid communication public key for peer ${did}: expected a 33-byte compressed secp256k1 key.`,
|
|
@@ -2567,14 +2629,14 @@ var HttpClientTransport = class {
|
|
|
2567
2629
|
const peerBytes = this.#peers.get(did);
|
|
2568
2630
|
if (peerBytes) {
|
|
2569
2631
|
try {
|
|
2570
|
-
return new
|
|
2632
|
+
return new import_keypair4.CompressedSecp256k1PublicKey(peerBytes);
|
|
2571
2633
|
} catch {
|
|
2572
2634
|
}
|
|
2573
2635
|
}
|
|
2574
2636
|
try {
|
|
2575
2637
|
const components = Identifier.decode(did);
|
|
2576
2638
|
if (components.idType === "KEY") {
|
|
2577
|
-
return new
|
|
2639
|
+
return new import_keypair4.CompressedSecp256k1PublicKey(components.genesisBytes);
|
|
2578
2640
|
}
|
|
2579
2641
|
} catch {
|
|
2580
2642
|
}
|
|
@@ -2619,7 +2681,7 @@ function flattenMessage(msg) {
|
|
|
2619
2681
|
}
|
|
2620
2682
|
|
|
2621
2683
|
// src/core/aggregation/transport/http/server.ts
|
|
2622
|
-
var
|
|
2684
|
+
var import_keypair5 = require("@did-btcr2/keypair");
|
|
2623
2685
|
|
|
2624
2686
|
// src/core/aggregation/transport/http/inbox-buffer.ts
|
|
2625
2687
|
var InboxBuffer = class {
|
|
@@ -2784,7 +2846,7 @@ var HttpServerTransport = class {
|
|
|
2784
2846
|
}
|
|
2785
2847
|
registerPeer(did, communicationPk) {
|
|
2786
2848
|
try {
|
|
2787
|
-
new
|
|
2849
|
+
new import_keypair5.CompressedSecp256k1PublicKey(communicationPk);
|
|
2788
2850
|
} catch {
|
|
2789
2851
|
throw new HttpTransportError(
|
|
2790
2852
|
`Invalid peer public key for ${did}`,
|
|
@@ -3062,14 +3124,14 @@ var HttpServerTransport = class {
|
|
|
3062
3124
|
const peerBytes = this.#peers.get(did);
|
|
3063
3125
|
if (peerBytes) {
|
|
3064
3126
|
try {
|
|
3065
|
-
return new
|
|
3127
|
+
return new import_keypair5.CompressedSecp256k1PublicKey(peerBytes);
|
|
3066
3128
|
} catch {
|
|
3067
3129
|
}
|
|
3068
3130
|
}
|
|
3069
3131
|
try {
|
|
3070
3132
|
const components = Identifier.decode(did);
|
|
3071
3133
|
if (components.idType === "KEY") {
|
|
3072
|
-
return new
|
|
3134
|
+
return new import_keypair5.CompressedSecp256k1PublicKey(components.genesisBytes);
|
|
3073
3135
|
}
|
|
3074
3136
|
} catch {
|
|
3075
3137
|
}
|
|
@@ -3168,7 +3230,7 @@ function flattenMessage2(msg) {
|
|
|
3168
3230
|
}
|
|
3169
3231
|
|
|
3170
3232
|
// src/core/aggregation/transport/nostr.ts
|
|
3171
|
-
var
|
|
3233
|
+
var import_keypair6 = require("@did-btcr2/keypair");
|
|
3172
3234
|
var import_utils6 = require("@noble/hashes/utils");
|
|
3173
3235
|
var import_nostr_tools = require("nostr-tools");
|
|
3174
3236
|
var import_pool = require("nostr-tools/pool");
|
|
@@ -3266,7 +3328,7 @@ var NostrTransport = class _NostrTransport {
|
|
|
3266
3328
|
*/
|
|
3267
3329
|
registerPeer(did, communicationPk) {
|
|
3268
3330
|
try {
|
|
3269
|
-
new
|
|
3331
|
+
new import_keypair6.CompressedSecp256k1PublicKey(communicationPk);
|
|
3270
3332
|
} catch {
|
|
3271
3333
|
throw new TransportAdapterError(
|
|
3272
3334
|
`Invalid communication public key for peer ${did}: expected a 33-byte compressed secp256k1 key.`,
|
|
@@ -3373,7 +3435,7 @@ var NostrTransport = class _NostrTransport {
|
|
|
3373
3435
|
if (to) {
|
|
3374
3436
|
const recipientPkBytes = this.#peerRegistry.get(to);
|
|
3375
3437
|
if (recipientPkBytes) {
|
|
3376
|
-
const recipientPk = new
|
|
3438
|
+
const recipientPk = new import_keypair6.CompressedSecp256k1PublicKey(recipientPkBytes);
|
|
3377
3439
|
tags.push(["p", (0, import_utils6.bytesToHex)(recipientPk.x)]);
|
|
3378
3440
|
}
|
|
3379
3441
|
}
|
|
@@ -3404,7 +3466,7 @@ var NostrTransport = class _NostrTransport {
|
|
|
3404
3466
|
{ adapter: this.name, did: to }
|
|
3405
3467
|
);
|
|
3406
3468
|
}
|
|
3407
|
-
const recipientPk = new
|
|
3469
|
+
const recipientPk = new import_keypair6.CompressedSecp256k1PublicKey(recipientPkBytes);
|
|
3408
3470
|
const conversationKey = import_nostr_tools.nip44.v2.utils.getConversationKey(
|
|
3409
3471
|
senderKeys.secretKey.bytes,
|
|
3410
3472
|
(0, import_utils6.bytesToHex)(recipientPk.x)
|
|
@@ -3695,10 +3757,10 @@ var InMemoryTransport = class {
|
|
|
3695
3757
|
start() {
|
|
3696
3758
|
}
|
|
3697
3759
|
registerActor(did, keys) {
|
|
3698
|
-
this.#actors.set(did, { keys, handlers: /* @__PURE__ */ new Map() });
|
|
3760
|
+
this.#actors.set(did, { publicKey: keys.publicKey.compressed, handlers: /* @__PURE__ */ new Map() });
|
|
3699
3761
|
}
|
|
3700
3762
|
getActorPk(did) {
|
|
3701
|
-
return this.#actors.get(did)?.
|
|
3763
|
+
return this.#actors.get(did)?.publicKey;
|
|
3702
3764
|
}
|
|
3703
3765
|
/** True if `did` is registered on this transport. Used by the bus for routing. */
|
|
3704
3766
|
hasActor(did) {
|
|
@@ -3909,8 +3971,11 @@ var AggregationServiceRunner = class _AggregationServiceRunner extends TypedEven
|
|
|
3909
3971
|
this.#phaseTimeoutMs = options.phaseTimeoutMs;
|
|
3910
3972
|
this.#advertRepeatIntervalMs = options.advertRepeatIntervalMs ?? DEFAULT_ADVERT_REPEAT_INTERVAL_MS;
|
|
3911
3973
|
this.session = new AggregationService({
|
|
3974
|
+
// The coordinator never signs, so the state machine receives only the
|
|
3975
|
+
// public half of the operator's keypair (see ADR 038). The full keypair
|
|
3976
|
+
// remains the operator's transport/communication identity.
|
|
3912
3977
|
did: options.did,
|
|
3913
|
-
|
|
3978
|
+
publicKey: options.keys.publicKey,
|
|
3914
3979
|
maxUpdateSizeBytes: options.maxUpdateSizeBytes
|
|
3915
3980
|
});
|
|
3916
3981
|
}
|
|
@@ -4262,7 +4327,10 @@ var AggregationParticipantRunner = class _AggregationParticipantRunner extends T
|
|
|
4262
4327
|
this.#onProvideUpdate = options.onProvideUpdate;
|
|
4263
4328
|
this.#onValidateData = options.onValidateData ?? (async (info) => ({ approved: info.matches }));
|
|
4264
4329
|
this.#onApproveSigning = options.onApproveSigning ?? (async () => ({ approved: true }));
|
|
4265
|
-
this.session = new AggregationParticipant({
|
|
4330
|
+
this.session = new AggregationParticipant({
|
|
4331
|
+
did: options.did,
|
|
4332
|
+
signer: new KeyPairAggregationSigner(options.keys)
|
|
4333
|
+
});
|
|
4266
4334
|
}
|
|
4267
4335
|
/**
|
|
4268
4336
|
* Start listening for cohorts. The runner stays active until {@link stop}
|
|
@@ -4275,6 +4343,7 @@ var AggregationParticipantRunner = class _AggregationParticipantRunner extends T
|
|
|
4275
4343
|
stop() {
|
|
4276
4344
|
this.#stopped = true;
|
|
4277
4345
|
this.#unregisterHandlers();
|
|
4346
|
+
this.session.clearSecrets();
|
|
4278
4347
|
}
|
|
4279
4348
|
/** Message types this runner listens for on the transport. */
|
|
4280
4349
|
static #HANDLED_MESSAGE_TYPES = [
|
|
@@ -5110,11 +5179,11 @@ var BeaconFactory = class {
|
|
|
5110
5179
|
};
|
|
5111
5180
|
|
|
5112
5181
|
// src/core/beacon/signal-discovery.ts
|
|
5113
|
-
var
|
|
5182
|
+
var import_bitcoin3 = require("@did-btcr2/bitcoin");
|
|
5114
5183
|
var import_common18 = require("@did-btcr2/common");
|
|
5115
5184
|
|
|
5116
5185
|
// src/core/beacon/utils.ts
|
|
5117
|
-
var
|
|
5186
|
+
var import_bitcoin2 = require("@did-btcr2/bitcoin");
|
|
5118
5187
|
var import_common17 = require("@did-btcr2/common");
|
|
5119
5188
|
var import_btc_signer5 = require("@scure/btc-signer");
|
|
5120
5189
|
|
|
@@ -6221,7 +6290,7 @@ var BeaconUtils = class {
|
|
|
6221
6290
|
static createBeaconService(did, addressType, beaconType) {
|
|
6222
6291
|
try {
|
|
6223
6292
|
const components = Identifier.decode(did);
|
|
6224
|
-
const network = (0,
|
|
6293
|
+
const network = (0, import_bitcoin2.getNetwork)(components.network);
|
|
6225
6294
|
const pubkey = components.genesisBytes;
|
|
6226
6295
|
const id = `${did}#initial${addressType.toUpperCase()}`;
|
|
6227
6296
|
const address = addressType === "p2tr" ? (0, import_btc_signer5.p2tr)(pubkey.slice(1, 33), void 0, network).address : addressType === "p2wpkh" ? (0, import_btc_signer5.p2wpkh)(pubkey, network).address : (0, import_btc_signer5.p2pkh)(pubkey, network).address;
|
|
@@ -6372,14 +6441,14 @@ var BeaconSignalDiscovery = class {
|
|
|
6372
6441
|
console.info(`Searching for beacon signals, please wait ...`);
|
|
6373
6442
|
while (block.height <= targetHeight) {
|
|
6374
6443
|
for (const tx of block.tx) {
|
|
6375
|
-
if (tx.txid ===
|
|
6444
|
+
if (tx.txid === import_bitcoin3.GENESIS_TX_ID) {
|
|
6376
6445
|
continue;
|
|
6377
6446
|
}
|
|
6378
6447
|
for (const vin of tx.vin) {
|
|
6379
6448
|
if (vin.coinbase) {
|
|
6380
6449
|
continue;
|
|
6381
6450
|
}
|
|
6382
|
-
if (vin.txinwitness && vin.txinwitness.length === 1 && vin.txinwitness[0] ===
|
|
6451
|
+
if (vin.txinwitness && vin.txinwitness.length === 1 && vin.txinwitness[0] === import_bitcoin3.TXIN_WITNESS_COINBASE) {
|
|
6383
6452
|
continue;
|
|
6384
6453
|
}
|
|
6385
6454
|
if (!vin.txid) {
|
|
@@ -6433,10 +6502,10 @@ var BeaconSignalDiscovery = class {
|
|
|
6433
6502
|
};
|
|
6434
6503
|
|
|
6435
6504
|
// src/core/resolver.ts
|
|
6436
|
-
var
|
|
6505
|
+
var import_bitcoin5 = require("@did-btcr2/bitcoin");
|
|
6437
6506
|
var import_common22 = require("@did-btcr2/common");
|
|
6438
6507
|
var import_cryptosuite3 = require("@did-btcr2/cryptosuite");
|
|
6439
|
-
var
|
|
6508
|
+
var import_keypair8 = require("@did-btcr2/keypair");
|
|
6440
6509
|
|
|
6441
6510
|
// src/did-btcr2.ts
|
|
6442
6511
|
var import_common21 = require("@did-btcr2/common");
|
|
@@ -6447,9 +6516,9 @@ var import_common20 = require("@did-btcr2/common");
|
|
|
6447
6516
|
var import_cryptosuite2 = require("@did-btcr2/cryptosuite");
|
|
6448
6517
|
|
|
6449
6518
|
// src/utils/did-document.ts
|
|
6450
|
-
var
|
|
6519
|
+
var import_bitcoin4 = require("@did-btcr2/bitcoin");
|
|
6451
6520
|
var import_common19 = require("@did-btcr2/common");
|
|
6452
|
-
var
|
|
6521
|
+
var import_keypair7 = require("@did-btcr2/keypair");
|
|
6453
6522
|
var import_utils11 = require("@web5/dids/utils");
|
|
6454
6523
|
var import_btc_signer6 = require("@scure/btc-signer");
|
|
6455
6524
|
var BTCR2_DID_DOCUMENT_CONTEXT = [
|
|
@@ -6771,9 +6840,9 @@ var GenesisDocument = class _GenesisDocument extends DidDocument {
|
|
|
6771
6840
|
* @returns {GenesisDocument} A new GenesisDocument with the placeholder ID.
|
|
6772
6841
|
*/
|
|
6773
6842
|
static fromPublicKey(publicKey, network) {
|
|
6774
|
-
const pk = new
|
|
6843
|
+
const pk = new import_keypair7.CompressedSecp256k1PublicKey(publicKey);
|
|
6775
6844
|
const id = ID_PLACEHOLDER_VALUE;
|
|
6776
|
-
const address = (0, import_btc_signer6.p2pkh)(pk.compressed, (0,
|
|
6845
|
+
const address = (0, import_btc_signer6.p2pkh)(pk.compressed, (0, import_bitcoin4.getNetwork)(network)).address;
|
|
6777
6846
|
const services = [{
|
|
6778
6847
|
id: `${id}#service-0`,
|
|
6779
6848
|
serviceEndpoint: `bitcoin:${address}`,
|
|
@@ -7280,11 +7349,11 @@ var Resolver = class _Resolver {
|
|
|
7280
7349
|
static deterministic(didComponents) {
|
|
7281
7350
|
const genesisBytes = didComponents.genesisBytes;
|
|
7282
7351
|
const did = Identifier.encode(genesisBytes, didComponents);
|
|
7283
|
-
const { multibase } = new
|
|
7352
|
+
const { multibase } = new import_keypair8.CompressedSecp256k1PublicKey(genesisBytes);
|
|
7284
7353
|
const service = BeaconUtils.generateBeaconServices({
|
|
7285
7354
|
id: did,
|
|
7286
7355
|
publicKey: genesisBytes,
|
|
7287
|
-
network: (0,
|
|
7356
|
+
network: (0, import_bitcoin5.getNetwork)(didComponents.network),
|
|
7288
7357
|
beaconType: "SingletonBeacon"
|
|
7289
7358
|
});
|
|
7290
7359
|
return new DidDocument({
|
|
@@ -7757,6 +7826,7 @@ var DidDocumentBuilder = class {
|
|
|
7757
7826
|
InMemoryRateLimitStore,
|
|
7758
7827
|
InMemoryTransport,
|
|
7759
7828
|
InboxBuffer,
|
|
7829
|
+
KeyPairAggregationSigner,
|
|
7760
7830
|
NONCE_CONTRIBUTION,
|
|
7761
7831
|
NonceCache,
|
|
7762
7832
|
NostrTransport,
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getNetwork } from '@did-btcr2/bitcoin';
|
|
1
2
|
import { canonicalHash, canonicalize, hash } from '@did-btcr2/common';
|
|
2
3
|
import { BTCR2MerkleTree } from '@did-btcr2/smt';
|
|
3
4
|
import { schnorr } from '@noble/curves/secp256k1.js';
|
|
@@ -84,7 +85,10 @@ export class AggregationCohort {
|
|
|
84
85
|
}
|
|
85
86
|
const keyAggContext = keyAggregate(this.#cohortKeys);
|
|
86
87
|
const aggPubkey = keyAggExport(keyAggContext);
|
|
87
|
-
|
|
88
|
+
// Derive the address for the cohort's network. Without the network arg
|
|
89
|
+
// p2tr defaults to mainnet, so a mutinynet/signet/regtest cohort would
|
|
90
|
+
// otherwise advertise a `bc1p...` address that no participant can fund.
|
|
91
|
+
const payment = p2tr(aggPubkey, undefined, getNetwork(this.network));
|
|
88
92
|
// BIP-341: key-path-only P2TR has no script tree. Compute the tweak:
|
|
89
93
|
// taggedHash("TapTweak", internalPubkey).
|
|
90
94
|
this.tapTweak = schnorr.utils.taggedHash('TapTweak', aggPubkey);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cohort.js","sourceRoot":"","sources":["../../../../src/core/aggregation/cohort.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAGtE,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjD,OAAO,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,YAAY,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AAEhF,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAUrD;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,iBAAiB;IAC5B,wCAAwC;IACxC,EAAE,CAAS;IAEX,2DAA2D;IAC3D,UAAU,CAAS;IAEnB,sEAAsE;IACtE,eAAe,CAAS;IAExB,uEAAuE;IACvE,OAAO,CAAS;IAEhB,qEAAqE;IACrE,UAAU,CAAS;IAEnB,wEAAwE;IACxE,YAAY,GAAkB,EAAE,CAAC;IAEjC;;;;;OAKG;IACH,eAAe,GAA4B,IAAI,GAAG,EAAE,CAAC;IAErD,kEAAkE;IAClE,WAAW,GAAsB,EAAE,CAAC;IAEpC;;;;OAIG;IACH,QAAQ,GAAe,IAAI,UAAU,EAAE,CAAC;IAExC,gDAAgD;IAChD,aAAa,GAAW,EAAE,CAAC;IAE3B,mEAAmE;IACnE,cAAc,GAAmC,IAAI,GAAG,EAAE,CAAC;IAE3D,qFAAqF;IACrF,eAAe,CAAmB;IAElC,yDAAyD;IACzD,SAAS,CAAmC;IAE5C,sFAAsF;IACtF,WAAW,CAAc;IAEzB,sEAAsE;IACtE,cAAc,GAAgB,IAAI,GAAG,EAAE,CAAC;IAExC,sEAAsE;IACtE,oBAAoB,GAAgB,IAAI,GAAG,EAAE,CAAC;IAE9C,YAAY,EAAE,EAAE,EAAE,eAAe,EAAE,UAAU,EAAE,OAAO,EAAE,UAAU,EAA2B;QAC3F,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACpC,IAAI,CAAC,eAAe,GAAG,eAAe,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,EAAE,CAAC;QACnC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,UAAU,GAAG,UAAU,IAAI,WAAW,CAAC;IAC9C,CAAC;IAED,6DAA6D;IAC7D,IAAI,UAAU;QACZ,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED,IAAI,UAAU,CAAC,IAAuB;QACpC,IAAI,CAAC,WAAW,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED;;;OAGG;IACI,oBAAoB;QACzB,IAAG,IAAI,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,MAAM,IAAI,sBAAsB,CAC9B,gDAAgD,EAChD,gBAAgB,EAAE,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,CACxC,CAAC;QACJ,CAAC;QACD,MAAM,aAAa,GAAG,YAAY,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,YAAY,CAAC,aAAa,CAAC,CAAC;QAC9C,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"cohort.js","sourceRoot":"","sources":["../../../../src/core/aggregation/cohort.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,12 +21,17 @@ import { BeaconSigningSession } from './signing-session.js';
|
|
|
21
21
|
*/
|
|
22
22
|
export class AggregationParticipant {
|
|
23
23
|
did;
|
|
24
|
-
|
|
24
|
+
/** MuSig2 signing capability. The raw secret never lives as a field here. */
|
|
25
|
+
#signer;
|
|
25
26
|
/** Per-cohort state, keyed by cohortId. */
|
|
26
27
|
#cohortStates = new Map();
|
|
27
|
-
constructor({ did,
|
|
28
|
+
constructor({ did, signer }) {
|
|
28
29
|
this.did = did;
|
|
29
|
-
this
|
|
30
|
+
this.#signer = signer;
|
|
31
|
+
}
|
|
32
|
+
/** The participant's compressed (33-byte) MuSig2 public key. Not secret. */
|
|
33
|
+
get publicKey() {
|
|
34
|
+
return this.#signer.publicKey;
|
|
30
35
|
}
|
|
31
36
|
/**
|
|
32
37
|
* Process an incoming message. Updates internal state but never produces
|
|
@@ -116,8 +121,8 @@ export class AggregationParticipant {
|
|
|
116
121
|
from: this.did,
|
|
117
122
|
to: state.serviceDid,
|
|
118
123
|
cohortId,
|
|
119
|
-
participantPk: this.
|
|
120
|
-
communicationPk: this.
|
|
124
|
+
participantPk: this.publicKey,
|
|
125
|
+
communicationPk: this.publicKey,
|
|
121
126
|
});
|
|
122
127
|
return [optInMessage];
|
|
123
128
|
}
|
|
@@ -153,7 +158,7 @@ export class AggregationParticipant {
|
|
|
153
158
|
const cohortKeys = message.body?.cohortKeys;
|
|
154
159
|
if (!beaconAddress || !cohortKeys)
|
|
155
160
|
return;
|
|
156
|
-
const participantPkHex = bytesToHex(this.
|
|
161
|
+
const participantPkHex = bytesToHex(this.publicKey);
|
|
157
162
|
const cohortKeysHex = cohortKeys.map(k => bytesToHex(new Uint8Array(k)));
|
|
158
163
|
state.cohort.validateMembership(participantPkHex, cohortKeysHex, beaconAddress);
|
|
159
164
|
state.phase = ParticipantCohortPhase.CohortReady;
|
|
@@ -314,7 +319,7 @@ export class AggregationParticipant {
|
|
|
314
319
|
prevOutValues,
|
|
315
320
|
});
|
|
316
321
|
state.signingSession = session;
|
|
317
|
-
const nonceContribution = session.generateNonceContribution(this.
|
|
322
|
+
const nonceContribution = this.#signer.withSecret(secretKey => session.generateNonceContribution(this.publicKey, secretKey));
|
|
318
323
|
state.phase = ParticipantCohortPhase.NonceSent;
|
|
319
324
|
return [createNonceContributionMessage({
|
|
320
325
|
from: this.did,
|
|
@@ -352,7 +357,8 @@ export class AggregationParticipant {
|
|
|
352
357
|
if (!state.signingSession) {
|
|
353
358
|
throw new AggregationParticipantError(`No signing session for cohort ${cohortId}.`, 'MISSING_STATE', { cohortId });
|
|
354
359
|
}
|
|
355
|
-
const
|
|
360
|
+
const signingSession = state.signingSession;
|
|
361
|
+
const partialSig = this.#signer.withSecret(secretKey => signingSession.generatePartialSignature(secretKey));
|
|
356
362
|
state.phase = ParticipantCohortPhase.Complete;
|
|
357
363
|
return [createSignatureAuthorizationMessage({
|
|
358
364
|
from: this.did,
|
|
@@ -365,5 +371,16 @@ export class AggregationParticipant {
|
|
|
365
371
|
getCohortPhase(cohortId) {
|
|
366
372
|
return this.#cohortStates.get(cohortId)?.phase;
|
|
367
373
|
}
|
|
374
|
+
/**
|
|
375
|
+
* Zeroize any retained MuSig2 secret nonces across all cohorts. The raw
|
|
376
|
+
* signing key is never held here (it lives behind the {@link AggregationSigner}
|
|
377
|
+
* and is wiped per-operation), but an abandoned signing session can still hold
|
|
378
|
+
* a secret nonce; call this on teardown to clear it deterministically.
|
|
379
|
+
*/
|
|
380
|
+
clearSecrets() {
|
|
381
|
+
for (const state of this.#cohortStates.values()) {
|
|
382
|
+
state.signingSession?.clearSecrets();
|
|
383
|
+
}
|
|
384
|
+
}
|
|
368
385
|
}
|
|
369
386
|
//# sourceMappingURL=participant.js.map
|