@dynamic-labs-wallet/btc-utils 1.0.105 → 1.0.107
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/index.cjs +269 -31
- package/index.esm.js +265 -32
- package/package.json +2 -2
- package/src/assertSighashAllowed/assertSighashAllowed.d.ts +21 -0
- package/src/assertSighashAllowed/assertSighashAllowed.d.ts.map +1 -0
- package/src/assertSighashAllowed/index.d.ts +2 -0
- package/src/assertSighashAllowed/index.d.ts.map +1 -0
- package/src/bytesEqual/bytesEqual.d.ts +10 -0
- package/src/bytesEqual/bytesEqual.d.ts.map +1 -0
- package/src/bytesEqual/index.d.ts +2 -0
- package/src/bytesEqual/index.d.ts.map +1 -0
- package/src/convertSignatureToDER/convertSignatureToDER.d.ts +4 -1
- package/src/convertSignatureToDER/convertSignatureToDER.d.ts.map +1 -1
- package/src/convertSignatureToTaprootBuffer/convertSignatureToTaprootBuffer.d.ts +5 -2
- package/src/convertSignatureToTaprootBuffer/convertSignatureToTaprootBuffer.d.ts.map +1 -1
- package/src/doesInputBelongToAddress/doesInputBelongToAddress.d.ts +14 -3
- package/src/doesInputBelongToAddress/doesInputBelongToAddress.d.ts.map +1 -1
- package/src/extractPsbtSighashes/extractPsbtSighashes.d.ts +6 -2
- package/src/extractPsbtSighashes/extractPsbtSighashes.d.ts.map +1 -1
- package/src/filterInputsBySigningIndexes/filterInputsBySigningIndexes.d.ts +12 -0
- package/src/filterInputsBySigningIndexes/filterInputsBySigningIndexes.d.ts.map +1 -0
- package/src/filterInputsBySigningIndexes/index.d.ts +2 -0
- package/src/filterInputsBySigningIndexes/index.d.ts.map +1 -0
- package/src/getSegwitV0ScriptCode/getSegwitV0ScriptCode.d.ts +20 -0
- package/src/getSegwitV0ScriptCode/getSegwitV0ScriptCode.d.ts.map +1 -0
- package/src/getSegwitV0ScriptCode/index.d.ts +2 -0
- package/src/getSegwitV0ScriptCode/index.d.ts.map +1 -0
- package/src/getSigHashType/getSigHashType.d.ts +21 -0
- package/src/getSigHashType/getSigHashType.d.ts.map +1 -0
- package/src/getSigHashType/index.d.ts +2 -0
- package/src/getSigHashType/index.d.ts.map +1 -0
- package/src/index.d.ts +5 -0
- package/src/index.d.ts.map +1 -1
- package/src/isP2wshOutputScript/index.d.ts +2 -0
- package/src/isP2wshOutputScript/index.d.ts.map +1 -0
- package/src/isP2wshOutputScript/isP2wshOutputScript.d.ts +10 -0
- package/src/isP2wshOutputScript/isP2wshOutputScript.d.ts.map +1 -0
package/index.cjs
CHANGED
|
@@ -726,8 +726,12 @@ function _instanceof$3(left, right) {
|
|
|
726
726
|
* Converts an ECDSA signature to DER format
|
|
727
727
|
*
|
|
728
728
|
* @param signature - The ECDSA signature
|
|
729
|
+
* @param sighashType - The sighash type to append as the DER trailing byte.
|
|
730
|
+
* Must match the type the signing hash was built with, or the signature will
|
|
731
|
+
* fail verification at finalize/broadcast. Defaults to SIGHASH_ALL.
|
|
729
732
|
* @returns The DER encoded signature
|
|
730
733
|
*/ var convertSignatureToDER = function(signature) {
|
|
734
|
+
var sighashType = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : bitcoin__namespace.Transaction.SIGHASH_ALL;
|
|
731
735
|
var r = _instanceof$3(signature.r, Uint8Array) ? signature.r : new Uint8Array(signature.r);
|
|
732
736
|
var s = _instanceof$3(signature.s, Uint8Array) ? signature.s : new Uint8Array(signature.s);
|
|
733
737
|
var r32 = new Uint8Array(32);
|
|
@@ -739,7 +743,7 @@ function _instanceof$3(left, right) {
|
|
|
739
743
|
var rawSignature = new Uint8Array(64);
|
|
740
744
|
rawSignature.set(r32, 0);
|
|
741
745
|
rawSignature.set(s32, 32);
|
|
742
|
-
var derSignature = bitcoin__namespace.script.signature.encode(rawSignature,
|
|
746
|
+
var derSignature = bitcoin__namespace.script.signature.encode(rawSignature, sighashType);
|
|
743
747
|
return derSignature;
|
|
744
748
|
};
|
|
745
749
|
|
|
@@ -1210,19 +1214,34 @@ function _instanceof$2(left, right) {
|
|
|
1210
1214
|
* Converts a signature to a Buffer format suitable for Taproot (BIP340/Schnorr)
|
|
1211
1215
|
*
|
|
1212
1216
|
* @param signature - The signature from MPC (can be Uint8Array, Buffer, or EcdsaSignature object)
|
|
1213
|
-
* @
|
|
1217
|
+
* @param sighashType - The sighash type the signing hash was built with. Per
|
|
1218
|
+
* BIP-341 the signature stays 64 bytes for SIGHASH_DEFAULT and gains the
|
|
1219
|
+
* sighash type as a 65th byte for any other type. Defaults to SIGHASH_DEFAULT.
|
|
1220
|
+
* @returns A Buffer containing the 64-byte (or 65-byte) Schnorr signature
|
|
1214
1221
|
*/ var convertSignatureToTaprootBuffer = function(signature) {
|
|
1222
|
+
var sighashType = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : bitcoin__namespace.Transaction.SIGHASH_DEFAULT;
|
|
1223
|
+
var schnorrSignature;
|
|
1215
1224
|
if (_instanceof$2(signature, Uint8Array) || Buffer.isBuffer(signature)) {
|
|
1216
|
-
|
|
1225
|
+
schnorrSignature = Buffer.from(signature);
|
|
1226
|
+
} else {
|
|
1227
|
+
var r = signature.r;
|
|
1228
|
+
var s = signature.s;
|
|
1229
|
+
var rBuf = Buffer.isBuffer(r) ? r : Buffer.from(r);
|
|
1230
|
+
var sBuf = Buffer.isBuffer(s) ? s : Buffer.from(s);
|
|
1231
|
+
// Safe: creates Uint8Array views over Buffer's underlying memory without copying
|
|
1232
|
+
schnorrSignature = Buffer.concat([
|
|
1233
|
+
new Uint8Array(rBuf),
|
|
1234
|
+
new Uint8Array(sBuf)
|
|
1235
|
+
]);
|
|
1236
|
+
}
|
|
1237
|
+
if (sighashType === bitcoin__namespace.Transaction.SIGHASH_DEFAULT) {
|
|
1238
|
+
return schnorrSignature;
|
|
1217
1239
|
}
|
|
1218
|
-
var r = signature.r;
|
|
1219
|
-
var s = signature.s;
|
|
1220
|
-
var rBuf = Buffer.isBuffer(r) ? r : Buffer.from(r);
|
|
1221
|
-
var sBuf = Buffer.isBuffer(s) ? s : Buffer.from(s);
|
|
1222
|
-
// Safe: creates Uint8Array views over Buffer's underlying memory without copying
|
|
1223
1240
|
return Buffer.concat([
|
|
1224
|
-
new Uint8Array(
|
|
1225
|
-
new Uint8Array(
|
|
1241
|
+
new Uint8Array(schnorrSignature),
|
|
1242
|
+
new Uint8Array([
|
|
1243
|
+
sighashType
|
|
1244
|
+
])
|
|
1226
1245
|
]);
|
|
1227
1246
|
};
|
|
1228
1247
|
|
|
@@ -1248,6 +1267,30 @@ function _instanceof$2(left, right) {
|
|
|
1248
1267
|
};
|
|
1249
1268
|
};
|
|
1250
1269
|
|
|
1270
|
+
/**
|
|
1271
|
+
* Checks if an output script (scriptPubKey) is P2WSH: OP_0 <32-byte sha256(witnessScript)>
|
|
1272
|
+
*
|
|
1273
|
+
* ArrayLike keeps this callable with Buffer or Uint8Array — the iframe build
|
|
1274
|
+
* compiles with browser typings where Buffer is not assignable to Uint8Array.
|
|
1275
|
+
* @param script - The output script to check
|
|
1276
|
+
* @returns True if the script has the P2WSH shape
|
|
1277
|
+
*/ var isP2wshOutputScript = function(script) {
|
|
1278
|
+
return script.length === 34 && script[0] === 0x00 && script[1] === 0x20;
|
|
1279
|
+
};
|
|
1280
|
+
|
|
1281
|
+
/**
|
|
1282
|
+
* Constant-shape byte equality without Buffer — the iframe build compiles
|
|
1283
|
+
* this package with browser typings where Buffer is not assignable to
|
|
1284
|
+
* Uint8Array.
|
|
1285
|
+
* @param a - First byte array
|
|
1286
|
+
* @param b - Second byte array
|
|
1287
|
+
* @returns True if both arrays have identical length and contents
|
|
1288
|
+
*/ var bytesEqual = function(a, b) {
|
|
1289
|
+
return a.length === b.length && a.every(function(byte, index) {
|
|
1290
|
+
return byte === b[index];
|
|
1291
|
+
});
|
|
1292
|
+
};
|
|
1293
|
+
|
|
1251
1294
|
function _instanceof$1(left, right) {
|
|
1252
1295
|
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
1253
1296
|
return !!right[Symbol.hasInstance](left);
|
|
@@ -1256,12 +1299,63 @@ function _instanceof$1(left, right) {
|
|
|
1256
1299
|
}
|
|
1257
1300
|
}
|
|
1258
1301
|
/**
|
|
1259
|
-
*
|
|
1302
|
+
* P2WSH ownership: the caller allowlisted the witnessScript, it hashes to the
|
|
1303
|
+
* scriptPubKey commitment, and it is a canonical m-of-n CHECKMULTISIG with
|
|
1304
|
+
* `publicKey` in a signing position.
|
|
1305
|
+
*/ var matchesAllowedP2wshMultisig = function(input, script, publicKey, allowedWitnessScripts) {
|
|
1306
|
+
if (!publicKey || !input.witnessScript || !(allowedWitnessScripts === null || allowedWitnessScripts === void 0 ? void 0 : allowedWitnessScripts.length)) {
|
|
1307
|
+
return false;
|
|
1308
|
+
}
|
|
1309
|
+
var witnessScript = Uint8Array.from(input.witnessScript);
|
|
1310
|
+
// P2WSH co-signing is opt-in: the wallet only signs arrangements the
|
|
1311
|
+
// caller explicitly named in this request.
|
|
1312
|
+
var witnessScriptHex = Buffer.from(witnessScript).toString('hex');
|
|
1313
|
+
if (!allowedWitnessScripts.some(function(hex) {
|
|
1314
|
+
return hex.toLowerCase() === witnessScriptHex;
|
|
1315
|
+
})) {
|
|
1316
|
+
return false;
|
|
1317
|
+
}
|
|
1318
|
+
// The scriptPubKey commits to the witnessScript; a mismatch means the
|
|
1319
|
+
// PSBT is lying about the script this signature would authorize.
|
|
1320
|
+
if (!bytesEqual(sha256.sha256(witnessScript), Uint8Array.from(script).subarray(2))) {
|
|
1321
|
+
return false;
|
|
1322
|
+
}
|
|
1323
|
+
// p2ms throws unless the script is exactly OP_m <keys...> OP_n
|
|
1324
|
+
// OP_CHECKMULTISIG, so the key must occupy a signing position.
|
|
1325
|
+
var multisigPubkeys;
|
|
1326
|
+
try {
|
|
1327
|
+
multisigPubkeys = bitcoin__namespace.payments.p2ms({
|
|
1328
|
+
output: witnessScript
|
|
1329
|
+
}).pubkeys;
|
|
1330
|
+
} catch (e) {
|
|
1331
|
+
return false;
|
|
1332
|
+
}
|
|
1333
|
+
if (!multisigPubkeys) {
|
|
1334
|
+
return false;
|
|
1335
|
+
}
|
|
1336
|
+
var publicKeyBytes = Uint8Array.from(publicKey);
|
|
1337
|
+
return multisigPubkeys.some(function(key) {
|
|
1338
|
+
return bytesEqual(Uint8Array.from(key), publicKeyBytes);
|
|
1339
|
+
});
|
|
1340
|
+
};
|
|
1341
|
+
/**
|
|
1342
|
+
* Checks if a PSBT input belongs to a specific address.
|
|
1343
|
+
*
|
|
1344
|
+
* For P2WSH inputs address equality cannot work (the address commits to the
|
|
1345
|
+
* script, not our key), so ownership is opt-in and means ALL of: the caller
|
|
1346
|
+
* explicitly allowlisted the witnessScript, it hashes to the scriptPubKey
|
|
1347
|
+
* commitment, and it is a canonical m-of-n CHECKMULTISIG script with
|
|
1348
|
+
* `publicKey` in a signing position. Any other script shape is rejected even
|
|
1349
|
+
* if the key appears in it, so a hostile PSBT cannot obtain a signature over
|
|
1350
|
+
* an arbitrary script that merely name-drops the wallet key, and the wallet
|
|
1351
|
+
* never co-signs a multisig arrangement the caller did not name.
|
|
1260
1352
|
* @param input - The PSBT input (from psbt.data.inputs)
|
|
1261
1353
|
* @param address - The address to check against
|
|
1262
1354
|
* @param network - The Bitcoin network
|
|
1263
|
-
* @
|
|
1264
|
-
|
|
1355
|
+
* @param publicKey - The wallet's compressed ECDSA public key; required to match P2WSH inputs
|
|
1356
|
+
* @param allowedWitnessScripts - Hex-encoded witnessScripts the caller consents to co-sign; required to match P2WSH inputs
|
|
1357
|
+
* @returns True if the input belongs to the address (or public key, for P2WSH), false otherwise
|
|
1358
|
+
*/ var doesInputBelongToAddress = function(input, address, network, publicKey, allowedWitnessScripts) {
|
|
1265
1359
|
if (!input.witnessUtxo) {
|
|
1266
1360
|
return false;
|
|
1267
1361
|
}
|
|
@@ -1285,6 +1379,10 @@ function _instanceof$1(left, right) {
|
|
|
1285
1379
|
}).address === address;
|
|
1286
1380
|
});
|
|
1287
1381
|
}
|
|
1382
|
+
// Try P2WSH - script is OP_0 <32-byte sha256(witnessScript)>
|
|
1383
|
+
if (isP2wshOutputScript(script)) {
|
|
1384
|
+
return matchesAllowedP2wshMultisig(input, script, publicKey, allowedWitnessScripts);
|
|
1385
|
+
}
|
|
1288
1386
|
// Try P2TR (Taproot) - script is OP_1 <32-byte x-only pubkey>
|
|
1289
1387
|
if (script.length === 34 && script[0] === 0x51 && script[1] === 0x20) {
|
|
1290
1388
|
return networksToTry.some(function(bitcoinNetwork) {
|
|
@@ -1306,6 +1404,139 @@ function _instanceof$1(left, right) {
|
|
|
1306
1404
|
}
|
|
1307
1405
|
};
|
|
1308
1406
|
|
|
1407
|
+
/**
|
|
1408
|
+
* Resolves the BIP-143 scriptCode for a segwit v0 input. Shared by the signer
|
|
1409
|
+
* and the sighash-verification helper so both derive the identical digest.
|
|
1410
|
+
*
|
|
1411
|
+
* P2WSH inputs sign over the full witnessScript, verified against the
|
|
1412
|
+
* scriptPubKey commitment so a PSBT cannot substitute a script the UTXO does
|
|
1413
|
+
* not commit to. P2WPKH inputs sign over the implied P2PKH script.
|
|
1414
|
+
*
|
|
1415
|
+
* @param input - The PSBT input (from psbt.data.inputs)
|
|
1416
|
+
* @param script - The input's witnessUtxo scriptPubKey
|
|
1417
|
+
* @param index - The input index (for error messages)
|
|
1418
|
+
* @param bitcoinNetwork - The bitcoinjs-lib network for P2PKH reconstruction
|
|
1419
|
+
* @returns The scriptCode to feed hashForWitnessV0
|
|
1420
|
+
* @throws Error if a P2WSH input is missing its witnessScript, the witnessScript
|
|
1421
|
+
* does not hash to the scriptPubKey commitment, or scriptCode generation fails
|
|
1422
|
+
*/ var getSegwitV0ScriptCode = function(input, script, index, bitcoinNetwork) {
|
|
1423
|
+
if (isP2wshOutputScript(script)) {
|
|
1424
|
+
if (!input.witnessScript) {
|
|
1425
|
+
throw new Error("Input ".concat(index, " is P2WSH but missing witnessScript"));
|
|
1426
|
+
}
|
|
1427
|
+
var witnessScript = Uint8Array.from(input.witnessScript);
|
|
1428
|
+
// The scriptPubKey commits to the witnessScript; refuse to compute a
|
|
1429
|
+
// sighash over a script the UTXO does not commit to.
|
|
1430
|
+
if (!bytesEqual(sha256.sha256(witnessScript), Uint8Array.from(script).subarray(2))) {
|
|
1431
|
+
throw new Error("Input ".concat(index, " witnessScript does not match the P2WSH scriptPubKey commitment"));
|
|
1432
|
+
}
|
|
1433
|
+
return witnessScript;
|
|
1434
|
+
}
|
|
1435
|
+
// Build P2PKH script code from the pubkey hash in the witness program
|
|
1436
|
+
var p2pkh = bitcoin__namespace.payments.p2pkh({
|
|
1437
|
+
hash: Uint8Array.from(script).subarray(2),
|
|
1438
|
+
network: bitcoinNetwork
|
|
1439
|
+
});
|
|
1440
|
+
if (!p2pkh.output) {
|
|
1441
|
+
throw new Error("Failed to generate scriptCode for input ".concat(index));
|
|
1442
|
+
}
|
|
1443
|
+
return p2pkh.output;
|
|
1444
|
+
};
|
|
1445
|
+
|
|
1446
|
+
/**
|
|
1447
|
+
* Restricts wallet-owned PSBT inputs to an explicitly requested subset.
|
|
1448
|
+
*
|
|
1449
|
+
* @param inputsToSign - Wallet-owned inputs, each carrying its PSBT index
|
|
1450
|
+
* @param signingIndexes - Optional subset of input indexes the caller wants signed
|
|
1451
|
+
* @returns The requested subset, or all inputs when signingIndexes is omitted/empty
|
|
1452
|
+
* @throws Error if signingIndexes references an input the wallet does not own
|
|
1453
|
+
*/ var filterInputsBySigningIndexes = function(inputsToSign, signingIndexes) {
|
|
1454
|
+
if (!(signingIndexes === null || signingIndexes === void 0 ? void 0 : signingIndexes.length)) {
|
|
1455
|
+
return inputsToSign;
|
|
1456
|
+
}
|
|
1457
|
+
var walletOwnedIndexSet = new Set(inputsToSign.map(function(param) {
|
|
1458
|
+
var index = param.index;
|
|
1459
|
+
return index;
|
|
1460
|
+
}));
|
|
1461
|
+
var invalidIndexes = signingIndexes.filter(function(i) {
|
|
1462
|
+
return !walletOwnedIndexSet.has(i);
|
|
1463
|
+
});
|
|
1464
|
+
if (invalidIndexes.length > 0) {
|
|
1465
|
+
throw new Error("signingIndexes contains indexes that do not belong to the signing address: ".concat(invalidIndexes.join(', ')));
|
|
1466
|
+
}
|
|
1467
|
+
var requestedIndexSet = new Set(signingIndexes);
|
|
1468
|
+
return inputsToSign.filter(function(param) {
|
|
1469
|
+
var index = param.index;
|
|
1470
|
+
return requestedIndexSet.has(index);
|
|
1471
|
+
});
|
|
1472
|
+
};
|
|
1473
|
+
|
|
1474
|
+
/**
|
|
1475
|
+
* Resolves the sighash type for a PSBT input.
|
|
1476
|
+
*
|
|
1477
|
+
* The type is read from the PSBT itself (BIP-174 `PSBT_IN_SIGHASH_TYPE`), never
|
|
1478
|
+
* supplied by the caller — the signing hash and the policy layer's verification
|
|
1479
|
+
* hash must be derived from the same bytes, or every non-default signature
|
|
1480
|
+
* would be rejected as tampered.
|
|
1481
|
+
*
|
|
1482
|
+
* When the input declares nothing, falls back to the historical default:
|
|
1483
|
+
* SIGHASH_DEFAULT (0x00) for Taproot, SIGHASH_ALL (0x01) otherwise.
|
|
1484
|
+
*
|
|
1485
|
+
* @param input - The PSBT input to resolve the sighash type for
|
|
1486
|
+
* @param isTaproot - Whether the input is spent as Taproot. Defaults to
|
|
1487
|
+
* detecting `tapInternalKey`; pass explicitly when the caller already knows
|
|
1488
|
+
* which signing branch it is on, so the fallback matches the hash function
|
|
1489
|
+
* actually used.
|
|
1490
|
+
* @returns The sighash type to build and encode the signature with
|
|
1491
|
+
*/ var getSigHashType = function(input) {
|
|
1492
|
+
var isTaproot = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : Boolean(input.tapInternalKey);
|
|
1493
|
+
var _input_sighashType;
|
|
1494
|
+
return (_input_sighashType = input.sighashType) !== null && _input_sighashType !== void 0 ? _input_sighashType : isTaproot ? bitcoin__namespace.Transaction.SIGHASH_DEFAULT : bitcoin__namespace.Transaction.SIGHASH_ALL;
|
|
1495
|
+
};
|
|
1496
|
+
|
|
1497
|
+
/**
|
|
1498
|
+
* Throws unless every input's PSBT-declared sighash type is in the allow-list.
|
|
1499
|
+
*
|
|
1500
|
+
* Call this before any signing begins — inputs are signed in parallel, so
|
|
1501
|
+
* throwing partway through would leave a partially signed PSBT behind.
|
|
1502
|
+
*
|
|
1503
|
+
* An empty array permits nothing rather than everything: a caller whose
|
|
1504
|
+
* allow-list computes to empty must not silently get the guard disabled. Omit
|
|
1505
|
+
* the parameter entirely to permit any declared type.
|
|
1506
|
+
*
|
|
1507
|
+
* @param inputsToSign - The wallet-owned inputs about to be signed, with their PSBT indexes
|
|
1508
|
+
* @param isTaproot - Whether signing takes the Taproot branch, so the fallback
|
|
1509
|
+
* sighash type matches the hash function actually used
|
|
1510
|
+
* @param allowedSighash - Optional allow-list of permitted sighash types
|
|
1511
|
+
*/ var assertSighashAllowed = function(inputsToSign, isTaproot, allowedSighash) {
|
|
1512
|
+
if (!allowedSighash) {
|
|
1513
|
+
return;
|
|
1514
|
+
}
|
|
1515
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
1516
|
+
try {
|
|
1517
|
+
for(var _iterator = inputsToSign[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
1518
|
+
var _step_value = _step.value, input = _step_value.input, index = _step_value.index;
|
|
1519
|
+
var sigHashType = getSigHashType(input, isTaproot);
|
|
1520
|
+
if (!allowedSighash.includes(sigHashType)) {
|
|
1521
|
+
throw new Error("Input ".concat(index, " declares sighash type ").concat(sigHashType, ", which is not in allowedSighash: ").concat(allowedSighash.join(', ') || '(empty)'));
|
|
1522
|
+
}
|
|
1523
|
+
}
|
|
1524
|
+
} catch (err) {
|
|
1525
|
+
_didIteratorError = true;
|
|
1526
|
+
_iteratorError = err;
|
|
1527
|
+
} finally{
|
|
1528
|
+
try {
|
|
1529
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
1530
|
+
_iterator.return();
|
|
1531
|
+
}
|
|
1532
|
+
} finally{
|
|
1533
|
+
if (_didIteratorError) {
|
|
1534
|
+
throw _iteratorError;
|
|
1535
|
+
}
|
|
1536
|
+
}
|
|
1537
|
+
}
|
|
1538
|
+
};
|
|
1539
|
+
|
|
1309
1540
|
function _instanceof(left, right) {
|
|
1310
1541
|
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
1311
1542
|
return !!right[Symbol.hasInstance](left);
|
|
@@ -1392,9 +1623,13 @@ function _type_of(obj) {
|
|
|
1392
1623
|
* Extracts sighashes from a PSBT for validation.
|
|
1393
1624
|
* This is used to verify that the message being signed matches the PSBT context.
|
|
1394
1625
|
*
|
|
1626
|
+
* P2WSH inputs whose witnessScript is absent yield `null` instead of a hash:
|
|
1627
|
+
* finalization strips witnessScript from completed inputs, so a co-signer's
|
|
1628
|
+
* already-finalized input must not block validation of the remaining inputs.
|
|
1629
|
+
*
|
|
1395
1630
|
* @param psbtBase64 - PSBT in base64 format
|
|
1396
1631
|
* @param network - 'mainnet' or 'testnet' or BitcoinNetwork enum (defaults to 'mainnet')
|
|
1397
|
-
* @returns Array of sighash hex strings for
|
|
1632
|
+
* @returns Array of sighash hex strings, aligned by input index; `null` for inputs whose sighash cannot be derived
|
|
1398
1633
|
*/ var extractPsbtSighashes = function(psbtBase64) {
|
|
1399
1634
|
var network = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 'mainnet';
|
|
1400
1635
|
// Convert string network to BitcoinNetwork enum
|
|
@@ -1412,25 +1647,23 @@ function _type_of(obj) {
|
|
|
1412
1647
|
for(var i = 0; i < psbt.inputCount; i++){
|
|
1413
1648
|
var input = psbt.data.inputs[i];
|
|
1414
1649
|
if (input.tapInternalKey) {
|
|
1415
|
-
// Taproot (BIP-341) - uses hashForWitnessV1 with
|
|
1416
|
-
|
|
1650
|
+
// Taproot (BIP-341) - uses hashForWitnessV1 with the input's declared
|
|
1651
|
+
// sighash type, defaulting to SIGHASH_DEFAULT
|
|
1652
|
+
var hash = tx.hashForWitnessV1(i, prevOutScripts, values, getSigHashType(input, true));
|
|
1417
1653
|
sighashes.push(Buffer.from(hash).toString('hex'));
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
var scriptCode = p2pkh.output;
|
|
1428
|
-
if (!scriptCode) {
|
|
1429
|
-
throw new Error("Failed to generate scriptCode for input ".concat(i));
|
|
1430
|
-
}
|
|
1431
|
-
var hash1 = tx.hashForWitnessV0(i, scriptCode, value, bitcoin__namespace.Transaction.SIGHASH_ALL);
|
|
1432
|
-
sighashes.push(Buffer.from(hash1).toString('hex'));
|
|
1654
|
+
continue;
|
|
1655
|
+
}
|
|
1656
|
+
// Native SegWit (BIP-143) - uses hashForWitnessV0 with the input's
|
|
1657
|
+
// declared sighash type, defaulting to SIGHASH_ALL
|
|
1658
|
+
// witnessUtxo is guaranteed to exist from collectPSBTInputData validation
|
|
1659
|
+
var _input_witnessUtxo = input.witnessUtxo, script = _input_witnessUtxo.script, value = _input_witnessUtxo.value;
|
|
1660
|
+
if (isP2wshOutputScript(script) && !input.witnessScript) {
|
|
1661
|
+
sighashes.push(null);
|
|
1662
|
+
continue;
|
|
1433
1663
|
}
|
|
1664
|
+
var scriptCode = getSegwitV0ScriptCode(input, script, i, bitcoinNetwork);
|
|
1665
|
+
var hash1 = tx.hashForWitnessV0(i, scriptCode, value, getSigHashType(input, false));
|
|
1666
|
+
sighashes.push(Buffer.from(hash1).toString('hex'));
|
|
1434
1667
|
}
|
|
1435
1668
|
return sighashes;
|
|
1436
1669
|
};
|
|
@@ -1470,6 +1703,7 @@ function _type_of(obj) {
|
|
|
1470
1703
|
return Buffer.from(formattedMessage).toString('hex');
|
|
1471
1704
|
};
|
|
1472
1705
|
|
|
1706
|
+
exports.assertSighashAllowed = assertSighashAllowed;
|
|
1473
1707
|
exports.calculateBip322Hash = calculateBip322Hash;
|
|
1474
1708
|
exports.calculateTaprootTweak = calculateTaprootTweak;
|
|
1475
1709
|
exports.collectPSBTInputData = collectPSBTInputData;
|
|
@@ -1484,13 +1718,17 @@ exports.doesInputBelongToAddress = doesInputBelongToAddress;
|
|
|
1484
1718
|
exports.encodeBip322Signature = encodeBip322Signature;
|
|
1485
1719
|
exports.extractPsbtSighashes = extractPsbtSighashes;
|
|
1486
1720
|
exports.extractPublicKeyHex = extractPublicKeyHex;
|
|
1721
|
+
exports.filterInputsBySigningIndexes = filterInputsBySigningIndexes;
|
|
1487
1722
|
exports.getAddressTypeFromDerivationPath = getAddressTypeFromDerivationPath;
|
|
1488
1723
|
exports.getBitcoinNetwork = getBitcoinNetwork;
|
|
1489
1724
|
exports.getDefaultRpcUrl = getDefaultRpcUrl;
|
|
1490
1725
|
exports.getFeeRates = getFeeRates;
|
|
1491
1726
|
exports.getPublicKeyFromPrivateKey = getPublicKeyFromPrivateKey;
|
|
1727
|
+
exports.getSegwitV0ScriptCode = getSegwitV0ScriptCode;
|
|
1728
|
+
exports.getSigHashType = getSigHashType;
|
|
1492
1729
|
exports.getUTXOs = getUTXOs;
|
|
1493
1730
|
exports.initEccLib = initEccLib;
|
|
1731
|
+
exports.isP2wshOutputScript = isP2wshOutputScript;
|
|
1494
1732
|
exports.normalizeForCompressed = normalizeForCompressed;
|
|
1495
1733
|
exports.normalizeForTaproot = normalizeForTaproot;
|
|
1496
1734
|
exports.normalizePublicKey = normalizePublicKey;
|
package/index.esm.js
CHANGED
|
@@ -706,8 +706,12 @@ function _instanceof$3(left, right) {
|
|
|
706
706
|
* Converts an ECDSA signature to DER format
|
|
707
707
|
*
|
|
708
708
|
* @param signature - The ECDSA signature
|
|
709
|
+
* @param sighashType - The sighash type to append as the DER trailing byte.
|
|
710
|
+
* Must match the type the signing hash was built with, or the signature will
|
|
711
|
+
* fail verification at finalize/broadcast. Defaults to SIGHASH_ALL.
|
|
709
712
|
* @returns The DER encoded signature
|
|
710
713
|
*/ var convertSignatureToDER = function(signature) {
|
|
714
|
+
var sighashType = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : bitcoin.Transaction.SIGHASH_ALL;
|
|
711
715
|
var r = _instanceof$3(signature.r, Uint8Array) ? signature.r : new Uint8Array(signature.r);
|
|
712
716
|
var s = _instanceof$3(signature.s, Uint8Array) ? signature.s : new Uint8Array(signature.s);
|
|
713
717
|
var r32 = new Uint8Array(32);
|
|
@@ -719,7 +723,7 @@ function _instanceof$3(left, right) {
|
|
|
719
723
|
var rawSignature = new Uint8Array(64);
|
|
720
724
|
rawSignature.set(r32, 0);
|
|
721
725
|
rawSignature.set(s32, 32);
|
|
722
|
-
var derSignature = bitcoin.script.signature.encode(rawSignature,
|
|
726
|
+
var derSignature = bitcoin.script.signature.encode(rawSignature, sighashType);
|
|
723
727
|
return derSignature;
|
|
724
728
|
};
|
|
725
729
|
|
|
@@ -1190,19 +1194,34 @@ function _instanceof$2(left, right) {
|
|
|
1190
1194
|
* Converts a signature to a Buffer format suitable for Taproot (BIP340/Schnorr)
|
|
1191
1195
|
*
|
|
1192
1196
|
* @param signature - The signature from MPC (can be Uint8Array, Buffer, or EcdsaSignature object)
|
|
1193
|
-
* @
|
|
1197
|
+
* @param sighashType - The sighash type the signing hash was built with. Per
|
|
1198
|
+
* BIP-341 the signature stays 64 bytes for SIGHASH_DEFAULT and gains the
|
|
1199
|
+
* sighash type as a 65th byte for any other type. Defaults to SIGHASH_DEFAULT.
|
|
1200
|
+
* @returns A Buffer containing the 64-byte (or 65-byte) Schnorr signature
|
|
1194
1201
|
*/ var convertSignatureToTaprootBuffer = function(signature) {
|
|
1202
|
+
var sighashType = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : bitcoin.Transaction.SIGHASH_DEFAULT;
|
|
1203
|
+
var schnorrSignature;
|
|
1195
1204
|
if (_instanceof$2(signature, Uint8Array) || Buffer.isBuffer(signature)) {
|
|
1196
|
-
|
|
1205
|
+
schnorrSignature = Buffer.from(signature);
|
|
1206
|
+
} else {
|
|
1207
|
+
var r = signature.r;
|
|
1208
|
+
var s = signature.s;
|
|
1209
|
+
var rBuf = Buffer.isBuffer(r) ? r : Buffer.from(r);
|
|
1210
|
+
var sBuf = Buffer.isBuffer(s) ? s : Buffer.from(s);
|
|
1211
|
+
// Safe: creates Uint8Array views over Buffer's underlying memory without copying
|
|
1212
|
+
schnorrSignature = Buffer.concat([
|
|
1213
|
+
new Uint8Array(rBuf),
|
|
1214
|
+
new Uint8Array(sBuf)
|
|
1215
|
+
]);
|
|
1216
|
+
}
|
|
1217
|
+
if (sighashType === bitcoin.Transaction.SIGHASH_DEFAULT) {
|
|
1218
|
+
return schnorrSignature;
|
|
1197
1219
|
}
|
|
1198
|
-
var r = signature.r;
|
|
1199
|
-
var s = signature.s;
|
|
1200
|
-
var rBuf = Buffer.isBuffer(r) ? r : Buffer.from(r);
|
|
1201
|
-
var sBuf = Buffer.isBuffer(s) ? s : Buffer.from(s);
|
|
1202
|
-
// Safe: creates Uint8Array views over Buffer's underlying memory without copying
|
|
1203
1220
|
return Buffer.concat([
|
|
1204
|
-
new Uint8Array(
|
|
1205
|
-
new Uint8Array(
|
|
1221
|
+
new Uint8Array(schnorrSignature),
|
|
1222
|
+
new Uint8Array([
|
|
1223
|
+
sighashType
|
|
1224
|
+
])
|
|
1206
1225
|
]);
|
|
1207
1226
|
};
|
|
1208
1227
|
|
|
@@ -1228,6 +1247,30 @@ function _instanceof$2(left, right) {
|
|
|
1228
1247
|
};
|
|
1229
1248
|
};
|
|
1230
1249
|
|
|
1250
|
+
/**
|
|
1251
|
+
* Checks if an output script (scriptPubKey) is P2WSH: OP_0 <32-byte sha256(witnessScript)>
|
|
1252
|
+
*
|
|
1253
|
+
* ArrayLike keeps this callable with Buffer or Uint8Array — the iframe build
|
|
1254
|
+
* compiles with browser typings where Buffer is not assignable to Uint8Array.
|
|
1255
|
+
* @param script - The output script to check
|
|
1256
|
+
* @returns True if the script has the P2WSH shape
|
|
1257
|
+
*/ var isP2wshOutputScript = function(script) {
|
|
1258
|
+
return script.length === 34 && script[0] === 0x00 && script[1] === 0x20;
|
|
1259
|
+
};
|
|
1260
|
+
|
|
1261
|
+
/**
|
|
1262
|
+
* Constant-shape byte equality without Buffer — the iframe build compiles
|
|
1263
|
+
* this package with browser typings where Buffer is not assignable to
|
|
1264
|
+
* Uint8Array.
|
|
1265
|
+
* @param a - First byte array
|
|
1266
|
+
* @param b - Second byte array
|
|
1267
|
+
* @returns True if both arrays have identical length and contents
|
|
1268
|
+
*/ var bytesEqual = function(a, b) {
|
|
1269
|
+
return a.length === b.length && a.every(function(byte, index) {
|
|
1270
|
+
return byte === b[index];
|
|
1271
|
+
});
|
|
1272
|
+
};
|
|
1273
|
+
|
|
1231
1274
|
function _instanceof$1(left, right) {
|
|
1232
1275
|
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
1233
1276
|
return !!right[Symbol.hasInstance](left);
|
|
@@ -1236,12 +1279,63 @@ function _instanceof$1(left, right) {
|
|
|
1236
1279
|
}
|
|
1237
1280
|
}
|
|
1238
1281
|
/**
|
|
1239
|
-
*
|
|
1282
|
+
* P2WSH ownership: the caller allowlisted the witnessScript, it hashes to the
|
|
1283
|
+
* scriptPubKey commitment, and it is a canonical m-of-n CHECKMULTISIG with
|
|
1284
|
+
* `publicKey` in a signing position.
|
|
1285
|
+
*/ var matchesAllowedP2wshMultisig = function(input, script, publicKey, allowedWitnessScripts) {
|
|
1286
|
+
if (!publicKey || !input.witnessScript || !(allowedWitnessScripts === null || allowedWitnessScripts === void 0 ? void 0 : allowedWitnessScripts.length)) {
|
|
1287
|
+
return false;
|
|
1288
|
+
}
|
|
1289
|
+
var witnessScript = Uint8Array.from(input.witnessScript);
|
|
1290
|
+
// P2WSH co-signing is opt-in: the wallet only signs arrangements the
|
|
1291
|
+
// caller explicitly named in this request.
|
|
1292
|
+
var witnessScriptHex = Buffer.from(witnessScript).toString('hex');
|
|
1293
|
+
if (!allowedWitnessScripts.some(function(hex) {
|
|
1294
|
+
return hex.toLowerCase() === witnessScriptHex;
|
|
1295
|
+
})) {
|
|
1296
|
+
return false;
|
|
1297
|
+
}
|
|
1298
|
+
// The scriptPubKey commits to the witnessScript; a mismatch means the
|
|
1299
|
+
// PSBT is lying about the script this signature would authorize.
|
|
1300
|
+
if (!bytesEqual(sha256(witnessScript), Uint8Array.from(script).subarray(2))) {
|
|
1301
|
+
return false;
|
|
1302
|
+
}
|
|
1303
|
+
// p2ms throws unless the script is exactly OP_m <keys...> OP_n
|
|
1304
|
+
// OP_CHECKMULTISIG, so the key must occupy a signing position.
|
|
1305
|
+
var multisigPubkeys;
|
|
1306
|
+
try {
|
|
1307
|
+
multisigPubkeys = bitcoin.payments.p2ms({
|
|
1308
|
+
output: witnessScript
|
|
1309
|
+
}).pubkeys;
|
|
1310
|
+
} catch (e) {
|
|
1311
|
+
return false;
|
|
1312
|
+
}
|
|
1313
|
+
if (!multisigPubkeys) {
|
|
1314
|
+
return false;
|
|
1315
|
+
}
|
|
1316
|
+
var publicKeyBytes = Uint8Array.from(publicKey);
|
|
1317
|
+
return multisigPubkeys.some(function(key) {
|
|
1318
|
+
return bytesEqual(Uint8Array.from(key), publicKeyBytes);
|
|
1319
|
+
});
|
|
1320
|
+
};
|
|
1321
|
+
/**
|
|
1322
|
+
* Checks if a PSBT input belongs to a specific address.
|
|
1323
|
+
*
|
|
1324
|
+
* For P2WSH inputs address equality cannot work (the address commits to the
|
|
1325
|
+
* script, not our key), so ownership is opt-in and means ALL of: the caller
|
|
1326
|
+
* explicitly allowlisted the witnessScript, it hashes to the scriptPubKey
|
|
1327
|
+
* commitment, and it is a canonical m-of-n CHECKMULTISIG script with
|
|
1328
|
+
* `publicKey` in a signing position. Any other script shape is rejected even
|
|
1329
|
+
* if the key appears in it, so a hostile PSBT cannot obtain a signature over
|
|
1330
|
+
* an arbitrary script that merely name-drops the wallet key, and the wallet
|
|
1331
|
+
* never co-signs a multisig arrangement the caller did not name.
|
|
1240
1332
|
* @param input - The PSBT input (from psbt.data.inputs)
|
|
1241
1333
|
* @param address - The address to check against
|
|
1242
1334
|
* @param network - The Bitcoin network
|
|
1243
|
-
* @
|
|
1244
|
-
|
|
1335
|
+
* @param publicKey - The wallet's compressed ECDSA public key; required to match P2WSH inputs
|
|
1336
|
+
* @param allowedWitnessScripts - Hex-encoded witnessScripts the caller consents to co-sign; required to match P2WSH inputs
|
|
1337
|
+
* @returns True if the input belongs to the address (or public key, for P2WSH), false otherwise
|
|
1338
|
+
*/ var doesInputBelongToAddress = function(input, address, network, publicKey, allowedWitnessScripts) {
|
|
1245
1339
|
if (!input.witnessUtxo) {
|
|
1246
1340
|
return false;
|
|
1247
1341
|
}
|
|
@@ -1265,6 +1359,10 @@ function _instanceof$1(left, right) {
|
|
|
1265
1359
|
}).address === address;
|
|
1266
1360
|
});
|
|
1267
1361
|
}
|
|
1362
|
+
// Try P2WSH - script is OP_0 <32-byte sha256(witnessScript)>
|
|
1363
|
+
if (isP2wshOutputScript(script)) {
|
|
1364
|
+
return matchesAllowedP2wshMultisig(input, script, publicKey, allowedWitnessScripts);
|
|
1365
|
+
}
|
|
1268
1366
|
// Try P2TR (Taproot) - script is OP_1 <32-byte x-only pubkey>
|
|
1269
1367
|
if (script.length === 34 && script[0] === 0x51 && script[1] === 0x20) {
|
|
1270
1368
|
return networksToTry.some(function(bitcoinNetwork) {
|
|
@@ -1286,6 +1384,139 @@ function _instanceof$1(left, right) {
|
|
|
1286
1384
|
}
|
|
1287
1385
|
};
|
|
1288
1386
|
|
|
1387
|
+
/**
|
|
1388
|
+
* Resolves the BIP-143 scriptCode for a segwit v0 input. Shared by the signer
|
|
1389
|
+
* and the sighash-verification helper so both derive the identical digest.
|
|
1390
|
+
*
|
|
1391
|
+
* P2WSH inputs sign over the full witnessScript, verified against the
|
|
1392
|
+
* scriptPubKey commitment so a PSBT cannot substitute a script the UTXO does
|
|
1393
|
+
* not commit to. P2WPKH inputs sign over the implied P2PKH script.
|
|
1394
|
+
*
|
|
1395
|
+
* @param input - The PSBT input (from psbt.data.inputs)
|
|
1396
|
+
* @param script - The input's witnessUtxo scriptPubKey
|
|
1397
|
+
* @param index - The input index (for error messages)
|
|
1398
|
+
* @param bitcoinNetwork - The bitcoinjs-lib network for P2PKH reconstruction
|
|
1399
|
+
* @returns The scriptCode to feed hashForWitnessV0
|
|
1400
|
+
* @throws Error if a P2WSH input is missing its witnessScript, the witnessScript
|
|
1401
|
+
* does not hash to the scriptPubKey commitment, or scriptCode generation fails
|
|
1402
|
+
*/ var getSegwitV0ScriptCode = function(input, script, index, bitcoinNetwork) {
|
|
1403
|
+
if (isP2wshOutputScript(script)) {
|
|
1404
|
+
if (!input.witnessScript) {
|
|
1405
|
+
throw new Error("Input ".concat(index, " is P2WSH but missing witnessScript"));
|
|
1406
|
+
}
|
|
1407
|
+
var witnessScript = Uint8Array.from(input.witnessScript);
|
|
1408
|
+
// The scriptPubKey commits to the witnessScript; refuse to compute a
|
|
1409
|
+
// sighash over a script the UTXO does not commit to.
|
|
1410
|
+
if (!bytesEqual(sha256(witnessScript), Uint8Array.from(script).subarray(2))) {
|
|
1411
|
+
throw new Error("Input ".concat(index, " witnessScript does not match the P2WSH scriptPubKey commitment"));
|
|
1412
|
+
}
|
|
1413
|
+
return witnessScript;
|
|
1414
|
+
}
|
|
1415
|
+
// Build P2PKH script code from the pubkey hash in the witness program
|
|
1416
|
+
var p2pkh = bitcoin.payments.p2pkh({
|
|
1417
|
+
hash: Uint8Array.from(script).subarray(2),
|
|
1418
|
+
network: bitcoinNetwork
|
|
1419
|
+
});
|
|
1420
|
+
if (!p2pkh.output) {
|
|
1421
|
+
throw new Error("Failed to generate scriptCode for input ".concat(index));
|
|
1422
|
+
}
|
|
1423
|
+
return p2pkh.output;
|
|
1424
|
+
};
|
|
1425
|
+
|
|
1426
|
+
/**
|
|
1427
|
+
* Restricts wallet-owned PSBT inputs to an explicitly requested subset.
|
|
1428
|
+
*
|
|
1429
|
+
* @param inputsToSign - Wallet-owned inputs, each carrying its PSBT index
|
|
1430
|
+
* @param signingIndexes - Optional subset of input indexes the caller wants signed
|
|
1431
|
+
* @returns The requested subset, or all inputs when signingIndexes is omitted/empty
|
|
1432
|
+
* @throws Error if signingIndexes references an input the wallet does not own
|
|
1433
|
+
*/ var filterInputsBySigningIndexes = function(inputsToSign, signingIndexes) {
|
|
1434
|
+
if (!(signingIndexes === null || signingIndexes === void 0 ? void 0 : signingIndexes.length)) {
|
|
1435
|
+
return inputsToSign;
|
|
1436
|
+
}
|
|
1437
|
+
var walletOwnedIndexSet = new Set(inputsToSign.map(function(param) {
|
|
1438
|
+
var index = param.index;
|
|
1439
|
+
return index;
|
|
1440
|
+
}));
|
|
1441
|
+
var invalidIndexes = signingIndexes.filter(function(i) {
|
|
1442
|
+
return !walletOwnedIndexSet.has(i);
|
|
1443
|
+
});
|
|
1444
|
+
if (invalidIndexes.length > 0) {
|
|
1445
|
+
throw new Error("signingIndexes contains indexes that do not belong to the signing address: ".concat(invalidIndexes.join(', ')));
|
|
1446
|
+
}
|
|
1447
|
+
var requestedIndexSet = new Set(signingIndexes);
|
|
1448
|
+
return inputsToSign.filter(function(param) {
|
|
1449
|
+
var index = param.index;
|
|
1450
|
+
return requestedIndexSet.has(index);
|
|
1451
|
+
});
|
|
1452
|
+
};
|
|
1453
|
+
|
|
1454
|
+
/**
|
|
1455
|
+
* Resolves the sighash type for a PSBT input.
|
|
1456
|
+
*
|
|
1457
|
+
* The type is read from the PSBT itself (BIP-174 `PSBT_IN_SIGHASH_TYPE`), never
|
|
1458
|
+
* supplied by the caller — the signing hash and the policy layer's verification
|
|
1459
|
+
* hash must be derived from the same bytes, or every non-default signature
|
|
1460
|
+
* would be rejected as tampered.
|
|
1461
|
+
*
|
|
1462
|
+
* When the input declares nothing, falls back to the historical default:
|
|
1463
|
+
* SIGHASH_DEFAULT (0x00) for Taproot, SIGHASH_ALL (0x01) otherwise.
|
|
1464
|
+
*
|
|
1465
|
+
* @param input - The PSBT input to resolve the sighash type for
|
|
1466
|
+
* @param isTaproot - Whether the input is spent as Taproot. Defaults to
|
|
1467
|
+
* detecting `tapInternalKey`; pass explicitly when the caller already knows
|
|
1468
|
+
* which signing branch it is on, so the fallback matches the hash function
|
|
1469
|
+
* actually used.
|
|
1470
|
+
* @returns The sighash type to build and encode the signature with
|
|
1471
|
+
*/ var getSigHashType = function(input) {
|
|
1472
|
+
var isTaproot = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : Boolean(input.tapInternalKey);
|
|
1473
|
+
var _input_sighashType;
|
|
1474
|
+
return (_input_sighashType = input.sighashType) !== null && _input_sighashType !== void 0 ? _input_sighashType : isTaproot ? bitcoin.Transaction.SIGHASH_DEFAULT : bitcoin.Transaction.SIGHASH_ALL;
|
|
1475
|
+
};
|
|
1476
|
+
|
|
1477
|
+
/**
|
|
1478
|
+
* Throws unless every input's PSBT-declared sighash type is in the allow-list.
|
|
1479
|
+
*
|
|
1480
|
+
* Call this before any signing begins — inputs are signed in parallel, so
|
|
1481
|
+
* throwing partway through would leave a partially signed PSBT behind.
|
|
1482
|
+
*
|
|
1483
|
+
* An empty array permits nothing rather than everything: a caller whose
|
|
1484
|
+
* allow-list computes to empty must not silently get the guard disabled. Omit
|
|
1485
|
+
* the parameter entirely to permit any declared type.
|
|
1486
|
+
*
|
|
1487
|
+
* @param inputsToSign - The wallet-owned inputs about to be signed, with their PSBT indexes
|
|
1488
|
+
* @param isTaproot - Whether signing takes the Taproot branch, so the fallback
|
|
1489
|
+
* sighash type matches the hash function actually used
|
|
1490
|
+
* @param allowedSighash - Optional allow-list of permitted sighash types
|
|
1491
|
+
*/ var assertSighashAllowed = function(inputsToSign, isTaproot, allowedSighash) {
|
|
1492
|
+
if (!allowedSighash) {
|
|
1493
|
+
return;
|
|
1494
|
+
}
|
|
1495
|
+
var _iteratorNormalCompletion = true, _didIteratorError = false, _iteratorError = undefined;
|
|
1496
|
+
try {
|
|
1497
|
+
for(var _iterator = inputsToSign[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true){
|
|
1498
|
+
var _step_value = _step.value, input = _step_value.input, index = _step_value.index;
|
|
1499
|
+
var sigHashType = getSigHashType(input, isTaproot);
|
|
1500
|
+
if (!allowedSighash.includes(sigHashType)) {
|
|
1501
|
+
throw new Error("Input ".concat(index, " declares sighash type ").concat(sigHashType, ", which is not in allowedSighash: ").concat(allowedSighash.join(', ') || '(empty)'));
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
} catch (err) {
|
|
1505
|
+
_didIteratorError = true;
|
|
1506
|
+
_iteratorError = err;
|
|
1507
|
+
} finally{
|
|
1508
|
+
try {
|
|
1509
|
+
if (!_iteratorNormalCompletion && _iterator.return != null) {
|
|
1510
|
+
_iterator.return();
|
|
1511
|
+
}
|
|
1512
|
+
} finally{
|
|
1513
|
+
if (_didIteratorError) {
|
|
1514
|
+
throw _iteratorError;
|
|
1515
|
+
}
|
|
1516
|
+
}
|
|
1517
|
+
}
|
|
1518
|
+
};
|
|
1519
|
+
|
|
1289
1520
|
function _instanceof(left, right) {
|
|
1290
1521
|
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
1291
1522
|
return !!right[Symbol.hasInstance](left);
|
|
@@ -1372,9 +1603,13 @@ function _type_of(obj) {
|
|
|
1372
1603
|
* Extracts sighashes from a PSBT for validation.
|
|
1373
1604
|
* This is used to verify that the message being signed matches the PSBT context.
|
|
1374
1605
|
*
|
|
1606
|
+
* P2WSH inputs whose witnessScript is absent yield `null` instead of a hash:
|
|
1607
|
+
* finalization strips witnessScript from completed inputs, so a co-signer's
|
|
1608
|
+
* already-finalized input must not block validation of the remaining inputs.
|
|
1609
|
+
*
|
|
1375
1610
|
* @param psbtBase64 - PSBT in base64 format
|
|
1376
1611
|
* @param network - 'mainnet' or 'testnet' or BitcoinNetwork enum (defaults to 'mainnet')
|
|
1377
|
-
* @returns Array of sighash hex strings for
|
|
1612
|
+
* @returns Array of sighash hex strings, aligned by input index; `null` for inputs whose sighash cannot be derived
|
|
1378
1613
|
*/ var extractPsbtSighashes = function(psbtBase64) {
|
|
1379
1614
|
var network = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : 'mainnet';
|
|
1380
1615
|
// Convert string network to BitcoinNetwork enum
|
|
@@ -1392,25 +1627,23 @@ function _type_of(obj) {
|
|
|
1392
1627
|
for(var i = 0; i < psbt.inputCount; i++){
|
|
1393
1628
|
var input = psbt.data.inputs[i];
|
|
1394
1629
|
if (input.tapInternalKey) {
|
|
1395
|
-
// Taproot (BIP-341) - uses hashForWitnessV1 with
|
|
1396
|
-
|
|
1630
|
+
// Taproot (BIP-341) - uses hashForWitnessV1 with the input's declared
|
|
1631
|
+
// sighash type, defaulting to SIGHASH_DEFAULT
|
|
1632
|
+
var hash = tx.hashForWitnessV1(i, prevOutScripts, values, getSigHashType(input, true));
|
|
1397
1633
|
sighashes.push(Buffer.from(hash).toString('hex'));
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
var scriptCode = p2pkh.output;
|
|
1408
|
-
if (!scriptCode) {
|
|
1409
|
-
throw new Error("Failed to generate scriptCode for input ".concat(i));
|
|
1410
|
-
}
|
|
1411
|
-
var hash1 = tx.hashForWitnessV0(i, scriptCode, value, bitcoin.Transaction.SIGHASH_ALL);
|
|
1412
|
-
sighashes.push(Buffer.from(hash1).toString('hex'));
|
|
1634
|
+
continue;
|
|
1635
|
+
}
|
|
1636
|
+
// Native SegWit (BIP-143) - uses hashForWitnessV0 with the input's
|
|
1637
|
+
// declared sighash type, defaulting to SIGHASH_ALL
|
|
1638
|
+
// witnessUtxo is guaranteed to exist from collectPSBTInputData validation
|
|
1639
|
+
var _input_witnessUtxo = input.witnessUtxo, script = _input_witnessUtxo.script, value = _input_witnessUtxo.value;
|
|
1640
|
+
if (isP2wshOutputScript(script) && !input.witnessScript) {
|
|
1641
|
+
sighashes.push(null);
|
|
1642
|
+
continue;
|
|
1413
1643
|
}
|
|
1644
|
+
var scriptCode = getSegwitV0ScriptCode(input, script, i, bitcoinNetwork);
|
|
1645
|
+
var hash1 = tx.hashForWitnessV0(i, scriptCode, value, getSigHashType(input, false));
|
|
1646
|
+
sighashes.push(Buffer.from(hash1).toString('hex'));
|
|
1414
1647
|
}
|
|
1415
1648
|
return sighashes;
|
|
1416
1649
|
};
|
|
@@ -1450,4 +1683,4 @@ function _type_of(obj) {
|
|
|
1450
1683
|
return Buffer.from(formattedMessage).toString('hex');
|
|
1451
1684
|
};
|
|
1452
1685
|
|
|
1453
|
-
export { calculateBip322Hash, calculateTaprootTweak, collectPSBTInputData, computeBip322HashHex, convertSignatureToDER, convertSignatureToTaprootBuffer, createLegacyAddress, createNativeSegWitAddress, createSegWitAddress, createTaprootAddress, doesInputBelongToAddress, encodeBip322Signature, extractPsbtSighashes, extractPublicKeyHex, getAddressTypeFromDerivationPath, getBitcoinNetwork, getDefaultRpcUrl, getFeeRates, getPublicKeyFromPrivateKey, getUTXOs, initEccLib, normalizeForCompressed, normalizeForTaproot, normalizePublicKey, privateKeyToWIF, publicKeyToBitcoinAddress, selectUTXOs, toBitcoinNetwork, toBuffer, wifToPrivateKey };
|
|
1686
|
+
export { assertSighashAllowed, calculateBip322Hash, calculateTaprootTweak, collectPSBTInputData, computeBip322HashHex, convertSignatureToDER, convertSignatureToTaprootBuffer, createLegacyAddress, createNativeSegWitAddress, createSegWitAddress, createTaprootAddress, doesInputBelongToAddress, encodeBip322Signature, extractPsbtSighashes, extractPublicKeyHex, filterInputsBySigningIndexes, getAddressTypeFromDerivationPath, getBitcoinNetwork, getDefaultRpcUrl, getFeeRates, getPublicKeyFromPrivateKey, getSegwitV0ScriptCode, getSigHashType, getUTXOs, initEccLib, isP2wshOutputScript, normalizeForCompressed, normalizeForTaproot, normalizePublicKey, privateKeyToWIF, publicKeyToBitcoinAddress, selectUTXOs, toBitcoinNetwork, toBuffer, wifToPrivateKey };
|
package/package.json
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dynamic-labs-wallet/btc-utils",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.107",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@dynamic-labs-wallet/core": "1.0.
|
|
8
|
+
"@dynamic-labs-wallet/core": "1.0.107",
|
|
9
9
|
"bitcoinjs-lib": "^7.0.0",
|
|
10
10
|
"bip322-js": "^3.0.0",
|
|
11
11
|
"@noble/hashes": "1.7.1",
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type * as bitcoin from 'bitcoinjs-lib';
|
|
2
|
+
/**
|
|
3
|
+
* Throws unless every input's PSBT-declared sighash type is in the allow-list.
|
|
4
|
+
*
|
|
5
|
+
* Call this before any signing begins — inputs are signed in parallel, so
|
|
6
|
+
* throwing partway through would leave a partially signed PSBT behind.
|
|
7
|
+
*
|
|
8
|
+
* An empty array permits nothing rather than everything: a caller whose
|
|
9
|
+
* allow-list computes to empty must not silently get the guard disabled. Omit
|
|
10
|
+
* the parameter entirely to permit any declared type.
|
|
11
|
+
*
|
|
12
|
+
* @param inputsToSign - The wallet-owned inputs about to be signed, with their PSBT indexes
|
|
13
|
+
* @param isTaproot - Whether signing takes the Taproot branch, so the fallback
|
|
14
|
+
* sighash type matches the hash function actually used
|
|
15
|
+
* @param allowedSighash - Optional allow-list of permitted sighash types
|
|
16
|
+
*/
|
|
17
|
+
export declare const assertSighashAllowed: (inputsToSign: {
|
|
18
|
+
input: bitcoin.Psbt["data"]["inputs"][number];
|
|
19
|
+
index: number;
|
|
20
|
+
}[], isTaproot: boolean, allowedSighash?: number[]) => void;
|
|
21
|
+
//# sourceMappingURL=assertSighashAllowed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"assertSighashAllowed.d.ts","sourceRoot":"","sources":["../../src/assertSighashAllowed/assertSighashAllowed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,OAAO,MAAM,eAAe,CAAC;AAG9C;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,oBAAoB,iBACjB;IAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAAE,aACrE,OAAO,mBACD,MAAM,EAAE,KACxB,IAgBF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/assertSighashAllowed/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constant-shape byte equality without Buffer — the iframe build compiles
|
|
3
|
+
* this package with browser typings where Buffer is not assignable to
|
|
4
|
+
* Uint8Array.
|
|
5
|
+
* @param a - First byte array
|
|
6
|
+
* @param b - Second byte array
|
|
7
|
+
* @returns True if both arrays have identical length and contents
|
|
8
|
+
*/
|
|
9
|
+
export declare const bytesEqual: (a: Uint8Array, b: Uint8Array) => boolean;
|
|
10
|
+
//# sourceMappingURL=bytesEqual.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bytesEqual.d.ts","sourceRoot":"","sources":["../../src/bytesEqual/bytesEqual.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,UAAU,MAAO,UAAU,KAAK,UAAU,KAAG,OACY,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bytesEqual/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC"}
|
|
@@ -3,7 +3,10 @@ import type { EcdsaSignature } from '#internal/core';
|
|
|
3
3
|
* Converts an ECDSA signature to DER format
|
|
4
4
|
*
|
|
5
5
|
* @param signature - The ECDSA signature
|
|
6
|
+
* @param sighashType - The sighash type to append as the DER trailing byte.
|
|
7
|
+
* Must match the type the signing hash was built with, or the signature will
|
|
8
|
+
* fail verification at finalize/broadcast. Defaults to SIGHASH_ALL.
|
|
6
9
|
* @returns The DER encoded signature
|
|
7
10
|
*/
|
|
8
|
-
export declare const convertSignatureToDER: (signature: EcdsaSignature) => Uint8Array;
|
|
11
|
+
export declare const convertSignatureToDER: (signature: EcdsaSignature, sighashType?: number) => Uint8Array;
|
|
9
12
|
//# sourceMappingURL=convertSignatureToDER.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertSignatureToDER.d.ts","sourceRoot":"","sources":["../../src/convertSignatureToDER/convertSignatureToDER.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD
|
|
1
|
+
{"version":3,"file":"convertSignatureToDER.d.ts","sourceRoot":"","sources":["../../src/convertSignatureToDER/convertSignatureToDER.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,cACrB,cAAc,gBACZ,MAAM,eAoBpB,CAAC"}
|
|
@@ -3,7 +3,10 @@ import type { EcdsaSignature } from '#internal/core';
|
|
|
3
3
|
* Converts a signature to a Buffer format suitable for Taproot (BIP340/Schnorr)
|
|
4
4
|
*
|
|
5
5
|
* @param signature - The signature from MPC (can be Uint8Array, Buffer, or EcdsaSignature object)
|
|
6
|
-
* @
|
|
6
|
+
* @param sighashType - The sighash type the signing hash was built with. Per
|
|
7
|
+
* BIP-341 the signature stays 64 bytes for SIGHASH_DEFAULT and gains the
|
|
8
|
+
* sighash type as a 65th byte for any other type. Defaults to SIGHASH_DEFAULT.
|
|
9
|
+
* @returns A Buffer containing the 64-byte (or 65-byte) Schnorr signature
|
|
7
10
|
*/
|
|
8
|
-
export declare const convertSignatureToTaprootBuffer: (signature: EcdsaSignature | Uint8Array | Buffer) => Buffer;
|
|
11
|
+
export declare const convertSignatureToTaprootBuffer: (signature: EcdsaSignature | Uint8Array | Buffer, sighashType?: number) => Buffer;
|
|
9
12
|
//# sourceMappingURL=convertSignatureToTaprootBuffer.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"convertSignatureToTaprootBuffer.d.ts","sourceRoot":"","sources":["../../src/convertSignatureToTaprootBuffer/convertSignatureToTaprootBuffer.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"convertSignatureToTaprootBuffer.d.ts","sourceRoot":"","sources":["../../src/convertSignatureToTaprootBuffer/convertSignatureToTaprootBuffer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD;;;;;;;;GAQG;AACH,eAAO,MAAM,+BAA+B,cAC/B,cAAc,GAAG,UAAU,GAAG,MAAM,gBAClC,MAAM,KAClB,MAmBF,CAAC"}
|
|
@@ -1,11 +1,22 @@
|
|
|
1
1
|
import type { Psbt } from 'bitcoinjs-lib';
|
|
2
2
|
import { BitcoinNetwork } from '@dynamic-labs-wallet/core';
|
|
3
3
|
/**
|
|
4
|
-
* Checks if a PSBT input belongs to a specific address
|
|
4
|
+
* Checks if a PSBT input belongs to a specific address.
|
|
5
|
+
*
|
|
6
|
+
* For P2WSH inputs address equality cannot work (the address commits to the
|
|
7
|
+
* script, not our key), so ownership is opt-in and means ALL of: the caller
|
|
8
|
+
* explicitly allowlisted the witnessScript, it hashes to the scriptPubKey
|
|
9
|
+
* commitment, and it is a canonical m-of-n CHECKMULTISIG script with
|
|
10
|
+
* `publicKey` in a signing position. Any other script shape is rejected even
|
|
11
|
+
* if the key appears in it, so a hostile PSBT cannot obtain a signature over
|
|
12
|
+
* an arbitrary script that merely name-drops the wallet key, and the wallet
|
|
13
|
+
* never co-signs a multisig arrangement the caller did not name.
|
|
5
14
|
* @param input - The PSBT input (from psbt.data.inputs)
|
|
6
15
|
* @param address - The address to check against
|
|
7
16
|
* @param network - The Bitcoin network
|
|
8
|
-
* @
|
|
17
|
+
* @param publicKey - The wallet's compressed ECDSA public key; required to match P2WSH inputs
|
|
18
|
+
* @param allowedWitnessScripts - Hex-encoded witnessScripts the caller consents to co-sign; required to match P2WSH inputs
|
|
19
|
+
* @returns True if the input belongs to the address (or public key, for P2WSH), false otherwise
|
|
9
20
|
*/
|
|
10
|
-
export declare const doesInputBelongToAddress: (input: Psbt["data"]["inputs"][number], address: string, network: BitcoinNetwork) => boolean;
|
|
21
|
+
export declare const doesInputBelongToAddress: (input: Psbt["data"]["inputs"][number], address: string, network: BitcoinNetwork, publicKey?: ArrayLike<number>, allowedWitnessScripts?: string[]) => boolean;
|
|
11
22
|
//# sourceMappingURL=doesInputBelongToAddress.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"doesInputBelongToAddress.d.ts","sourceRoot":"","sources":["../../src/doesInputBelongToAddress/doesInputBelongToAddress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"doesInputBelongToAddress.d.ts","sourceRoot":"","sources":["../../src/doesInputBelongToAddress/doesInputBelongToAddress.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAmD3D;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,wBAAwB,UAC5B,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,WAC5B,MAAM,WACN,cAAc,cACX,SAAS,CAAC,MAAM,CAAC,0BACL,MAAM,EAAE,KAC/B,OAuDF,CAAC"}
|
|
@@ -3,9 +3,13 @@ import type { BitcoinNetwork } from '@dynamic-labs-wallet/core';
|
|
|
3
3
|
* Extracts sighashes from a PSBT for validation.
|
|
4
4
|
* This is used to verify that the message being signed matches the PSBT context.
|
|
5
5
|
*
|
|
6
|
+
* P2WSH inputs whose witnessScript is absent yield `null` instead of a hash:
|
|
7
|
+
* finalization strips witnessScript from completed inputs, so a co-signer's
|
|
8
|
+
* already-finalized input must not block validation of the remaining inputs.
|
|
9
|
+
*
|
|
6
10
|
* @param psbtBase64 - PSBT in base64 format
|
|
7
11
|
* @param network - 'mainnet' or 'testnet' or BitcoinNetwork enum (defaults to 'mainnet')
|
|
8
|
-
* @returns Array of sighash hex strings for
|
|
12
|
+
* @returns Array of sighash hex strings, aligned by input index; `null` for inputs whose sighash cannot be derived
|
|
9
13
|
*/
|
|
10
|
-
export declare const extractPsbtSighashes: (psbtBase64: string, network?: BitcoinNetwork | "mainnet" | "testnet") => string[];
|
|
14
|
+
export declare const extractPsbtSighashes: (psbtBase64: string, network?: BitcoinNetwork | "mainnet" | "testnet") => (string | null)[];
|
|
11
15
|
//# sourceMappingURL=extractPsbtSighashes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"extractPsbtSighashes.d.ts","sourceRoot":"","sources":["../../src/extractPsbtSighashes/extractPsbtSighashes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"extractPsbtSighashes.d.ts","sourceRoot":"","sources":["../../src/extractPsbtSighashes/extractPsbtSighashes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAQhE;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,eACnB,MAAM,YACT,cAAc,GAAG,SAAS,GAAG,SAAS,KAC9C,CAAC,MAAM,GAAG,IAAI,CAAC,EA2CjB,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Restricts wallet-owned PSBT inputs to an explicitly requested subset.
|
|
3
|
+
*
|
|
4
|
+
* @param inputsToSign - Wallet-owned inputs, each carrying its PSBT index
|
|
5
|
+
* @param signingIndexes - Optional subset of input indexes the caller wants signed
|
|
6
|
+
* @returns The requested subset, or all inputs when signingIndexes is omitted/empty
|
|
7
|
+
* @throws Error if signingIndexes references an input the wallet does not own
|
|
8
|
+
*/
|
|
9
|
+
export declare const filterInputsBySigningIndexes: <T extends {
|
|
10
|
+
index: number;
|
|
11
|
+
}>(inputsToSign: T[], signingIndexes?: number[]) => T[];
|
|
12
|
+
//# sourceMappingURL=filterInputsBySigningIndexes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filterInputsBySigningIndexes.d.ts","sourceRoot":"","sources":["../../src/filterInputsBySigningIndexes/filterInputsBySigningIndexes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,GAAI,CAAC,SAAS;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,gBACxD,CAAC,EAAE,mBACA,MAAM,EAAE,KACxB,CAAC,EAeH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/filterInputsBySigningIndexes/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,4BAA4B,EAAE,MAAM,mCAAmC,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import * as bitcoin from 'bitcoinjs-lib';
|
|
2
|
+
import type { Psbt } from 'bitcoinjs-lib';
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the BIP-143 scriptCode for a segwit v0 input. Shared by the signer
|
|
5
|
+
* and the sighash-verification helper so both derive the identical digest.
|
|
6
|
+
*
|
|
7
|
+
* P2WSH inputs sign over the full witnessScript, verified against the
|
|
8
|
+
* scriptPubKey commitment so a PSBT cannot substitute a script the UTXO does
|
|
9
|
+
* not commit to. P2WPKH inputs sign over the implied P2PKH script.
|
|
10
|
+
*
|
|
11
|
+
* @param input - The PSBT input (from psbt.data.inputs)
|
|
12
|
+
* @param script - The input's witnessUtxo scriptPubKey
|
|
13
|
+
* @param index - The input index (for error messages)
|
|
14
|
+
* @param bitcoinNetwork - The bitcoinjs-lib network for P2PKH reconstruction
|
|
15
|
+
* @returns The scriptCode to feed hashForWitnessV0
|
|
16
|
+
* @throws Error if a P2WSH input is missing its witnessScript, the witnessScript
|
|
17
|
+
* does not hash to the scriptPubKey commitment, or scriptCode generation fails
|
|
18
|
+
*/
|
|
19
|
+
export declare const getSegwitV0ScriptCode: (input: Psbt["data"]["inputs"][number], script: ArrayLike<number>, index: number, bitcoinNetwork: bitcoin.networks.Network) => Uint8Array;
|
|
20
|
+
//# sourceMappingURL=getSegwitV0ScriptCode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getSegwitV0ScriptCode.d.ts","sourceRoot":"","sources":["../../src/getSegwitV0ScriptCode/getSegwitV0ScriptCode.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,eAAe,CAAC;AACzC,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAK1C;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,qBAAqB,UACzB,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,UAC7B,SAAS,CAAC,MAAM,CAAC,SAClB,MAAM,kBACG,OAAO,CAAC,QAAQ,CAAC,OAAO,KACvC,UAyBF,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/getSegwitV0ScriptCode/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as bitcoin from 'bitcoinjs-lib';
|
|
2
|
+
/**
|
|
3
|
+
* Resolves the sighash type for a PSBT input.
|
|
4
|
+
*
|
|
5
|
+
* The type is read from the PSBT itself (BIP-174 `PSBT_IN_SIGHASH_TYPE`), never
|
|
6
|
+
* supplied by the caller — the signing hash and the policy layer's verification
|
|
7
|
+
* hash must be derived from the same bytes, or every non-default signature
|
|
8
|
+
* would be rejected as tampered.
|
|
9
|
+
*
|
|
10
|
+
* When the input declares nothing, falls back to the historical default:
|
|
11
|
+
* SIGHASH_DEFAULT (0x00) for Taproot, SIGHASH_ALL (0x01) otherwise.
|
|
12
|
+
*
|
|
13
|
+
* @param input - The PSBT input to resolve the sighash type for
|
|
14
|
+
* @param isTaproot - Whether the input is spent as Taproot. Defaults to
|
|
15
|
+
* detecting `tapInternalKey`; pass explicitly when the caller already knows
|
|
16
|
+
* which signing branch it is on, so the fallback matches the hash function
|
|
17
|
+
* actually used.
|
|
18
|
+
* @returns The sighash type to build and encode the signature with
|
|
19
|
+
*/
|
|
20
|
+
export declare const getSigHashType: (input: bitcoin.Psbt["data"]["inputs"][number], isTaproot?: boolean) => number;
|
|
21
|
+
//# sourceMappingURL=getSigHashType.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getSigHashType.d.ts","sourceRoot":"","sources":["../../src/getSigHashType/getSigHashType.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,eAAe,CAAC;AAEzC;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,cAAc,UAClB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,0BAE5C,MAAkH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/getSigHashType/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC"}
|
package/src/index.d.ts
CHANGED
|
@@ -15,7 +15,12 @@ export { calculateTaprootTweak } from './calculateTaprootTweak/index.js';
|
|
|
15
15
|
export { convertSignatureToTaprootBuffer } from './convertSignatureToTaprootBuffer/index.js';
|
|
16
16
|
export { collectPSBTInputData } from './collectPSBTInputData/index.js';
|
|
17
17
|
export { doesInputBelongToAddress } from './doesInputBelongToAddress/index.js';
|
|
18
|
+
export { isP2wshOutputScript } from './isP2wshOutputScript/index.js';
|
|
19
|
+
export { getSegwitV0ScriptCode } from './getSegwitV0ScriptCode/index.js';
|
|
20
|
+
export { filterInputsBySigningIndexes } from './filterInputsBySigningIndexes/index.js';
|
|
18
21
|
export { getBitcoinNetwork } from './getBitcoinNetwork/index.js';
|
|
22
|
+
export { getSigHashType } from './getSigHashType/index.js';
|
|
23
|
+
export { assertSighashAllowed } from './assertSighashAllowed/index.js';
|
|
19
24
|
export { initEccLib } from './initEccLib/index.js';
|
|
20
25
|
export { extractPublicKeyHex } from './extractPublicKeyHex/index.js';
|
|
21
26
|
export type { UTXO } from './types.js';
|
package/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../packages/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,+BAA+B,EAAE,MAAM,4CAA4C,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAG/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../packages/src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,+BAA+B,CAAC;AACnE,OAAO,EAAE,gCAAgC,EAAE,MAAM,6CAA6C,CAAC;AAC/F,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,0BAA0B,EAAE,MAAM,uCAAuC,CAAC;AACnF,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAC/D,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,+BAA+B,EAAE,MAAM,4CAA4C,CAAC;AAC7F,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,wBAAwB,EAAE,MAAM,qCAAqC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAC;AACzE,OAAO,EAAE,4BAA4B,EAAE,MAAM,yCAAyC,CAAC;AACvF,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,YAAY,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAGvC,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,sCAAsC,CAAC;AACjF,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AAGvE,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AAC/C,OAAO,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAC3E,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AAG/D,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/isP2wshOutputScript/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Checks if an output script (scriptPubKey) is P2WSH: OP_0 <32-byte sha256(witnessScript)>
|
|
3
|
+
*
|
|
4
|
+
* ArrayLike keeps this callable with Buffer or Uint8Array — the iframe build
|
|
5
|
+
* compiles with browser typings where Buffer is not assignable to Uint8Array.
|
|
6
|
+
* @param script - The output script to check
|
|
7
|
+
* @returns True if the script has the P2WSH shape
|
|
8
|
+
*/
|
|
9
|
+
export declare const isP2wshOutputScript: (script: ArrayLike<number>) => boolean;
|
|
10
|
+
//# sourceMappingURL=isP2wshOutputScript.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"isP2wshOutputScript.d.ts","sourceRoot":"","sources":["../../src/isP2wshOutputScript/isP2wshOutputScript.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,mBAAmB,WAAY,SAAS,CAAC,MAAM,CAAC,KAAG,OACE,CAAC"}
|