@btc-vision/bitcoin 7.0.0-alpha.9 → 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-BBFlkmiv.js → psbt-parallel-B-dfm5GZ.js} +2430 -2523
- 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 +2 -2
- 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/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/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 +2 -2
- 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.js +1 -1
- 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/p2op.d.ts.map +1 -1
- package/build/payments/p2op.js +6 -4
- package/build/payments/p2op.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/psbt-parallel.js.map +1 -1
- package/package.json +7 -5
- package/src/address.ts +18 -13
- package/src/bip66.ts +18 -18
- package/src/block.ts +7 -2
- 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 +6 -6
- package/src/index.ts +3 -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 +1 -1
- 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 +5 -4
- package/src/payments/p2op.ts +6 -4
- package/src/payments/p2pkh.ts +4 -5
- package/src/payments/p2sh.ts +4 -5
- package/src/payments/p2tr.ts +18 -11
- package/src/payments/p2wpkh.ts +7 -5
- package/src/payments/p2wsh.ts +1 -1
- package/src/psbt/PsbtCache.ts +14 -11
- package/src/psbt/PsbtFinalizer.ts +14 -8
- package/src/psbt/PsbtSigner.ts +4 -3
- 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 +10 -8
- 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 +14 -13
- 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/psbt-parallel.ts +2 -2
- 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/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 {
|
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
|
}
|
|
@@ -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 {
|
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 {
|
|
@@ -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
|
}
|
|
@@ -484,9 +488,9 @@ export class P2TR {
|
|
|
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,
|
|
@@ -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.`,
|
|
@@ -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,
|
|
@@ -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
|
@@ -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
|
@@ -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
|
}
|
|
@@ -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
|
}
|
package/src/psbt/PsbtSigner.ts
CHANGED
|
@@ -69,7 +69,8 @@ export class PsbtSigner {
|
|
|
69
69
|
this.#txFromBuffer,
|
|
70
70
|
);
|
|
71
71
|
|
|
72
|
-
const
|
|
72
|
+
const txIn = unsignedTx.ins[inputIndex] as Transaction['ins'][0];
|
|
73
|
+
const prevoutHash = txIn.hash;
|
|
73
74
|
const utxoHash = nonWitnessUtxoTx.getHash();
|
|
74
75
|
|
|
75
76
|
if (!equals(prevoutHash, utxoHash)) {
|
|
@@ -78,8 +79,8 @@ export class PsbtSigner {
|
|
|
78
79
|
);
|
|
79
80
|
}
|
|
80
81
|
|
|
81
|
-
const prevoutIndex =
|
|
82
|
-
prevout = nonWitnessUtxoTx.outs[prevoutIndex]
|
|
82
|
+
const prevoutIndex = txIn.index;
|
|
83
|
+
prevout = nonWitnessUtxoTx.outs[prevoutIndex] as Transaction['outs'][0];
|
|
83
84
|
} else if (input.witnessUtxo) {
|
|
84
85
|
prevout = {
|
|
85
86
|
script: input.witnessUtxo.script as Script,
|
|
@@ -3,7 +3,7 @@ import { fromHex, reverse } from '../io/index.js';
|
|
|
3
3
|
import { Transaction } from '../transaction.js';
|
|
4
4
|
import type { Bytes32 } from '../types.js';
|
|
5
5
|
import { checkTxEmpty } from './validation.js';
|
|
6
|
-
import type {
|
|
6
|
+
import type { PsbtTxOutput, TransactionInput } from './types.js';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* Empty version-2 transaction with zero inputs and zero outputs.
|
|
@@ -56,7 +56,7 @@ export class PsbtTransaction implements ITransaction {
|
|
|
56
56
|
this.tx.addInput(hash, input.index, input.sequence);
|
|
57
57
|
}
|
|
58
58
|
|
|
59
|
-
public addOutput(output:
|
|
59
|
+
public addOutput(output: PsbtTxOutput): void {
|
|
60
60
|
if (
|
|
61
61
|
output.script === undefined ||
|
|
62
62
|
output.value === undefined ||
|
package/src/psbt/bip371.ts
CHANGED
|
@@ -180,10 +180,11 @@ export function tapTreeToList(tree: Taptree): TapLeaf[] {
|
|
|
180
180
|
* @returns the corresponding taptree, or throws an exception if the tree cannot be reconstructed
|
|
181
181
|
*/
|
|
182
182
|
export function tapTreeFromList(leaves: TapLeaf[] = []): Taptree {
|
|
183
|
-
|
|
183
|
+
const firstLeaf = leaves[0];
|
|
184
|
+
if (leaves.length === 1 && firstLeaf && firstLeaf.depth === 0)
|
|
184
185
|
return {
|
|
185
|
-
output: new Uint8Array(
|
|
186
|
-
version:
|
|
186
|
+
output: new Uint8Array(firstLeaf.script),
|
|
187
|
+
version: firstLeaf.leafVersion,
|
|
187
188
|
};
|
|
188
189
|
|
|
189
190
|
return insertLeavesInTree(leaves);
|
package/src/psbt/utils.ts
CHANGED
|
@@ -73,7 +73,7 @@ export function sighashTypeToString(sighashType: number): string {
|
|
|
73
73
|
*/
|
|
74
74
|
export function compressPubkey(pubkey: Uint8Array): Uint8Array {
|
|
75
75
|
if (pubkey.length === 65) {
|
|
76
|
-
const parity = pubkey[64]
|
|
76
|
+
const parity = (pubkey[64] as number) & 1;
|
|
77
77
|
const newKey = new Uint8Array(pubkey.subarray(0, 33));
|
|
78
78
|
newKey[0] = 2 | parity;
|
|
79
79
|
return newKey;
|
package/src/psbt.ts
CHANGED
|
@@ -3,6 +3,7 @@ import type {
|
|
|
3
3
|
PsbtGlobalUpdate,
|
|
4
4
|
PsbtInput,
|
|
5
5
|
PsbtInputUpdate,
|
|
6
|
+
PsbtOutput,
|
|
6
7
|
PsbtOutputUpdate,
|
|
7
8
|
TapKeySig,
|
|
8
9
|
TapScriptSig,
|
|
@@ -79,6 +80,7 @@ export type {
|
|
|
79
80
|
PsbtInputExtended,
|
|
80
81
|
PsbtOutputExtended,
|
|
81
82
|
PsbtOutputExtendedScript,
|
|
83
|
+
PsbtOutputExtendedAddress,
|
|
82
84
|
HDSigner,
|
|
83
85
|
HDSignerAsync,
|
|
84
86
|
Signer,
|
|
@@ -348,7 +350,7 @@ export class Psbt {
|
|
|
348
350
|
if (this.#cache.tx.ins.length <= inputIndex) {
|
|
349
351
|
throw new Error('Input index too high');
|
|
350
352
|
}
|
|
351
|
-
this.#cache.tx.ins[inputIndex]
|
|
353
|
+
(this.#cache.tx.ins[inputIndex] as { sequence: number }).sequence = sequence;
|
|
352
354
|
this.#cache.invalidate('outputs');
|
|
353
355
|
return this;
|
|
354
356
|
}
|
|
@@ -386,11 +388,11 @@ export class Psbt {
|
|
|
386
388
|
}
|
|
387
389
|
: inputData;
|
|
388
390
|
this.data.addInput(normalizedInputData);
|
|
389
|
-
const txIn = this.#cache.tx.ins[this.#cache.tx.ins.length - 1]
|
|
391
|
+
const txIn = this.#cache.tx.ins[this.#cache.tx.ins.length - 1] as Transaction['ins'][0];
|
|
390
392
|
checkTxInputCache(this.#cache, txIn);
|
|
391
393
|
|
|
392
394
|
const inputIndex = this.data.inputs.length - 1;
|
|
393
|
-
const input = this.data.inputs[inputIndex]
|
|
395
|
+
const input = this.data.inputs[inputIndex] as PsbtInput;
|
|
394
396
|
if (input.nonWitnessUtxo) {
|
|
395
397
|
this.#cache.addNonWitnessTxCache(input, inputIndex, txFromBuffer);
|
|
396
398
|
}
|
|
@@ -558,7 +560,7 @@ export class Psbt {
|
|
|
558
560
|
validator: ValidateSigFunction,
|
|
559
561
|
pubkey?: PublicKey,
|
|
560
562
|
): boolean {
|
|
561
|
-
const input = this.data.inputs[inputIndex]
|
|
563
|
+
const input = this.data.inputs[inputIndex] as PsbtInput;
|
|
562
564
|
if (isTaprootInput(input))
|
|
563
565
|
return this.#validateSignaturesOfTaprootInput(inputIndex, validator, pubkey);
|
|
564
566
|
|
|
@@ -795,7 +797,7 @@ export class Psbt {
|
|
|
795
797
|
|
|
796
798
|
public updateInput(inputIndex: number, updateData: PsbtInputUpdate): this {
|
|
797
799
|
if (updateData.witnessScript) checkInvalidP2WSH(updateData.witnessScript);
|
|
798
|
-
checkTaprootInputFields(this.data.inputs[inputIndex]
|
|
800
|
+
checkTaprootInputFields(this.data.inputs[inputIndex] as PsbtInput, updateData, 'updateInput');
|
|
799
801
|
const normalizedUpdate = updateData.witnessUtxo
|
|
800
802
|
? {
|
|
801
803
|
...updateData,
|
|
@@ -811,7 +813,7 @@ export class Psbt {
|
|
|
811
813
|
this.data.updateInput(inputIndex, normalizedUpdate);
|
|
812
814
|
if (updateData.nonWitnessUtxo) {
|
|
813
815
|
this.#cache.addNonWitnessTxCache(
|
|
814
|
-
this.data.inputs[inputIndex]
|
|
816
|
+
this.data.inputs[inputIndex] as PsbtInput,
|
|
815
817
|
inputIndex,
|
|
816
818
|
txFromBuffer,
|
|
817
819
|
);
|
|
@@ -820,7 +822,7 @@ export class Psbt {
|
|
|
820
822
|
}
|
|
821
823
|
|
|
822
824
|
public updateOutput(outputIndex: number, updateData: PsbtOutputUpdate): this {
|
|
823
|
-
const outputData = this.data.outputs[outputIndex]
|
|
825
|
+
const outputData = this.data.outputs[outputIndex] as PsbtOutput;
|
|
824
826
|
checkTaprootOutputFields(outputData, updateData, 'updateOutput');
|
|
825
827
|
|
|
826
828
|
this.data.updateOutput(outputIndex, updateData);
|
|
@@ -986,7 +988,7 @@ export class Psbt {
|
|
|
986
988
|
validator: ValidateSigFunction,
|
|
987
989
|
pubkey?: PublicKey,
|
|
988
990
|
): boolean {
|
|
989
|
-
const input = this.data.inputs[inputIndex]
|
|
991
|
+
const input = this.data.inputs[inputIndex] as PsbtInput;
|
|
990
992
|
const tapKeySig = input?.tapKeySig;
|
|
991
993
|
const tapScriptSig = input?.tapScriptSig;
|
|
992
994
|
if (!input && !tapKeySig && !(tapScriptSig && !tapScriptSig.length))
|
package/src/push_data.ts
CHANGED
|
@@ -61,19 +61,19 @@ export function decode(
|
|
|
61
61
|
size: number;
|
|
62
62
|
} | null {
|
|
63
63
|
const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
|
|
64
|
-
const opcode = buffer[offset];
|
|
64
|
+
const opcode = buffer[offset] as number;
|
|
65
65
|
let num: number;
|
|
66
66
|
let size: number;
|
|
67
67
|
|
|
68
68
|
// ~6 bit
|
|
69
|
-
if (opcode
|
|
70
|
-
num = opcode
|
|
69
|
+
if (opcode < opcodes.OP_PUSHDATA1) {
|
|
70
|
+
num = opcode;
|
|
71
71
|
size = 1;
|
|
72
72
|
|
|
73
73
|
// 8 bit
|
|
74
74
|
} else if (opcode === opcodes.OP_PUSHDATA1) {
|
|
75
75
|
if (offset + 2 > buffer.length) return null;
|
|
76
|
-
num = buffer[offset + 1]
|
|
76
|
+
num = buffer[offset + 1] as number;
|
|
77
77
|
size = 2;
|
|
78
78
|
|
|
79
79
|
// 16 bit
|
|
@@ -92,7 +92,7 @@ export function decode(
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
return {
|
|
95
|
-
opcode
|
|
95
|
+
opcode,
|
|
96
96
|
number: num,
|
|
97
97
|
size,
|
|
98
98
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare module 'react-native-quick-crypto' {
|
|
2
|
+
interface Hash {
|
|
3
|
+
update(data: Uint8Array | string): Hash;
|
|
4
|
+
digest(): Buffer;
|
|
5
|
+
}
|
|
6
|
+
interface QuickCrypto {
|
|
7
|
+
createHash(algorithm: string): Hash;
|
|
8
|
+
}
|
|
9
|
+
const QuickCrypto: QuickCrypto;
|
|
10
|
+
export default QuickCrypto;
|
|
11
|
+
}
|
package/src/script.ts
CHANGED
|
@@ -41,8 +41,9 @@ export function countNonPushOnlyOPs(value: Stack): number {
|
|
|
41
41
|
function asMinimalOP(buffer: Uint8Array): number | undefined {
|
|
42
42
|
if (buffer.length === 0) return opcodes.OP_0;
|
|
43
43
|
if (buffer.length !== 1) return undefined;
|
|
44
|
-
|
|
45
|
-
if (
|
|
44
|
+
const firstByte = buffer[0] as number;
|
|
45
|
+
if (firstByte >= 1 && firstByte <= 16) return OP_INT_BASE + firstByte;
|
|
46
|
+
if (firstByte === 0x81) return opcodes.OP_1NEGATE;
|
|
46
47
|
return undefined;
|
|
47
48
|
}
|
|
48
49
|
|
|
@@ -129,7 +130,7 @@ export function decompile(buffer: Uint8Array | Stack): Array<number | Uint8Array
|
|
|
129
130
|
let i = 0;
|
|
130
131
|
|
|
131
132
|
while (i < buffer.length) {
|
|
132
|
-
const opcode = buffer[i]
|
|
133
|
+
const opcode = buffer[i] as number;
|
|
133
134
|
|
|
134
135
|
// data chunk
|
|
135
136
|
if (opcode > opcodes.OP_0 && opcode <= opcodes.OP_PUSHDATA4) {
|
|
@@ -248,7 +249,7 @@ export function isCanonicalPubKey(buffer: Uint8Array): boolean {
|
|
|
248
249
|
|
|
249
250
|
export function isCanonicalScriptSignature(buffer: Uint8Array): boolean {
|
|
250
251
|
if (!(buffer instanceof Uint8Array)) return false;
|
|
251
|
-
if (!isDefinedHashType(buffer[buffer.length - 1]
|
|
252
|
+
if (!isDefinedHashType(buffer[buffer.length - 1] as number)) return false;
|
|
252
253
|
|
|
253
254
|
return bip66.check(buffer.subarray(0, -1));
|
|
254
255
|
}
|
package/src/script_number.ts
CHANGED
|
@@ -16,8 +16,8 @@ export function decode(buffer: Buffer, maxLength?: number, minimal?: boolean): n
|
|
|
16
16
|
if (length === 0) return 0;
|
|
17
17
|
if (length > maxLength) throw new TypeError('Script number overflow');
|
|
18
18
|
if (minimal) {
|
|
19
|
-
if ((buffer[length - 1]
|
|
20
|
-
if (length <= 1 || (buffer[length - 2]
|
|
19
|
+
if (((buffer[length - 1] as number) & 0x7f) === 0) {
|
|
20
|
+
if (length <= 1 || ((buffer[length - 2] as number) & 0x80) === 0)
|
|
21
21
|
throw new Error('Non-minimally encoded script number');
|
|
22
22
|
}
|
|
23
23
|
}
|
|
@@ -34,10 +34,10 @@ export function decode(buffer: Buffer, maxLength?: number, minimal?: boolean): n
|
|
|
34
34
|
// 32-bit / 24-bit / 16-bit / 8-bit
|
|
35
35
|
let result = 0;
|
|
36
36
|
for (let i = 0; i < length; ++i) {
|
|
37
|
-
result |= buffer[i]
|
|
37
|
+
result |= (buffer[i] as number) << (8 * i);
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
if (buffer[length - 1]
|
|
40
|
+
if ((buffer[length - 1] as number) & 0x80) return -(result & ~(0x80 << (8 * (length - 1))));
|
|
41
41
|
return result;
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -62,10 +62,10 @@ export function encode(_number: number): Buffer {
|
|
|
62
62
|
value >>= 8;
|
|
63
63
|
}
|
|
64
64
|
|
|
65
|
-
if (buffer[size - 1]
|
|
65
|
+
if ((buffer[size - 1] as number) & 0x80) {
|
|
66
66
|
buffer.writeUInt8(negative ? 0x80 : 0x00, size - 1);
|
|
67
67
|
} else if (negative) {
|
|
68
|
-
buffer[size - 1]
|
|
68
|
+
buffer[size - 1] = (buffer[size - 1] as number) | 0x80;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
71
|
return buffer;
|
package/src/script_signature.ts
CHANGED
|
@@ -24,7 +24,7 @@ function toDER(x: Uint8Array): Uint8Array {
|
|
|
24
24
|
while (x[i] === 0) ++i;
|
|
25
25
|
if (i === x.length) return ZERO;
|
|
26
26
|
x = x.subarray(i);
|
|
27
|
-
if (x[0]
|
|
27
|
+
if ((x[0] as number) & 0x80) return concat([ZERO, x]);
|
|
28
28
|
return x;
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -56,7 +56,7 @@ export interface ScriptSignature {
|
|
|
56
56
|
* @throws Error if the hashType is invalid.
|
|
57
57
|
*/
|
|
58
58
|
export function decode(buffer: Uint8Array): ScriptSignature {
|
|
59
|
-
const hashType = buffer[buffer.length - 1]
|
|
59
|
+
const hashType = buffer[buffer.length - 1] as number;
|
|
60
60
|
if (!isDefinedHashType(hashType)) {
|
|
61
61
|
throw new Error(`Invalid hashType ${hashType}`);
|
|
62
62
|
}
|