@btc-vision/bitcoin 7.0.0-alpha.8 → 7.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/benchmark-compare/BENCHMARK.md +144 -0
- package/benchmark-compare/compare.bench.ts +1024 -0
- package/benchmark-compare/harness.ts +220 -0
- package/benchmark-compare/package.json +18 -0
- package/browser/address.d.ts.map +1 -1
- package/browser/block.d.ts.map +1 -1
- package/browser/chunks/{psbt-parallel-PtTJ19DC.js → psbt-parallel-B-dfm5GZ.js} +2433 -2524
- package/browser/crypto-hashes.d.ts +4 -0
- package/browser/crypto-hashes.d.ts.map +1 -0
- package/browser/crypto-hashes.native.d.ts +4 -0
- package/browser/crypto-hashes.native.d.ts.map +1 -0
- package/browser/crypto.d.ts.map +1 -1
- package/browser/index.d.ts +3 -3
- package/browser/index.d.ts.map +1 -1
- package/browser/index.js +571 -547
- package/browser/io/base58check.d.ts +26 -0
- package/browser/io/base58check.d.ts.map +1 -0
- package/browser/io/base64.d.ts +8 -0
- package/browser/io/base64.d.ts.map +1 -1
- package/browser/io/hex.d.ts.map +1 -1
- package/browser/io/index.d.ts +2 -1
- package/browser/io/index.d.ts.map +1 -1
- package/browser/io/utils.d.ts.map +1 -1
- package/browser/payments/bip341.d.ts.map +1 -1
- package/browser/payments/p2op.d.ts.map +1 -1
- package/browser/payments/p2pkh.d.ts.map +1 -1
- package/browser/payments/p2sh.d.ts.map +1 -1
- package/browser/payments/p2tr.d.ts.map +1 -1
- package/browser/payments/p2wpkh.d.ts.map +1 -1
- package/browser/psbt/PsbtCache.d.ts.map +1 -1
- package/browser/psbt/PsbtSigner.d.ts.map +1 -1
- package/browser/psbt/PsbtTransaction.d.ts +2 -2
- package/browser/psbt/PsbtTransaction.d.ts.map +1 -1
- package/browser/psbt/bip371.d.ts.map +1 -1
- package/browser/psbt.d.ts +1 -1
- package/browser/psbt.d.ts.map +1 -1
- package/browser/react-native-quick-crypto.d.ts +11 -0
- package/browser/script.d.ts.map +1 -1
- package/browser/transaction.d.ts.map +1 -1
- package/browser/workers/WorkerSigningPool.node.d.ts.map +1 -1
- package/browser/workers/WorkerSigningPool.sequential.d.ts.map +1 -1
- package/browser/workers/index.js +5 -5
- package/build/address.d.ts.map +1 -1
- package/build/address.js +19 -12
- package/build/address.js.map +1 -1
- package/build/bech32utils.js.map +1 -1
- package/build/bip66.js +4 -4
- package/build/bip66.js.map +1 -1
- package/build/block.d.ts.map +1 -1
- package/build/block.js +9 -2
- package/build/block.js.map +1 -1
- package/build/crypto-hashes.d.ts +4 -0
- package/build/crypto-hashes.d.ts.map +1 -0
- package/build/crypto-hashes.js +4 -0
- package/build/crypto-hashes.js.map +1 -0
- package/build/crypto-hashes.native.d.ts +4 -0
- package/build/crypto-hashes.native.d.ts.map +1 -0
- package/build/crypto-hashes.native.js +15 -0
- package/build/crypto-hashes.native.js.map +1 -0
- package/build/crypto.d.ts.map +1 -1
- package/build/crypto.js +1 -2
- package/build/crypto.js.map +1 -1
- package/build/env.js.map +1 -1
- package/build/index.d.ts +3 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +1 -1
- package/build/index.js.map +1 -1
- package/build/io/BinaryReader.js +1 -1
- package/build/io/BinaryReader.js.map +1 -1
- package/build/io/base58check.d.ts +26 -0
- package/build/io/base58check.d.ts.map +1 -0
- package/build/io/base58check.js +32 -0
- package/build/io/base58check.js.map +1 -0
- package/build/io/base64.d.ts +8 -0
- package/build/io/base64.d.ts.map +1 -1
- package/build/io/base64.js +14 -0
- package/build/io/base64.js.map +1 -1
- package/build/io/hex.d.ts.map +1 -1
- package/build/io/hex.js +3 -2
- package/build/io/hex.js.map +1 -1
- package/build/io/index.d.ts +2 -1
- package/build/io/index.d.ts.map +1 -1
- package/build/io/index.js +4 -2
- package/build/io/index.js.map +1 -1
- package/build/io/utils.d.ts.map +1 -1
- package/build/io/utils.js +3 -4
- package/build/io/utils.js.map +1 -1
- package/build/merkle.js.map +1 -1
- package/build/payments/bip341.d.ts.map +1 -1
- package/build/payments/bip341.js +4 -3
- package/build/payments/bip341.js.map +1 -1
- package/build/payments/embed.js.map +1 -1
- package/build/payments/p2ms.js.map +1 -1
- package/build/payments/p2op.d.ts.map +1 -1
- package/build/payments/p2op.js +6 -4
- package/build/payments/p2op.js.map +1 -1
- package/build/payments/p2pk.js.map +1 -1
- package/build/payments/p2pkh.d.ts.map +1 -1
- package/build/payments/p2pkh.js +3 -4
- package/build/payments/p2pkh.js.map +1 -1
- package/build/payments/p2sh.d.ts.map +1 -1
- package/build/payments/p2sh.js +3 -4
- package/build/payments/p2sh.js.map +1 -1
- package/build/payments/p2tr.d.ts.map +1 -1
- package/build/payments/p2tr.js +13 -6
- package/build/payments/p2tr.js.map +1 -1
- package/build/payments/p2wpkh.d.ts.map +1 -1
- package/build/payments/p2wpkh.js +7 -5
- package/build/payments/p2wpkh.js.map +1 -1
- package/build/payments/p2wsh.js.map +1 -1
- package/build/psbt/PsbtCache.d.ts.map +1 -1
- package/build/psbt/PsbtCache.js +8 -4
- package/build/psbt/PsbtCache.js.map +1 -1
- package/build/psbt/PsbtFinalizer.js +14 -8
- package/build/psbt/PsbtFinalizer.js.map +1 -1
- package/build/psbt/PsbtSigner.d.ts.map +1 -1
- package/build/psbt/PsbtSigner.js +3 -2
- package/build/psbt/PsbtSigner.js.map +1 -1
- package/build/psbt/PsbtTransaction.d.ts +2 -2
- package/build/psbt/PsbtTransaction.d.ts.map +1 -1
- package/build/psbt/PsbtTransaction.js.map +1 -1
- package/build/psbt/bip371.d.ts.map +1 -1
- package/build/psbt/bip371.js +4 -3
- package/build/psbt/bip371.js.map +1 -1
- package/build/psbt/utils.js.map +1 -1
- package/build/psbt.d.ts +1 -1
- package/build/psbt.d.ts.map +1 -1
- package/build/psbt.js.map +1 -1
- package/build/push_data.js +1 -1
- package/build/push_data.js.map +1 -1
- package/build/script.d.ts.map +1 -1
- package/build/script.js +4 -3
- package/build/script.js.map +1 -1
- package/build/script_number.js +1 -1
- package/build/script_number.js.map +1 -1
- package/build/script_signature.js.map +1 -1
- package/build/transaction.d.ts.map +1 -1
- package/build/transaction.js +2 -1
- package/build/transaction.js.map +1 -1
- package/build/tsconfig.build.tsbuildinfo +1 -1
- package/build/types.js.map +1 -1
- package/build/workers/WorkerSigningPool.js.map +1 -1
- package/build/workers/WorkerSigningPool.node.d.ts.map +1 -1
- package/build/workers/WorkerSigningPool.node.js +25 -3
- package/build/workers/WorkerSigningPool.node.js.map +1 -1
- package/build/workers/WorkerSigningPool.sequential.d.ts.map +1 -1
- package/build/workers/WorkerSigningPool.sequential.js +2 -0
- package/build/workers/WorkerSigningPool.sequential.js.map +1 -1
- package/build/workers/index.js.map +1 -1
- package/build/workers/psbt-parallel.js.map +1 -1
- package/package.json +7 -5
- package/src/address.ts +18 -13
- package/src/bech32utils.ts +3 -3
- package/src/bip66.ts +18 -18
- package/src/block.ts +8 -3
- package/src/crypto-hashes.native.ts +18 -0
- package/src/crypto-hashes.ts +3 -0
- package/src/crypto.ts +1 -2
- package/src/env.ts +10 -8
- package/src/index.ts +4 -0
- package/src/io/BinaryReader.ts +1 -1
- package/src/io/base58check.ts +35 -0
- package/src/io/base64.ts +15 -0
- package/src/io/hex.ts +3 -2
- package/src/io/index.ts +5 -2
- package/src/io/utils.ts +6 -7
- package/src/merkle.ts +3 -3
- package/src/payments/bip341.ts +8 -7
- package/src/payments/embed.ts +1 -1
- package/src/payments/p2ms.ts +2 -2
- package/src/payments/p2op.ts +6 -4
- package/src/payments/p2pk.ts +2 -2
- package/src/payments/p2pkh.ts +7 -8
- package/src/payments/p2sh.ts +8 -9
- package/src/payments/p2tr.ts +24 -17
- package/src/payments/p2wpkh.ts +9 -7
- package/src/payments/p2wsh.ts +3 -3
- package/src/psbt/PsbtCache.ts +14 -11
- package/src/psbt/PsbtFinalizer.ts +17 -11
- package/src/psbt/PsbtSigner.ts +7 -6
- package/src/psbt/PsbtTransaction.ts +2 -2
- package/src/psbt/bip371.ts +4 -3
- package/src/psbt/utils.ts +1 -1
- package/src/psbt.ts +11 -9
- package/src/push_data.ts +5 -5
- package/src/react-native-quick-crypto.d.ts +11 -0
- package/src/script.ts +5 -4
- package/src/script_number.ts +6 -6
- package/src/script_signature.ts +2 -2
- package/src/transaction.ts +15 -14
- package/src/types.ts +1 -1
- package/src/workers/WorkerSigningPool.node.ts +28 -4
- package/src/workers/WorkerSigningPool.sequential.ts +2 -1
- package/src/workers/WorkerSigningPool.ts +3 -3
- package/src/workers/index.ts +1 -1
- package/src/workers/psbt-parallel.ts +3 -3
- package/test/address.spec.ts +1 -0
- package/test/bitcoin.core.spec.ts +9 -2
- package/test/browser/psbt.spec.ts +54 -29
- package/test/browser/workers-signing.spec.ts +8 -8
- package/test/crypto.spec.ts +1 -1
- package/test/env.spec.ts +2 -2
- package/test/integration/_regtest.ts +2 -2
- package/test/integration/blocks.spec.ts +1 -1
- package/test/integration/csv.spec.ts +1 -1
- package/test/integration/payments.spec.ts +2 -2
- package/test/integration/taproot.spec.ts +3 -3
- package/test/integration/transactions.spec.ts +6 -5
- package/test/psbt.spec.ts +49 -25
- package/test/transaction.spec.ts +6 -3
- package/test/workers-pool.spec.ts +5 -5
- package/test/workers-signing.spec.ts +8 -8
- package/test/workers.spec.ts +3 -3
package/src/io/utils.ts
CHANGED
|
@@ -27,14 +27,13 @@
|
|
|
27
27
|
*/
|
|
28
28
|
export function concat(arrays: readonly Uint8Array[]): Uint8Array {
|
|
29
29
|
let totalLength = 0;
|
|
30
|
-
for (
|
|
31
|
-
totalLength +=
|
|
30
|
+
for (const arr of arrays) {
|
|
31
|
+
totalLength += arr.length;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
34
|
const result = new Uint8Array(totalLength);
|
|
35
35
|
let offset = 0;
|
|
36
|
-
for (
|
|
37
|
-
const arr = arrays[i]!;
|
|
36
|
+
for (const arr of arrays) {
|
|
38
37
|
result.set(arr, offset);
|
|
39
38
|
offset += arr.length;
|
|
40
39
|
}
|
|
@@ -95,7 +94,7 @@ export function equals(a: Uint8Array, b: Uint8Array): boolean {
|
|
|
95
94
|
export function compare(a: Uint8Array, b: Uint8Array): number {
|
|
96
95
|
const minLength = Math.min(a.length, b.length);
|
|
97
96
|
for (let i = 0; i < minLength; i++) {
|
|
98
|
-
const diff = a[i]
|
|
97
|
+
const diff = (a[i] as number) - (b[i] as number);
|
|
99
98
|
if (diff !== 0) {
|
|
100
99
|
return diff;
|
|
101
100
|
}
|
|
@@ -187,7 +186,7 @@ export function reverse(bytes: Uint8Array): Uint8Array {
|
|
|
187
186
|
export function reverseCopy(bytes: Uint8Array): Uint8Array {
|
|
188
187
|
const result = new Uint8Array(bytes.length);
|
|
189
188
|
for (let i = 0; i < bytes.length; i++) {
|
|
190
|
-
result[i] = bytes[bytes.length - 1 - i]
|
|
189
|
+
result[i] = bytes[bytes.length - 1 - i] as number;
|
|
191
190
|
}
|
|
192
191
|
return result;
|
|
193
192
|
}
|
|
@@ -240,7 +239,7 @@ export function xor(a: Uint8Array, b: Uint8Array): Uint8Array {
|
|
|
240
239
|
}
|
|
241
240
|
const result = new Uint8Array(a.length);
|
|
242
241
|
for (let i = 0; i < a.length; i++) {
|
|
243
|
-
result[i] = a[i]
|
|
242
|
+
result[i] = (a[i] as number) ^ (b[i] as number);
|
|
244
243
|
}
|
|
245
244
|
return result;
|
|
246
245
|
}
|
package/src/merkle.ts
CHANGED
|
@@ -20,8 +20,8 @@ export function fastMerkleRoot(
|
|
|
20
20
|
let j = 0;
|
|
21
21
|
|
|
22
22
|
for (let i = 0; i < length; i += 2, ++j) {
|
|
23
|
-
const left = results[i]
|
|
24
|
-
const right = i + 1 === length ? left : results[i + 1]
|
|
23
|
+
const left = results[i] as Uint8Array;
|
|
24
|
+
const right = i + 1 === length ? left : (results[i + 1] as Uint8Array);
|
|
25
25
|
const data = new Uint8Array(left.length + right.length);
|
|
26
26
|
data.set(left);
|
|
27
27
|
data.set(right, left.length);
|
|
@@ -32,5 +32,5 @@ export function fastMerkleRoot(
|
|
|
32
32
|
length = j;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
return results[0]
|
|
35
|
+
return results[0] as Uint8Array;
|
|
36
36
|
}
|
package/src/payments/bip341.ts
CHANGED
|
@@ -68,12 +68,13 @@ export function toHashTree(scriptTree: Taptree): HashTree {
|
|
|
68
68
|
|
|
69
69
|
const hashes = [toHashTree(scriptTree[0]), toHashTree(scriptTree[1])];
|
|
70
70
|
hashes.sort((a, b) => compare(a.hash, b.hash));
|
|
71
|
-
const
|
|
71
|
+
const left = hashes[0] as HashTree;
|
|
72
|
+
const right = hashes[1] as HashTree;
|
|
72
73
|
|
|
73
74
|
return {
|
|
74
|
-
hash: tapBranchHash(left
|
|
75
|
-
left
|
|
76
|
-
right
|
|
75
|
+
hash: tapBranchHash(left.hash, right.hash),
|
|
76
|
+
left,
|
|
77
|
+
right,
|
|
77
78
|
};
|
|
78
79
|
}
|
|
79
80
|
|
|
@@ -104,11 +105,11 @@ export function tapleafHash(leaf: Tapleaf): Bytes32 {
|
|
|
104
105
|
return bcrypto.taggedHash(
|
|
105
106
|
'TapLeaf',
|
|
106
107
|
concat([new Uint8Array([version]), serializeScript(leaf.output)]),
|
|
107
|
-
)
|
|
108
|
+
);
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
export function tapTweakHash(pubKey: XOnlyPublicKey, h: Bytes32 | undefined): Bytes32 {
|
|
111
|
-
return bcrypto.taggedHash('TapTweak', h ? concat([pubKey, h]) : pubKey)
|
|
112
|
+
return bcrypto.taggedHash('TapTweak', h ? concat([pubKey, h]) : pubKey);
|
|
112
113
|
}
|
|
113
114
|
|
|
114
115
|
export function tweakKey(pubKey: XOnlyPublicKey, h: Bytes32 | undefined): TweakedPublicKey | null {
|
|
@@ -128,7 +129,7 @@ export function tweakKey(pubKey: XOnlyPublicKey, h: Bytes32 | undefined): Tweake
|
|
|
128
129
|
}
|
|
129
130
|
|
|
130
131
|
function tapBranchHash(a: Uint8Array, b: Uint8Array): Bytes32 {
|
|
131
|
-
return bcrypto.taggedHash('TapBranch', concat([a, b]))
|
|
132
|
+
return bcrypto.taggedHash('TapBranch', concat([a, b]));
|
|
132
133
|
}
|
|
133
134
|
|
|
134
135
|
function serializeScript(s: Uint8Array): Uint8Array {
|
package/src/payments/embed.ts
CHANGED
|
@@ -199,7 +199,7 @@ export class Embed {
|
|
|
199
199
|
if (!this.#inputData) {
|
|
200
200
|
return undefined;
|
|
201
201
|
}
|
|
202
|
-
return bscript.compile(([OPS.OP_RETURN] as Stack).concat(this.#inputData))
|
|
202
|
+
return bscript.compile(([OPS.OP_RETURN] as Stack).concat(this.#inputData));
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
#validate(): void {
|
package/src/payments/p2ms.ts
CHANGED
|
@@ -377,7 +377,7 @@ export class P2MS {
|
|
|
377
377
|
}
|
|
378
378
|
return bscript.compile(
|
|
379
379
|
([] as Stack).concat(OP_INT_BASE + m, pubkeys, OP_INT_BASE + n, OPS.OP_CHECKMULTISIG),
|
|
380
|
-
)
|
|
380
|
+
);
|
|
381
381
|
}
|
|
382
382
|
|
|
383
383
|
#computeInput(): Script | undefined {
|
|
@@ -387,7 +387,7 @@ export class P2MS {
|
|
|
387
387
|
if (!this.#inputSignatures) {
|
|
388
388
|
return undefined;
|
|
389
389
|
}
|
|
390
|
-
return bscript.compile(([OPS.OP_0] as Stack).concat(this.#inputSignatures))
|
|
390
|
+
return bscript.compile(([OPS.OP_0] as Stack).concat(this.#inputSignatures));
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
// Validation
|
package/src/payments/p2op.ts
CHANGED
|
@@ -326,11 +326,13 @@ export class P2OP {
|
|
|
326
326
|
}
|
|
327
327
|
let pushPos = 1;
|
|
328
328
|
let progLen: number;
|
|
329
|
-
|
|
330
|
-
|
|
329
|
+
const byte1 = this.#inputOutput[1];
|
|
330
|
+
const byte2 = this.#inputOutput[2];
|
|
331
|
+
if (byte1 !== undefined && byte1 < 0x4c) {
|
|
332
|
+
progLen = byte1;
|
|
331
333
|
pushPos = 2;
|
|
332
|
-
} else if (
|
|
333
|
-
progLen =
|
|
334
|
+
} else if (byte1 === 0x4c && byte2 !== undefined) {
|
|
335
|
+
progLen = byte2;
|
|
334
336
|
pushPos = 3;
|
|
335
337
|
} else {
|
|
336
338
|
throw new TypeError('Unsupported push opcode in P2OP script');
|
package/src/payments/p2pk.ts
CHANGED
|
@@ -285,7 +285,7 @@ export class P2PK {
|
|
|
285
285
|
}
|
|
286
286
|
const pubkey = this.#inputPubkey;
|
|
287
287
|
if (pubkey) {
|
|
288
|
-
return bscript.compile([pubkey, OPS.OP_CHECKSIG])
|
|
288
|
+
return bscript.compile([pubkey, OPS.OP_CHECKSIG]);
|
|
289
289
|
}
|
|
290
290
|
return undefined;
|
|
291
291
|
}
|
|
@@ -296,7 +296,7 @@ export class P2PK {
|
|
|
296
296
|
}
|
|
297
297
|
const signature = this.#inputSignature;
|
|
298
298
|
if (signature) {
|
|
299
|
-
return bscript.compile([signature])
|
|
299
|
+
return bscript.compile([signature]);
|
|
300
300
|
}
|
|
301
301
|
return undefined;
|
|
302
302
|
}
|
package/src/payments/p2pkh.ts
CHANGED
|
@@ -8,13 +8,12 @@
|
|
|
8
8
|
* @packageDocumentation
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import * as bs58check from 'bs58check';
|
|
12
11
|
import * as bcrypto from '../crypto.js';
|
|
13
12
|
import { bitcoin as BITCOIN_NETWORK, type Network } from '../networks.js';
|
|
14
13
|
import { decompressPublicKey } from '../pubkey.js';
|
|
15
14
|
import * as bscript from '../script.js';
|
|
16
15
|
import { type Bytes20, isPoint, type PublicKey, type Script, type Signature } from '../types.js';
|
|
17
|
-
import { alloc, equals } from '../io/index.js';
|
|
16
|
+
import { alloc, base58check, equals } from '../io/index.js';
|
|
18
17
|
import { type P2PKHPayment, type PaymentOpts, PaymentType } from './types.js';
|
|
19
18
|
|
|
20
19
|
const OPS = bscript.opcodes;
|
|
@@ -325,9 +324,9 @@ export class P2PKH {
|
|
|
325
324
|
#getDecodedAddress(): { version: number; hash: Uint8Array } | undefined {
|
|
326
325
|
if (!this.#decodedAddressComputed) {
|
|
327
326
|
if (this.#inputAddress) {
|
|
328
|
-
const payload = new Uint8Array(
|
|
327
|
+
const payload = new Uint8Array(base58check.decode(this.#inputAddress));
|
|
329
328
|
this.#decodedAddress = {
|
|
330
|
-
version: payload[0]
|
|
329
|
+
version: payload[0] as number,
|
|
331
330
|
hash: payload.subarray(1),
|
|
332
331
|
};
|
|
333
332
|
}
|
|
@@ -358,7 +357,7 @@ export class P2PKH {
|
|
|
358
357
|
const payload = alloc(21);
|
|
359
358
|
payload[0] = this.#network.pubKeyHash;
|
|
360
359
|
payload.set(h, 1);
|
|
361
|
-
return
|
|
360
|
+
return base58check.encode(payload);
|
|
362
361
|
}
|
|
363
362
|
|
|
364
363
|
#computeHash(): Bytes20 | undefined {
|
|
@@ -374,7 +373,7 @@ export class P2PKH {
|
|
|
374
373
|
// Use the pubkey getter to derive pubkey from input if available
|
|
375
374
|
const pk = this.pubkey;
|
|
376
375
|
if (pk) {
|
|
377
|
-
return bcrypto.hash160(pk)
|
|
376
|
+
return bcrypto.hash160(pk);
|
|
378
377
|
}
|
|
379
378
|
return undefined;
|
|
380
379
|
}
|
|
@@ -418,7 +417,7 @@ export class P2PKH {
|
|
|
418
417
|
h,
|
|
419
418
|
OPS.OP_EQUALVERIFY,
|
|
420
419
|
OPS.OP_CHECKSIG,
|
|
421
|
-
])
|
|
420
|
+
]);
|
|
422
421
|
}
|
|
423
422
|
|
|
424
423
|
#computeInput(): Script | undefined {
|
|
@@ -441,7 +440,7 @@ export class P2PKH {
|
|
|
441
440
|
}
|
|
442
441
|
}
|
|
443
442
|
|
|
444
|
-
return bscript.compile([this.#inputSignature, pubKey])
|
|
443
|
+
return bscript.compile([this.#inputSignature, pubKey]);
|
|
445
444
|
}
|
|
446
445
|
|
|
447
446
|
// Validation
|
package/src/payments/p2sh.ts
CHANGED
|
@@ -8,12 +8,11 @@
|
|
|
8
8
|
* @packageDocumentation
|
|
9
9
|
*/
|
|
10
10
|
|
|
11
|
-
import * as bs58check from 'bs58check';
|
|
12
11
|
import * as bcrypto from '../crypto.js';
|
|
13
12
|
import { bitcoin as BITCOIN_NETWORK, type Network } from '../networks.js';
|
|
14
13
|
import * as bscript from '../script.js';
|
|
15
14
|
import { type Bytes20, type Script, type Stack, stacksEqual } from '../types.js';
|
|
16
|
-
import { alloc, equals } from '../io/index.js';
|
|
15
|
+
import { alloc, base58check, equals } from '../io/index.js';
|
|
17
16
|
import {
|
|
18
17
|
type P2SHPayment,
|
|
19
18
|
type Payment,
|
|
@@ -303,9 +302,9 @@ export class P2SH {
|
|
|
303
302
|
#getDecodedAddress(): { version: number; hash: Uint8Array } | undefined {
|
|
304
303
|
if (!this.#decodedAddressComputed) {
|
|
305
304
|
if (this.#inputAddress) {
|
|
306
|
-
const payload = new Uint8Array(
|
|
305
|
+
const payload = new Uint8Array(base58check.decode(this.#inputAddress));
|
|
307
306
|
this.#decodedAddress = {
|
|
308
|
-
version: payload[0]
|
|
307
|
+
version: payload[0] as number,
|
|
309
308
|
hash: payload.subarray(1),
|
|
310
309
|
};
|
|
311
310
|
}
|
|
@@ -336,7 +335,7 @@ export class P2SH {
|
|
|
336
335
|
output: (lastChunk === OPS.OP_FALSE
|
|
337
336
|
? new Uint8Array(0)
|
|
338
337
|
: (lastChunk as Uint8Array)) as Script,
|
|
339
|
-
input: bscript.compile(chunks.slice(0, -1))
|
|
338
|
+
input: bscript.compile(chunks.slice(0, -1)),
|
|
340
339
|
witness: this.#inputWitness || [],
|
|
341
340
|
};
|
|
342
341
|
}
|
|
@@ -355,7 +354,7 @@ export class P2SH {
|
|
|
355
354
|
const payload = alloc(21);
|
|
356
355
|
payload[0] = this.#network.scriptHash;
|
|
357
356
|
payload.set(h, 1);
|
|
358
|
-
return
|
|
357
|
+
return base58check.encode(payload);
|
|
359
358
|
}
|
|
360
359
|
|
|
361
360
|
#computeHash(): Bytes20 | undefined {
|
|
@@ -370,7 +369,7 @@ export class P2SH {
|
|
|
370
369
|
}
|
|
371
370
|
const r = this.redeem;
|
|
372
371
|
if (r && r.output) {
|
|
373
|
-
return bcrypto.hash160(r.output)
|
|
372
|
+
return bcrypto.hash160(r.output);
|
|
374
373
|
}
|
|
375
374
|
return undefined;
|
|
376
375
|
}
|
|
@@ -382,7 +381,7 @@ export class P2SH {
|
|
|
382
381
|
const h = this.hash;
|
|
383
382
|
if (!h) return undefined;
|
|
384
383
|
|
|
385
|
-
return bscript.compile([OPS.OP_HASH160, h, OPS.OP_EQUAL])
|
|
384
|
+
return bscript.compile([OPS.OP_HASH160, h, OPS.OP_EQUAL]);
|
|
386
385
|
}
|
|
387
386
|
|
|
388
387
|
#computeInput(): Script | undefined {
|
|
@@ -395,7 +394,7 @@ export class P2SH {
|
|
|
395
394
|
}
|
|
396
395
|
return bscript.compile(
|
|
397
396
|
([] as Stack).concat(bscript.decompile(r.input) as Stack, r.output),
|
|
398
|
-
)
|
|
397
|
+
);
|
|
399
398
|
}
|
|
400
399
|
|
|
401
400
|
#computeRedeem(): ScriptRedeem | undefined {
|
package/src/payments/p2tr.ts
CHANGED
|
@@ -405,9 +405,10 @@ export class P2TR {
|
|
|
405
405
|
if (!this.#witnessWithoutAnnexComputed) {
|
|
406
406
|
if (this.#inputWitness && this.#inputWitness.length > 0) {
|
|
407
407
|
// Remove annex if present
|
|
408
|
+
const lastWitness = this.#inputWitness[this.#inputWitness.length - 1];
|
|
408
409
|
if (
|
|
409
410
|
this.#inputWitness.length >= 2 &&
|
|
410
|
-
|
|
411
|
+
lastWitness && lastWitness[0] === ANNEX_PREFIX
|
|
411
412
|
) {
|
|
412
413
|
this.#witnessWithoutAnnex = this.#inputWitness.slice(0, -1);
|
|
413
414
|
} else {
|
|
@@ -459,7 +460,7 @@ export class P2TR {
|
|
|
459
460
|
if (internalPk) {
|
|
460
461
|
const tweakedKey = tweakKey(internalPk, this.hash);
|
|
461
462
|
if (tweakedKey) {
|
|
462
|
-
return tweakedKey.x
|
|
463
|
+
return tweakedKey.x;
|
|
463
464
|
}
|
|
464
465
|
}
|
|
465
466
|
return undefined;
|
|
@@ -471,7 +472,10 @@ export class P2TR {
|
|
|
471
472
|
}
|
|
472
473
|
const witness = this.#getWitnessWithoutAnnex();
|
|
473
474
|
if (witness && witness.length > 1) {
|
|
474
|
-
|
|
475
|
+
const lastWitness = witness[witness.length - 1];
|
|
476
|
+
if (lastWitness) {
|
|
477
|
+
return lastWitness.subarray(1, 33) as XOnlyPublicKey;
|
|
478
|
+
}
|
|
475
479
|
}
|
|
476
480
|
return undefined;
|
|
477
481
|
}
|
|
@@ -479,19 +483,19 @@ export class P2TR {
|
|
|
479
483
|
#computeHash(): Bytes32 | undefined {
|
|
480
484
|
const hashTree = this.#getHashTree();
|
|
481
485
|
if (hashTree) {
|
|
482
|
-
return hashTree.hash
|
|
486
|
+
return hashTree.hash;
|
|
483
487
|
}
|
|
484
488
|
|
|
485
489
|
const w = this.#getWitnessWithoutAnnex();
|
|
486
490
|
if (w && w.length > 1) {
|
|
487
|
-
const controlBlock = w[w.length - 1]
|
|
488
|
-
const leafVersion = controlBlock[0]
|
|
489
|
-
const script = w[w.length - 2]
|
|
491
|
+
const controlBlock = w[w.length - 1] as Uint8Array;
|
|
492
|
+
const leafVersion = (controlBlock[0] as number) & TAPLEAF_VERSION_MASK;
|
|
493
|
+
const script = w[w.length - 2] as Uint8Array;
|
|
490
494
|
const leafHash = tapleafHash({
|
|
491
495
|
output: script,
|
|
492
496
|
version: leafVersion,
|
|
493
497
|
});
|
|
494
|
-
return rootHashFromPath(controlBlock, leafHash)
|
|
498
|
+
return rootHashFromPath(controlBlock, leafHash);
|
|
495
499
|
}
|
|
496
500
|
|
|
497
501
|
return undefined;
|
|
@@ -515,7 +519,7 @@ export class P2TR {
|
|
|
515
519
|
const pk = this.pubkey;
|
|
516
520
|
if (!pk) return undefined;
|
|
517
521
|
|
|
518
|
-
return bscript.compile([OPS.OP_1, pk])
|
|
522
|
+
return bscript.compile([OPS.OP_1, pk]);
|
|
519
523
|
}
|
|
520
524
|
|
|
521
525
|
#computeRedeem(): ScriptRedeem | undefined {
|
|
@@ -526,10 +530,11 @@ export class P2TR {
|
|
|
526
530
|
if (!witness || witness.length < 2) {
|
|
527
531
|
return undefined;
|
|
528
532
|
}
|
|
533
|
+
const lastWitness = witness[witness.length - 1] as Uint8Array;
|
|
529
534
|
return {
|
|
530
535
|
output: witness[witness.length - 2] as Script,
|
|
531
536
|
witness: witness.slice(0, -2),
|
|
532
|
-
redeemVersion:
|
|
537
|
+
redeemVersion: (lastWitness[0] as number) & TAPLEAF_VERSION_MASK,
|
|
533
538
|
};
|
|
534
539
|
}
|
|
535
540
|
|
|
@@ -688,12 +693,13 @@ export class P2TR {
|
|
|
688
693
|
if (witness && witness.length > 0) {
|
|
689
694
|
if (witness.length === 1) {
|
|
690
695
|
// Key-path spending
|
|
691
|
-
|
|
696
|
+
const firstWitness = witness[0] as Uint8Array;
|
|
697
|
+
if (this.#inputSignature && !equals(this.#inputSignature, firstWitness)) {
|
|
692
698
|
throw new TypeError('Signature mismatch');
|
|
693
699
|
}
|
|
694
700
|
} else {
|
|
695
701
|
// Script-path spending
|
|
696
|
-
const controlBlock = witness[witness.length - 1]
|
|
702
|
+
const controlBlock = witness[witness.length - 1] as Uint8Array;
|
|
697
703
|
if (controlBlock.length < 33) {
|
|
698
704
|
throw new TypeError(
|
|
699
705
|
`The control-block length is too small. Got ${controlBlock.length}, expected min 33.`,
|
|
@@ -712,7 +718,7 @@ export class P2TR {
|
|
|
712
718
|
}
|
|
713
719
|
|
|
714
720
|
const internalPk = controlBlock.subarray(1, 33);
|
|
715
|
-
if (this.#inputInternalPubkey && !equals(this.#inputInternalPubkey
|
|
721
|
+
if (this.#inputInternalPubkey && !equals(this.#inputInternalPubkey, internalPk)) {
|
|
716
722
|
throw new TypeError('Internal pubkey mismatch');
|
|
717
723
|
}
|
|
718
724
|
|
|
@@ -720,8 +726,9 @@ export class P2TR {
|
|
|
720
726
|
throw new TypeError('Invalid internalPubkey for p2tr witness');
|
|
721
727
|
}
|
|
722
728
|
|
|
723
|
-
const
|
|
724
|
-
const
|
|
729
|
+
const controlBlockFirstByte = controlBlock[0] as number;
|
|
730
|
+
const leafVersion = controlBlockFirstByte & TAPLEAF_VERSION_MASK;
|
|
731
|
+
const script = witness[witness.length - 2] as Uint8Array;
|
|
725
732
|
|
|
726
733
|
const leafHash = tapleafHash({
|
|
727
734
|
output: script,
|
|
@@ -729,7 +736,7 @@ export class P2TR {
|
|
|
729
736
|
});
|
|
730
737
|
const computedHash = rootHashFromPath(controlBlock, leafHash);
|
|
731
738
|
|
|
732
|
-
const outputKey = tweakKey(internalPk
|
|
739
|
+
const outputKey = tweakKey(internalPk, computedHash);
|
|
733
740
|
if (!outputKey) {
|
|
734
741
|
throw new TypeError('Invalid outputKey for p2tr witness');
|
|
735
742
|
}
|
|
@@ -738,7 +745,7 @@ export class P2TR {
|
|
|
738
745
|
throw new TypeError('Pubkey mismatch for p2tr witness');
|
|
739
746
|
}
|
|
740
747
|
|
|
741
|
-
if (outputKey.parity !== (
|
|
748
|
+
if (outputKey.parity !== (controlBlockFirstByte & 1)) {
|
|
742
749
|
throw new Error('Incorrect parity');
|
|
743
750
|
}
|
|
744
751
|
}
|
package/src/payments/p2wpkh.ts
CHANGED
|
@@ -341,7 +341,7 @@ export class P2WPKH {
|
|
|
341
341
|
}
|
|
342
342
|
const pk = this.#inputPubkey ?? this.pubkey;
|
|
343
343
|
if (pk) {
|
|
344
|
-
return bcrypto.hash160(pk)
|
|
344
|
+
return bcrypto.hash160(pk);
|
|
345
345
|
}
|
|
346
346
|
return undefined;
|
|
347
347
|
}
|
|
@@ -373,7 +373,7 @@ export class P2WPKH {
|
|
|
373
373
|
const h = this.hash;
|
|
374
374
|
if (!h) return undefined;
|
|
375
375
|
|
|
376
|
-
return bscript.compile([OPS.OP_0, h])
|
|
376
|
+
return bscript.compile([OPS.OP_0, h]);
|
|
377
377
|
}
|
|
378
378
|
|
|
379
379
|
#computeInput(): Uint8Array | undefined {
|
|
@@ -454,21 +454,23 @@ export class P2WPKH {
|
|
|
454
454
|
if (this.#inputWitness.length !== 2) {
|
|
455
455
|
throw new TypeError('Witness is invalid');
|
|
456
456
|
}
|
|
457
|
-
|
|
457
|
+
const witnessSig = this.#inputWitness[0] as Uint8Array;
|
|
458
|
+
const witnessPubkey = this.#inputWitness[1] as Uint8Array;
|
|
459
|
+
if (!bscript.isCanonicalScriptSignature(witnessSig)) {
|
|
458
460
|
throw new TypeError('Witness has invalid signature');
|
|
459
461
|
}
|
|
460
|
-
if (!isPoint(
|
|
462
|
+
if (!isPoint(witnessPubkey) || witnessPubkey.length !== 33) {
|
|
461
463
|
throw new TypeError('Witness has invalid pubkey');
|
|
462
464
|
}
|
|
463
465
|
|
|
464
|
-
if (this.#inputSignature && !equals(this.#inputSignature
|
|
466
|
+
if (this.#inputSignature && !equals(this.#inputSignature, witnessSig)) {
|
|
465
467
|
throw new TypeError('Signature mismatch');
|
|
466
468
|
}
|
|
467
|
-
if (this.#inputPubkey && !equals(this.#inputPubkey
|
|
469
|
+
if (this.#inputPubkey && !equals(this.#inputPubkey, witnessPubkey)) {
|
|
468
470
|
throw new TypeError('Pubkey mismatch');
|
|
469
471
|
}
|
|
470
472
|
|
|
471
|
-
const pkh = bcrypto.hash160(
|
|
473
|
+
const pkh = bcrypto.hash160(witnessPubkey);
|
|
472
474
|
if (hash.length > 0 && !equals(hash, pkh)) {
|
|
473
475
|
throw new TypeError('Hash mismatch');
|
|
474
476
|
}
|
package/src/payments/p2wsh.ts
CHANGED
|
@@ -352,7 +352,7 @@ export class P2WSH {
|
|
|
352
352
|
}
|
|
353
353
|
const r = this.redeem;
|
|
354
354
|
if (r && r.output) {
|
|
355
|
-
return bcrypto.sha256(r.output)
|
|
355
|
+
return bcrypto.sha256(r.output);
|
|
356
356
|
}
|
|
357
357
|
return undefined;
|
|
358
358
|
}
|
|
@@ -364,7 +364,7 @@ export class P2WSH {
|
|
|
364
364
|
const h = this.hash;
|
|
365
365
|
if (!h) return undefined;
|
|
366
366
|
|
|
367
|
-
return bscript.compile([OPS.OP_0, h])
|
|
367
|
+
return bscript.compile([OPS.OP_0, h]);
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
#computeInput(): Uint8Array | undefined {
|
|
@@ -523,7 +523,7 @@ export class P2WSH {
|
|
|
523
523
|
}
|
|
524
524
|
|
|
525
525
|
if (this.#inputWitness && this.#inputWitness.length > 0) {
|
|
526
|
-
const wScript = this.#inputWitness[this.#inputWitness.length - 1]
|
|
526
|
+
const wScript = this.#inputWitness[this.#inputWitness.length - 1] as Uint8Array;
|
|
527
527
|
if (
|
|
528
528
|
this.#inputRedeem &&
|
|
529
529
|
this.#inputRedeem.output &&
|
package/src/psbt/PsbtCache.ts
CHANGED
|
@@ -75,7 +75,7 @@ export class PsbtCache {
|
|
|
75
75
|
if (!cached) {
|
|
76
76
|
this.addNonWitnessTxCache(input, inputIndex, txFromBuffer);
|
|
77
77
|
}
|
|
78
|
-
return this.nonWitnessUtxoTxCache[inputIndex]
|
|
78
|
+
return this.nonWitnessUtxoTxCache[inputIndex] as Transaction;
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
public getScriptFromUtxo(
|
|
@@ -99,7 +99,8 @@ export class PsbtCache {
|
|
|
99
99
|
};
|
|
100
100
|
} else if (input.nonWitnessUtxo !== undefined) {
|
|
101
101
|
const nonWitnessUtxoTx = this.getNonWitnessUtxoTx(input, inputIndex, txFromBuffer);
|
|
102
|
-
const
|
|
102
|
+
const txIn = this.tx.ins[inputIndex] as Transaction['ins'][0];
|
|
103
|
+
const o = nonWitnessUtxoTx.outs[txIn.index] as Transaction['outs'][0];
|
|
103
104
|
return { script: o.script, value: o.value };
|
|
104
105
|
} else {
|
|
105
106
|
throw new Error("Can't find pubkey in input without Utxo data");
|
|
@@ -192,7 +193,7 @@ export class PsbtCache {
|
|
|
192
193
|
}
|
|
193
194
|
|
|
194
195
|
public pubkeyInOutput(pubkey: PublicKey, output: PsbtOutput, outputIndex: number): boolean {
|
|
195
|
-
const script = this.tx.outs[outputIndex]
|
|
196
|
+
const script = (this.tx.outs[outputIndex] as Transaction['outs'][0]).script;
|
|
196
197
|
const { meaningfulScript } = getMeaningfulScript(
|
|
197
198
|
script,
|
|
198
199
|
outputIndex,
|
|
@@ -207,7 +208,7 @@ export class PsbtCache {
|
|
|
207
208
|
if (!finalScript) return;
|
|
208
209
|
const decomp = bscript.decompile(finalScript);
|
|
209
210
|
if (!decomp) return;
|
|
210
|
-
const lastItem = decomp[decomp.length - 1]
|
|
211
|
+
const lastItem = decomp[decomp.length - 1];
|
|
211
212
|
if (!(lastItem instanceof Uint8Array) || isPubkeyLike(lastItem) || isSigLike(lastItem))
|
|
212
213
|
return;
|
|
213
214
|
const sDecomp = bscript.decompile(lastItem);
|
|
@@ -220,7 +221,8 @@ export class PsbtCache {
|
|
|
220
221
|
): Uint8Array | undefined {
|
|
221
222
|
if (!finalScript) return;
|
|
222
223
|
const decomp = scriptWitnessToWitnessStack(finalScript);
|
|
223
|
-
const lastItem = decomp[decomp.length - 1]
|
|
224
|
+
const lastItem = decomp[decomp.length - 1];
|
|
225
|
+
if (!lastItem) return;
|
|
224
226
|
if (isPubkeyLike(lastItem)) return;
|
|
225
227
|
const sDecomp = bscript.decompile(lastItem);
|
|
226
228
|
if (!sDecomp) return;
|
|
@@ -240,10 +242,11 @@ export class PsbtCache {
|
|
|
240
242
|
): { fee: number; feeRate: number } {
|
|
241
243
|
let inputAmount = 0n;
|
|
242
244
|
inputs.forEach((input, idx) => {
|
|
245
|
+
const txIn = tx.ins[idx] as Transaction['ins'][0];
|
|
243
246
|
if (mustFinalize && input.finalScriptSig)
|
|
244
|
-
|
|
247
|
+
txIn.script = input.finalScriptSig as Script;
|
|
245
248
|
if (mustFinalize && input.finalScriptWitness) {
|
|
246
|
-
|
|
249
|
+
txIn.witness = scriptWitnessToWitnessStack(input.finalScriptWitness);
|
|
247
250
|
}
|
|
248
251
|
if (input.witnessUtxo) {
|
|
249
252
|
inputAmount += input.witnessUtxo.value;
|
|
@@ -251,8 +254,8 @@ export class PsbtCache {
|
|
|
251
254
|
if (!txFromBuffer)
|
|
252
255
|
throw new Error('txFromBuffer is required for nonWitnessUtxo inputs');
|
|
253
256
|
const nwTx = this.getNonWitnessUtxoTx(input, idx, txFromBuffer);
|
|
254
|
-
const vout =
|
|
255
|
-
const out = nwTx.outs[vout]
|
|
257
|
+
const vout = txIn.index;
|
|
258
|
+
const out = nwTx.outs[vout] as Transaction['outs'][0];
|
|
256
259
|
inputAmount += out.value;
|
|
257
260
|
}
|
|
258
261
|
});
|
|
@@ -296,8 +299,8 @@ export class PsbtCache {
|
|
|
296
299
|
} else {
|
|
297
300
|
if (input.nonWitnessUtxo) {
|
|
298
301
|
const nonWitnessUtxoTx = this.getNonWitnessUtxoTx(input, inputIndex, txFromBuffer);
|
|
299
|
-
const prevoutIndex = this.tx.ins[inputIndex]
|
|
300
|
-
res.script = nonWitnessUtxoTx.outs[prevoutIndex]
|
|
302
|
+
const prevoutIndex = (this.tx.ins[inputIndex] as Transaction['ins'][0]).index;
|
|
303
|
+
res.script = (nonWitnessUtxoTx.outs[prevoutIndex] as Transaction['outs'][0]).script;
|
|
301
304
|
} else if (input.witnessUtxo) {
|
|
302
305
|
res.script = input.witnessUtxo.script as Script;
|
|
303
306
|
}
|
|
@@ -110,18 +110,18 @@ export function prepareFinalScripts(
|
|
|
110
110
|
finalScriptWitness = witnessStackToScriptWitness(solution ?? [new Uint8Array([0x00])]);
|
|
111
111
|
}
|
|
112
112
|
if (p2sh) {
|
|
113
|
-
finalScriptSig = p2sh?.input
|
|
113
|
+
finalScriptSig = p2sh?.input;
|
|
114
114
|
}
|
|
115
115
|
} else {
|
|
116
116
|
if (p2sh) {
|
|
117
|
-
finalScriptSig = p2sh?.input
|
|
117
|
+
finalScriptSig = p2sh?.input;
|
|
118
118
|
} else {
|
|
119
119
|
if (!payment) {
|
|
120
120
|
finalScriptSig = (
|
|
121
121
|
Array.isArray(solution) && solution[0] ? solution[0] : new Uint8Array([0x01])
|
|
122
122
|
) as Script;
|
|
123
123
|
} else {
|
|
124
|
-
finalScriptSig = payment.input
|
|
124
|
+
finalScriptSig = payment.input;
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
}
|
|
@@ -175,23 +175,29 @@ function getPayment(script: Uint8Array, scriptType: string, partialSig: PartialS
|
|
|
175
175
|
signatures: sigs as Signature[],
|
|
176
176
|
});
|
|
177
177
|
}
|
|
178
|
-
case 'pubkey':
|
|
178
|
+
case 'pubkey': {
|
|
179
|
+
const sig0 = partialSig[0] as PartialSig;
|
|
179
180
|
return payments.p2pk({
|
|
180
181
|
output: scriptBranded,
|
|
181
|
-
signature:
|
|
182
|
+
signature: sig0.signature as Signature,
|
|
182
183
|
});
|
|
183
|
-
|
|
184
|
+
}
|
|
185
|
+
case 'pubkeyhash': {
|
|
186
|
+
const sig0 = partialSig[0] as PartialSig;
|
|
184
187
|
return payments.p2pkh({
|
|
185
188
|
output: scriptBranded,
|
|
186
|
-
pubkey:
|
|
187
|
-
signature:
|
|
189
|
+
pubkey: sig0.pubkey as PublicKey,
|
|
190
|
+
signature: sig0.signature as Signature,
|
|
188
191
|
});
|
|
189
|
-
|
|
192
|
+
}
|
|
193
|
+
case 'witnesspubkeyhash': {
|
|
194
|
+
const sig0 = partialSig[0] as PartialSig;
|
|
190
195
|
return payments.p2wpkh({
|
|
191
196
|
output: scriptBranded,
|
|
192
|
-
pubkey:
|
|
193
|
-
signature:
|
|
197
|
+
pubkey: sig0.pubkey as PublicKey,
|
|
198
|
+
signature: sig0.signature as Signature,
|
|
194
199
|
});
|
|
200
|
+
}
|
|
195
201
|
default:
|
|
196
202
|
throw new Error(`Unknown script type: ${scriptType}`);
|
|
197
203
|
}
|