@ledgerhq/hw-app-btc 6.2.0 → 6.9.1-6.9.1-taproot.0.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.
Files changed (187) hide show
  1. package/lib/Btc.d.ts +7 -3
  2. package/lib/Btc.d.ts.map +1 -1
  3. package/lib/Btc.js +99 -30
  4. package/lib/Btc.js.map +1 -1
  5. package/lib/BtcNew.d.ts +70 -0
  6. package/lib/BtcNew.d.ts.map +1 -0
  7. package/lib/BtcNew.js +372 -0
  8. package/lib/BtcNew.js.map +1 -0
  9. package/lib/BtcOld.d.ts +114 -0
  10. package/lib/BtcOld.d.ts.map +1 -0
  11. package/lib/BtcOld.js +138 -0
  12. package/lib/BtcOld.js.map +1 -0
  13. package/lib/bip32.d.ts +8 -0
  14. package/lib/bip32.d.ts.map +1 -1
  15. package/lib/bip32.js +32 -3
  16. package/lib/bip32.js.map +1 -1
  17. package/lib/buffertools.d.ts +28 -0
  18. package/lib/buffertools.d.ts.map +1 -0
  19. package/lib/buffertools.js +100 -0
  20. package/lib/buffertools.js.map +1 -0
  21. package/lib/createTransaction.d.ts.map +1 -1
  22. package/lib/createTransaction.js +16 -16
  23. package/lib/createTransaction.js.map +1 -1
  24. package/lib/finalizeInput.js +1 -1
  25. package/lib/finalizeInput.js.map +1 -1
  26. package/lib/getAppAndVersion.js +1 -1
  27. package/lib/getAppAndVersion.js.map +1 -1
  28. package/lib/getTrustedInput.js +6 -6
  29. package/lib/getTrustedInput.js.map +1 -1
  30. package/lib/getTrustedInputBIP143.js +2 -2
  31. package/lib/getTrustedInputBIP143.js.map +1 -1
  32. package/lib/getWalletPublicKey.d.ts +1 -1
  33. package/lib/getWalletPublicKey.d.ts.map +1 -1
  34. package/lib/getWalletPublicKey.js +1 -1
  35. package/lib/getWalletPublicKey.js.map +1 -1
  36. package/lib/hashPublicKey.d.ts +1 -1
  37. package/lib/hashPublicKey.d.ts.map +1 -1
  38. package/lib/hashPublicKey.js +1 -1
  39. package/lib/hashPublicKey.js.map +1 -1
  40. package/lib/index.d.ts +3 -0
  41. package/lib/index.d.ts.map +1 -0
  42. package/lib/index.js +8 -0
  43. package/lib/index.js.map +1 -0
  44. package/lib/newops/appClient.d.ts +14 -0
  45. package/lib/newops/appClient.d.ts.map +1 -0
  46. package/lib/newops/appClient.js +242 -0
  47. package/lib/newops/appClient.js.map +1 -0
  48. package/lib/newops/clientCommands.d.ts +61 -0
  49. package/lib/newops/clientCommands.d.ts.map +1 -0
  50. package/lib/newops/clientCommands.js +331 -0
  51. package/lib/newops/clientCommands.js.map +1 -0
  52. package/lib/newops/merkelizedPsbt.d.ts +15 -0
  53. package/lib/newops/merkelizedPsbt.d.ts.map +1 -0
  54. package/lib/newops/merkelizedPsbt.js +91 -0
  55. package/lib/newops/merkelizedPsbt.js.map +1 -0
  56. package/lib/newops/merkle.d.ts +29 -0
  57. package/lib/newops/merkle.d.ts.map +1 -0
  58. package/lib/newops/merkle.js +133 -0
  59. package/lib/newops/merkle.js.map +1 -0
  60. package/lib/newops/merkleMap.d.ts +15 -0
  61. package/lib/newops/merkleMap.d.ts.map +1 -0
  62. package/lib/newops/merkleMap.js +37 -0
  63. package/lib/newops/merkleMap.js.map +1 -0
  64. package/lib/newops/policy.d.ts +14 -0
  65. package/lib/newops/policy.d.ts.map +1 -0
  66. package/lib/newops/policy.js +40 -0
  67. package/lib/newops/policy.js.map +1 -0
  68. package/lib/newops/psbtExtractor.d.ts +4 -0
  69. package/lib/newops/psbtExtractor.d.ts.map +1 -0
  70. package/lib/newops/psbtExtractor.js +36 -0
  71. package/lib/newops/psbtExtractor.js.map +1 -0
  72. package/lib/newops/psbtFinalizer.d.ts +7 -0
  73. package/lib/newops/psbtFinalizer.d.ts.map +1 -0
  74. package/lib/newops/psbtFinalizer.js +111 -0
  75. package/lib/newops/psbtFinalizer.js.map +1 -0
  76. package/lib/newops/psbtv2.d.ts +129 -0
  77. package/lib/newops/psbtv2.d.ts.map +1 -0
  78. package/lib/newops/psbtv2.js +478 -0
  79. package/lib/newops/psbtv2.js.map +1 -0
  80. package/lib/serializeTransaction.js +4 -4
  81. package/lib/serializeTransaction.js.map +1 -1
  82. package/lib/signP2SHTransaction.js +5 -5
  83. package/lib/signP2SHTransaction.js.map +1 -1
  84. package/lib/signTransaction.js +1 -1
  85. package/lib/signTransaction.js.map +1 -1
  86. package/lib/splitTransaction.js +7 -7
  87. package/lib/splitTransaction.js.map +1 -1
  88. package/lib/startUntrustedHashTransactionInput.js +2 -2
  89. package/lib/startUntrustedHashTransactionInput.js.map +1 -1
  90. package/lib/varint.d.ts.map +1 -1
  91. package/lib/varint.js +1 -0
  92. package/lib/varint.js.map +1 -1
  93. package/lib-es/Btc.d.ts +7 -3
  94. package/lib-es/Btc.d.ts.map +1 -1
  95. package/lib-es/Btc.js +92 -26
  96. package/lib-es/Btc.js.map +1 -1
  97. package/lib-es/BtcNew.d.ts +70 -0
  98. package/lib-es/BtcNew.d.ts.map +1 -0
  99. package/lib-es/BtcNew.js +370 -0
  100. package/lib-es/BtcNew.js.map +1 -0
  101. package/lib-es/BtcOld.d.ts +114 -0
  102. package/lib-es/BtcOld.d.ts.map +1 -0
  103. package/lib-es/BtcOld.js +136 -0
  104. package/lib-es/BtcOld.js.map +1 -0
  105. package/lib-es/bip32.d.ts +8 -0
  106. package/lib-es/bip32.d.ts.map +1 -1
  107. package/lib-es/bip32.js +26 -2
  108. package/lib-es/bip32.js.map +1 -1
  109. package/lib-es/buffertools.d.ts +28 -0
  110. package/lib-es/buffertools.d.ts.map +1 -0
  111. package/lib-es/buffertools.js +94 -0
  112. package/lib-es/buffertools.js.map +1 -0
  113. package/lib-es/createTransaction.d.ts.map +1 -1
  114. package/lib-es/getWalletPublicKey.d.ts +1 -1
  115. package/lib-es/getWalletPublicKey.d.ts.map +1 -1
  116. package/lib-es/getWalletPublicKey.js.map +1 -1
  117. package/lib-es/hashPublicKey.d.ts +1 -1
  118. package/lib-es/hashPublicKey.d.ts.map +1 -1
  119. package/lib-es/index.d.ts +3 -0
  120. package/lib-es/index.d.ts.map +1 -0
  121. package/lib-es/index.js +3 -0
  122. package/lib-es/index.js.map +1 -0
  123. package/lib-es/newops/appClient.d.ts +14 -0
  124. package/lib-es/newops/appClient.d.ts.map +1 -0
  125. package/lib-es/newops/appClient.js +239 -0
  126. package/lib-es/newops/appClient.js.map +1 -0
  127. package/lib-es/newops/clientCommands.d.ts +61 -0
  128. package/lib-es/newops/clientCommands.d.ts.map +1 -0
  129. package/lib-es/newops/clientCommands.js +328 -0
  130. package/lib-es/newops/clientCommands.js.map +1 -0
  131. package/lib-es/newops/merkelizedPsbt.d.ts +15 -0
  132. package/lib-es/newops/merkelizedPsbt.d.ts.map +1 -0
  133. package/lib-es/newops/merkelizedPsbt.js +88 -0
  134. package/lib-es/newops/merkelizedPsbt.js.map +1 -0
  135. package/lib-es/newops/merkle.d.ts +29 -0
  136. package/lib-es/newops/merkle.d.ts.map +1 -0
  137. package/lib-es/newops/merkle.js +129 -0
  138. package/lib-es/newops/merkle.js.map +1 -0
  139. package/lib-es/newops/merkleMap.d.ts +15 -0
  140. package/lib-es/newops/merkleMap.d.ts.map +1 -0
  141. package/lib-es/newops/merkleMap.js +34 -0
  142. package/lib-es/newops/merkleMap.js.map +1 -0
  143. package/lib-es/newops/policy.d.ts +14 -0
  144. package/lib-es/newops/policy.d.ts.map +1 -0
  145. package/lib-es/newops/policy.js +36 -0
  146. package/lib-es/newops/policy.js.map +1 -0
  147. package/lib-es/newops/psbtExtractor.d.ts +4 -0
  148. package/lib-es/newops/psbtExtractor.d.ts.map +1 -0
  149. package/lib-es/newops/psbtExtractor.js +32 -0
  150. package/lib-es/newops/psbtExtractor.js.map +1 -0
  151. package/lib-es/newops/psbtFinalizer.d.ts +7 -0
  152. package/lib-es/newops/psbtFinalizer.d.ts.map +1 -0
  153. package/lib-es/newops/psbtFinalizer.js +107 -0
  154. package/lib-es/newops/psbtFinalizer.js.map +1 -0
  155. package/lib-es/newops/psbtv2.d.ts +129 -0
  156. package/lib-es/newops/psbtv2.d.ts.map +1 -0
  157. package/lib-es/newops/psbtv2.js +475 -0
  158. package/lib-es/newops/psbtv2.js.map +1 -0
  159. package/lib-es/varint.d.ts.map +1 -1
  160. package/lib-es/varint.js +1 -0
  161. package/lib-es/varint.js.map +1 -1
  162. package/package.json +7 -4
  163. package/src/Btc.ts +42 -25
  164. package/src/BtcNew.ts +326 -0
  165. package/src/BtcOld.ts +156 -0
  166. package/src/bip32.ts +34 -2
  167. package/src/buffertools.ts +102 -0
  168. package/src/createTransaction.ts +2 -2
  169. package/src/getWalletPublicKey.ts +6 -1
  170. package/src/hashPublicKey.ts +1 -1
  171. package/src/index.ts +2 -0
  172. package/src/newops/appClient.ts +178 -0
  173. package/src/newops/clientCommands.ts +312 -0
  174. package/src/newops/merkelizedPsbt.ts +55 -0
  175. package/src/newops/merkle.ts +123 -0
  176. package/src/newops/merkleMap.ts +39 -0
  177. package/src/newops/policy.ts +52 -0
  178. package/src/newops/psbtExtractor.ts +33 -0
  179. package/src/newops/psbtFinalizer.ts +110 -0
  180. package/src/newops/psbtv2.ts +548 -0
  181. package/src/varint.ts +2 -0
  182. package/tests/Btc.integration.test.ts +89 -0
  183. package/tests/Btc.test.ts +6 -0
  184. package/tests/newops/BtcNew.test.ts +646 -0
  185. package/tests/newops/common.ts +25 -0
  186. package/tests/newops/merkle.test.ts +97 -0
  187. package/tests/trustedInputs.test.ts +4 -0
@@ -0,0 +1,123 @@
1
+ import { crypto } from "bitcoinjs-lib";
2
+
3
+ export class Merkle {
4
+ private leaves: Buffer[];
5
+ private rootNode: Node;
6
+ private leafNodes: Node[];
7
+ private h: (buf: Buffer) => Buffer;
8
+ constructor(
9
+ leaves: Buffer[],
10
+ hasher: (buf: Buffer) => Buffer = crypto.sha256
11
+ ) {
12
+ this.leaves = leaves;
13
+ this.h = hasher;
14
+ const nodes = this.calculateRoot(leaves);
15
+ this.rootNode = nodes.root;
16
+ this.leafNodes = nodes.leaves;
17
+ }
18
+ getRoot(): Buffer {
19
+ return this.rootNode.hash;
20
+ }
21
+ size(): number {
22
+ return this.leaves.length;
23
+ }
24
+ getLeaves(): Buffer[] {
25
+ return this.leaves;
26
+ }
27
+ getLeafHash(index: number): Buffer {
28
+ return this.leafNodes[index].hash;
29
+ }
30
+ getProof(index: number): Buffer[] {
31
+ if (index >= this.leaves.length) throw Error("Index out of bounds");
32
+ return proveNode(this.leafNodes[index]);
33
+ }
34
+
35
+ calculateRoot(leaves: Buffer[]): { root: Node; leaves: Node[] } {
36
+ const n = leaves.length;
37
+ if (n == 0) {
38
+ return {
39
+ root: new Node(undefined, undefined, Buffer.alloc(32, 0)),
40
+ leaves: [],
41
+ };
42
+ }
43
+ if (n == 1) {
44
+ const newNode = new Node(undefined, undefined, leaves[0]);
45
+ return { root: newNode, leaves: [newNode] };
46
+ }
47
+ const leftCount = highestPowerOf2LessThan(n);
48
+ const leftBranch = this.calculateRoot(leaves.slice(0, leftCount));
49
+ const rightBranch = this.calculateRoot(leaves.slice(leftCount));
50
+ const leftChild = leftBranch.root;
51
+ const rightChild = rightBranch.root;
52
+ const hash = this.hashNode(leftChild.hash, rightChild.hash);
53
+ const node = new Node(leftChild, rightChild, hash);
54
+ leftChild.parent = node;
55
+ rightChild.parent = node;
56
+ return { root: node, leaves: leftBranch.leaves.concat(rightBranch.leaves) };
57
+ }
58
+
59
+ hashNode(left: Buffer, right: Buffer): Buffer {
60
+ return this.h(Buffer.concat([Buffer.of(1), left, right]));
61
+ }
62
+ }
63
+
64
+ export function hashLeaf(
65
+ buf: Buffer,
66
+ hashFunction: (buf: Buffer) => Buffer = crypto.sha256
67
+ ): Buffer {
68
+ return hashConcat(Buffer.of(0), buf, hashFunction);
69
+ }
70
+
71
+ function hashConcat(
72
+ bufA: Buffer,
73
+ bufB: Buffer,
74
+ hashFunction: (buf: Buffer) => Buffer
75
+ ): Buffer {
76
+ return hashFunction(Buffer.concat([bufA, bufB]));
77
+ }
78
+
79
+ class Node {
80
+ leftChild?: Node;
81
+ rightChild?: Node;
82
+ parent?: Node;
83
+ hash: Buffer;
84
+ constructor(left: Node | undefined, right: Node | undefined, hash: Buffer) {
85
+ this.leftChild = left;
86
+ this.rightChild = right;
87
+ this.hash = hash;
88
+ }
89
+ isLeaf(): boolean {
90
+ return this.leftChild == undefined;
91
+ }
92
+ }
93
+
94
+ function proveNode(node: Node): Buffer[] {
95
+ if (!node.parent) {
96
+ return [];
97
+ }
98
+ if (node.parent.leftChild == node) {
99
+ if (!node.parent.rightChild) {
100
+ throw new Error("Expected right child to exist");
101
+ }
102
+ return [node.parent.rightChild.hash, ...proveNode(node.parent)];
103
+ } else {
104
+ if (!node.parent.leftChild) {
105
+ throw new Error("Expected left child to exist");
106
+ }
107
+ return [node.parent.leftChild.hash, ...proveNode(node.parent)];
108
+ }
109
+ }
110
+
111
+ function highestPowerOf2LessThan(n: number) {
112
+ if (n < 2) {
113
+ throw Error("Expected n >= 2");
114
+ }
115
+ if (isPowerOf2(n)) {
116
+ return n / 2;
117
+ }
118
+ return 1 << Math.floor(Math.log2(n));
119
+ }
120
+
121
+ function isPowerOf2(n: number): boolean {
122
+ return (n & (n - 1)) == 0;
123
+ }
@@ -0,0 +1,39 @@
1
+ import { createVarint } from "../varint";
2
+ import { hashLeaf, Merkle } from "./merkle";
3
+
4
+ export class MerkleMap {
5
+ keys: Buffer[];
6
+ keysTree: Merkle;
7
+ values: Buffer[];
8
+ valuesTree: Merkle;
9
+ /**
10
+ * @param keys Sorted list of (unhashed) keys
11
+ * @param values values, in corresponding order as the keys, and of equal length
12
+ */
13
+ constructor(keys: Buffer[], values: Buffer[]) {
14
+ if (keys.length != values.length) {
15
+ throw new Error("keys and values should have the same length");
16
+ }
17
+
18
+ // Sanity check: verify that keys are actually sorted and with no duplicates
19
+ for (let i = 0; i < keys.length - 1; i++) {
20
+ if (keys[i].toString("hex") >= keys[i + 1].toString("hex")) {
21
+ throw new Error("keys must be in strictly increasing order");
22
+ }
23
+ }
24
+
25
+ this.keys = keys;
26
+ this.keysTree = new Merkle(keys.map((k) => hashLeaf(k)));
27
+ this.values = values;
28
+ this.valuesTree = new Merkle(values.map((v) => hashLeaf(v)));
29
+ }
30
+
31
+ commitment(): Buffer {
32
+ // returns a buffer between 65 and 73 (included) bytes long
33
+ return Buffer.concat([
34
+ createVarint(this.keys.length),
35
+ this.keysTree.getRoot(),
36
+ this.valuesTree.getRoot(),
37
+ ]);
38
+ }
39
+ }
@@ -0,0 +1,52 @@
1
+ import { pathArrayToString } from "../bip32";
2
+ import { BufferWriter } from "../buffertools";
3
+ import { crypto } from "bitcoinjs-lib";
4
+ import { Merkle, hashLeaf } from "./merkle";
5
+
6
+ export type DefaultDescriptorTemplate =
7
+ | "pkh(@0)"
8
+ | "sh(wpkh(@0))"
9
+ | "wpkh(@0)"
10
+ | "tr(@0)";
11
+
12
+ export class WalletPolicy {
13
+ descriptorTemplate: string;
14
+ keys: string[];
15
+ /**
16
+ * For now, we only support default descriptor templates.
17
+ */
18
+ constructor(descriptorTemplate: DefaultDescriptorTemplate, key: string) {
19
+ this.descriptorTemplate = descriptorTemplate;
20
+ this.keys = [key];
21
+ }
22
+
23
+ getWalletId(): Buffer {
24
+ // wallet_id (sha256 of the wallet serialization),
25
+ return crypto.sha256(this.serialize());
26
+ }
27
+
28
+ serialize(): Buffer {
29
+ const keyBuffers = this.keys.map((k) => {
30
+ return Buffer.from(k, "ascii");
31
+ });
32
+ const m = new Merkle(keyBuffers.map((k) => hashLeaf(k)));
33
+
34
+ const buf = new BufferWriter();
35
+ buf.writeUInt8(0x01); // wallet type (policy map)
36
+ buf.writeUInt8(0); // length of wallet name (empty string for default wallets)
37
+ buf.writeVarSlice(Buffer.from(this.descriptorTemplate, "ascii"));
38
+ buf.writeVarInt(this.keys.length), buf.writeSlice(m.getRoot());
39
+ return buf.buffer();
40
+ }
41
+ }
42
+
43
+ export function createKey(
44
+ masterFingerprint: Buffer,
45
+ path: number[],
46
+ xpub: string
47
+ ): string {
48
+ const accountPath = pathArrayToString(path);
49
+ return `[${masterFingerprint.toString("hex")}${accountPath.substring(
50
+ 1
51
+ )}]${xpub}/**`;
52
+ }
@@ -0,0 +1,33 @@
1
+ import { BufferWriter } from "../buffertools";
2
+ import { PsbtV2 } from "./psbtv2";
3
+
4
+ export function extract(psbt: PsbtV2): Buffer {
5
+ const tx = new BufferWriter();
6
+ tx.writeUInt32(psbt.getGlobalTxVersion());
7
+
8
+ const isSegwit = !!psbt.getInputWitnessUtxo(0);
9
+ if (isSegwit) {
10
+ tx.writeSlice(Buffer.of(0, 1));
11
+ }
12
+ const inputCount = psbt.getGlobalInputCount();
13
+ tx.writeVarInt(inputCount);
14
+ const witnessWriter = new BufferWriter();
15
+ for (let i = 0; i < inputCount; i++) {
16
+ tx.writeSlice(psbt.getInputPreviousTxid(i));
17
+ tx.writeUInt32(psbt.getInputOutputIndex(i));
18
+ tx.writeVarSlice(psbt.getInputFinalScriptsig(i) ?? Buffer.of());
19
+ tx.writeUInt32(psbt.getInputSequence(i));
20
+ if (isSegwit) {
21
+ witnessWriter.writeSlice(psbt.getInputFinalScriptwitness(i));
22
+ }
23
+ }
24
+ const outputCount = psbt.getGlobalOutputCount();
25
+ tx.writeVarInt(outputCount);
26
+ for (let i = 0; i < outputCount; i++) {
27
+ tx.writeUInt64(BigInt(psbt.getOutputAmount(i)));
28
+ tx.writeVarSlice(psbt.getOutputScript(i));
29
+ }
30
+ tx.writeSlice(witnessWriter.buffer());
31
+ tx.writeUInt32(psbt.getGlobalFallbackLocktime() ?? 0);
32
+ return tx.buffer();
33
+ }
@@ -0,0 +1,110 @@
1
+ import { BufferWriter } from "../buffertools";
2
+ import { psbtIn, PsbtV2 } from "./psbtv2";
3
+
4
+ /**
5
+ *
6
+ * @param psbt The psbt with all signatures added as partial sigs, either through PSBT_IN_PARTIAL_SIG or PSBT_IN_TAP_KEY_SIG
7
+ */
8
+ export function finalize(psbt: PsbtV2): void {
9
+ // First check that each input has a signature
10
+ const inputCount = psbt.getGlobalInputCount();
11
+ for (let i = 0; i < inputCount; i++) {
12
+ const legacyPubkeys = psbt.getInputKeyDatas(i, psbtIn.PARTIAL_SIG);
13
+ const taprootSig = psbt.getInputTapKeySig(i);
14
+ if (legacyPubkeys.length == 0 && !taprootSig) {
15
+ throw Error(`No signature for input ${i} present`);
16
+ }
17
+ if (legacyPubkeys.length > 0) {
18
+ if (legacyPubkeys.length > 1) {
19
+ throw Error(
20
+ `Expected exactly one signature, got ${legacyPubkeys.length}`
21
+ );
22
+ }
23
+ if (taprootSig) {
24
+ throw Error("Both taproot and non-taproot signatures present.");
25
+ }
26
+
27
+ const isSegwitV0 = !!psbt.getInputWitnessUtxo(i);
28
+ const redeemScript = psbt.getInputRedeemScript(i);
29
+ const isWrappedSegwit = !!redeemScript;
30
+ const signature = psbt.getInputPartialSig(i, legacyPubkeys[0]);
31
+ if (!signature)
32
+ throw new Error("Expected partial signature for input " + i);
33
+ if (isSegwitV0) {
34
+ const witnessBuf = new BufferWriter();
35
+ witnessBuf.writeVarInt(2);
36
+ witnessBuf.writeVarInt(signature.length);
37
+ witnessBuf.writeSlice(signature);
38
+ witnessBuf.writeVarInt(legacyPubkeys[0].length);
39
+ witnessBuf.writeSlice(legacyPubkeys[0]);
40
+ psbt.setInputFinalScriptwitness(i, witnessBuf.buffer());
41
+ if (isWrappedSegwit) {
42
+ if (!redeemScript || redeemScript.length == 0) {
43
+ throw new Error(
44
+ "Expected non-empty redeemscript. Can't finalize intput " + i
45
+ );
46
+ }
47
+ const scriptSigBuf = new BufferWriter();
48
+ // Push redeemScript length
49
+ scriptSigBuf.writeUInt8(redeemScript.length);
50
+ scriptSigBuf.writeSlice(redeemScript);
51
+ psbt.setInputFinalScriptsig(i, scriptSigBuf.buffer());
52
+ }
53
+ } else {
54
+ // Legacy input
55
+ const scriptSig = new BufferWriter();
56
+ writePush(scriptSig, signature);
57
+ writePush(scriptSig, legacyPubkeys[0]);
58
+ psbt.setInputFinalScriptsig(i, scriptSig.buffer());
59
+ }
60
+ } else {
61
+ // Taproot input
62
+ const signature = psbt.getInputTapKeySig(i);
63
+ if (!signature) {
64
+ throw Error("No taproot signature found");
65
+ }
66
+ if (signature.length != 64) {
67
+ throw Error("Unexpected length of schnorr signature.");
68
+ }
69
+ const witnessBuf = new BufferWriter();
70
+ witnessBuf.writeVarInt(1);
71
+ witnessBuf.writeVarInt(64);
72
+ witnessBuf.writeSlice(signature);
73
+ psbt.setInputFinalScriptwitness(i, witnessBuf.buffer());
74
+ }
75
+ clearFinalizedInput(psbt, i);
76
+ }
77
+ }
78
+
79
+ function clearFinalizedInput(psbt: PsbtV2, inputIndex: number) {
80
+ const keyTypes = [
81
+ psbtIn.BIP32_DERIVATION,
82
+ psbtIn.PARTIAL_SIG,
83
+ psbtIn.TAP_BIP32_DERIVATION,
84
+ psbtIn.TAP_KEY_SIG,
85
+ ];
86
+ const witnessUtxoAvailable = !!psbt.getInputWitnessUtxo(inputIndex);
87
+ const nonWitnessUtxoAvailable = !!psbt.getInputNonWitnessUtxo(inputIndex);
88
+ if (witnessUtxoAvailable && nonWitnessUtxoAvailable) {
89
+ // Remove NON_WITNESS_UTXO for segwit v0 as it's only needed while signing.
90
+ // Segwit v1 doesn't have NON_WITNESS_UTXO set.
91
+ // See https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki#cite_note-7
92
+ keyTypes.push(psbtIn.NON_WITNESS_UTXO);
93
+ }
94
+ psbt.deleteInputEntries(inputIndex, keyTypes);
95
+ }
96
+
97
+ function writePush(buf: BufferWriter, data: Buffer) {
98
+ if (data.length <= 75) {
99
+ buf.writeUInt8(data.length);
100
+ } else if (data.length <= 256) {
101
+ buf.writeUInt8(76);
102
+ buf.writeUInt8(data.length);
103
+ } else if (data.length <= 256 * 256) {
104
+ buf.writeUInt8(77);
105
+ const b = Buffer.alloc(2);
106
+ b.writeUInt16LE(data.length, 0);
107
+ buf.writeSlice(b);
108
+ }
109
+ buf.writeSlice(data);
110
+ }