@btc-vision/bitcoin 6.4.5 → 6.4.7

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/psbt.d.ts CHANGED
@@ -43,6 +43,7 @@ export declare class Psbt {
43
43
  clone(): Psbt;
44
44
  setMaximumFeeRate(satoshiPerByte: number): void;
45
45
  setVersion(version: number): this;
46
+ setVersionTRUC(): this;
46
47
  setLocktime(locktime: number): this;
47
48
  setInputSequence(inputIndex: number, sequence: number): this;
48
49
  addInputs(inputDatas: PsbtInputExtended[], checkPartialSigs?: boolean): this;
@@ -98,6 +99,7 @@ export declare class Psbt {
98
99
  export interface PsbtOptsOptional {
99
100
  network?: Network;
100
101
  maximumFeeRate?: number;
102
+ version?: 1 | 2 | 3;
101
103
  }
102
104
  export interface PsbtOpts {
103
105
  network: Network;
@@ -155,11 +157,11 @@ type FinalScriptsFunc = (inputIndex: number, input: PsbtInput, script: Buffer, i
155
157
  type FinalTaprootScriptsFunc = (inputIndex: number, input: PsbtInput, tapLeafHashToFinalize?: Buffer) => {
156
158
  finalScriptWitness: Buffer | undefined;
157
159
  };
158
- export declare function getFinalScripts(inputIndex: number, input: PsbtInput, script: Buffer, isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean, canRunChecks?: boolean): {
160
+ export declare function getFinalScripts(inputIndex: number, input: PsbtInput, script: Buffer, isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean, canRunChecks?: boolean, solution?: Buffer[]): {
159
161
  finalScriptSig: Buffer | undefined;
160
162
  finalScriptWitness: Buffer | undefined;
161
163
  };
162
- export declare function prepareFinalScripts(script: Buffer, scriptType: string, partialSig: PartialSig[], isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean): {
164
+ export declare function prepareFinalScripts(script: Buffer, scriptType: string, partialSig: PartialSig[], isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean, solution?: Buffer[]): {
163
165
  finalScriptSig: Buffer | undefined;
164
166
  finalScriptWitness: Buffer | undefined;
165
167
  };
@@ -20,6 +20,9 @@ export declare class Transaction {
20
20
  static readonly SIGHASH_INPUT_MASK = 128;
21
21
  static readonly ADVANCED_TRANSACTION_MARKER = 0;
22
22
  static readonly ADVANCED_TRANSACTION_FLAG = 1;
23
+ static readonly TRUC_VERSION = 3;
24
+ static readonly TRUC_MAX_VSIZE = 10000;
25
+ static readonly TRUC_CHILD_MAX_VSIZE = 1000;
23
26
  version: number;
24
27
  locktime: number;
25
28
  ins: Input[];
@@ -8,7 +8,16 @@ export interface Bech32Result {
8
8
  prefix: string;
9
9
  data: Buffer;
10
10
  }
11
+ export declare const FUTURE_SEGWIT_MAX_SIZE: number;
12
+ export declare const FUTURE_SEGWIT_MIN_SIZE: number;
13
+ export declare const FUTURE_SEGWIT_MAX_VERSION: number;
14
+ export declare const FUTURE_MAX_VERSION: number;
15
+ export declare const FUTURE_OPNET_VERSION: number;
16
+ export declare const FUTURE_SEGWIT_MIN_VERSION: number;
17
+ export declare const FUTURE_SEGWIT_VERSION_DIFF: number;
18
+ export declare const isUnknownSegwitVersion: (output: Buffer) => boolean;
11
19
  export declare function toFutureOPNetAddress(output: Buffer, network: Network): string;
20
+ export declare function _toFutureSegwitAddress(output: Buffer, network: Network): string;
12
21
  export declare function fromBase58Check(address: string): Base58CheckResult;
13
22
  export declare function fromBech32(address: string): Bech32Result;
14
23
  export declare function toBase58Check(hash: Buffer, version: number): string;
package/build/address.js CHANGED
@@ -4,17 +4,34 @@ import { opcodes, payments } from './index.js';
4
4
  import * as networks from './networks.js';
5
5
  import * as bscript from './script.js';
6
6
  import { Hash160bit, tuple, typeforce, UInt8 } from './types.js';
7
- const FUTURE_SEGWIT_MAX_SIZE = 40;
8
- const FUTURE_SEGWIT_MIN_SIZE = 2;
9
- const FUTURE_SEGWIT_MAX_VERSION = 15;
10
- const FUTURE_MAX_VERSION = 16;
11
- const FUTURE_OPNET_VERSION = 16;
12
- const FUTURE_SEGWIT_MIN_VERSION = 2;
13
- const FUTURE_SEGWIT_VERSION_DIFF = 0x50;
7
+ export const FUTURE_SEGWIT_MAX_SIZE = 40;
8
+ export const FUTURE_SEGWIT_MIN_SIZE = 2;
9
+ export const FUTURE_SEGWIT_MAX_VERSION = 15;
10
+ export const FUTURE_MAX_VERSION = 16;
11
+ export const FUTURE_OPNET_VERSION = 16;
12
+ export const FUTURE_SEGWIT_MIN_VERSION = 2;
13
+ export const FUTURE_SEGWIT_VERSION_DIFF = 0x50;
14
14
  const FUTURE_SEGWIT_VERSION_WARNING = 'WARNING: Sending to a future segwit version address can lead to loss of funds. ' +
15
15
  'End users MUST be warned carefully in the GUI and asked if they wish to proceed ' +
16
16
  'with caution. Wallets should verify the segwit version from the output of fromBech32, ' +
17
17
  'then decide when it is safe to use which version of segwit.';
18
+ export const isUnknownSegwitVersion = (output) => {
19
+ try {
20
+ const data = output.subarray(2);
21
+ if (data.length < FUTURE_SEGWIT_MIN_SIZE || data.length > FUTURE_SEGWIT_MAX_SIZE) {
22
+ throw new TypeError('Invalid program length for segwit address');
23
+ }
24
+ const version = output[0] - FUTURE_SEGWIT_VERSION_DIFF;
25
+ if (version < FUTURE_SEGWIT_MIN_VERSION || version > FUTURE_SEGWIT_MAX_VERSION + 1) {
26
+ throw new TypeError('Invalid version for segwit address');
27
+ }
28
+ if (version === 1)
29
+ throw new TypeError('taproot');
30
+ return true;
31
+ }
32
+ catch (e) { }
33
+ return false;
34
+ };
18
35
  export function toFutureOPNetAddress(output, network) {
19
36
  if (!Buffer.isBuffer(output))
20
37
  throw new TypeError('output must be a Buffer');
@@ -46,7 +63,7 @@ export function toFutureOPNetAddress(output, network) {
46
63
  const words = [version, ...bech32m.toWords(program)];
47
64
  return bech32m.encode(network.bech32Opnet, words);
48
65
  }
49
- function _toFutureSegwitAddress(output, network) {
66
+ export function _toFutureSegwitAddress(output, network) {
50
67
  const data = output.subarray(2);
51
68
  if (data.length < FUTURE_SEGWIT_MIN_SIZE || data.length > FUTURE_SEGWIT_MAX_SIZE) {
52
69
  throw new TypeError('Invalid program length for segwit address');
package/build/psbt.d.ts CHANGED
@@ -43,6 +43,7 @@ export declare class Psbt {
43
43
  clone(): Psbt;
44
44
  setMaximumFeeRate(satoshiPerByte: number): void;
45
45
  setVersion(version: number): this;
46
+ setVersionTRUC(): this;
46
47
  setLocktime(locktime: number): this;
47
48
  setInputSequence(inputIndex: number, sequence: number): this;
48
49
  addInputs(inputDatas: PsbtInputExtended[], checkPartialSigs?: boolean): this;
@@ -98,6 +99,7 @@ export declare class Psbt {
98
99
  export interface PsbtOptsOptional {
99
100
  network?: Network;
100
101
  maximumFeeRate?: number;
102
+ version?: 1 | 2 | 3;
101
103
  }
102
104
  export interface PsbtOpts {
103
105
  network: Network;
@@ -155,11 +157,11 @@ type FinalScriptsFunc = (inputIndex: number, input: PsbtInput, script: Buffer, i
155
157
  type FinalTaprootScriptsFunc = (inputIndex: number, input: PsbtInput, tapLeafHashToFinalize?: Buffer) => {
156
158
  finalScriptWitness: Buffer | undefined;
157
159
  };
158
- export declare function getFinalScripts(inputIndex: number, input: PsbtInput, script: Buffer, isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean, canRunChecks?: boolean): {
160
+ export declare function getFinalScripts(inputIndex: number, input: PsbtInput, script: Buffer, isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean, canRunChecks?: boolean, solution?: Buffer[]): {
159
161
  finalScriptSig: Buffer | undefined;
160
162
  finalScriptWitness: Buffer | undefined;
161
163
  };
162
- export declare function prepareFinalScripts(script: Buffer, scriptType: string, partialSig: PartialSig[], isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean): {
164
+ export declare function prepareFinalScripts(script: Buffer, scriptType: string, partialSig: PartialSig[], isSegwit: boolean, isP2SH: boolean, isP2WSH: boolean, solution?: Buffer[]): {
163
165
  finalScriptSig: Buffer | undefined;
164
166
  finalScriptWitness: Buffer | undefined;
165
167
  };
package/build/psbt.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { Psbt as PsbtBase } from 'bip174';
2
2
  import * as varuint from 'bip174/src/lib/converter/varint.js';
3
3
  import { checkForInput, checkForOutput } from 'bip174/src/lib/utils.js';
4
- import { fromOutputScript, toOutputScript } from './address.js';
4
+ import { fromOutputScript, isUnknownSegwitVersion, toOutputScript } from './address.js';
5
5
  import { cloneBuffer, reverseBuffer } from './bufferutils.js';
6
6
  import { payments } from './index.js';
7
7
  import { bitcoin as btcNetwork } from './networks.js';
@@ -25,7 +25,10 @@ export class Psbt {
25
25
  __TX: this.data.globalMap.unsignedTx.tx,
26
26
  __UNSAFE_SIGN_NONSEGWIT: false,
27
27
  };
28
- if (this.data.inputs.length === 0)
28
+ if (opts.version === 3) {
29
+ this.setVersionTRUC();
30
+ }
31
+ else if (this.data.inputs.length === 0)
29
32
  this.setVersion(2);
30
33
  const dpew = (obj, attr, enumerable, writable) => {
31
34
  Object.defineProperty(obj, attr, {
@@ -105,6 +108,9 @@ export class Psbt {
105
108
  c.__EXTRACTED_TX = undefined;
106
109
  return this;
107
110
  }
111
+ setVersionTRUC() {
112
+ return this.setVersion(Transaction.TRUC_VERSION);
113
+ }
108
114
  setLocktime(locktime) {
109
115
  check32Bit(locktime);
110
116
  checkInputsForPartialSig(this.data.inputs, 'setLocktime');
@@ -818,14 +824,14 @@ function getTxCacheValue(key, name, inputs, c, disableOutputChecks = false) {
818
824
  else if (key === '__FEE')
819
825
  return c.__FEE;
820
826
  }
821
- export function getFinalScripts(inputIndex, input, script, isSegwit, isP2SH, isP2WSH, canRunChecks = true) {
827
+ export function getFinalScripts(inputIndex, input, script, isSegwit, isP2SH, isP2WSH, canRunChecks = true, solution) {
822
828
  const scriptType = classifyScript(script);
823
829
  if (!canFinalize(input, script, scriptType) && canRunChecks) {
824
830
  throw new Error(`Can not finalize input #${inputIndex}`);
825
831
  }
826
- return prepareFinalScripts(script, scriptType, input.partialSig, isSegwit, isP2SH, isP2WSH);
832
+ return prepareFinalScripts(script, scriptType, input.partialSig, isSegwit, isP2SH, isP2WSH, solution);
827
833
  }
828
- export function prepareFinalScripts(script, scriptType, partialSig, isSegwit, isP2SH, isP2WSH) {
834
+ export function prepareFinalScripts(script, scriptType, partialSig, isSegwit, isP2SH, isP2WSH, solution) {
829
835
  let finalScriptSig;
830
836
  let finalScriptWitness;
831
837
  const payment = getPayment(script, scriptType, partialSig);
@@ -835,19 +841,28 @@ export function prepareFinalScripts(script, scriptType, partialSig, isSegwit, is
835
841
  if (p2wsh) {
836
842
  finalScriptWitness = witnessStackToScriptWitness(p2wsh.witness);
837
843
  }
838
- else {
844
+ else if (payment) {
839
845
  finalScriptWitness = witnessStackToScriptWitness(payment.witness);
840
846
  }
847
+ else {
848
+ finalScriptWitness = witnessStackToScriptWitness(solution ?? [Buffer.from([0x00])]);
849
+ }
841
850
  if (p2sh) {
842
- finalScriptSig = p2sh.input;
851
+ finalScriptSig = p2sh?.input;
843
852
  }
844
853
  }
845
854
  else {
846
855
  if (p2sh) {
847
- finalScriptSig = p2sh.input;
856
+ finalScriptSig = p2sh?.input;
848
857
  }
849
858
  else {
850
- finalScriptSig = payment.input;
859
+ if (!payment) {
860
+ finalScriptSig =
861
+ Array.isArray(solution) && solution[0] ? solution[0] : Buffer.from([0x01]);
862
+ }
863
+ else {
864
+ finalScriptSig = payment.input;
865
+ }
851
866
  }
852
867
  }
853
868
  return {
@@ -1043,6 +1058,15 @@ function getScriptFromInput(inputIndex, input, cache) {
1043
1058
  if (input.witnessScript || isP2WPKH(res.script)) {
1044
1059
  res.isSegwit = true;
1045
1060
  }
1061
+ else {
1062
+ try {
1063
+ const output = res.script;
1064
+ if (!output)
1065
+ throw new TypeError('Invalid script for segwit address');
1066
+ res.isSegwit = isUnknownSegwitVersion(output);
1067
+ }
1068
+ catch (e) { }
1069
+ }
1046
1070
  return res;
1047
1071
  }
1048
1072
  function getSignersFromHD(inputIndex, inputs, hdKeyPair) {
@@ -1167,7 +1191,7 @@ function inputFinalizeGetAmts(inputs, tx, cache, mustFinalize, disableOutputChec
1167
1191
  const fee = inputAmount - outputAmount;
1168
1192
  if (!disableOutputChecks) {
1169
1193
  if (fee < 0) {
1170
- throw new Error('Outputs are spending more than Inputs');
1194
+ throw new Error(`Outputs are spending more than Inputs ${inputAmount} < ${outputAmount}`);
1171
1195
  }
1172
1196
  }
1173
1197
  const bytes = tx.virtualSize();
@@ -20,6 +20,9 @@ export declare class Transaction {
20
20
  static readonly SIGHASH_INPUT_MASK = 128;
21
21
  static readonly ADVANCED_TRANSACTION_MARKER = 0;
22
22
  static readonly ADVANCED_TRANSACTION_FLAG = 1;
23
+ static readonly TRUC_VERSION = 3;
24
+ static readonly TRUC_MAX_VSIZE = 10000;
25
+ static readonly TRUC_CHILD_MAX_VSIZE = 1000;
23
26
  version: number;
24
27
  locktime: number;
25
28
  ins: Input[];
@@ -443,3 +443,6 @@ Transaction.SIGHASH_OUTPUT_MASK = 0x03;
443
443
  Transaction.SIGHASH_INPUT_MASK = 0x80;
444
444
  Transaction.ADVANCED_TRANSACTION_MARKER = 0x00;
445
445
  Transaction.ADVANCED_TRANSACTION_FLAG = 0x01;
446
+ Transaction.TRUC_VERSION = 3;
447
+ Transaction.TRUC_MAX_VSIZE = 10000;
448
+ Transaction.TRUC_CHILD_MAX_VSIZE = 1000;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@btc-vision/bitcoin",
3
3
  "type": "module",
4
- "version": "6.4.5",
4
+ "version": "6.4.7",
5
5
  "description": "Client-side Bitcoin JavaScript library",
6
6
  "engines": {
7
7
  "node": ">=16.0.0"
package/src/address.ts CHANGED
@@ -33,19 +33,39 @@ export interface Bech32Result {
33
33
  data: Buffer;
34
34
  }
35
35
 
36
- const FUTURE_SEGWIT_MAX_SIZE: number = 40;
37
- const FUTURE_SEGWIT_MIN_SIZE: number = 2;
38
- const FUTURE_SEGWIT_MAX_VERSION: number = 15;
39
- const FUTURE_MAX_VERSION: number = 16;
40
- const FUTURE_OPNET_VERSION: number = 16;
41
- const FUTURE_SEGWIT_MIN_VERSION: number = 2;
42
- const FUTURE_SEGWIT_VERSION_DIFF: number = 0x50;
36
+ export const FUTURE_SEGWIT_MAX_SIZE: number = 40;
37
+ export const FUTURE_SEGWIT_MIN_SIZE: number = 2;
38
+ export const FUTURE_SEGWIT_MAX_VERSION: number = 15;
39
+ export const FUTURE_MAX_VERSION: number = 16;
40
+ export const FUTURE_OPNET_VERSION: number = 16;
41
+ export const FUTURE_SEGWIT_MIN_VERSION: number = 2;
42
+ export const FUTURE_SEGWIT_VERSION_DIFF: number = 0x50;
43
43
  const FUTURE_SEGWIT_VERSION_WARNING: string =
44
44
  'WARNING: Sending to a future segwit version address can lead to loss of funds. ' +
45
45
  'End users MUST be warned carefully in the GUI and asked if they wish to proceed ' +
46
46
  'with caution. Wallets should verify the segwit version from the output of fromBech32, ' +
47
47
  'then decide when it is safe to use which version of segwit.';
48
48
 
49
+ export const isUnknownSegwitVersion = (output: Buffer): boolean => {
50
+ try {
51
+ const data = output.subarray(2);
52
+ if (data.length < FUTURE_SEGWIT_MIN_SIZE || data.length > FUTURE_SEGWIT_MAX_SIZE) {
53
+ throw new TypeError('Invalid program length for segwit address');
54
+ }
55
+
56
+ const version = output[0] - FUTURE_SEGWIT_VERSION_DIFF;
57
+ if (version < FUTURE_SEGWIT_MIN_VERSION || version > FUTURE_SEGWIT_MAX_VERSION + 1) {
58
+ throw new TypeError('Invalid version for segwit address');
59
+ }
60
+
61
+ if (version === 1) throw new TypeError('taproot');
62
+
63
+ return true;
64
+ } catch (e) {}
65
+
66
+ return false;
67
+ };
68
+
49
69
  /**
50
70
  * Encode a future Taproot-style segwit address (SegWit v2 - v16) using bech32m.
51
71
  * Only for versions not yet assigned specific meanings (future use).
@@ -92,7 +112,7 @@ export function toFutureOPNetAddress(output: Buffer, network: Network): string {
92
112
  return bech32m.encode(network.bech32Opnet, words);
93
113
  }
94
114
 
95
- function _toFutureSegwitAddress(output: Buffer, network: Network): string {
115
+ export function _toFutureSegwitAddress(output: Buffer, network: Network): string {
96
116
  const data = output.subarray(2);
97
117
  if (data.length < FUTURE_SEGWIT_MIN_SIZE || data.length > FUTURE_SEGWIT_MAX_SIZE) {
98
118
  throw new TypeError('Invalid program length for segwit address');