@vbyte/btc-dev 1.0.11 → 1.0.12
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/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/lib/sighash/segwit.d.ts +4 -1
- package/dist/lib/sighash/segwit.js +6 -6
- package/dist/lib/sighash/taproot.d.ts +7 -6
- package/dist/lib/sighash/taproot.js +24 -53
- package/dist/lib/sighash/util.d.ts +4 -2
- package/dist/lib/sighash/util.js +16 -2
- package/dist/lib/signer/sign.js +8 -5
- package/dist/lib/signer/verify.d.ts +1 -2
- package/dist/lib/signer/verify.js +1 -5
- package/dist/lib/tx/create.d.ts +7 -6
- package/dist/lib/tx/create.js +25 -27
- package/dist/lib/tx/decode.d.ts +4 -9
- package/dist/lib/tx/decode.js +16 -28
- package/dist/lib/tx/encode.d.ts +1 -1
- package/dist/lib/tx/encode.js +6 -6
- package/dist/lib/tx/parse.d.ts +3 -2
- package/dist/lib/tx/parse.js +38 -5
- package/dist/lib/tx/util.d.ts +8 -4
- package/dist/lib/tx/util.js +39 -15
- package/dist/lib/tx/validate.d.ts +4 -2
- package/dist/lib/tx/validate.js +9 -2
- package/dist/main.cjs +4049 -4230
- package/dist/main.cjs.map +1 -1
- package/dist/module.mjs +4040 -4216
- package/dist/module.mjs.map +1 -1
- package/dist/package.json +2 -2
- package/dist/schema/taproot.d.ts +2 -2
- package/dist/schema/tx.d.ts +53 -40
- package/dist/schema/tx.js +9 -6
- package/dist/script.js +8 -8
- package/dist/script.js.map +1 -1
- package/dist/types/txdata.d.ts +28 -5
- package/package.json +2 -2
- package/src/index.ts +0 -2
- package/src/lib/sighash/segwit.ts +6 -6
- package/src/lib/sighash/taproot.ts +40 -70
- package/src/lib/sighash/util.ts +25 -3
- package/src/lib/signer/sign.ts +9 -5
- package/src/lib/signer/verify.ts +1 -18
- package/src/lib/tx/create.ts +44 -36
- package/src/lib/tx/decode.ts +23 -45
- package/src/lib/tx/encode.ts +10 -9
- package/src/lib/tx/parse.ts +61 -8
- package/src/lib/tx/util.ts +57 -20
- package/src/lib/tx/validate.ts +15 -2
- package/src/schema/tx.ts +10 -6
- package/src/types/txdata.ts +32 -5
- package/dist/class/index.d.ts +0 -5
- package/dist/class/index.js +0 -5
- package/dist/class/signer.d.ts +0 -18
- package/dist/class/signer.js +0 -34
- package/dist/class/tx.d.ts +0 -40
- package/dist/class/tx.js +0 -96
- package/dist/class/txin.d.ts +0 -29
- package/dist/class/txin.js +0 -62
- package/dist/class/txout.d.ts +0 -19
- package/dist/class/txout.js +0 -37
- package/dist/class/witness.d.ts +0 -18
- package/dist/class/witness.js +0 -46
- package/src/class/index.ts +0 -5
- package/src/class/signer.ts +0 -49
- package/src/class/tx.ts +0 -136
- package/src/class/txin.ts +0 -89
- package/src/class/txout.ts +0 -61
- package/src/class/witness.ts +0 -75
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
1
|
import { Buff } from '@vbyte/buff';
|
|
2
|
-
import { SigHashOptions, TxData } from '../../types/index.js';
|
|
2
|
+
import { SigHashOptions, TxData, TxInput, TxOutput } from '../../types/index.js';
|
|
3
3
|
export declare function hash_segwit_tx(txdata: TxData, options?: SigHashOptions): Buff;
|
|
4
|
+
export declare function bip143_hash_prevouts(vin: TxInput[], isAnypay?: boolean): Uint8Array;
|
|
5
|
+
export declare function bip143_hash_sequence(vin: TxInput[], sigflag: number, isAnyPay: boolean): Uint8Array;
|
|
6
|
+
export declare function bip143_hash_outputs(vout: TxOutput[], sigflag: number, idx?: number): Uint8Array;
|
|
@@ -33,20 +33,20 @@ export function hash_segwit_tx(txdata, options = {}) {
|
|
|
33
33
|
}
|
|
34
34
|
const sighash = [
|
|
35
35
|
encode_tx_version(version),
|
|
36
|
-
|
|
37
|
-
|
|
36
|
+
bip143_hash_prevouts(vin, is_anypay),
|
|
37
|
+
bip143_hash_sequence(vin, flag, is_anypay),
|
|
38
38
|
encode_txin_txid(txid),
|
|
39
39
|
encode_txin_vout(prevIdx),
|
|
40
40
|
prefix_script_size(script),
|
|
41
41
|
encode_vout_value(value),
|
|
42
42
|
encode_txin_sequence(sequence),
|
|
43
|
-
|
|
43
|
+
bip143_hash_outputs(vout, flag, txindex),
|
|
44
44
|
encode_tx_locktime(locktime),
|
|
45
45
|
Buff.num(sigflag, 4).reverse()
|
|
46
46
|
];
|
|
47
47
|
return hash256(Buff.join(sighash));
|
|
48
48
|
}
|
|
49
|
-
function
|
|
49
|
+
export function bip143_hash_prevouts(vin, isAnypay) {
|
|
50
50
|
if (isAnypay === true) {
|
|
51
51
|
return Buff.num(0, 32);
|
|
52
52
|
}
|
|
@@ -57,7 +57,7 @@ function hash_prevouts(vin, isAnypay) {
|
|
|
57
57
|
}
|
|
58
58
|
return hash256(Buff.join(stack));
|
|
59
59
|
}
|
|
60
|
-
function
|
|
60
|
+
export function bip143_hash_sequence(vin, sigflag, isAnyPay) {
|
|
61
61
|
if (isAnyPay || sigflag !== 0x01) {
|
|
62
62
|
return Buff.num(0, 32);
|
|
63
63
|
}
|
|
@@ -67,7 +67,7 @@ function hash_sequence(vin, sigflag, isAnyPay) {
|
|
|
67
67
|
}
|
|
68
68
|
return hash256(Buff.join(stack));
|
|
69
69
|
}
|
|
70
|
-
function
|
|
70
|
+
export function bip143_hash_outputs(vout, sigflag, idx) {
|
|
71
71
|
const stack = [];
|
|
72
72
|
if (sigflag === 0x01) {
|
|
73
73
|
for (const { value, script_pk } of vout) {
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { Buff } from '@vbyte/buff';
|
|
2
2
|
import type { SigHashOptions, TxData, TxInput, TxOutput } from '../../types/index.js';
|
|
3
3
|
export declare function hash_taproot_tx(template: TxData | string, config?: SigHashOptions): Buff;
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
7
|
-
export declare function
|
|
8
|
-
export declare function
|
|
9
|
-
export declare function
|
|
4
|
+
export declare function get_taproot_tx_preimage(template: TxData | string, config?: SigHashOptions): Buff;
|
|
5
|
+
export declare function bip341_hash_outpoints(vin: TxInput[]): Buff;
|
|
6
|
+
export declare function bip341_hash_sequence(vin: TxInput[]): Buff;
|
|
7
|
+
export declare function bip341_hash_amounts(prevouts: TxOutput[]): Buff;
|
|
8
|
+
export declare function bip341_hash_scripts(prevouts: TxOutput[]): Buff;
|
|
9
|
+
export declare function bip341_hash_outputs(vout: TxOutput[]): Buff;
|
|
10
|
+
export declare function bip341_hash_output(vout: TxOutput): Buff;
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
import { Buff } from '@vbyte/buff';
|
|
2
2
|
import { Assert } from '@vbyte/micro-lib';
|
|
3
3
|
import { hash340, sha256 } from '@vbyte/micro-lib/hash';
|
|
4
|
-
import { prefix_script_size } from '../../lib/script/util.js';
|
|
5
4
|
import { encode_tapscript } from '../../lib/taproot/encode.js';
|
|
6
5
|
import { parse_tx } from '../../lib/tx/parse.js';
|
|
7
6
|
import * as CONST from '../../const.js';
|
|
8
|
-
import { parse_txinput } from './util.js';
|
|
9
|
-
import { encode_txin_vout, encode_tx_locktime, encode_txin_sequence, encode_txin_txid, encode_vout_value, encode_tx_version } from '../../lib/tx/encode.js';
|
|
7
|
+
import { parse_txinput, get_annex_data, get_prevout } from './util.js';
|
|
8
|
+
import { encode_txin_vout, encode_tx_locktime, encode_txin_sequence, encode_txin_txid, encode_vout_value, encode_tx_version, encode_script_data } from '../../lib/tx/encode.js';
|
|
10
9
|
export function hash_taproot_tx(template, config = {}) {
|
|
10
|
+
const preimage = get_taproot_tx_preimage(template, config);
|
|
11
|
+
return hash340('TapSighash', preimage);
|
|
12
|
+
}
|
|
13
|
+
export function get_taproot_tx_preimage(template, config = {}) {
|
|
11
14
|
const { script, txindex, sigflag = 0x00, extflag = 0x00, key_version = 0x00, separator_pos = 0xFFFFFFFF } = config;
|
|
12
15
|
const tx = parse_tx(template);
|
|
13
16
|
const { version, vin: input, vout: output, locktime } = tx;
|
|
@@ -28,9 +31,7 @@ export function hash_taproot_tx(template, config = {}) {
|
|
|
28
31
|
const annexBit = (annex !== undefined) ? 1 : 0;
|
|
29
32
|
const extendBit = (extension !== undefined) ? 1 : 0;
|
|
30
33
|
const spendType = ((extflag + extendBit) * 2) + annexBit;
|
|
31
|
-
const hashtag = hash340('TapSighash');
|
|
32
34
|
const preimage = [
|
|
33
|
-
hashtag,
|
|
34
35
|
Buff.num(0x00, 1),
|
|
35
36
|
Buff.num(sigflag, 1),
|
|
36
37
|
encode_tx_version(version),
|
|
@@ -38,15 +39,15 @@ export function hash_taproot_tx(template, config = {}) {
|
|
|
38
39
|
];
|
|
39
40
|
if (!is_anypay) {
|
|
40
41
|
const prevouts = input.map(e => get_prevout(e));
|
|
41
|
-
preimage.push(
|
|
42
|
+
preimage.push(bip341_hash_outpoints(input), bip341_hash_amounts(prevouts), bip341_hash_scripts(prevouts), bip341_hash_sequence(input));
|
|
42
43
|
}
|
|
43
44
|
if ((sigflag & 0x03) < 2 || (sigflag & 0x03) > 3) {
|
|
44
|
-
preimage.push(
|
|
45
|
+
preimage.push(bip341_hash_outputs(output));
|
|
45
46
|
}
|
|
46
47
|
preimage.push(Buff.num(spendType, 1));
|
|
47
48
|
if (is_anypay) {
|
|
48
49
|
const { value, script_pk } = get_prevout(txinput);
|
|
49
|
-
preimage.push(encode_txin_txid(txid), encode_txin_vout(vout), encode_vout_value(value),
|
|
50
|
+
preimage.push(encode_txin_txid(txid), encode_txin_vout(vout), encode_vout_value(value), encode_script_data(script_pk), encode_txin_sequence(sequence));
|
|
50
51
|
}
|
|
51
52
|
else {
|
|
52
53
|
Assert.ok(typeof txindex === 'number');
|
|
@@ -57,14 +58,14 @@ export function hash_taproot_tx(template, config = {}) {
|
|
|
57
58
|
}
|
|
58
59
|
if ((sigflag & 0x03) === 0x03) {
|
|
59
60
|
Assert.ok(typeof txindex === 'number');
|
|
60
|
-
preimage.push(
|
|
61
|
+
preimage.push(bip341_hash_output(output[txindex]));
|
|
61
62
|
}
|
|
62
63
|
if (extension !== undefined) {
|
|
63
|
-
preimage.push(Buff.bytes(extension), Buff.num(key_version), Buff.num(separator_pos, 4));
|
|
64
|
+
preimage.push(Buff.bytes(extension), Buff.num(key_version), Buff.num(separator_pos, 4, 'le'));
|
|
64
65
|
}
|
|
65
|
-
return
|
|
66
|
+
return Buff.join(preimage);
|
|
66
67
|
}
|
|
67
|
-
export function
|
|
68
|
+
export function bip341_hash_outpoints(vin) {
|
|
68
69
|
const stack = [];
|
|
69
70
|
for (const { txid, vout } of vin) {
|
|
70
71
|
stack.push(encode_txin_txid(txid));
|
|
@@ -72,53 +73,23 @@ export function hash_outpoints(vin) {
|
|
|
72
73
|
}
|
|
73
74
|
return sha256(Buff.join(stack));
|
|
74
75
|
}
|
|
75
|
-
export function
|
|
76
|
-
|
|
77
|
-
for (const { sequence } of vin) {
|
|
78
|
-
stack.push(encode_txin_sequence(sequence));
|
|
79
|
-
}
|
|
80
|
-
return sha256(Buff.join(stack));
|
|
76
|
+
export function bip341_hash_sequence(vin) {
|
|
77
|
+
return sha256(...vin.map(vin => encode_txin_sequence(vin.sequence)));
|
|
81
78
|
}
|
|
82
|
-
export function
|
|
83
|
-
|
|
84
|
-
for (const { value } of prevouts) {
|
|
85
|
-
stack.push(encode_vout_value(value));
|
|
86
|
-
}
|
|
87
|
-
return sha256(Buff.join(stack));
|
|
79
|
+
export function bip341_hash_amounts(prevouts) {
|
|
80
|
+
return sha256(...prevouts.map(prevout => encode_vout_value(prevout.value)));
|
|
88
81
|
}
|
|
89
|
-
export function
|
|
90
|
-
|
|
91
|
-
for (const { script_pk } of prevouts) {
|
|
92
|
-
stack.push(prefix_script_size(script_pk));
|
|
93
|
-
}
|
|
94
|
-
return sha256(Buff.join(stack));
|
|
82
|
+
export function bip341_hash_scripts(prevouts) {
|
|
83
|
+
return sha256(...prevouts.map(prevout => encode_script_data(prevout.script_pk)));
|
|
95
84
|
}
|
|
96
|
-
export function
|
|
85
|
+
export function bip341_hash_outputs(vout) {
|
|
97
86
|
const stack = [];
|
|
98
87
|
for (const { value, script_pk } of vout) {
|
|
99
88
|
stack.push(encode_vout_value(value));
|
|
100
|
-
stack.push(
|
|
101
|
-
}
|
|
102
|
-
return sha256(Buff.join(stack));
|
|
103
|
-
}
|
|
104
|
-
export function hash_output(vout) {
|
|
105
|
-
return sha256(encode_vout_value(vout.value), prefix_script_size(vout.script_pk));
|
|
106
|
-
}
|
|
107
|
-
function get_annex_data(witness) {
|
|
108
|
-
if (witness === undefined)
|
|
109
|
-
return;
|
|
110
|
-
if (witness.length < 2)
|
|
111
|
-
return;
|
|
112
|
-
const annex = witness.at(-1);
|
|
113
|
-
if (typeof annex === 'string' && annex.startsWith('50')) {
|
|
114
|
-
const bytes = Buff.hex(annex).prefix_varint('be');
|
|
115
|
-
return sha256(bytes);
|
|
89
|
+
stack.push(encode_script_data(script_pk));
|
|
116
90
|
}
|
|
117
|
-
return
|
|
91
|
+
return sha256(...stack);
|
|
118
92
|
}
|
|
119
|
-
function
|
|
120
|
-
|
|
121
|
-
throw new Error('Prevout data missing for input: ' + String(vin.txid));
|
|
122
|
-
}
|
|
123
|
-
return vin.prevout;
|
|
93
|
+
export function bip341_hash_output(vout) {
|
|
94
|
+
return sha256(encode_vout_value(vout.value), encode_script_data(vout.script_pk));
|
|
124
95
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { Buff } from '@vbyte/buff';
|
|
2
|
+
import type { SigHashOptions, TxInput, TxData, TxOutput } from '../../types/index.js';
|
|
3
|
+
export declare function get_prevout(vin: TxInput): TxOutput;
|
|
2
4
|
export declare function parse_txinput(txdata: TxData, config?: SigHashOptions): TxInput;
|
|
3
|
-
export declare function
|
|
5
|
+
export declare function get_annex_data(witness?: string[]): Buff | undefined;
|
package/dist/lib/sighash/util.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { Buff } from '@vbyte/buff';
|
|
2
2
|
import { Assert } from '@vbyte/micro-lib';
|
|
3
|
+
import { sha256 } from '@vbyte/micro-lib/hash';
|
|
4
|
+
export function get_prevout(vin) {
|
|
5
|
+
Assert.exists(vin.prevout, 'Prevout data missing for input: ' + String(vin.txid));
|
|
6
|
+
return vin.prevout;
|
|
7
|
+
}
|
|
3
8
|
export function parse_txinput(txdata, config) {
|
|
4
9
|
let { txindex, txinput } = config ?? {};
|
|
5
10
|
if (txindex !== undefined) {
|
|
@@ -11,6 +16,15 @@ export function parse_txinput(txdata, config) {
|
|
|
11
16
|
Assert.ok(txinput !== undefined);
|
|
12
17
|
return txinput;
|
|
13
18
|
}
|
|
14
|
-
export function
|
|
15
|
-
|
|
19
|
+
export function get_annex_data(witness) {
|
|
20
|
+
if (witness === undefined)
|
|
21
|
+
return;
|
|
22
|
+
if (witness.length < 2)
|
|
23
|
+
return;
|
|
24
|
+
const annex = witness.at(-1);
|
|
25
|
+
if (typeof annex === 'string' && annex.startsWith('50')) {
|
|
26
|
+
const bytes = Buff.hex(annex).prefix_varint('be');
|
|
27
|
+
return sha256(bytes);
|
|
28
|
+
}
|
|
29
|
+
return undefined;
|
|
16
30
|
}
|
package/dist/lib/signer/sign.js
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
|
+
import { Buff } from '@vbyte/buff';
|
|
1
2
|
import { ECC } from '@vbyte/micro-lib';
|
|
2
3
|
import { parse_tx } from '../../lib/tx/parse.js';
|
|
3
4
|
import { SIGHASH_DEFAULT } from '../../const.js';
|
|
4
|
-
import { hash_segwit_tx } from '
|
|
5
|
-
import { hash_taproot_tx } from '
|
|
6
|
-
import { format_sigflag } from '../sighash/util.js';
|
|
5
|
+
import { hash_segwit_tx } from '../../lib/sighash/segwit.js';
|
|
6
|
+
import { hash_taproot_tx } from '../../lib/sighash/taproot.js';
|
|
7
7
|
export function sign_segwit_tx(seckey, txdata, options) {
|
|
8
8
|
const tx = parse_tx(txdata);
|
|
9
9
|
const msg = hash_segwit_tx(tx, options);
|
|
10
|
-
const sig = ECC.
|
|
10
|
+
const sig = ECC.get_ecdsa_sig(seckey, msg).hex;
|
|
11
11
|
const flag = format_sigflag(options.sigflag ?? SIGHASH_DEFAULT);
|
|
12
12
|
return sig + flag;
|
|
13
13
|
}
|
|
14
14
|
export function sign_taproot_tx(seckey, txdata, options) {
|
|
15
15
|
const tx = parse_tx(txdata);
|
|
16
16
|
const msg = hash_taproot_tx(tx, options);
|
|
17
|
-
const sig = ECC.
|
|
17
|
+
const sig = ECC.get_bip340_sig(seckey, msg).hex;
|
|
18
18
|
const flag = format_sigflag(options.sigflag ?? 0);
|
|
19
19
|
return sig + flag;
|
|
20
20
|
}
|
|
21
|
+
function format_sigflag(flag) {
|
|
22
|
+
return (flag !== 0) ? Buff.num(flag, 1).hex : '';
|
|
23
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
1
|
import { Bytes } from '@vbyte/buff';
|
|
2
2
|
import type { SigHashOptions, TxData } from '../../types/index.js';
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function verify_taproot_tx(_txdata: TxData | Bytes, _config?: SigHashOptions): boolean;
|
|
3
|
+
export declare function verify_tx(_txdata: TxData | Bytes, _config?: SigHashOptions): boolean;
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function verify_tx(_txdata, _config = {}) {
|
|
2
2
|
console.warn('verify_segwit_tx is not implemented');
|
|
3
3
|
return true;
|
|
4
4
|
}
|
|
5
|
-
export function verify_taproot_tx(_txdata, _config = {}) {
|
|
6
|
-
console.warn('verify_taproot_tx is not implemented');
|
|
7
|
-
return true;
|
|
8
|
-
}
|
package/dist/lib/tx/create.d.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { TxData,
|
|
2
|
-
export declare function create_coinbase_input(config:
|
|
3
|
-
export declare function
|
|
4
|
-
export declare function
|
|
5
|
-
export declare function
|
|
6
|
-
export declare function
|
|
1
|
+
import type { TxData, TxInput, TxOutput, TxTemplate, TxSpendInput, TxCoinbaseInput, TxOutputTemplate, TxVirtualInput, TxInputConfig } from '../../types/index.js';
|
|
2
|
+
export declare function create_coinbase_input(config: TxInputConfig): TxCoinbaseInput;
|
|
3
|
+
export declare function create_virtual_input(config: TxInputConfig): TxVirtualInput;
|
|
4
|
+
export declare function create_spend_input(config: TxInputConfig): TxSpendInput;
|
|
5
|
+
export declare function create_tx_input(config: TxInputConfig): TxInput;
|
|
6
|
+
export declare function create_tx_output(config: TxOutputTemplate): TxOutput;
|
|
7
|
+
export declare function create_tx(config?: Partial<TxTemplate>): TxData;
|
package/dist/lib/tx/create.js
CHANGED
|
@@ -1,49 +1,47 @@
|
|
|
1
1
|
import { Assert } from '@vbyte/micro-lib';
|
|
2
2
|
import { COINBASE, DEFAULT } from '../../const.js';
|
|
3
|
-
import {
|
|
3
|
+
import { normalize_prevout, normalize_sequence, normalize_value } from './util.js';
|
|
4
|
+
import { assert_tx_template, assert_vin_template, assert_vout_template } from './validate.js';
|
|
4
5
|
export function create_coinbase_input(config) {
|
|
5
6
|
assert_vin_template(config);
|
|
6
7
|
Assert.exists(config.coinbase, 'coinbase is required');
|
|
7
|
-
const coinbase = config.coinbase;
|
|
8
|
-
const prevout = null;
|
|
9
|
-
const script_sig = null;
|
|
10
|
-
const sequence = config.sequence ?? DEFAULT.SEQUENCE;
|
|
11
8
|
const txid = COINBASE.TXID;
|
|
12
9
|
const vout = COINBASE.VOUT;
|
|
10
|
+
const coinbase = config.coinbase;
|
|
13
11
|
const witness = config.witness ?? [];
|
|
14
|
-
|
|
12
|
+
const sequence = normalize_sequence(config.sequence);
|
|
13
|
+
return { coinbase, prevout: null, script_sig: null, sequence, witness, txid, vout };
|
|
14
|
+
}
|
|
15
|
+
export function create_virtual_input(config) {
|
|
16
|
+
assert_vin_template(config);
|
|
17
|
+
Assert.is_empty(config.coinbase, 'coinbase is not allowed');
|
|
18
|
+
Assert.is_empty(config.prevout, 'prevout is not allowed');
|
|
19
|
+
const { txid, vout, script_sig = null, witness = [] } = config;
|
|
20
|
+
const sequence = normalize_sequence(config.sequence);
|
|
21
|
+
return { txid, vout, coinbase: null, prevout: null, script_sig, sequence, witness };
|
|
15
22
|
}
|
|
16
23
|
export function create_spend_input(config) {
|
|
17
24
|
assert_vin_template(config);
|
|
18
25
|
Assert.exists(config.prevout, 'prevout is required');
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
23
|
-
const witness = config.witness ?? [];
|
|
24
|
-
return { ...config, coinbase, prevout, script_sig, sequence, witness };
|
|
26
|
+
const { txid, vout, script_sig = null, witness = [] } = config;
|
|
27
|
+
const prevout = normalize_prevout(config.prevout);
|
|
28
|
+
const sequence = normalize_sequence(config.sequence);
|
|
29
|
+
return { txid, vout, coinbase: null, prevout, script_sig, sequence, witness };
|
|
25
30
|
}
|
|
26
31
|
export function create_tx_input(config) {
|
|
27
|
-
|
|
28
|
-
Assert.exists(config.txid, 'txid is required');
|
|
29
|
-
Assert.exists(config.vout, 'vout is required');
|
|
30
|
-
const coinbase = config.coinbase ?? null;
|
|
31
|
-
const prevout = config.prevout ?? null;
|
|
32
|
-
const script_sig = config.script_sig ?? null;
|
|
33
|
-
const sequence = config.sequence ?? DEFAULT.SEQUENCE;
|
|
34
|
-
const witness = config.witness ?? [];
|
|
35
|
-
if (coinbase !== null)
|
|
32
|
+
if (config.coinbase)
|
|
36
33
|
return create_coinbase_input(config);
|
|
37
|
-
if (prevout
|
|
34
|
+
if (config.prevout)
|
|
38
35
|
return create_spend_input(config);
|
|
39
|
-
return
|
|
36
|
+
return create_virtual_input(config);
|
|
40
37
|
}
|
|
41
38
|
export function create_tx_output(config) {
|
|
42
|
-
|
|
43
|
-
const
|
|
44
|
-
|
|
39
|
+
assert_vout_template(config);
|
|
40
|
+
const script_pk = config.script_pk;
|
|
41
|
+
const value = normalize_value(config.value);
|
|
42
|
+
return { script_pk, value };
|
|
45
43
|
}
|
|
46
|
-
export function create_tx(config) {
|
|
44
|
+
export function create_tx(config = {}) {
|
|
47
45
|
assert_tx_template(config);
|
|
48
46
|
const { vin = [], vout = [] } = config;
|
|
49
47
|
const locktime = config.locktime ?? DEFAULT.LOCKTIME;
|
package/dist/lib/tx/decode.d.ts
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
segwit: boolean;
|
|
6
|
-
}
|
|
7
|
-
export declare function decode_tx(txbytes: Bytes, options?: Partial<TxEncoderConfig>): TxData;
|
|
8
|
-
export declare function read_script(stream: Stream, varint?: boolean): string | null;
|
|
9
|
-
export {};
|
|
1
|
+
import { Stream } from '@vbyte/buff';
|
|
2
|
+
import { TxDecodedData } from '../../types/index.js';
|
|
3
|
+
export declare function decode_tx(txdata: string | Uint8Array, use_segwit?: boolean): TxDecodedData;
|
|
4
|
+
export declare function read_payload(stream: Stream): string | null;
|
package/dist/lib/tx/decode.js
CHANGED
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
import { Stream } from '@vbyte/buff';
|
|
2
|
-
import { Assert } from '@vbyte/micro-lib';
|
|
2
|
+
import { Assert } from '@vbyte/micro-lib/assert';
|
|
3
3
|
import { parse_error } from '@vbyte/micro-lib/util';
|
|
4
4
|
import { COINBASE } from '../../const.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
};
|
|
9
|
-
export function decode_tx(txbytes, options = {}) {
|
|
10
|
-
const config = { ...DEFAULT_CONFIG, ...options };
|
|
11
|
-
Assert.is_bytes(txbytes, 'transaction must be hex or a byte-array');
|
|
12
|
-
const stream = new Stream(txbytes);
|
|
5
|
+
export function decode_tx(txdata, use_segwit = true) {
|
|
6
|
+
Assert.is_bytes(txdata, 'txdata must be hex or bytes');
|
|
7
|
+
const stream = new Stream(txdata);
|
|
13
8
|
const version = read_version(stream);
|
|
14
|
-
const has_witness = (
|
|
9
|
+
const has_witness = (use_segwit)
|
|
15
10
|
? check_witness_flag(stream)
|
|
16
11
|
: false;
|
|
17
|
-
const vin = read_inputs(stream
|
|
12
|
+
const vin = read_inputs(stream);
|
|
18
13
|
const vout = read_outputs(stream);
|
|
19
14
|
if (has_witness) {
|
|
20
15
|
for (const txin of vin) {
|
|
@@ -40,29 +35,26 @@ function check_witness_flag(stream) {
|
|
|
40
35
|
}
|
|
41
36
|
return false;
|
|
42
37
|
}
|
|
43
|
-
function read_inputs(stream
|
|
38
|
+
function read_inputs(stream) {
|
|
44
39
|
const inputs = [];
|
|
45
40
|
const vinCount = stream.varint();
|
|
46
41
|
for (let i = 0; i < vinCount; i++) {
|
|
47
|
-
const txinput = read_vin(stream
|
|
42
|
+
const txinput = read_vin(stream);
|
|
48
43
|
inputs.push(txinput);
|
|
49
44
|
}
|
|
50
45
|
return inputs;
|
|
51
46
|
}
|
|
52
|
-
function read_vin(stream
|
|
47
|
+
function read_vin(stream) {
|
|
53
48
|
const txid = stream.read(32).reverse().hex;
|
|
54
49
|
const vout = stream.read(4).reverse().num;
|
|
55
|
-
const script_sig =
|
|
50
|
+
const script_sig = read_payload(stream);
|
|
56
51
|
const sequence = stream.read(4).reverse().num;
|
|
57
52
|
const witness = [];
|
|
58
53
|
if (txid === COINBASE.TXID && vout === COINBASE.VOUT) {
|
|
59
54
|
return { coinbase: script_sig, prevout: null, script_sig: null, sequence, txid, vout, witness };
|
|
60
55
|
}
|
|
61
|
-
else if (prevout !== null) {
|
|
62
|
-
return { coinbase: null, prevout, script_sig, sequence, txid, vout, witness };
|
|
63
|
-
}
|
|
64
56
|
else {
|
|
65
|
-
return { coinbase: null, prevout, script_sig, sequence, txid, vout, witness };
|
|
57
|
+
return { coinbase: null, prevout: null, script_sig, sequence, txid, vout, witness };
|
|
66
58
|
}
|
|
67
59
|
}
|
|
68
60
|
function read_outputs(stream) {
|
|
@@ -80,7 +72,7 @@ function read_outputs(stream) {
|
|
|
80
72
|
}
|
|
81
73
|
function read_vout(stream) {
|
|
82
74
|
const value = stream.read(8).reverse().big;
|
|
83
|
-
const script_pk =
|
|
75
|
+
const script_pk = read_payload(stream);
|
|
84
76
|
Assert.exists(script_pk, 'failed to decode script_pk');
|
|
85
77
|
return { value, script_pk };
|
|
86
78
|
}
|
|
@@ -88,7 +80,7 @@ function read_witness(stream) {
|
|
|
88
80
|
const stack = [];
|
|
89
81
|
const count = stream.varint();
|
|
90
82
|
for (let i = 0; i < count; i++) {
|
|
91
|
-
const element =
|
|
83
|
+
const element = read_payload(stream);
|
|
92
84
|
if (element === null) {
|
|
93
85
|
throw new Error('failed to decode witness element: ' + i);
|
|
94
86
|
}
|
|
@@ -96,13 +88,9 @@ function read_witness(stream) {
|
|
|
96
88
|
}
|
|
97
89
|
return stack;
|
|
98
90
|
}
|
|
99
|
-
export function
|
|
100
|
-
const size = (
|
|
101
|
-
|
|
102
|
-
: stream.size;
|
|
103
|
-
return size > 0
|
|
104
|
-
? stream.read(size).hex
|
|
105
|
-
: null;
|
|
91
|
+
export function read_payload(stream) {
|
|
92
|
+
const size = stream.varint('le');
|
|
93
|
+
return (size > 0) ? stream.read(size).hex : null;
|
|
106
94
|
}
|
|
107
95
|
function read_locktime(stream) {
|
|
108
96
|
return stream.read(4).reverse().to_num();
|
package/dist/lib/tx/encode.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Buff } from '@vbyte/buff';
|
|
2
2
|
import { TxInput, TxOutput, TxData } from '../../types/index.js';
|
|
3
|
-
export declare function encode_tx(txdata: TxData,
|
|
3
|
+
export declare function encode_tx(txdata: TxData, use_segwit?: boolean): Buff;
|
|
4
4
|
export declare function encode_tx_version(num: number): Buff;
|
|
5
5
|
export declare function encode_txin_txid(txid: string): Buff;
|
|
6
6
|
export declare function encode_txin_vout(vout: number): Buff;
|
package/dist/lib/tx/encode.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { Buff } from '@vbyte/buff';
|
|
2
2
|
import { Assert } from '@vbyte/micro-lib';
|
|
3
|
-
import {
|
|
3
|
+
import { assert_tx_data } from './validate.js';
|
|
4
4
|
import { COINBASE } from '../../const.js';
|
|
5
|
-
export function encode_tx(txdata,
|
|
6
|
-
|
|
7
|
-
const { version, vin, vout, locktime } =
|
|
5
|
+
export function encode_tx(txdata, use_segwit = true) {
|
|
6
|
+
assert_tx_data(txdata);
|
|
7
|
+
const { version, vin, vout, locktime } = txdata;
|
|
8
8
|
const buffer = [encode_tx_version(version)];
|
|
9
|
-
if (
|
|
9
|
+
if (use_segwit) {
|
|
10
10
|
buffer.push(Buff.hex('0001'));
|
|
11
11
|
}
|
|
12
12
|
buffer.push(encode_tx_inputs(vin));
|
|
13
13
|
buffer.push(encode_tx_outputs(vout));
|
|
14
|
-
if (
|
|
14
|
+
if (use_segwit) {
|
|
15
15
|
for (const input of vin) {
|
|
16
16
|
buffer.push(encode_vin_witness(input.witness));
|
|
17
17
|
}
|
package/dist/lib/tx/parse.d.ts
CHANGED
|
@@ -1,2 +1,3 @@
|
|
|
1
|
-
import type { TxData } from '../../types/index.js';
|
|
2
|
-
export declare function parse_tx(txdata: unknown): TxData;
|
|
1
|
+
import type { TxData, TxOutputTemplate } from '../../types/index.js';
|
|
2
|
+
export declare function parse_tx(txdata: unknown, prevouts?: TxOutputTemplate[]): TxData;
|
|
3
|
+
export declare function serialize_tx(txdata: unknown): Record<string, unknown>;
|
package/dist/lib/tx/parse.js
CHANGED
|
@@ -1,12 +1,45 @@
|
|
|
1
|
+
import { Assert } from '@vbyte/micro-lib/assert';
|
|
1
2
|
import { decode_tx } from './decode.js';
|
|
2
|
-
import { create_tx } from './create.js';
|
|
3
3
|
import { assert_tx_template } from './validate.js';
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
import { create_tx, create_tx_output } from './create.js';
|
|
5
|
+
export function parse_tx(txdata, prevouts) {
|
|
6
|
+
let tx;
|
|
7
|
+
if (typeof txdata === 'string' || txdata instanceof Uint8Array) {
|
|
8
|
+
tx = decode_tx(txdata);
|
|
7
9
|
}
|
|
8
10
|
else {
|
|
9
11
|
assert_tx_template(txdata);
|
|
10
|
-
|
|
12
|
+
tx = create_tx(txdata);
|
|
11
13
|
}
|
|
14
|
+
if (prevouts) {
|
|
15
|
+
Assert.has_items(prevouts, 'prevouts must be a non-empty array');
|
|
16
|
+
for (const [idx, vin] of tx.vin.entries()) {
|
|
17
|
+
const prevout = prevouts.at(idx);
|
|
18
|
+
Assert.exists(prevout, 'prevout not found for input index: ' + idx);
|
|
19
|
+
vin.prevout = create_tx_output(prevout);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return tx;
|
|
23
|
+
}
|
|
24
|
+
export function serialize_tx(txdata) {
|
|
25
|
+
const tx = parse_tx(txdata);
|
|
26
|
+
const version = tx.version;
|
|
27
|
+
const locktime = tx.locktime;
|
|
28
|
+
const vin = [];
|
|
29
|
+
const vout = [];
|
|
30
|
+
for (const e of tx.vin) {
|
|
31
|
+
if (e.prevout !== null) {
|
|
32
|
+
vin.push({
|
|
33
|
+
script_pk: e.prevout.script_pk,
|
|
34
|
+
value: Number(e.prevout.value)
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
for (const e of tx.vout) {
|
|
39
|
+
vout.push({
|
|
40
|
+
script_pk: e.script_pk,
|
|
41
|
+
value: Number(e.value)
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return { version, locktime, vin, vout };
|
|
12
45
|
}
|
package/dist/lib/tx/util.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import type { TxData, TxOutput, TxOutputInfo, TxOutputType, TxValue, WitnessVersion } from '../../types/index.js';
|
|
1
|
+
import type { TxData, TxOutput, TxOutputInfo, TxOutputTemplate, TxOutputType, TxValue, WitnessVersion } from '../../types/index.js';
|
|
2
2
|
export declare function is_return_script(script: string): boolean;
|
|
3
3
|
export declare function get_vout_info(txout: TxOutput): TxOutputInfo;
|
|
4
4
|
export declare function get_vout_type(script: string): TxOutputType;
|
|
5
5
|
export declare function get_vout_version(script: string): WitnessVersion;
|
|
6
|
-
export declare function get_txid(txdata:
|
|
7
|
-
export declare function get_txhash(txdata:
|
|
8
|
-
export declare function get_tx_value(txdata:
|
|
6
|
+
export declare function get_txid(txdata: TxData): string;
|
|
7
|
+
export declare function get_txhash(txdata: TxData): string;
|
|
8
|
+
export declare function get_tx_value(txdata: TxData): TxValue;
|
|
9
|
+
export declare function get_prevouts(txdata: TxData): TxOutput[];
|
|
10
|
+
export declare function normalize_sequence(sequence?: number | string | null): number;
|
|
11
|
+
export declare function normalize_value(value: number | bigint): bigint;
|
|
12
|
+
export declare function normalize_prevout(prevout: TxOutputTemplate): TxOutput;
|