@btc-vision/bitcoin 6.5.1 → 6.5.2
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/browser/chunks/crypto-0PweVewC.js +2033 -0
- package/browser/chunks/{payments-BE4vwHhV.js → payments-CgasufRS.js} +410 -408
- package/browser/chunks/psbt-BIwOrKer.js +4096 -0
- package/browser/chunks/{script-COWGdiOo.js → script-CROJPzz_.js} +96 -96
- package/browser/chunks/{transaction-BiXwH2v4.js → transaction-DchBu35N.js} +158 -147
- package/browser/chunks/{utils-BKmkTzNZ.js → utils-CO5kmxe9.js} +225 -223
- package/browser/crypto.d.ts +1 -1
- package/browser/hooks/HookedSigner.d.ts +1 -1
- package/browser/index.d.ts +23 -1
- package/browser/index.js +6 -6
- package/browser/payments/index.d.ts +2 -2
- package/browser/payments/lazy.d.ts +1 -1
- package/browser/psbt/bip371.d.ts +5 -1
- package/browser/psbt.d.ts +1 -1
- package/browser/typeforce.d.ts +38 -0
- package/browser/types.d.ts +22 -20
- package/build/address.js +2 -2
- package/build/bip66.js +2 -2
- package/build/block.js +2 -2
- package/build/crypto.d.ts +1 -1
- package/build/crypto.js +2 -3
- package/build/hooks/HookedSigner.d.ts +1 -1
- package/build/index.d.ts +23 -1
- package/build/payments/bip341.js +1 -1
- package/build/payments/index.d.ts +2 -2
- package/build/payments/lazy.d.ts +1 -1
- package/build/payments/p2op.js +3 -3
- package/build/payments/p2pk.js +1 -1
- package/build/payments/p2pkh.js +3 -3
- package/build/payments/p2sh.js +3 -3
- package/build/payments/p2tr.js +9 -5
- package/build/payments/p2wpkh.js +3 -3
- package/build/payments/p2wsh.js +2 -2
- package/build/psbt/bip371.d.ts +5 -1
- package/build/psbt/bip371.js +10 -7
- package/build/psbt/psbtutils.js +5 -4
- package/build/psbt.d.ts +1 -1
- package/build/psbt.js +78 -45
- package/build/script.js +2 -2
- package/build/script_signature.js +7 -7
- package/build/transaction.js +22 -10
- package/build/tsconfig.tsbuildinfo +1 -0
- package/build/types.d.ts +22 -20
- package/build/types.js +10 -9
- package/package.json +30 -59
- package/src/address.ts +2 -2
- package/src/bip66.ts +2 -2
- package/src/block.ts +8 -5
- package/src/crypto.ts +3 -4
- package/src/ecc_lib.ts +1 -1
- package/src/hooks/HookedSigner.ts +1 -1
- package/src/index.ts +34 -12
- package/src/payments/bip341.ts +1 -1
- package/src/payments/embed.ts +1 -2
- package/src/payments/index.ts +4 -4
- package/src/payments/lazy.ts +3 -3
- package/src/payments/p2op.ts +4 -3
- package/src/payments/p2pk.ts +1 -1
- package/src/payments/p2pkh.ts +3 -3
- package/src/payments/p2sh.ts +13 -5
- package/src/payments/p2tr.ts +8 -9
- package/src/payments/p2wpkh.ts +3 -3
- package/src/payments/p2wsh.ts +4 -4
- package/src/psbt/bip371.ts +22 -13
- package/src/psbt/psbtutils.ts +8 -5
- package/src/psbt.ts +127 -80
- package/src/script.ts +4 -4
- package/src/script_signature.ts +7 -7
- package/src/transaction.ts +31 -18
- package/src/typeforce.d.ts +38 -0
- package/src/types.ts +34 -29
- package/test/address.spec.ts +12 -4
- package/test/bitcoin.core.spec.ts +1 -1
- package/test/block.spec.ts +1 -1
- package/test/bufferutils.spec.ts +1 -1
- package/test/crypto.spec.ts +3 -2
- package/test/fixtures/address.json +1 -1
- package/test/integration/addresses.spec.ts +1 -1
- package/test/integration/bip32.spec.ts +2 -2
- package/test/integration/blocks.spec.ts +1 -1
- package/test/integration/cltv.spec.ts +3 -3
- package/test/integration/csv.spec.ts +3 -3
- package/test/integration/payments.spec.ts +1 -1
- package/test/integration/taproot.spec.ts +8 -7
- package/test/integration/transactions.spec.ts +2 -2
- package/test/payments.spec.ts +4 -3
- package/test/psbt.spec.ts +106 -74
- package/test/script.spec.ts +73 -7
- package/test/script_number.spec.ts +1 -1
- package/test/script_signature.spec.ts +1 -1
- package/test/transaction.spec.ts +1 -1
- package/test/tsconfig.json +1 -1
- package/test/types.spec.ts +1 -1
- package/vitest.config.ts +16 -0
- package/.babelrc +0 -13
- package/.mocharc.json +0 -13
- package/browser/chunks/crypto-C6FlKKmp.js +0 -2006
- package/browser/chunks/psbt-Dlosf9CT.js +0 -3853
- package/cjs/package.json +0 -3
- package/gulpfile.js +0 -42
- package/src/crypto/crypto-browser.js +0 -75
- package/test/ts-node-register.js +0 -7
- package/webpack.config.js +0 -79
package/src/payments/lazy.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
export function prop<T extends
|
|
1
|
+
export function prop<T extends object>(object: T, name: string, f: () => T[keyof T]): void {
|
|
2
2
|
Object.defineProperty(object, name, {
|
|
3
3
|
configurable: true,
|
|
4
4
|
enumerable: true,
|
|
5
5
|
get(): unknown {
|
|
6
|
-
const _value = f.call(this);
|
|
7
|
-
this[name] = _value;
|
|
6
|
+
const _value = f.call(this as T);
|
|
7
|
+
(this as Record<string, unknown>)[name] = _value;
|
|
8
8
|
return _value;
|
|
9
9
|
},
|
|
10
10
|
set(_value: unknown): void {
|
package/src/payments/p2op.ts
CHANGED
|
@@ -115,7 +115,7 @@ export function p2op(a: Omit<P2OPPaymentParams, 'name'>, opts?: PaymentOpts): P2
|
|
|
115
115
|
} else {
|
|
116
116
|
throw new TypeError('Unsupported push opcode in P2OP script');
|
|
117
117
|
}
|
|
118
|
-
return a.output.
|
|
118
|
+
return a.output.subarray(pushPos, pushPos + progLen);
|
|
119
119
|
}
|
|
120
120
|
|
|
121
121
|
if (a.address) {
|
|
@@ -131,7 +131,7 @@ export function p2op(a: Omit<P2OPPaymentParams, 'name'>, opts?: PaymentOpts): P2
|
|
|
131
131
|
|
|
132
132
|
lazy.prop(o, 'hash160', () => {
|
|
133
133
|
if (!o.program) return;
|
|
134
|
-
return o.program.
|
|
134
|
+
return o.program.subarray(1);
|
|
135
135
|
});
|
|
136
136
|
|
|
137
137
|
lazy.prop(o, 'output', () => {
|
|
@@ -188,7 +188,8 @@ export function p2op(a: Omit<P2OPPaymentParams, 'name'>, opts?: PaymentOpts): P2
|
|
|
188
188
|
if (a.deploymentVersion !== undefined && a.deploymentVersion !== prog[0])
|
|
189
189
|
throw new TypeError('deploymentVersion mismatch');
|
|
190
190
|
|
|
191
|
-
if (a.hash160 && !a.hash160.equals(prog.
|
|
191
|
+
if (a.hash160 && !a.hash160.equals(prog.subarray(1)))
|
|
192
|
+
throw new TypeError('hash160 mismatch');
|
|
192
193
|
}
|
|
193
194
|
|
|
194
195
|
return Object.assign(o, a);
|
package/src/payments/p2pk.ts
CHANGED
package/src/payments/p2pkh.ts
CHANGED
|
@@ -43,7 +43,7 @@ export function p2pkh(a: Omit<P2PKHPayment, 'name'>, opts?: PaymentOpts): P2PKHP
|
|
|
43
43
|
const _address = lazy.value(() => {
|
|
44
44
|
const payload = Buffer.from(bs58check.default.decode(a.address!));
|
|
45
45
|
const version = payload.readUInt8(0);
|
|
46
|
-
const hash = payload.
|
|
46
|
+
const hash = payload.subarray(1);
|
|
47
47
|
return { version, hash };
|
|
48
48
|
});
|
|
49
49
|
|
|
@@ -68,7 +68,7 @@ export function p2pkh(a: Omit<P2PKHPayment, 'name'>, opts?: PaymentOpts): P2PKHP
|
|
|
68
68
|
});
|
|
69
69
|
|
|
70
70
|
lazy.prop(o, 'hash', () => {
|
|
71
|
-
if (a.output) return a.output.
|
|
71
|
+
if (a.output) return a.output.subarray(3, 23);
|
|
72
72
|
if (a.address) return _address().hash;
|
|
73
73
|
if (a.pubkey || o.pubkey) return bcrypto.hash160(a.pubkey! || o.pubkey!);
|
|
74
74
|
});
|
|
@@ -153,7 +153,7 @@ export function p2pkh(a: Omit<P2PKHPayment, 'name'>, opts?: PaymentOpts): P2PKHP
|
|
|
153
153
|
throw new TypeError('Output is invalid');
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
const hash2 = a.output.
|
|
156
|
+
const hash2 = a.output.subarray(3, 23);
|
|
157
157
|
if (hash.length > 0 && !hash.equals(hash2)) throw new TypeError('Hash mismatch');
|
|
158
158
|
else hash = hash2;
|
|
159
159
|
}
|
package/src/payments/p2sh.ts
CHANGED
|
@@ -3,7 +3,15 @@ import * as bcrypto from '../crypto.js';
|
|
|
3
3
|
import { bitcoin as BITCOIN_NETWORK } from '../networks.js';
|
|
4
4
|
import * as bscript from '../script.js';
|
|
5
5
|
import { stacksEqual, typeforce as typef } from '../types.js';
|
|
6
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
P2SHPayment,
|
|
8
|
+
Payment,
|
|
9
|
+
PaymentOpts,
|
|
10
|
+
PaymentType,
|
|
11
|
+
ScriptRedeem,
|
|
12
|
+
Stack,
|
|
13
|
+
StackFunction,
|
|
14
|
+
} from './index.js';
|
|
7
15
|
import * as lazy from './lazy.js';
|
|
8
16
|
|
|
9
17
|
const OPS = bscript.opcodes;
|
|
@@ -58,7 +66,7 @@ export function p2sh(a: Omit<P2SHPayment, 'name'>, opts?: PaymentOpts): P2SHPaym
|
|
|
58
66
|
const _address = lazy.value(() => {
|
|
59
67
|
const payload = Buffer.from(bs58check.default.decode(a.address!));
|
|
60
68
|
const version = payload.readUInt8(0);
|
|
61
|
-
const hash = payload.
|
|
69
|
+
const hash = payload.subarray(1);
|
|
62
70
|
return { version, hash };
|
|
63
71
|
});
|
|
64
72
|
const _chunks = lazy.value(() => {
|
|
@@ -87,7 +95,7 @@ export function p2sh(a: Omit<P2SHPayment, 'name'>, opts?: PaymentOpts): P2SHPaym
|
|
|
87
95
|
});
|
|
88
96
|
lazy.prop(o, 'hash', () => {
|
|
89
97
|
// in order of least effort
|
|
90
|
-
if (a.output) return a.output.
|
|
98
|
+
if (a.output) return a.output.subarray(2, 22);
|
|
91
99
|
if (a.address) return _address().hash;
|
|
92
100
|
if (o.redeem && o.redeem.output) return bcrypto.hash160(o.redeem.output);
|
|
93
101
|
});
|
|
@@ -113,7 +121,7 @@ export function p2sh(a: Omit<P2SHPayment, 'name'>, opts?: PaymentOpts): P2SHPaym
|
|
|
113
121
|
});
|
|
114
122
|
lazy.prop(o, 'name', () => {
|
|
115
123
|
const nameParts = ['p2sh'];
|
|
116
|
-
if (o.redeem !== undefined && o.redeem.name !== undefined) nameParts.push(o.redeem.name
|
|
124
|
+
if (o.redeem !== undefined && o.redeem.name !== undefined) nameParts.push(o.redeem.name);
|
|
117
125
|
return nameParts.join('-');
|
|
118
126
|
});
|
|
119
127
|
|
|
@@ -140,7 +148,7 @@ export function p2sh(a: Omit<P2SHPayment, 'name'>, opts?: PaymentOpts): P2SHPaym
|
|
|
140
148
|
)
|
|
141
149
|
throw new TypeError('Output is invalid');
|
|
142
150
|
|
|
143
|
-
const hash2 = a.output.
|
|
151
|
+
const hash2 = a.output.subarray(2, 22);
|
|
144
152
|
if (hash.length > 0 && !hash.equals(hash2)) throw new TypeError('Hash mismatch');
|
|
145
153
|
else hash = hash2;
|
|
146
154
|
}
|
package/src/payments/p2tr.ts
CHANGED
|
@@ -137,7 +137,7 @@ export function p2tr(a: Omit<P2TRPayment, 'name'>, opts?: PaymentOpts): P2TRPaym
|
|
|
137
137
|
});
|
|
138
138
|
lazy.prop(o, 'pubkey', () => {
|
|
139
139
|
if (a.pubkey) return a.pubkey;
|
|
140
|
-
if (a.output) return a.output.
|
|
140
|
+
if (a.output) return a.output.subarray(2);
|
|
141
141
|
if (a.address) return _address().data;
|
|
142
142
|
if (o.internalPubkey) {
|
|
143
143
|
const tweakedKey = tweakKey(o.internalPubkey, o.hash);
|
|
@@ -147,7 +147,7 @@ export function p2tr(a: Omit<P2TRPayment, 'name'>, opts?: PaymentOpts): P2TRPaym
|
|
|
147
147
|
lazy.prop(o, 'internalPubkey', () => {
|
|
148
148
|
if (a.internalPubkey) return a.internalPubkey;
|
|
149
149
|
const witness = _witness();
|
|
150
|
-
if (witness && witness.length > 1) return witness[witness.length - 1].
|
|
150
|
+
if (witness && witness.length > 1) return witness[witness.length - 1].subarray(1, 33);
|
|
151
151
|
});
|
|
152
152
|
lazy.prop(o, 'signature', () => {
|
|
153
153
|
if (a.signature) return a.signature;
|
|
@@ -199,9 +199,9 @@ export function p2tr(a: Omit<P2TRPayment, 'name'>, opts?: PaymentOpts): P2TRPaym
|
|
|
199
199
|
if (a.output) {
|
|
200
200
|
if (a.output.length !== 34 || a.output[0] !== OPS.OP_1 || a.output[1] !== 0x20)
|
|
201
201
|
throw new TypeError('Output is invalid');
|
|
202
|
-
if (pubkey.length > 0 && !pubkey.equals(a.output.
|
|
202
|
+
if (pubkey.length > 0 && !pubkey.equals(a.output.subarray(2)))
|
|
203
203
|
throw new TypeError('Pubkey mismatch');
|
|
204
|
-
else pubkey = a.output.
|
|
204
|
+
else pubkey = a.output.subarray(2);
|
|
205
205
|
}
|
|
206
206
|
|
|
207
207
|
if (a.internalPubkey) {
|
|
@@ -211,10 +211,9 @@ export function p2tr(a: Omit<P2TRPayment, 'name'>, opts?: PaymentOpts): P2TRPaym
|
|
|
211
211
|
else pubkey = tweakedKey!.x;
|
|
212
212
|
}
|
|
213
213
|
|
|
214
|
-
|
|
215
|
-
if (!getEccLib().isXOnlyPoint(pubkey))
|
|
216
|
-
|
|
217
|
-
}*/
|
|
214
|
+
if (pubkey && pubkey.length) {
|
|
215
|
+
if (!getEccLib().isXOnlyPoint(pubkey)) throw new TypeError('Invalid pubkey for p2tr');
|
|
216
|
+
}
|
|
218
217
|
|
|
219
218
|
const hashTree = _hashTree();
|
|
220
219
|
|
|
@@ -276,7 +275,7 @@ export function p2tr(a: Omit<P2TRPayment, 'name'>, opts?: PaymentOpts): P2TRPaym
|
|
|
276
275
|
if (m > 128)
|
|
277
276
|
throw new TypeError(`The script path is too long. Got ${m}, expected max 128.`);
|
|
278
277
|
|
|
279
|
-
const internalPubkey = controlBlock.
|
|
278
|
+
const internalPubkey = controlBlock.subarray(1, 33);
|
|
280
279
|
if (a.internalPubkey && !a.internalPubkey.equals(internalPubkey))
|
|
281
280
|
throw new TypeError('Internal pubkey mismatch');
|
|
282
281
|
|
package/src/payments/p2wpkh.ts
CHANGED
|
@@ -65,7 +65,7 @@ export function p2wpkh(a: Omit<P2WPKHPayment, 'name'>, opts?: PaymentOpts): P2WP
|
|
|
65
65
|
return bech32.encode(network.bech32, words);
|
|
66
66
|
});
|
|
67
67
|
lazy.prop(o, 'hash', () => {
|
|
68
|
-
if (a.output) return a.output.
|
|
68
|
+
if (a.output) return a.output.subarray(2, 22);
|
|
69
69
|
if (a.address) return _address().data;
|
|
70
70
|
if (a.pubkey || o.pubkey) return bcrypto.hash160(a.pubkey! || o.pubkey!);
|
|
71
71
|
});
|
|
@@ -111,9 +111,9 @@ export function p2wpkh(a: Omit<P2WPKHPayment, 'name'>, opts?: PaymentOpts): P2WP
|
|
|
111
111
|
if (a.output) {
|
|
112
112
|
if (a.output.length !== 22 || a.output[0] !== OPS.OP_0 || a.output[1] !== 0x14)
|
|
113
113
|
throw new TypeError('Output is invalid');
|
|
114
|
-
if (hash.length > 0 && !hash.equals(a.output.
|
|
114
|
+
if (hash.length > 0 && !hash.equals(a.output.subarray(2)))
|
|
115
115
|
throw new TypeError('Hash mismatch');
|
|
116
|
-
else hash = a.output.
|
|
116
|
+
else hash = a.output.subarray(2);
|
|
117
117
|
}
|
|
118
118
|
|
|
119
119
|
if (a.pubkey) {
|
package/src/payments/p2wsh.ts
CHANGED
|
@@ -82,10 +82,10 @@ export function p2wsh(a: Omit<P2WSHPayment, 'name'>, opts?: PaymentOpts): P2WSHP
|
|
|
82
82
|
if (!o.hash) return;
|
|
83
83
|
const words = bech32.toWords(o.hash);
|
|
84
84
|
words.unshift(0x00);
|
|
85
|
-
return bech32.encode(network
|
|
85
|
+
return bech32.encode(network.bech32, words);
|
|
86
86
|
});
|
|
87
87
|
lazy.prop(o, 'hash', () => {
|
|
88
|
-
if (a.output) return a.output.
|
|
88
|
+
if (a.output) return a.output.subarray(2);
|
|
89
89
|
if (a.address) return _address().data;
|
|
90
90
|
if (o.redeem && o.redeem.output) return bcrypto.sha256(o.redeem.output);
|
|
91
91
|
});
|
|
@@ -129,7 +129,7 @@ export function p2wsh(a: Omit<P2WSHPayment, 'name'>, opts?: PaymentOpts): P2WSHP
|
|
|
129
129
|
});
|
|
130
130
|
lazy.prop(o, 'name', () => {
|
|
131
131
|
const nameParts = ['p2wsh'];
|
|
132
|
-
if (o.redeem !== undefined && o.redeem.name !== undefined) nameParts.push(o.redeem.name
|
|
132
|
+
if (o.redeem !== undefined && o.redeem.name !== undefined) nameParts.push(o.redeem.name);
|
|
133
133
|
return nameParts.join('-');
|
|
134
134
|
});
|
|
135
135
|
|
|
@@ -152,7 +152,7 @@ export function p2wsh(a: Omit<P2WSHPayment, 'name'>, opts?: PaymentOpts): P2WSHP
|
|
|
152
152
|
if (a.output) {
|
|
153
153
|
if (a.output.length !== 34 || a.output[0] !== OPS.OP_0 || a.output[1] !== 0x20)
|
|
154
154
|
throw new TypeError('Output is invalid');
|
|
155
|
-
const hash2 = a.output.
|
|
155
|
+
const hash2 = a.output.subarray(2);
|
|
156
156
|
if (hash.length > 0 && !hash.equals(hash2)) throw new TypeError('Hash mismatch');
|
|
157
157
|
else hash = hash2;
|
|
158
158
|
}
|
package/src/psbt/bip371.ts
CHANGED
|
@@ -9,6 +9,10 @@ import {
|
|
|
9
9
|
} from 'bip174/src/lib/interfaces.js';
|
|
10
10
|
import { isTapleaf, isTaptree, Tapleaf, Taptree } from '../types.js';
|
|
11
11
|
|
|
12
|
+
interface PsbtOutputWithScript extends PsbtOutput {
|
|
13
|
+
script?: Buffer;
|
|
14
|
+
}
|
|
15
|
+
|
|
12
16
|
import { Transaction } from '../transaction.js';
|
|
13
17
|
|
|
14
18
|
import {
|
|
@@ -27,7 +31,7 @@ import {
|
|
|
27
31
|
} from './psbtutils.js';
|
|
28
32
|
|
|
29
33
|
export const toXOnly = (pubKey: Buffer | Uint8Array): Buffer => {
|
|
30
|
-
const buffer = pubKey.length === 32 ? pubKey : pubKey.
|
|
34
|
+
const buffer = pubKey.length === 32 ? pubKey : pubKey.subarray(1, 33);
|
|
31
35
|
|
|
32
36
|
return Buffer.isBuffer(buffer) ? buffer : Buffer.from(buffer);
|
|
33
37
|
};
|
|
@@ -60,7 +64,7 @@ export function tapScriptFinalizer(
|
|
|
60
64
|
}
|
|
61
65
|
|
|
62
66
|
export function serializeTaprootSignature(sig: Buffer, sighashType?: number): Buffer {
|
|
63
|
-
const sighashTypeByte = sighashType ? Buffer.from([sighashType
|
|
67
|
+
const sighashTypeByte = sighashType ? Buffer.from([sighashType]) : Buffer.from([]);
|
|
64
68
|
|
|
65
69
|
return Buffer.concat([sig, sighashTypeByte]);
|
|
66
70
|
}
|
|
@@ -100,7 +104,7 @@ export function checkTaprootInputFields(
|
|
|
100
104
|
}
|
|
101
105
|
|
|
102
106
|
export function checkTaprootOutputFields(
|
|
103
|
-
outputData:
|
|
107
|
+
outputData: PsbtOutputWithScript,
|
|
104
108
|
newOutputData: PsbtOutput,
|
|
105
109
|
action: string,
|
|
106
110
|
): void {
|
|
@@ -108,14 +112,17 @@ export function checkTaprootOutputFields(
|
|
|
108
112
|
checkTaprootScriptPubkey(outputData, newOutputData);
|
|
109
113
|
}
|
|
110
114
|
|
|
111
|
-
function checkTaprootScriptPubkey(
|
|
115
|
+
function checkTaprootScriptPubkey(
|
|
116
|
+
outputData: PsbtOutputWithScript,
|
|
117
|
+
newOutputData: PsbtOutput,
|
|
118
|
+
): void {
|
|
112
119
|
if (!newOutputData.tapTree && !newOutputData.tapInternalKey) return;
|
|
113
120
|
|
|
114
121
|
const tapInternalKey = newOutputData.tapInternalKey || outputData.tapInternalKey;
|
|
115
122
|
const tapTree = newOutputData.tapTree || outputData.tapTree;
|
|
116
123
|
|
|
117
124
|
if (tapInternalKey) {
|
|
118
|
-
const
|
|
125
|
+
const scriptPubkey = outputData.script;
|
|
119
126
|
const script = getTaprootScripPubkey(tapInternalKey, tapTree);
|
|
120
127
|
if (scriptPubkey && !scriptPubkey.equals(script))
|
|
121
128
|
throw new Error('Error adding output. Script or address missmatch.');
|
|
@@ -128,7 +135,8 @@ function getTaprootScripPubkey(tapInternalKey: TapInternalKey, tapTree?: TapTree
|
|
|
128
135
|
internalPubkey: tapInternalKey,
|
|
129
136
|
scriptTree,
|
|
130
137
|
});
|
|
131
|
-
|
|
138
|
+
if (!output) throw new Error('Failed to generate taproot script pubkey');
|
|
139
|
+
return output;
|
|
132
140
|
}
|
|
133
141
|
|
|
134
142
|
export function tweakInternalPubKey(inputIndex: number, input: PsbtInput): Buffer {
|
|
@@ -186,8 +194,8 @@ function decodeSchnorrSignature(signature: Buffer): {
|
|
|
186
194
|
hashType: number;
|
|
187
195
|
} {
|
|
188
196
|
return {
|
|
189
|
-
signature: signature.
|
|
190
|
-
hashType: signature.
|
|
197
|
+
signature: signature.subarray(0, 64),
|
|
198
|
+
hashType: signature.subarray(64)[0] || Transaction.SIGHASH_DEFAULT,
|
|
191
199
|
};
|
|
192
200
|
}
|
|
193
201
|
|
|
@@ -205,7 +213,7 @@ function extractTaprootSigs(input: PsbtInput): Buffer[] {
|
|
|
205
213
|
|
|
206
214
|
export function getTapKeySigFromWitness(finalScriptWitness?: Buffer): Buffer | undefined {
|
|
207
215
|
if (!finalScriptWitness) return;
|
|
208
|
-
const witness = finalScriptWitness.
|
|
216
|
+
const witness = finalScriptWitness.subarray(2);
|
|
209
217
|
// todo: add schnorr signature validation
|
|
210
218
|
if (witness.length === 64 || witness.length === 65) return witness;
|
|
211
219
|
}
|
|
@@ -358,7 +366,7 @@ function sortSignatures(input: PsbtInput, tapLeaf: TapLeafScript): Buffer[] {
|
|
|
358
366
|
.filter((tss) => tss.leafHash.equals(leafHash))
|
|
359
367
|
.map((tss) => addPubkeyPositionInScript(tapLeaf.script, tss))
|
|
360
368
|
.sort((t1, t2) => t2.positionInScript - t1.positionInScript)
|
|
361
|
-
.map((t) => t.signature)
|
|
369
|
+
.map((t) => t.signature);
|
|
362
370
|
}
|
|
363
371
|
|
|
364
372
|
/**
|
|
@@ -384,13 +392,14 @@ function findTapLeafToFinalize(
|
|
|
384
392
|
inputIndex: number,
|
|
385
393
|
leafHashToFinalize?: Buffer,
|
|
386
394
|
): TapLeafScript {
|
|
387
|
-
|
|
395
|
+
const { tapScriptSig } = input;
|
|
396
|
+
if (!tapScriptSig || !tapScriptSig.length)
|
|
388
397
|
throw new Error(
|
|
389
398
|
`Can not finalize taproot input #${inputIndex}. No tapleaf script signature provided.`,
|
|
390
399
|
);
|
|
391
400
|
const tapLeaf = (input.tapLeafScript || [])
|
|
392
401
|
.sort((a, b) => a.controlBlock.length - b.controlBlock.length)
|
|
393
|
-
.find((leaf) => canFinalizeLeaf(leaf,
|
|
402
|
+
.find((leaf) => canFinalizeLeaf(leaf, tapScriptSig, leafHashToFinalize));
|
|
394
403
|
|
|
395
404
|
if (!tapLeaf)
|
|
396
405
|
throw new Error(
|
|
@@ -419,7 +428,7 @@ function canFinalizeLeaf(
|
|
|
419
428
|
});
|
|
420
429
|
const whiteListedHash = !hash || hash.equals(leafHash);
|
|
421
430
|
return (
|
|
422
|
-
whiteListedHash && tapScriptSig
|
|
431
|
+
whiteListedHash && tapScriptSig.find((tss) => tss.leafHash.equals(leafHash)) !== undefined
|
|
423
432
|
);
|
|
424
433
|
}
|
|
425
434
|
|
package/src/psbt/psbtutils.ts
CHANGED
|
@@ -14,12 +14,14 @@ import { Transaction } from '../transaction.js';
|
|
|
14
14
|
import { toXOnly } from './bip371.js';
|
|
15
15
|
import { p2op } from '../payments/p2op.js';
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
type PaymentFunction = (opts: { output: Buffer }) => unknown;
|
|
18
|
+
|
|
19
|
+
function isPaymentFactory(payment: PaymentFunction): (script: Buffer) => boolean {
|
|
18
20
|
return (script: Buffer): boolean => {
|
|
19
21
|
try {
|
|
20
22
|
payment({ output: script });
|
|
21
23
|
return true;
|
|
22
|
-
} catch
|
|
24
|
+
} catch {
|
|
23
25
|
return false;
|
|
24
26
|
}
|
|
25
27
|
};
|
|
@@ -299,12 +301,13 @@ export function signatureBlocksAction(
|
|
|
299
301
|
* @returns An array of signatures extracted from the PsbtInput object.
|
|
300
302
|
*/
|
|
301
303
|
function extractPartialSigs(input: PsbtInput): Buffer[] {
|
|
302
|
-
|
|
303
|
-
|
|
304
|
+
const { partialSig } = input;
|
|
305
|
+
let pSigs: PartialSig[];
|
|
306
|
+
if (!partialSig || partialSig.length === 0) {
|
|
304
307
|
if (!input.finalScriptSig && !input.finalScriptWitness) return [];
|
|
305
308
|
pSigs = getPsigsFromInputFinalScripts(input);
|
|
306
309
|
} else {
|
|
307
|
-
pSigs =
|
|
310
|
+
pSigs = partialSig;
|
|
308
311
|
}
|
|
309
312
|
return pSigs.map((p) => p.signature);
|
|
310
313
|
}
|