@scure/btc-signer 2.2.0 → 2.4.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/README.md +196 -37
- package/index.d.ts +4 -4
- package/index.js +3 -4
- package/musig2.d.ts +28 -9
- package/musig2.js +46 -18
- package/net.d.ts +355 -0
- package/net.js +880 -0
- package/p2p.d.ts +0 -1
- package/p2p.js +23 -7
- package/package.json +18 -21
- package/payment.d.ts +18 -11
- package/payment.js +203 -58
- package/psbt.d.ts +680 -10
- package/psbt.js +204 -43
- package/script.d.ts +1 -2
- package/script.js +71 -59
- package/src/_type_test.ts +83 -0
- package/src/index.ts +4 -2
- package/src/musig2.ts +71 -19
- package/src/net.ts +1111 -0
- package/src/p2p.ts +22 -6
- package/src/payment.ts +233 -70
- package/src/psbt.ts +228 -39
- package/src/script.ts +57 -35
- package/src/transaction.ts +869 -168
- package/src/utils.ts +92 -4
- package/src/utxo.ts +223 -113
- package/transaction.d.ts +40 -7
- package/transaction.js +745 -151
- package/utils.d.ts +45 -2
- package/utils.js +80 -5
- package/utxo.d.ts +192 -2
- package/utxo.js +200 -99
- package/index.d.ts.map +0 -1
- package/index.js.map +0 -1
- package/musig2.d.ts.map +0 -1
- package/musig2.js.map +0 -1
- package/p2p.d.ts.map +0 -1
- package/p2p.js.map +0 -1
- package/payment.d.ts.map +0 -1
- package/payment.js.map +0 -1
- package/psbt.d.ts.map +0 -1
- package/psbt.js.map +0 -1
- package/script.d.ts.map +0 -1
- package/script.js.map +0 -1
- package/transaction.d.ts.map +0 -1
- package/transaction.js.map +0 -1
- package/utils.d.ts.map +0 -1
- package/utils.js.map +0 -1
- package/utxo.d.ts.map +0 -1
- package/utxo.js.map +0 -1
package/src/p2p.ts
CHANGED
|
@@ -42,6 +42,9 @@ const MINUS_3_SQRT = Fp.sqrt(Fp.create(BigInt(-3)));
|
|
|
42
42
|
const _3n = BigInt(3);
|
|
43
43
|
const _4n = BigInt(4);
|
|
44
44
|
const _7n = BigInt(7);
|
|
45
|
+
// Precomputed 1/2 mod p: turns the frequent "divide by 2" steps of XSwiftEC/XSwiftECInv
|
|
46
|
+
// into single multiplications instead of one modular inversion per call.
|
|
47
|
+
const INV_2 = Fp.inv(Fp.create(_2n));
|
|
45
48
|
// This is the "lift_x(x) succeeds" predicate for field-normalized x values.
|
|
46
49
|
// Raw x >= p would need the full BIP340 range check before reducing modulo p.
|
|
47
50
|
const isValidX = (x: bigint) => FpIsSquare(Fp, Fp.add(Fp.mul(Fp.mul(x, x), x), _7n));
|
|
@@ -91,7 +94,7 @@ export const elligatorSwift = /* @__PURE__ */ Object.freeze({
|
|
|
91
94
|
const r = trySqrt(Fp.mul(Fp.neg(s), Fp.add(Fp.mul(_4n, t0), t1)));
|
|
92
95
|
if (r === undefined) return; // [2 condition]
|
|
93
96
|
if (ellCase & 1 && Fp.is0(r)) return;
|
|
94
|
-
v = Fp.
|
|
97
|
+
v = Fp.mul(Fp.add(Fp.neg(u), Fp.div(r, s)), INV_2); // v = (-u + r / s) / 2
|
|
95
98
|
}
|
|
96
99
|
const w = trySqrt(s);
|
|
97
100
|
if (w === undefined) return; // [3 condition]
|
|
@@ -99,7 +102,7 @@ export const elligatorSwift = /* @__PURE__ */ Object.freeze({
|
|
|
99
102
|
const t0 = last & 1 ? Fp.add(_1n, MINUS_3_SQRT) : Fp.sub(_1n, MINUS_3_SQRT);
|
|
100
103
|
const w0 = last === 0 || last === 5 ? Fp.neg(w) : w; // -w | w
|
|
101
104
|
// w0 * (u * t0 / 2 + v)
|
|
102
|
-
return Fp.mul(w0, Fp.add(Fp.
|
|
105
|
+
return Fp.mul(w0, Fp.add(Fp.mul(Fp.mul(u, t0), INV_2), v));
|
|
103
106
|
},
|
|
104
107
|
// Encode public key (point or x coordinate bigint) into 64-byte pseudorandom encoding
|
|
105
108
|
// BIP324 samples encodings for x(P), so callers must pass a curve X coordinate in 0..p-1;
|
|
@@ -109,11 +112,18 @@ export const elligatorSwift = /* @__PURE__ */ Object.freeze({
|
|
|
109
112
|
// so encode() must reject out-of-range x instead of silently reducing a different bigint modulo p.
|
|
110
113
|
if (!Fp.isValid(x))
|
|
111
114
|
throw new RangeError('elligatorSwift.encode: expected x coordinate in range 0..p-1');
|
|
115
|
+
// Off-curve x cannot round-trip: decode() only returns lift_x-able candidates, so
|
|
116
|
+
// the loop below would silently emit an encoding of a *different* public key.
|
|
117
|
+
if (!isValidX(x))
|
|
118
|
+
throw new RangeError('elligatorSwift.encode: expected x coordinate of a curve point');
|
|
112
119
|
// 200k test cycles per keygen: avg=4 max=48
|
|
113
120
|
// seems too much, but same as for reference implementation
|
|
114
121
|
while (true) {
|
|
115
|
-
//
|
|
116
|
-
|
|
122
|
+
// Random field element 1..p-1: BIP324 samples u over the whole field (the previous
|
|
123
|
+
// secret-key sampler silently restricted u to 1..n-1); decode() remaps u = 0, so
|
|
124
|
+
// zero cannot round-trip and is skipped.
|
|
125
|
+
const u = Fp.create(Fp.fromBytes(randomBytes(32), true));
|
|
126
|
+
if (Fp.is0(u)) continue;
|
|
117
127
|
const ellCase = randomBytes(1)[0] & 7; // [0..8)
|
|
118
128
|
const t = elligatorSwift._inv(x, u, ellCase);
|
|
119
129
|
if (!t) continue;
|
|
@@ -140,9 +150,11 @@ export const elligatorSwift = /* @__PURE__ */ Object.freeze({
|
|
|
140
150
|
// try different cases
|
|
141
151
|
let res = Fp.add(u, Fp.mul(Fp.mul(y, y), _4n)); // u + 4 * Y ** 2,
|
|
142
152
|
if (isValidX(res)) return Fp.toBytes(res) as TRet<Uint8Array>;
|
|
143
|
-
|
|
153
|
+
// X / Y is shared by the remaining candidates; computing it once saves an inversion.
|
|
154
|
+
const xDivY = Fp.div(x, y);
|
|
155
|
+
res = Fp.mul(Fp.sub(Fp.neg(xDivY), u), INV_2); // (-X / Y - u) / 2
|
|
144
156
|
if (isValidX(res)) return Fp.toBytes(res) as TRet<Uint8Array>;
|
|
145
|
-
res = Fp.
|
|
157
|
+
res = Fp.mul(Fp.sub(xDivY, u), INV_2); // (X / Y - u) / 2
|
|
146
158
|
if (isValidX(res)) return Fp.toBytes(res) as TRet<Uint8Array>;
|
|
147
159
|
throw new Error('elligatorSwift: cannot decode public key');
|
|
148
160
|
},
|
|
@@ -173,6 +185,10 @@ export const elligatorSwift = /* @__PURE__ */ Object.freeze({
|
|
|
173
185
|
): TRet<Uint8Array> => {
|
|
174
186
|
// BIP324 Shared secret computation hashes "the exactly 64-byte public keys'
|
|
175
187
|
// encodings sent over the wire", so both ElligatorSwift inputs must be 64 bytes here.
|
|
188
|
+
// Initiator/responder ordering decides the hash-input order, so require a real boolean
|
|
189
|
+
// instead of letting arbitrary truthy values pick a side.
|
|
190
|
+
if (typeof initiating !== 'boolean')
|
|
191
|
+
throw new TypeError('"initiating" expected boolean, got type=' + typeof initiating);
|
|
176
192
|
const ours = abytes(publicKeyOurs, 64, 'publicKeyOurs');
|
|
177
193
|
const theirs = abytes(publicKeyTheirs, 64, 'publicKeyTheirs');
|
|
178
194
|
const ecdhPoint = elligatorSwift.getSharedSecret(privateKeyOurs, theirs);
|