@scure/btc-signer 1.0.0 → 1.1.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/index.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  import { secp256k1 as _secp, schnorr } from '@noble/curves/secp256k1';
3
3
  import { sha256 } from '@noble/hashes/sha256';
4
4
  import { ripemd160 } from '@noble/hashes/ripemd160';
5
- import { hex, base58, base58check as _b58, bech32, bech32m } from '@scure/base';
5
+ import { hex, base58check as _b58, bech32, bech32m } from '@scure/base';
6
6
  import type { Coder } from '@scure/base';
7
7
  import * as P from 'micro-packed';
8
8
 
@@ -327,6 +327,7 @@ export function OpToNum(op: ScriptOP, bytesLimit = 4, forceMinimal = true) {
327
327
  return;
328
328
  }
329
329
  }
330
+ return;
330
331
  }
331
332
 
332
333
  // BTC specific variable length integer encoding
@@ -680,8 +681,8 @@ const PSBTInputCoder = P.validate(PSBTKeyMap(PSBTInput), (i) => {
680
681
  throw new Error('validateInput: wmpty finalScriptWitness');
681
682
  //if (i.finalScriptSig && !i.finalScriptSig.length) throw new Error('validateInput: empty finalScriptSig');
682
683
  if (i.partialSig && !i.partialSig.length) throw new Error('Empty partialSig');
683
- if (i.partialSig) for (const [k, v] of i.partialSig) validatePubkey(k, PubT.ecdsa);
684
- if (i.bip32Derivation) for (const [k, v] of i.bip32Derivation) validatePubkey(k, PubT.ecdsa);
684
+ if (i.partialSig) for (const [k] of i.partialSig) validatePubkey(k, PubT.ecdsa);
685
+ if (i.bip32Derivation) for (const [k] of i.bip32Derivation) validatePubkey(k, PubT.ecdsa);
685
686
  // Locktime = unsigned little endian integer greater than or equal to 500000000 representing
686
687
  if (i.requiredTimeLocktime !== undefined && i.requiredTimeLocktime < 500000000)
687
688
  throw new Error(`validateInput: wrong timeLocktime=${i.requiredTimeLocktime}`);
@@ -724,7 +725,7 @@ const PSBTInputCoder = P.validate(PSBTKeyMap(PSBTInput), (i) => {
724
725
  });
725
726
 
726
727
  const PSBTOutputCoder = P.validate(PSBTKeyMap(PSBTOutput), (o) => {
727
- if (o.bip32Derivation) for (const [k, v] of o.bip32Derivation) validatePubkey(k, PubT.ecdsa);
728
+ if (o.bip32Derivation) for (const [k] of o.bip32Derivation) validatePubkey(k, PubT.ecdsa);
728
729
  return o;
729
730
  });
730
731
 
@@ -906,7 +907,7 @@ const TxHashIdx = P.struct({ txid: P.bytes(32, true), index: P.U32LE });
906
907
  // - generate input script
907
908
  // - generate address/output/redeem from user input
908
909
  // P2ret represents generic interface for all p2* methods
909
- type P2Ret = {
910
+ export type P2Ret = {
910
911
  type: string;
911
912
  script: Bytes;
912
913
  address?: string;
@@ -929,7 +930,9 @@ const OutPK: Coder<OptScript, OutPKType | undefined> = {
929
930
  },
930
931
  decode: (to: OutPKType): OptScript => (to.type === 'pk' ? [to.pubkey, 'CHECKSIG'] : undefined),
931
932
  };
933
+ // @ts-ignore
932
934
  export const p2pk = (pubkey: Bytes, network = NETWORK): P2Ret => {
935
+ // network is unused
933
936
  if (!isValidPubkey(pubkey, PubT.ecdsa)) throw new Error('P2PK: invalid publicKey');
934
937
  return {
935
938
  type: 'pk',
@@ -937,7 +940,7 @@ export const p2pk = (pubkey: Bytes, network = NETWORK): P2Ret => {
937
940
  };
938
941
  };
939
942
 
940
- // Publick Key Hash (P2PKH)
943
+ // Public Key Hash (P2PKH)
941
944
  type OutPKHType = { type: 'pkh'; hash: Bytes };
942
945
  const OutPKH: Coder<OptScript, OutPKHType | undefined> = {
943
946
  encode(from: ScriptType): OutPKHType | undefined {
@@ -1094,32 +1097,51 @@ export function taprootListToTree(taprootList: TaprootScriptList): TaprootScript
1094
1097
  return (last?.childs || last) as TaprootScriptTree;
1095
1098
  }
1096
1099
  type HashedTree =
1097
- | { type: 'leaf'; version?: number; script: Bytes; hash: Bytes; tapInternalKey?: Bytes }
1100
+ | { type: 'leaf'; version?: number; script: Bytes; hash: Bytes }
1098
1101
  | { type: 'branch'; left: HashedTree; right: HashedTree; hash: Bytes };
1099
- function checkTaprootScript(script: Bytes, allowUnknowOutput = false) {
1102
+ function checkTaprootScript(script: Bytes, internalPubKey: Bytes, allowUnknownOutputs = false) {
1100
1103
  const out = OutScript.decode(script);
1101
- if (out.type === 'unknown' && allowUnknowOutput) return;
1104
+ if (out.type === 'unknown' && allowUnknownOutputs) return;
1102
1105
  if (!['tr_ns', 'tr_ms'].includes(out.type))
1103
1106
  throw new Error(`P2TR: invalid leaf script=${out.type}`);
1107
+ const outms = out as OutTRNSType | OutTRMSType;
1108
+ if (!allowUnknownOutputs && outms.pubkeys) {
1109
+ for (const p of outms.pubkeys) {
1110
+ if (P.equalBytes(p, TAPROOT_UNSPENDABLE_KEY))
1111
+ throw new Error('Unspendable taproot key in leaf script');
1112
+ // It's likely a mistake at this point:
1113
+ // 1. p2tr(A, p2tr_ns(2, [A, B])) == p2tr(A, p2tr_pk(B)) (A or B key)
1114
+ // but will take more space and fees.
1115
+ // 2. For multi-sig p2tr(A, p2tr_ns(2, [A, B, C])) it's probably a security issue:
1116
+ // User creates 2 of 3 multisig of keys [A, B, C],
1117
+ // but key A always can spend whole output without signatures from other keys.
1118
+ // p2tr(A, p2tr_ns(2, [B, C, D])) is ok: A or (B and C) or (B and D) or (C and D)
1119
+ if (P.equalBytes(p, internalPubKey)) {
1120
+ throw new Error(
1121
+ 'Using P2TR with leaf script with same key as internal key is not supported'
1122
+ );
1123
+ }
1124
+ }
1125
+ }
1104
1126
  }
1105
- function taprootHashTree(tree: TaprootScriptTree, allowUnknowOutput = false): HashedTree {
1127
+ function taprootHashTree(
1128
+ tree: TaprootScriptTree,
1129
+ internalPubKey: Bytes,
1130
+ allowUnknownOutputs = false
1131
+ ): HashedTree {
1106
1132
  if (!tree) throw new Error('taprootHashTree: empty tree');
1107
1133
  if (Array.isArray(tree) && tree.length === 1) tree = tree[0];
1108
1134
  // Terminal node (leaf)
1109
1135
  if (!Array.isArray(tree)) {
1110
- const { leafVersion: version, script: leafScript, tapInternalKey } = tree;
1136
+ const { leafVersion: version, script: leafScript } = tree;
1111
1137
  // Earliest tree walk where we can validate tapScripts
1112
1138
  if (tree.tapLeafScript || (tree.tapMerkleRoot && !P.equalBytes(tree.tapMerkleRoot, P.EMPTY)))
1113
1139
  throw new Error('P2TR: tapRoot leafScript cannot have tree');
1114
- // Just to be sure that it is spendable
1115
- if (tapInternalKey && P.equalBytes(tapInternalKey, TAPROOT_UNSPENDABLE_KEY))
1116
- throw new Error('P2TR: tapRoot leafScript cannot have unspendble key');
1117
1140
  const script = typeof leafScript === 'string' ? hex.decode(leafScript) : leafScript;
1118
1141
  if (!isBytes(script)) throw new Error(`checkScript: wrong script type=${script}`);
1119
- checkTaprootScript(script, allowUnknowOutput);
1142
+ checkTaprootScript(script, internalPubKey, allowUnknownOutputs);
1120
1143
  return {
1121
1144
  type: 'leaf',
1122
- tapInternalKey,
1123
1145
  version,
1124
1146
  script,
1125
1147
  hash: tapLeafHash(script, version),
@@ -1130,8 +1152,8 @@ function taprootHashTree(tree: TaprootScriptTree, allowUnknowOutput = false): Ha
1130
1152
  if (tree.length !== 2) throw new Error('hashTree: non binary tree!');
1131
1153
  // branch
1132
1154
  // Both nodes should exist
1133
- const left = taprootHashTree(tree[0], allowUnknowOutput);
1134
- const right = taprootHashTree(tree[1], allowUnknowOutput);
1155
+ const left = taprootHashTree(tree[0], internalPubKey, allowUnknownOutputs);
1156
+ const right = taprootHashTree(tree[1], internalPubKey, allowUnknownOutputs);
1135
1157
  // We cannot swap left/right here, since it will change structure of tree
1136
1158
  let [lH, rH] = [left.hash, right.hash];
1137
1159
  if (_cmpBytes(rH, lH) === -1) [lH, rH] = [rH, lH];
@@ -1143,7 +1165,6 @@ type TaprootLeaf = {
1143
1165
  script: Bytes;
1144
1166
  hash: Bytes;
1145
1167
  path: Bytes[];
1146
- tapInternalKey?: Bytes;
1147
1168
  };
1148
1169
 
1149
1170
  type HashedTreeWithPath =
@@ -1197,7 +1218,7 @@ export function p2tr(
1197
1218
  internalPubKey?: Bytes | string,
1198
1219
  tree?: TaprootScriptTree,
1199
1220
  network = NETWORK,
1200
- allowUnknowOutput = false
1221
+ allowUnknownOutputs = false
1201
1222
  ): P2TROut {
1202
1223
  // Unspendable
1203
1224
  if (!internalPubKey && !tree) throw new Error('p2tr: should have pubKey or scriptTree (or both)');
@@ -1206,7 +1227,9 @@ export function p2tr(
1206
1227
  ? hex.decode(internalPubKey)
1207
1228
  : internalPubKey || TAPROOT_UNSPENDABLE_KEY;
1208
1229
  if (!isValidPubkey(pubKey, PubT.schnorr)) throw new Error('p2tr: non-schnorr pubkey');
1209
- let hashedTree = tree ? taprootAddPath(taprootHashTree(tree, allowUnknowOutput)) : undefined;
1230
+ let hashedTree = tree
1231
+ ? taprootAddPath(taprootHashTree(tree, pubKey, allowUnknownOutputs))
1232
+ : undefined;
1210
1233
  const tapMerkleRoot = hashedTree ? hashedTree.hash : undefined;
1211
1234
  const [tweakedPubkey, parity] = taprootTweakPubkey(pubKey, tapMerkleRoot || P.EMPTY);
1212
1235
  let leaves;
@@ -1215,7 +1238,7 @@ export function p2tr(
1215
1238
  ...l,
1216
1239
  controlBlock: TaprootControlBlock.encode({
1217
1240
  version: (l.version || TAP_LEAF_VERSION) + parity,
1218
- internalKey: l.tapInternalKey || pubKey,
1241
+ internalKey: pubKey,
1219
1242
  merklePath: l.path,
1220
1243
  }),
1221
1244
  }));
@@ -1351,7 +1374,7 @@ export function p2tr_ms(m: number, pubkeys: Bytes[], allowSamePubkeys = false) {
1351
1374
  script: OutScript.encode({ type: 'tr_ms', pubkeys, m }),
1352
1375
  };
1353
1376
  }
1354
- // Uknown output type
1377
+ // Unknown output type
1355
1378
  type OutUnknownType = { type: 'unknown'; script: Bytes };
1356
1379
  const OutUnknown: Coder<OptScript, OutUnknownType | undefined> = {
1357
1380
  encode(from: ScriptType): OutUnknownType | undefined {
@@ -1481,19 +1504,17 @@ export function Address(network = NETWORK) {
1481
1504
  if (version === 0 && data.length === 32) return { type: 'wsh', hash: data };
1482
1505
  else if (version === 0 && data.length === 20) return { type: 'wpkh', hash: data };
1483
1506
  else if (version === 1 && data.length === 32) return { type: 'tr', pubkey: data };
1484
- else throw new Error('Unkown witness program');
1507
+ else throw new Error('Unknown witness program');
1485
1508
  }
1486
- const data = base58.decode(address);
1487
- if (data.length !== 25) throw new Error('Invalid base58 address');
1509
+ const data = base58check.decode(address);
1510
+ if (data.length !== 21) throw new Error('Invalid base58 address');
1488
1511
  // Pay To Public Key Hash
1489
1512
  if (data[0] === network.pubKeyHash) {
1490
- const bytes = base58.decode(address);
1491
- return { type: 'pkh', hash: bytes.slice(1, bytes.length - 4) };
1513
+ return { type: 'pkh', hash: data.slice(1) };
1492
1514
  } else if (data[0] === network.scriptHash) {
1493
- const bytes = base58.decode(address);
1494
1515
  return {
1495
1516
  type: 'sh',
1496
- hash: base58.decode(address).slice(1, bytes.length - 4),
1517
+ hash: data.slice(1),
1497
1518
  };
1498
1519
  }
1499
1520
  throw new Error(`Invalid address prefix=${data[0]}`);
@@ -1502,6 +1523,10 @@ export function Address(network = NETWORK) {
1502
1523
  }
1503
1524
  // /Address
1504
1525
 
1526
+ /**
1527
+ * Internal, exported only for backwards-compat. Use `SigHash` instead.
1528
+ * @deprecated
1529
+ */
1505
1530
  export enum SignatureHash {
1506
1531
  DEFAULT,
1507
1532
  ALL,
@@ -1509,7 +1534,23 @@ export enum SignatureHash {
1509
1534
  SINGLE,
1510
1535
  ANYONECANPAY = 0x80,
1511
1536
  }
1512
- export const SigHashCoder = P.apply(P.U32LE, P.coders.tsEnum(SignatureHash));
1537
+
1538
+ export enum SigHash {
1539
+ DEFAULT = SignatureHash.DEFAULT,
1540
+ ALL = SignatureHash.ALL,
1541
+ NONE = SignatureHash.NONE,
1542
+ SINGLE = SignatureHash.SINGLE,
1543
+ DEFAULT_ANYONECANPAY = SignatureHash.DEFAULT | SignatureHash.ANYONECANPAY,
1544
+ ALL_ANYONECANPAY = SignatureHash.ALL | SignatureHash.ANYONECANPAY,
1545
+ NONE_ANYONECANPAY = SignatureHash.NONE | SignatureHash.ANYONECANPAY,
1546
+ SINGLE_ANYONECANPAY = SignatureHash.SINGLE | SignatureHash.ANYONECANPAY,
1547
+ }
1548
+
1549
+ function validateSigHash(s: SigHash) {
1550
+ if (typeof s !== 'number' || typeof SigHash[s] !== 'string')
1551
+ throw new Error(`Invalid SigHash=${s}`);
1552
+ return s;
1553
+ }
1513
1554
 
1514
1555
  function unpackSighash(hashType: number) {
1515
1556
  const masked = hashType & 0b0011111;
@@ -1605,9 +1646,13 @@ export type TxOpts = {
1605
1646
  PSBTVersion?: number;
1606
1647
  // Flags
1607
1648
  // Allow output scripts to be unknown scripts (probably unspendable)
1649
+ /** @deprecated Use `allowUnknownOutputs` */
1608
1650
  allowUnknowOutput?: boolean;
1651
+ allowUnknownOutputs?: boolean;
1609
1652
  // Try to sign/finalize unknown input. All bets are off, but there is chance that it will work
1653
+ /** @deprecated Use `allowUnknownInputs` */
1610
1654
  allowUnknowInput?: boolean;
1655
+ allowUnknownInputs?: boolean;
1611
1656
  // Check input/output scripts for sanity
1612
1657
  disableScriptCheck?: boolean;
1613
1658
  // There is strange behaviour where tx without outputs encoded with empty output in the end,
@@ -1619,18 +1664,22 @@ export type TxOpts = {
1619
1664
  lowR?: boolean; // Use lowR signatures
1620
1665
  };
1621
1666
 
1622
- // Check if object doens't have custom constructor (like Uint8Array/Array)
1623
- const isPlainObject = (obj: any) =>
1624
- Object.prototype.toString.call(obj) === '[object Object]' && obj.constructor === Object;
1625
-
1667
+ const toStr = {}.toString;
1626
1668
  function validateOpts(opts: TxOpts) {
1627
- if (!isPlainObject(opts)) throw new Error(`Wrong object type for transaction options: ${opts}`);
1669
+ if (opts !== undefined && toStr.call(opts) !== '[object Object]')
1670
+ throw new Error(`Wrong object type for transaction options: ${opts}`);
1671
+
1628
1672
  const _opts = {
1629
1673
  ...opts,
1674
+ // Defaults
1630
1675
  version: def(opts.version, DEFAULT_VERSION),
1631
1676
  lockTime: def(opts.lockTime, 0),
1632
1677
  PSBTVersion: def(opts.PSBTVersion, 0),
1633
- }; // Defaults
1678
+ };
1679
+ if (typeof _opts.allowUnknowInput !== 'undefined')
1680
+ opts.allowUnknownInputs = _opts.allowUnknowInput;
1681
+ if (typeof _opts.allowUnknowOutput !== 'undefined')
1682
+ opts.allowUnknownOutputs = _opts.allowUnknowOutput;
1634
1683
  // 0 and -1 happens in tests
1635
1684
  if (![-1, 0, 1, 2].includes(_opts.version)) throw new Error(`Unknown version: ${_opts.version}`);
1636
1685
  if (typeof _opts.lockTime !== 'number') throw new Error('Transaction lock time should be number');
@@ -1641,8 +1690,8 @@ function validateOpts(opts: TxOpts) {
1641
1690
  throw new Error(`Unknown PSBT version ${_opts.PSBTVersion}`);
1642
1691
  // Flags
1643
1692
  for (const k of [
1644
- 'allowUnknowOutput',
1645
- 'allowUnknowInput',
1693
+ 'allowUnknownOutputs',
1694
+ 'allowUnknownInputs',
1646
1695
  'disableScriptCheck',
1647
1696
  'bip174jsCompat',
1648
1697
  'allowLegacyWitnessUtxo',
@@ -1856,7 +1905,7 @@ export class Transaction {
1856
1905
  out += 4 * CompactSizeLen.encode(this.inputs.length).length;
1857
1906
  out += 4 * CompactSizeLen.encode(this.outputs.length).length;
1858
1907
  for (const i of this.inputs)
1859
- if (i.finalScriptSig) out += 160 + 4 * VarBytes.encode(i.finalScriptSig).length;
1908
+ out += 160 + 4 * VarBytes.encode(i.finalScriptSig || P.EMPTY).length;
1860
1909
  for (const o of outputs) out += 32 + 4 * VarBytes.encode(o.script).length;
1861
1910
  if (this.hasWitnesses) {
1862
1911
  for (const i of this.inputs)
@@ -1980,11 +2029,11 @@ export class Transaction {
1980
2029
  PSBTOutputCoder.encode(res);
1981
2030
  if (
1982
2031
  res.script &&
1983
- !this.opts.allowUnknowOutput &&
2032
+ !this.opts.allowUnknownOutputs &&
1984
2033
  OutScript.decode(res.script).type === 'unknown'
1985
2034
  ) {
1986
2035
  throw new Error(
1987
- 'Transaction/output: unknown output script type, there is a chance that input is unspendable. Pass allowUnkownScript=true, if you sure'
2036
+ 'Transaction/output: unknown output script type, there is a chance that input is unspendable. Pass allowUnknownScript=true, if you sure'
1988
2037
  );
1989
2038
  }
1990
2039
  if (!this.opts.disableScriptCheck) checkScript(res.script, res.redeemScript, res.witnessScript);
@@ -2148,10 +2197,10 @@ export class Transaction {
2148
2197
  // Used pretty often, should be fast
2149
2198
  private prevOut(input: TransactionInput): P.UnwrapCoder<typeof RawOutput> {
2150
2199
  if (input.nonWitnessUtxo) {
2151
- if (input.index === undefined) throw new Error('Uknown input index');
2200
+ if (input.index === undefined) throw new Error('Unknown input index');
2152
2201
  return input.nonWitnessUtxo.outputs[input.index];
2153
2202
  } else if (input.witnessUtxo) return input.witnessUtxo;
2154
- else throw new Error('Cannot find previous output info.');
2203
+ else throw new Error('Cannot find previous output info');
2155
2204
  }
2156
2205
  private inputType(input: TransactionInput) {
2157
2206
  let txType = 'legacy';
@@ -2212,12 +2261,7 @@ export class Transaction {
2212
2261
  }
2213
2262
 
2214
2263
  // Signer can be privateKey OR instance of bip32 HD stuff
2215
- signIdx(
2216
- privateKey: Signer,
2217
- idx: number,
2218
- allowedSighash?: SignatureHash[],
2219
- _auxRand?: Bytes
2220
- ): boolean {
2264
+ signIdx(privateKey: Signer, idx: number, allowedSighash?: SigHash[], _auxRand?: Bytes): boolean {
2221
2265
  this.checkInputIdx(idx);
2222
2266
  const input = this.inputs[idx];
2223
2267
  const inputType = this.inputType(input);
@@ -2242,7 +2286,8 @@ export class Transaction {
2242
2286
  }
2243
2287
  // Sighash checks
2244
2288
  // Just for compat with bitcoinjs-lib, so users won't face unexpected behaviour.
2245
- if (!allowedSighash) allowedSighash = [inputType.defaultSighash];
2289
+ if (!allowedSighash) allowedSighash = [inputType.defaultSighash as unknown as SigHash];
2290
+ else allowedSighash.forEach(validateSigHash);
2246
2291
  const sighash = inputType.sighash;
2247
2292
  if (!allowedSighash.includes(sighash)) {
2248
2293
  throw new Error(
@@ -2253,7 +2298,7 @@ export class Transaction {
2253
2298
  // however this was because of bug in bitcoin-core, which remains here because of consensus.
2254
2299
  // If this is absolutely neccessary for your case, please open issue.
2255
2300
  // We disable it to avoid complicated workflow where SINGLE will block adding new outputs
2256
- const { sigInputs, sigOutputs } = this.inputSighash(idx);
2301
+ const { sigOutputs } = this.inputSighash(idx);
2257
2302
  if (sigOutputs === SignatureHash.SINGLE && idx >= this.outputs.length) {
2258
2303
  throw new Error(
2259
2304
  `Input with sighash SINGLE, but there is no output with corresponding index=${idx}`
@@ -2282,7 +2327,7 @@ export class Transaction {
2282
2327
  input.tapInternalKey,
2283
2328
  merkleRoot
2284
2329
  );
2285
- const [taprootPubKey, parity] = taprootTweakPubkey(input.tapInternalKey, merkleRoot);
2330
+ const [taprootPubKey, _] = taprootTweakPubkey(input.tapInternalKey, merkleRoot);
2286
2331
  if (P.equalBytes(taprootPubKey, pubKey)) {
2287
2332
  const hash = this.preimageWitnessV1(idx, prevOutScript, sighash, amount);
2288
2333
  const sig = concat(
@@ -2295,18 +2340,13 @@ export class Transaction {
2295
2340
  }
2296
2341
  if (input.tapLeafScript) {
2297
2342
  input.tapScriptSig = input.tapScriptSig || [];
2298
- for (const [cb, _script] of input.tapLeafScript) {
2343
+ for (const [_, _script] of input.tapLeafScript) {
2299
2344
  const script = _script.subarray(0, -1);
2300
2345
  const scriptDecoded = Script.decode(script);
2301
2346
  const ver = _script[_script.length - 1];
2302
2347
  const hash = tapLeafHash(script, ver);
2303
- const { pubKey, privKey } = getTaprootKeys(
2304
- privateKey,
2305
- schnorrPub,
2306
- cb.internalKey,
2307
- P.EMPTY // Because we cannot have nested taproot tree
2308
- );
2309
- const pos = scriptDecoded.findIndex((i) => isBytes(i) && P.equalBytes(i, pubKey));
2348
+ // NOTE: no need to tweak internal key here, since we don't support nested p2tr
2349
+ const pos = scriptDecoded.findIndex((i) => isBytes(i) && P.equalBytes(i, schnorrPub));
2310
2350
  // Skip if there is no public key in tapLeafScript
2311
2351
  if (pos === -1) continue;
2312
2352
  const msg = this.preimageWitnessV1(
@@ -2319,12 +2359,12 @@ export class Transaction {
2319
2359
  ver
2320
2360
  );
2321
2361
  const sig = concat(
2322
- schnorr.sign(msg, privKey, _auxRand),
2362
+ schnorr.sign(msg, privateKey, _auxRand),
2323
2363
  sighash !== SignatureHash.DEFAULT ? new Uint8Array([sighash]) : P.EMPTY
2324
2364
  );
2325
2365
  this.updateInput(
2326
2366
  idx,
2327
- { tapScriptSig: [[{ pubKey: pubKey, leafHash: hash }, sig]] },
2367
+ { tapScriptSig: [[{ pubKey: schnorrPub, leafHash: hash }, sig]] },
2328
2368
  true
2329
2369
  );
2330
2370
  signed = true;
@@ -2428,7 +2468,7 @@ export class Transaction {
2428
2468
  signatures.push(scriptSig[sigIdx][1]);
2429
2469
  }
2430
2470
  if (signatures.length !== outScript.pubkeys.length) continue;
2431
- } else if (outScript.type === 'unknown' && this.opts.allowUnknowInput) {
2471
+ } else if (outScript.type === 'unknown' && this.opts.allowUnknownInputs) {
2432
2472
  // Trying our best to sign what we can
2433
2473
  const scriptDecoded = Script.decode(script);
2434
2474
  signatures = scriptSig
@@ -2485,7 +2525,7 @@ export class Transaction {
2485
2525
  } else if (inputType.last.type === 'wpkh') {
2486
2526
  inputScript = P.EMPTY;
2487
2527
  witness = [input.partialSig[0][1], input.partialSig[0][0]];
2488
- } else if (inputType.last.type === 'unknown' && !this.opts.allowUnknowInput)
2528
+ } else if (inputType.last.type === 'unknown' && !this.opts.allowUnknownInputs)
2489
2529
  throw new Error('Unknown inputs not allowed');
2490
2530
 
2491
2531
  // Create final scripts (generic part)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scure/btc-signer",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "Audited & minimal library for creating, signing & decoding Bitcoin transactions: with Schnorr, Taproot, UTXO & PSBT",
5
5
  "files": [
6
6
  "index.js",
@@ -14,13 +14,13 @@
14
14
  "module": "index.js",
15
15
  "types": "index.d.ts",
16
16
  "dependencies": {
17
- "@noble/curves": "~1.0.0",
18
- "@noble/hashes": "~1.3.0",
19
- "@scure/base": "~1.1.1",
17
+ "@noble/curves": "~1.2.0",
18
+ "@noble/hashes": "~1.3.1",
19
+ "@scure/base": "~1.1.3",
20
20
  "micro-packed": "~0.3.2"
21
21
  },
22
22
  "devDependencies": {
23
- "@scure/bip32": "~1.3.0",
23
+ "@scure/bip32": "~1.3.2",
24
24
  "micro-packed-debugger": "0.3.1",
25
25
  "micro-should": "0.4.0",
26
26
  "prettier": "2.8.4",
@@ -36,8 +36,10 @@
36
36
  "scripts": {
37
37
  "build": "tsc",
38
38
  "lint": "prettier --check index.ts",
39
+ "format": "prettier --write index.ts",
39
40
  "test": "node test/index.test.js && node test/psbt-test/bip174-psbt-extended.test.js",
40
- "test:extended": "node --experimental-loader ./test/bitcoinjs-test/esm-loader.js ./test/bitcoinjs-test/index.test.js"
41
+ "test:extended": "node --experimental-loader ./test/bitcoinjs-test/esm-loader.js ./test/bitcoinjs-test/index.test.js",
42
+ "test:slow": "node test/index.test.js && node test/slow.test.js"
41
43
  },
42
44
  "keywords": [
43
45
  "bitcoin",
@@ -55,10 +57,5 @@
55
57
  "p2wsh",
56
58
  "p2tr"
57
59
  ],
58
- "funding": [
59
- {
60
- "type": "individual",
61
- "url": "https://paulmillr.com/funding/"
62
- }
63
- ]
64
- }
60
+ "funding": "https://paulmillr.com/funding/"
61
+ }