@vbyte/btc-dev 1.0.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/LICENSE +121 -0
- package/README.md +5 -0
- package/dist/class/index.d.ts +5 -0
- package/dist/class/index.js +5 -0
- package/dist/class/signer.d.ts +18 -0
- package/dist/class/signer.js +32 -0
- package/dist/class/tx.d.ts +38 -0
- package/dist/class/tx.js +73 -0
- package/dist/class/txin.d.ts +29 -0
- package/dist/class/txin.js +68 -0
- package/dist/class/txout.d.ts +18 -0
- package/dist/class/txout.js +38 -0
- package/dist/class/witness.d.ts +20 -0
- package/dist/class/witness.js +57 -0
- package/dist/const.d.ts +22 -0
- package/dist/const.js +36 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +10 -0
- package/dist/lib/address/encode.d.ts +3 -0
- package/dist/lib/address/encode.js +79 -0
- package/dist/lib/address/index.d.ts +20 -0
- package/dist/lib/address/index.js +21 -0
- package/dist/lib/address/p2pkh.d.ts +10 -0
- package/dist/lib/address/p2pkh.js +33 -0
- package/dist/lib/address/p2sh.d.ts +10 -0
- package/dist/lib/address/p2sh.js +33 -0
- package/dist/lib/address/p2tr.d.ts +8 -0
- package/dist/lib/address/p2tr.js +26 -0
- package/dist/lib/address/p2wpkh.d.ts +10 -0
- package/dist/lib/address/p2wpkh.js +34 -0
- package/dist/lib/address/p2wsh.d.ts +10 -0
- package/dist/lib/address/p2wsh.js +33 -0
- package/dist/lib/address/script.d.ts +5 -0
- package/dist/lib/address/script.js +46 -0
- package/dist/lib/address/util.d.ts +4 -0
- package/dist/lib/address/util.js +57 -0
- package/dist/lib/meta/index.d.ts +2 -0
- package/dist/lib/meta/index.js +2 -0
- package/dist/lib/meta/pointer.d.ts +42 -0
- package/dist/lib/meta/pointer.js +69 -0
- package/dist/lib/meta/scribe.d.ts +7 -0
- package/dist/lib/meta/scribe.js +192 -0
- package/dist/lib/psbt/encoder.d.ts +5 -0
- package/dist/lib/psbt/encoder.js +21 -0
- package/dist/lib/psbt/index.d.ts +4 -0
- package/dist/lib/psbt/index.js +4 -0
- package/dist/lib/psbt/meta.d.ts +3 -0
- package/dist/lib/psbt/meta.js +11 -0
- package/dist/lib/psbt/util.d.ts +5 -0
- package/dist/lib/psbt/util.js +44 -0
- package/dist/lib/psbt/validate.d.ts +2 -0
- package/dist/lib/psbt/validate.js +11 -0
- package/dist/lib/script/decode.d.ts +2 -0
- package/dist/lib/script/decode.js +55 -0
- package/dist/lib/script/encode.d.ts +6 -0
- package/dist/lib/script/encode.js +80 -0
- package/dist/lib/script/index.d.ts +126 -0
- package/dist/lib/script/index.js +17 -0
- package/dist/lib/script/util.d.ts +2 -0
- package/dist/lib/script/util.js +10 -0
- package/dist/lib/script/words.d.ts +116 -0
- package/dist/lib/script/words.js +164 -0
- package/dist/lib/sighash/index.d.ts +5 -0
- package/dist/lib/sighash/index.js +5 -0
- package/dist/lib/sighash/segwit.d.ts +3 -0
- package/dist/lib/sighash/segwit.js +89 -0
- package/dist/lib/sighash/sign.d.ts +3 -0
- package/dist/lib/sighash/sign.js +20 -0
- package/dist/lib/sighash/taproot.d.ts +9 -0
- package/dist/lib/sighash/taproot.js +124 -0
- package/dist/lib/sighash/util.d.ts +3 -0
- package/dist/lib/sighash/util.js +16 -0
- package/dist/lib/sighash/verify.d.ts +1 -0
- package/dist/lib/sighash/verify.js +1 -0
- package/dist/lib/taproot/cblock.d.ts +3 -0
- package/dist/lib/taproot/cblock.js +55 -0
- package/dist/lib/taproot/encode.d.ts +6 -0
- package/dist/lib/taproot/encode.js +26 -0
- package/dist/lib/taproot/index.d.ts +4 -0
- package/dist/lib/taproot/index.js +4 -0
- package/dist/lib/taproot/parse.d.ts +11 -0
- package/dist/lib/taproot/parse.js +47 -0
- package/dist/lib/taproot/tree.d.ts +3 -0
- package/dist/lib/taproot/tree.js +49 -0
- package/dist/lib/tx/create.d.ts +6 -0
- package/dist/lib/tx/create.js +54 -0
- package/dist/lib/tx/decode.d.ts +9 -0
- package/dist/lib/tx/decode.js +109 -0
- package/dist/lib/tx/encode.d.ts +15 -0
- package/dist/lib/tx/encode.js +94 -0
- package/dist/lib/tx/index.d.ts +10 -0
- package/dist/lib/tx/index.js +10 -0
- package/dist/lib/tx/locktime.d.ts +7 -0
- package/dist/lib/tx/locktime.js +37 -0
- package/dist/lib/tx/meta.d.ts +8 -0
- package/dist/lib/tx/meta.js +48 -0
- package/dist/lib/tx/parse.d.ts +2 -0
- package/dist/lib/tx/parse.js +12 -0
- package/dist/lib/tx/sequence.d.ts +7 -0
- package/dist/lib/tx/sequence.js +65 -0
- package/dist/lib/tx/size.d.ts +10 -0
- package/dist/lib/tx/size.js +48 -0
- package/dist/lib/tx/validate.d.ts +7 -0
- package/dist/lib/tx/validate.js +21 -0
- package/dist/lib/tx/witness.d.ts +3 -0
- package/dist/lib/tx/witness.js +85 -0
- package/dist/main.cjs +14625 -0
- package/dist/main.cjs.map +1 -0
- package/dist/module.mjs +14610 -0
- package/dist/module.mjs.map +1 -0
- package/dist/package.json +106 -0
- package/dist/schema/index.d.ts +2 -0
- package/dist/schema/index.js +2 -0
- package/dist/schema/taproot.d.ts +18 -0
- package/dist/schema/taproot.js +9 -0
- package/dist/schema/tx.d.ts +278 -0
- package/dist/schema/tx.js +35 -0
- package/dist/script.js +15 -0
- package/dist/script.js.map +1 -0
- package/dist/types/address.d.ts +34 -0
- package/dist/types/address.js +1 -0
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.js +9 -0
- package/dist/types/meta.d.ts +10 -0
- package/dist/types/meta.js +1 -0
- package/dist/types/psbt.d.ts +9 -0
- package/dist/types/psbt.js +1 -0
- package/dist/types/sighash.d.ts +14 -0
- package/dist/types/sighash.js +1 -0
- package/dist/types/taproot.d.ts +35 -0
- package/dist/types/taproot.js +1 -0
- package/dist/types/transaction.d.ts +81 -0
- package/dist/types/transaction.js +1 -0
- package/dist/types/txdata.d.ts +45 -0
- package/dist/types/txdata.js +1 -0
- package/dist/types/txmeta.d.ts +19 -0
- package/dist/types/txmeta.js +1 -0
- package/dist/types/witness.d.ts +30 -0
- package/dist/types/witness.js +1 -0
- package/package.json +106 -0
- package/src/class/index.ts +5 -0
- package/src/class/signer.ts +47 -0
- package/src/class/tx.ts +118 -0
- package/src/class/txin.ts +95 -0
- package/src/class/txout.ts +57 -0
- package/src/class/witness.ts +85 -0
- package/src/const.ts +43 -0
- package/src/index.ts +14 -0
- package/src/lib/address/encode.ts +183 -0
- package/src/lib/address/index.ts +24 -0
- package/src/lib/address/p2pkh.ts +65 -0
- package/src/lib/address/p2sh.ts +65 -0
- package/src/lib/address/p2tr.ts +51 -0
- package/src/lib/address/p2wpkh.ts +67 -0
- package/src/lib/address/p2wsh.ts +65 -0
- package/src/lib/address/script.ts +63 -0
- package/src/lib/address/util.ts +102 -0
- package/src/lib/meta/index.ts +2 -0
- package/src/lib/meta/pointer.ts +107 -0
- package/src/lib/meta/scribe.ts +251 -0
- package/src/lib/psbt/encoder.ts +24 -0
- package/src/lib/psbt/index.ts +4 -0
- package/src/lib/psbt/meta.ts +15 -0
- package/src/lib/psbt/util.ts +62 -0
- package/src/lib/psbt/validate.ts +18 -0
- package/src/lib/script/decode.ts +75 -0
- package/src/lib/script/encode.ts +130 -0
- package/src/lib/script/index.ts +26 -0
- package/src/lib/script/util.ts +78 -0
- package/src/lib/script/words.ts +182 -0
- package/src/lib/sighash/index.ts +5 -0
- package/src/lib/sighash/segwit.ts +152 -0
- package/src/lib/sighash/sign.ts +35 -0
- package/src/lib/sighash/taproot.ts +236 -0
- package/src/lib/sighash/util.ts +29 -0
- package/src/lib/sighash/verify.ts +83 -0
- package/src/lib/taproot/cblock.ts +95 -0
- package/src/lib/taproot/encode.ts +49 -0
- package/src/lib/taproot/index.ts +4 -0
- package/src/lib/taproot/parse.ts +65 -0
- package/src/lib/taproot/tree.ts +94 -0
- package/src/lib/tx/create.ts +82 -0
- package/src/lib/tx/decode.ts +145 -0
- package/src/lib/tx/encode.ts +154 -0
- package/src/lib/tx/index.ts +10 -0
- package/src/lib/tx/locktime.ts +57 -0
- package/src/lib/tx/meta.ts +73 -0
- package/src/lib/tx/parse.ts +16 -0
- package/src/lib/tx/sequence.ts +146 -0
- package/src/lib/tx/size.ts +77 -0
- package/src/lib/tx/validate.ts +36 -0
- package/src/lib/tx/witness.ts +122 -0
- package/src/schema/index.ts +2 -0
- package/src/schema/taproot.ts +12 -0
- package/src/schema/tx.ts +42 -0
- package/src/types/address.ts +39 -0
- package/src/types/index.ts +9 -0
- package/src/types/meta.ts +10 -0
- package/src/types/psbt.ts +15 -0
- package/src/types/sighash.ts +16 -0
- package/src/types/taproot.ts +40 -0
- package/src/types/transaction.ts +98 -0
- package/src/types/txdata.ts +53 -0
- package/src/types/txmeta.ts +25 -0
- package/src/types/witness.ts +36 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
export declare const OPCODE_MAP: {
|
|
2
|
+
OP_0: number;
|
|
3
|
+
OP_PUSHDATA1: number;
|
|
4
|
+
OP_PUSHDATA2: number;
|
|
5
|
+
OP_PUSHDATA4: number;
|
|
6
|
+
OP_1NEGATE: number;
|
|
7
|
+
OP_SUCCESS80: number;
|
|
8
|
+
OP_1: number;
|
|
9
|
+
OP_2: number;
|
|
10
|
+
OP_3: number;
|
|
11
|
+
OP_4: number;
|
|
12
|
+
OP_5: number;
|
|
13
|
+
OP_6: number;
|
|
14
|
+
OP_7: number;
|
|
15
|
+
OP_8: number;
|
|
16
|
+
OP_9: number;
|
|
17
|
+
OP_10: number;
|
|
18
|
+
OP_11: number;
|
|
19
|
+
OP_12: number;
|
|
20
|
+
OP_13: number;
|
|
21
|
+
OP_14: number;
|
|
22
|
+
OP_15: number;
|
|
23
|
+
OP_16: number;
|
|
24
|
+
OP_NOP: number;
|
|
25
|
+
OP_SUCCESS98: number;
|
|
26
|
+
OP_IF: number;
|
|
27
|
+
OP_NOTIF: number;
|
|
28
|
+
OP_ELSE: number;
|
|
29
|
+
OP_ENDIF: number;
|
|
30
|
+
OP_VERIFY: number;
|
|
31
|
+
OP_RETURN: number;
|
|
32
|
+
OP_TOALTSTACK: number;
|
|
33
|
+
OP_FROMALTSTACK: number;
|
|
34
|
+
OP_2DROP: number;
|
|
35
|
+
OP_2DUP: number;
|
|
36
|
+
OP_3DUP: number;
|
|
37
|
+
OP_2OVER: number;
|
|
38
|
+
OP_2ROT: number;
|
|
39
|
+
OP_2SWAP: number;
|
|
40
|
+
OP_IFDUP: number;
|
|
41
|
+
OP_DEPTH: number;
|
|
42
|
+
OP_DROP: number;
|
|
43
|
+
OP_DUP: number;
|
|
44
|
+
OP_NIP: number;
|
|
45
|
+
OP_OVER: number;
|
|
46
|
+
OP_PICK: number;
|
|
47
|
+
OP_ROLL: number;
|
|
48
|
+
OP_ROT: number;
|
|
49
|
+
OP_SWAP: number;
|
|
50
|
+
OP_TUCK: number;
|
|
51
|
+
OP_SUCCESS126: number;
|
|
52
|
+
OP_SUCCESS127: number;
|
|
53
|
+
OP_SUCCESS128: number;
|
|
54
|
+
OP_SUCCESS129: number;
|
|
55
|
+
OP_SIZE: number;
|
|
56
|
+
OP_SUCCESS131: number;
|
|
57
|
+
OP_SUCCESS132: number;
|
|
58
|
+
OP_SUCCESS133: number;
|
|
59
|
+
OP_SUCCESS134: number;
|
|
60
|
+
OP_EQUAL: number;
|
|
61
|
+
OP_EQUALVERIFY: number;
|
|
62
|
+
OP_SUCCESS137: number;
|
|
63
|
+
OP_SUCCESS138: number;
|
|
64
|
+
OP_1ADD: number;
|
|
65
|
+
OP_1SUB: number;
|
|
66
|
+
OP_SUCCESS141: number;
|
|
67
|
+
OP_SUCCESS142: number;
|
|
68
|
+
OP_NEGATE: number;
|
|
69
|
+
OP_ABS: number;
|
|
70
|
+
OP_NOT: number;
|
|
71
|
+
OP_0NOTEQUAL: number;
|
|
72
|
+
OP_ADD: number;
|
|
73
|
+
OP_SUB: number;
|
|
74
|
+
OP_SUCCESS149: number;
|
|
75
|
+
OP_SUCCESS150: number;
|
|
76
|
+
OP_SUCCESS151: number;
|
|
77
|
+
OP_SUCCESS152: number;
|
|
78
|
+
OP_SUCCESS153: number;
|
|
79
|
+
OP_BOOLAND: number;
|
|
80
|
+
OP_BOOLOR: number;
|
|
81
|
+
OP_NUMEQUAL: number;
|
|
82
|
+
OP_NUMEQUALVERIFY: number;
|
|
83
|
+
OP_NUMNOTEQUAL: number;
|
|
84
|
+
OP_LESSTHAN: number;
|
|
85
|
+
OP_GREATERTHAN: number;
|
|
86
|
+
OP_LESSTHANOREQUAL: number;
|
|
87
|
+
OP_GREATERTHANOREQUAL: number;
|
|
88
|
+
OP_MIN: number;
|
|
89
|
+
OP_MAX: number;
|
|
90
|
+
OP_WITHIN: number;
|
|
91
|
+
OP_RIPEMD160: number;
|
|
92
|
+
OP_SHA1: number;
|
|
93
|
+
OP_SHA256: number;
|
|
94
|
+
OP_HASH160: number;
|
|
95
|
+
OP_HASH256: number;
|
|
96
|
+
OP_CODESEPARATOR: number;
|
|
97
|
+
OP_CHECKSIG: number;
|
|
98
|
+
OP_CHECKSIGVERIFY: number;
|
|
99
|
+
OP_CHECKMULTISIG: number;
|
|
100
|
+
OP_CHECKMULTISIGVERIFY: number;
|
|
101
|
+
OP_NOP1: number;
|
|
102
|
+
OP_CHECKLOCKTIMEVERIFY: number;
|
|
103
|
+
OP_CHECKSEQUENCEVERIFY: number;
|
|
104
|
+
OP_NOP4: number;
|
|
105
|
+
OP_NOP5: number;
|
|
106
|
+
OP_NOP6: number;
|
|
107
|
+
OP_NOP7: number;
|
|
108
|
+
OP_NOP8: number;
|
|
109
|
+
OP_NOP9: number;
|
|
110
|
+
OP_NOP10: number;
|
|
111
|
+
OP_CHECKSIGADD: number;
|
|
112
|
+
};
|
|
113
|
+
export declare function get_op_code(num: number): string;
|
|
114
|
+
export declare function get_asm_code(string: string): number;
|
|
115
|
+
export declare function get_op_type(word: number): string;
|
|
116
|
+
export declare function is_valid_op(word: number): boolean;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
export const OPCODE_MAP = {
|
|
2
|
+
OP_0: 0,
|
|
3
|
+
OP_PUSHDATA1: 76,
|
|
4
|
+
OP_PUSHDATA2: 77,
|
|
5
|
+
OP_PUSHDATA4: 78,
|
|
6
|
+
OP_1NEGATE: 79,
|
|
7
|
+
OP_SUCCESS80: 80,
|
|
8
|
+
OP_1: 81,
|
|
9
|
+
OP_2: 82,
|
|
10
|
+
OP_3: 83,
|
|
11
|
+
OP_4: 84,
|
|
12
|
+
OP_5: 85,
|
|
13
|
+
OP_6: 86,
|
|
14
|
+
OP_7: 87,
|
|
15
|
+
OP_8: 88,
|
|
16
|
+
OP_9: 89,
|
|
17
|
+
OP_10: 90,
|
|
18
|
+
OP_11: 91,
|
|
19
|
+
OP_12: 92,
|
|
20
|
+
OP_13: 93,
|
|
21
|
+
OP_14: 94,
|
|
22
|
+
OP_15: 95,
|
|
23
|
+
OP_16: 96,
|
|
24
|
+
OP_NOP: 97,
|
|
25
|
+
OP_SUCCESS98: 98,
|
|
26
|
+
OP_IF: 99,
|
|
27
|
+
OP_NOTIF: 100,
|
|
28
|
+
OP_ELSE: 103,
|
|
29
|
+
OP_ENDIF: 104,
|
|
30
|
+
OP_VERIFY: 105,
|
|
31
|
+
OP_RETURN: 106,
|
|
32
|
+
OP_TOALTSTACK: 107,
|
|
33
|
+
OP_FROMALTSTACK: 108,
|
|
34
|
+
OP_2DROP: 109,
|
|
35
|
+
OP_2DUP: 110,
|
|
36
|
+
OP_3DUP: 111,
|
|
37
|
+
OP_2OVER: 112,
|
|
38
|
+
OP_2ROT: 113,
|
|
39
|
+
OP_2SWAP: 114,
|
|
40
|
+
OP_IFDUP: 115,
|
|
41
|
+
OP_DEPTH: 116,
|
|
42
|
+
OP_DROP: 117,
|
|
43
|
+
OP_DUP: 118,
|
|
44
|
+
OP_NIP: 119,
|
|
45
|
+
OP_OVER: 120,
|
|
46
|
+
OP_PICK: 121,
|
|
47
|
+
OP_ROLL: 122,
|
|
48
|
+
OP_ROT: 123,
|
|
49
|
+
OP_SWAP: 124,
|
|
50
|
+
OP_TUCK: 125,
|
|
51
|
+
OP_SUCCESS126: 126,
|
|
52
|
+
OP_SUCCESS127: 127,
|
|
53
|
+
OP_SUCCESS128: 128,
|
|
54
|
+
OP_SUCCESS129: 129,
|
|
55
|
+
OP_SIZE: 130,
|
|
56
|
+
OP_SUCCESS131: 131,
|
|
57
|
+
OP_SUCCESS132: 132,
|
|
58
|
+
OP_SUCCESS133: 133,
|
|
59
|
+
OP_SUCCESS134: 134,
|
|
60
|
+
OP_EQUAL: 135,
|
|
61
|
+
OP_EQUALVERIFY: 136,
|
|
62
|
+
OP_SUCCESS137: 137,
|
|
63
|
+
OP_SUCCESS138: 138,
|
|
64
|
+
OP_1ADD: 139,
|
|
65
|
+
OP_1SUB: 140,
|
|
66
|
+
OP_SUCCESS141: 141,
|
|
67
|
+
OP_SUCCESS142: 142,
|
|
68
|
+
OP_NEGATE: 143,
|
|
69
|
+
OP_ABS: 144,
|
|
70
|
+
OP_NOT: 145,
|
|
71
|
+
OP_0NOTEQUAL: 146,
|
|
72
|
+
OP_ADD: 147,
|
|
73
|
+
OP_SUB: 148,
|
|
74
|
+
OP_SUCCESS149: 149,
|
|
75
|
+
OP_SUCCESS150: 150,
|
|
76
|
+
OP_SUCCESS151: 151,
|
|
77
|
+
OP_SUCCESS152: 152,
|
|
78
|
+
OP_SUCCESS153: 153,
|
|
79
|
+
OP_BOOLAND: 154,
|
|
80
|
+
OP_BOOLOR: 155,
|
|
81
|
+
OP_NUMEQUAL: 156,
|
|
82
|
+
OP_NUMEQUALVERIFY: 157,
|
|
83
|
+
OP_NUMNOTEQUAL: 158,
|
|
84
|
+
OP_LESSTHAN: 159,
|
|
85
|
+
OP_GREATERTHAN: 160,
|
|
86
|
+
OP_LESSTHANOREQUAL: 161,
|
|
87
|
+
OP_GREATERTHANOREQUAL: 162,
|
|
88
|
+
OP_MIN: 163,
|
|
89
|
+
OP_MAX: 164,
|
|
90
|
+
OP_WITHIN: 165,
|
|
91
|
+
OP_RIPEMD160: 166,
|
|
92
|
+
OP_SHA1: 167,
|
|
93
|
+
OP_SHA256: 168,
|
|
94
|
+
OP_HASH160: 169,
|
|
95
|
+
OP_HASH256: 170,
|
|
96
|
+
OP_CODESEPARATOR: 171,
|
|
97
|
+
OP_CHECKSIG: 172,
|
|
98
|
+
OP_CHECKSIGVERIFY: 173,
|
|
99
|
+
OP_CHECKMULTISIG: 174,
|
|
100
|
+
OP_CHECKMULTISIGVERIFY: 175,
|
|
101
|
+
OP_NOP1: 176,
|
|
102
|
+
OP_CHECKLOCKTIMEVERIFY: 177,
|
|
103
|
+
OP_CHECKSEQUENCEVERIFY: 178,
|
|
104
|
+
OP_NOP4: 179,
|
|
105
|
+
OP_NOP5: 180,
|
|
106
|
+
OP_NOP6: 181,
|
|
107
|
+
OP_NOP7: 182,
|
|
108
|
+
OP_NOP8: 183,
|
|
109
|
+
OP_NOP9: 184,
|
|
110
|
+
OP_NOP10: 185,
|
|
111
|
+
OP_CHECKSIGADD: 186
|
|
112
|
+
};
|
|
113
|
+
export function get_op_code(num) {
|
|
114
|
+
if (num > 186 && num < 255) {
|
|
115
|
+
return 'OP_SUCCESS' + String(num);
|
|
116
|
+
}
|
|
117
|
+
for (const [k, v] of Object.entries(OPCODE_MAP)) {
|
|
118
|
+
if (v === num)
|
|
119
|
+
return k;
|
|
120
|
+
}
|
|
121
|
+
throw new Error('OPCODE not found:' + String(num));
|
|
122
|
+
}
|
|
123
|
+
export function get_asm_code(string) {
|
|
124
|
+
for (const [k, v] of Object.entries(OPCODE_MAP)) {
|
|
125
|
+
if (k === string)
|
|
126
|
+
return Number(v);
|
|
127
|
+
}
|
|
128
|
+
throw new Error('OPCODE not found:' + string);
|
|
129
|
+
}
|
|
130
|
+
export function get_op_type(word) {
|
|
131
|
+
switch (true) {
|
|
132
|
+
case (word === 0):
|
|
133
|
+
return 'opcode';
|
|
134
|
+
case (word >= 1 && word <= 75):
|
|
135
|
+
return 'varint';
|
|
136
|
+
case (word === 76):
|
|
137
|
+
return 'pushdata1';
|
|
138
|
+
case (word === 77):
|
|
139
|
+
return 'pushdata2';
|
|
140
|
+
case (word === 78):
|
|
141
|
+
return 'pushdata4';
|
|
142
|
+
case (word <= 254):
|
|
143
|
+
return 'opcode';
|
|
144
|
+
default:
|
|
145
|
+
throw new Error(`Invalid word range: ${word}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
export function is_valid_op(word) {
|
|
149
|
+
const MIN_RANGE = 75;
|
|
150
|
+
const MAX_RANGE = 254;
|
|
151
|
+
const DISABLED_OPCODES = [];
|
|
152
|
+
switch (true) {
|
|
153
|
+
case (typeof (word) !== 'number'):
|
|
154
|
+
return false;
|
|
155
|
+
case (word === 0):
|
|
156
|
+
return true;
|
|
157
|
+
case (DISABLED_OPCODES.includes(word)):
|
|
158
|
+
return false;
|
|
159
|
+
case (MIN_RANGE < word && word < MAX_RANGE):
|
|
160
|
+
return true;
|
|
161
|
+
default:
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { Buff } from '@vbyte/buff';
|
|
2
|
+
import { hash160, hash256 } from '@vbyte/micro-lib/hash';
|
|
3
|
+
import { Assert } from '@vbyte/micro-lib';
|
|
4
|
+
import { parse_txinput } from './util.js';
|
|
5
|
+
import { prefix_script_size, decode_script } from '../../lib/script/index.js';
|
|
6
|
+
import { encode_txin_vout, encode_tx_locktime, encode_txin_sequence, encode_txin_txid, encode_vout_value, encode_tx_version, parse_tx_data } from '../../lib/tx/index.js';
|
|
7
|
+
import * as CONST from '../../const.js';
|
|
8
|
+
export function hash_segwit_tx(txdata, options = {}) {
|
|
9
|
+
const { sigflag = 0x01, txindex } = options;
|
|
10
|
+
const tx = parse_tx_data(txdata);
|
|
11
|
+
const is_anypay = (sigflag & 0x80) === 0x80;
|
|
12
|
+
const flag = sigflag % 0x80;
|
|
13
|
+
if (!CONST.SIGHASH_SEGWIT.includes(flag)) {
|
|
14
|
+
throw new Error('Invalid hash type: ' + String(sigflag));
|
|
15
|
+
}
|
|
16
|
+
const { version, vin, vout, locktime } = tx;
|
|
17
|
+
const txinput = parse_txinput(tx, options);
|
|
18
|
+
const { txid, vout: prevIdx, prevout, sequence } = txinput;
|
|
19
|
+
const { value } = prevout ?? {};
|
|
20
|
+
if (value === undefined) {
|
|
21
|
+
throw new Error('Prevout value is empty!');
|
|
22
|
+
}
|
|
23
|
+
let { pubkey, script } = options;
|
|
24
|
+
if (script === undefined && pubkey !== undefined) {
|
|
25
|
+
const pkhash = hash160(pubkey).hex;
|
|
26
|
+
script = `76a914${String(pkhash)}88ac`;
|
|
27
|
+
}
|
|
28
|
+
if (script === undefined) {
|
|
29
|
+
throw new Error('No pubkey / script has been set!');
|
|
30
|
+
}
|
|
31
|
+
if (decode_script(script).includes('OP_CODESEPARATOR')) {
|
|
32
|
+
throw new Error('This library does not currently support the use of OP_CODESEPARATOR in segwit scripts.');
|
|
33
|
+
}
|
|
34
|
+
const sighash = [
|
|
35
|
+
encode_tx_version(version),
|
|
36
|
+
hash_prevouts(vin, is_anypay),
|
|
37
|
+
hash_sequence(vin, flag, is_anypay),
|
|
38
|
+
encode_txin_txid(txid),
|
|
39
|
+
encode_txin_vout(prevIdx),
|
|
40
|
+
prefix_script_size(script),
|
|
41
|
+
encode_vout_value(value),
|
|
42
|
+
encode_txin_sequence(sequence),
|
|
43
|
+
hash_outputs(vout, flag, txindex),
|
|
44
|
+
encode_tx_locktime(locktime),
|
|
45
|
+
Buff.num(sigflag, 4).reverse()
|
|
46
|
+
];
|
|
47
|
+
return hash256(Buff.join(sighash));
|
|
48
|
+
}
|
|
49
|
+
function hash_prevouts(vin, isAnypay) {
|
|
50
|
+
if (isAnypay === true) {
|
|
51
|
+
return Buff.num(0, 32);
|
|
52
|
+
}
|
|
53
|
+
const stack = [];
|
|
54
|
+
for (const { txid, vout } of vin) {
|
|
55
|
+
stack.push(encode_txin_txid(txid));
|
|
56
|
+
stack.push(encode_txin_vout(vout));
|
|
57
|
+
}
|
|
58
|
+
return hash256(Buff.join(stack));
|
|
59
|
+
}
|
|
60
|
+
function hash_sequence(vin, sigflag, isAnyPay) {
|
|
61
|
+
if (isAnyPay || sigflag !== 0x01) {
|
|
62
|
+
return Buff.num(0, 32);
|
|
63
|
+
}
|
|
64
|
+
const stack = [];
|
|
65
|
+
for (const { sequence } of vin) {
|
|
66
|
+
stack.push(encode_txin_sequence(sequence));
|
|
67
|
+
}
|
|
68
|
+
return hash256(Buff.join(stack));
|
|
69
|
+
}
|
|
70
|
+
function hash_outputs(vout, sigflag, idx) {
|
|
71
|
+
const stack = [];
|
|
72
|
+
if (sigflag === 0x01) {
|
|
73
|
+
for (const { value, script_pk } of vout) {
|
|
74
|
+
stack.push(encode_vout_value(value));
|
|
75
|
+
stack.push(prefix_script_size(script_pk));
|
|
76
|
+
}
|
|
77
|
+
return hash256(Buff.join(stack));
|
|
78
|
+
}
|
|
79
|
+
if (sigflag === 0x03) {
|
|
80
|
+
Assert.ok(idx !== undefined);
|
|
81
|
+
if (idx < vout.length) {
|
|
82
|
+
const { value, script_pk } = vout[idx];
|
|
83
|
+
stack.push(encode_vout_value(value));
|
|
84
|
+
stack.push(prefix_script_size(script_pk));
|
|
85
|
+
return hash256(Buff.join(stack));
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return Buff.num(0, 32);
|
|
89
|
+
}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { SigHashOptions, TxData } from '../../types/index.js';
|
|
2
|
+
export declare function sign_segwit_tx(seckey: string, txdata: TxData, options: SigHashOptions): string;
|
|
3
|
+
export declare function sign_taproot_tx(seckey: string, txdata: TxData, options: SigHashOptions): string;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { ECC } from '@vbyte/micro-lib';
|
|
2
|
+
import { parse_tx_data } from '../../lib/tx/parse.js';
|
|
3
|
+
import { SIGHASH_DEFAULT } from '../../const.js';
|
|
4
|
+
import { hash_segwit_tx } from './segwit.js';
|
|
5
|
+
import { hash_taproot_tx } from './taproot.js';
|
|
6
|
+
import { format_sigflag } from './util.js';
|
|
7
|
+
export function sign_segwit_tx(seckey, txdata, options) {
|
|
8
|
+
const tx = parse_tx_data(txdata);
|
|
9
|
+
const msg = hash_segwit_tx(tx, options);
|
|
10
|
+
const sig = ECC.sign_ecdsa(seckey, msg).hex;
|
|
11
|
+
const flag = format_sigflag(options.sigflag ?? SIGHASH_DEFAULT);
|
|
12
|
+
return sig + flag;
|
|
13
|
+
}
|
|
14
|
+
export function sign_taproot_tx(seckey, txdata, options) {
|
|
15
|
+
const tx = parse_tx_data(txdata);
|
|
16
|
+
const msg = hash_taproot_tx(tx, options);
|
|
17
|
+
const sig = ECC.sign_bip340(seckey, msg).hex;
|
|
18
|
+
const flag = format_sigflag(options.sigflag ?? 0);
|
|
19
|
+
return sig + flag;
|
|
20
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Buff } from '@vbyte/buff';
|
|
2
|
+
import type { SigHashOptions, TxData, TxInput, TxOutput } from '../../types/index.js';
|
|
3
|
+
export declare function hash_taproot_tx(template: TxData | string, config?: SigHashOptions): Buff;
|
|
4
|
+
export declare function hash_outpoints(vin: TxInput[]): Buff;
|
|
5
|
+
export declare function hash_sequence(vin: TxInput[]): Buff;
|
|
6
|
+
export declare function hash_amounts(prevouts: TxOutput[]): Buff;
|
|
7
|
+
export declare function hash_scripts(prevouts: TxOutput[]): Buff;
|
|
8
|
+
export declare function hash_outputs(vout: TxOutput[]): Buff;
|
|
9
|
+
export declare function hash_output(vout: TxOutput): Buff;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Buff } from '@vbyte/buff';
|
|
2
|
+
import { Assert } from '@vbyte/micro-lib';
|
|
3
|
+
import { hash340, sha256 } from '@vbyte/micro-lib/hash';
|
|
4
|
+
import { prefix_script_size } from '../../lib/script/util.js';
|
|
5
|
+
import { encode_tapscript } from '../../lib/taproot/encode.js';
|
|
6
|
+
import { parse_tx_data } from '../../lib/tx/parse.js';
|
|
7
|
+
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';
|
|
10
|
+
export function hash_taproot_tx(template, config = {}) {
|
|
11
|
+
const { script, txindex, sigflag = 0x00, extflag = 0x00, key_version = 0x00, separator_pos = 0xFFFFFFFF } = config;
|
|
12
|
+
const tx = parse_tx_data(template);
|
|
13
|
+
const { version, vin: input, vout: output, locktime } = tx;
|
|
14
|
+
const txinput = parse_txinput(tx, config);
|
|
15
|
+
const { txid, vout, sequence, witness = [] } = txinput;
|
|
16
|
+
if (!CONST.SIGHASH_TAPROOT.includes(sigflag)) {
|
|
17
|
+
throw new Error('Invalid hash type: ' + String(sigflag));
|
|
18
|
+
}
|
|
19
|
+
if (extflag < 0 || extflag > 127) {
|
|
20
|
+
throw new Error('Extention flag out of range: ' + String(extflag));
|
|
21
|
+
}
|
|
22
|
+
let { extension } = config;
|
|
23
|
+
if (script !== undefined) {
|
|
24
|
+
extension = encode_tapscript(script).hex;
|
|
25
|
+
}
|
|
26
|
+
const is_anypay = (sigflag & 0x80) === 0x80;
|
|
27
|
+
const annex = get_annex_data(witness);
|
|
28
|
+
const annexBit = (annex !== undefined) ? 1 : 0;
|
|
29
|
+
const extendBit = (extension !== undefined) ? 1 : 0;
|
|
30
|
+
const spendType = ((extflag + extendBit) * 2) + annexBit;
|
|
31
|
+
const hashtag = hash340('TapSighash');
|
|
32
|
+
const preimage = [
|
|
33
|
+
hashtag,
|
|
34
|
+
Buff.num(0x00, 1),
|
|
35
|
+
Buff.num(sigflag, 1),
|
|
36
|
+
encode_tx_version(version),
|
|
37
|
+
encode_tx_locktime(locktime)
|
|
38
|
+
];
|
|
39
|
+
if (!is_anypay) {
|
|
40
|
+
const prevouts = input.map(e => get_prevout(e));
|
|
41
|
+
preimage.push(hash_outpoints(input), hash_amounts(prevouts), hash_scripts(prevouts), hash_sequence(input));
|
|
42
|
+
}
|
|
43
|
+
if ((sigflag & 0x03) < 2 || (sigflag & 0x03) > 3) {
|
|
44
|
+
preimage.push(hash_outputs(output));
|
|
45
|
+
}
|
|
46
|
+
preimage.push(Buff.num(spendType, 1));
|
|
47
|
+
if (is_anypay) {
|
|
48
|
+
const { value, script_pk } = get_prevout(txinput);
|
|
49
|
+
preimage.push(encode_txin_txid(txid), encode_txin_vout(vout), encode_vout_value(value), prefix_script_size(script_pk), encode_txin_sequence(sequence));
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
Assert.ok(typeof txindex === 'number');
|
|
53
|
+
preimage.push(Buff.num(txindex, 4).reverse());
|
|
54
|
+
}
|
|
55
|
+
if (annex !== undefined) {
|
|
56
|
+
preimage.push(annex);
|
|
57
|
+
}
|
|
58
|
+
if ((sigflag & 0x03) === 0x03) {
|
|
59
|
+
Assert.ok(typeof txindex === 'number');
|
|
60
|
+
preimage.push(hash_output(output[txindex]));
|
|
61
|
+
}
|
|
62
|
+
if (extension !== undefined) {
|
|
63
|
+
preimage.push(Buff.bytes(extension), Buff.num(key_version), Buff.num(separator_pos, 4));
|
|
64
|
+
}
|
|
65
|
+
return sha256(Buff.join(preimage));
|
|
66
|
+
}
|
|
67
|
+
export function hash_outpoints(vin) {
|
|
68
|
+
const stack = [];
|
|
69
|
+
for (const { txid, vout } of vin) {
|
|
70
|
+
stack.push(encode_txin_txid(txid));
|
|
71
|
+
stack.push(encode_txin_vout(vout));
|
|
72
|
+
}
|
|
73
|
+
return sha256(Buff.join(stack));
|
|
74
|
+
}
|
|
75
|
+
export function hash_sequence(vin) {
|
|
76
|
+
const stack = [];
|
|
77
|
+
for (const { sequence } of vin) {
|
|
78
|
+
stack.push(encode_txin_sequence(sequence));
|
|
79
|
+
}
|
|
80
|
+
return sha256(Buff.join(stack));
|
|
81
|
+
}
|
|
82
|
+
export function hash_amounts(prevouts) {
|
|
83
|
+
const stack = [];
|
|
84
|
+
for (const { value } of prevouts) {
|
|
85
|
+
stack.push(encode_vout_value(value));
|
|
86
|
+
}
|
|
87
|
+
return sha256(Buff.join(stack));
|
|
88
|
+
}
|
|
89
|
+
export function hash_scripts(prevouts) {
|
|
90
|
+
const stack = [];
|
|
91
|
+
for (const { script_pk } of prevouts) {
|
|
92
|
+
stack.push(prefix_script_size(script_pk));
|
|
93
|
+
}
|
|
94
|
+
return sha256(Buff.join(stack));
|
|
95
|
+
}
|
|
96
|
+
export function hash_outputs(vout) {
|
|
97
|
+
const stack = [];
|
|
98
|
+
for (const { value, script_pk } of vout) {
|
|
99
|
+
stack.push(encode_vout_value(value));
|
|
100
|
+
stack.push(prefix_script_size(script_pk));
|
|
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);
|
|
116
|
+
}
|
|
117
|
+
return undefined;
|
|
118
|
+
}
|
|
119
|
+
function get_prevout(vin) {
|
|
120
|
+
if (vin.prevout === null) {
|
|
121
|
+
throw new Error('Prevout data missing for input: ' + String(vin.txid));
|
|
122
|
+
}
|
|
123
|
+
return vin.prevout;
|
|
124
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Buff } from '@vbyte/buff';
|
|
2
|
+
import { Assert } from '@vbyte/micro-lib';
|
|
3
|
+
export function parse_txinput(txdata, config) {
|
|
4
|
+
let { txindex, txinput } = config ?? {};
|
|
5
|
+
if (txindex !== undefined) {
|
|
6
|
+
if (txindex >= txdata.vin.length) {
|
|
7
|
+
throw new Error('Input index out of bounds: ' + String(txindex));
|
|
8
|
+
}
|
|
9
|
+
txinput = txdata.vin.at(txindex);
|
|
10
|
+
}
|
|
11
|
+
Assert.ok(txinput !== undefined);
|
|
12
|
+
return txinput;
|
|
13
|
+
}
|
|
14
|
+
export function format_sigflag(flag) {
|
|
15
|
+
return (flag !== 0) ? Buff.num(flag, 1).hex : '';
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { Buff } from '@vbyte/buff';
|
|
2
|
+
import { Assert, ECC } from '@vbyte/micro-lib';
|
|
3
|
+
import { merkleize } from './tree.js';
|
|
4
|
+
import { TAPLEAF_DEFAULT_VERSION } from '../../const.js';
|
|
5
|
+
import * as Schema from '../../schema/index.js';
|
|
6
|
+
import { encode_tapbranch, encode_taptweak } from './encode.js';
|
|
7
|
+
import { parse_pubkey_parity, parse_cblock } from './parse.js';
|
|
8
|
+
const DEFAULT_VERSION = TAPLEAF_DEFAULT_VERSION;
|
|
9
|
+
export function create_taproot(config) {
|
|
10
|
+
Schema.taproot.config.parse(config);
|
|
11
|
+
const { pubkey, version = DEFAULT_VERSION } = config;
|
|
12
|
+
const leaves = config.leaves ?? [];
|
|
13
|
+
const target = (config.target !== undefined)
|
|
14
|
+
? Buff.bytes(config.target).hex
|
|
15
|
+
: undefined;
|
|
16
|
+
let path = [], taproot;
|
|
17
|
+
if (leaves.length > 0) {
|
|
18
|
+
const [root, _, proofs] = merkleize(leaves, target);
|
|
19
|
+
path = proofs;
|
|
20
|
+
taproot = root;
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
taproot = target;
|
|
24
|
+
}
|
|
25
|
+
const taptweak = encode_taptweak(pubkey, taproot);
|
|
26
|
+
const twk_key = ECC.tweak_pubkey(pubkey, taptweak, 'ecdsa');
|
|
27
|
+
const parity = parse_pubkey_parity(twk_key);
|
|
28
|
+
const tapkey = ECC.serialize_pubkey(twk_key, 'bip340');
|
|
29
|
+
const cbit = Buff.num(version + parity);
|
|
30
|
+
const block = [cbit, Buff.bytes(pubkey)];
|
|
31
|
+
if (path.length > 0) {
|
|
32
|
+
path.forEach(e => block.push(e));
|
|
33
|
+
}
|
|
34
|
+
const cblock = Buff.join(block);
|
|
35
|
+
return {
|
|
36
|
+
int_key: Buff.bytes(pubkey).hex,
|
|
37
|
+
parity,
|
|
38
|
+
taproot: taproot ?? null,
|
|
39
|
+
cblock: cblock.hex,
|
|
40
|
+
tapkey: tapkey.hex,
|
|
41
|
+
taptweak: taptweak.hex
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
export function verify_taproot(tapkey, target, cblock) {
|
|
45
|
+
Assert.size(tapkey, 32);
|
|
46
|
+
const { parity, path, int_key } = parse_cblock(cblock);
|
|
47
|
+
const ext_key = Buff.join([parity, tapkey]);
|
|
48
|
+
let branch = Buff.bytes(target).hex;
|
|
49
|
+
for (const leaf of path) {
|
|
50
|
+
branch = encode_tapbranch(branch, leaf).hex;
|
|
51
|
+
}
|
|
52
|
+
const tap_tweak = encode_taptweak(int_key, branch);
|
|
53
|
+
const tweaked_key = ECC.tweak_pubkey(int_key, tap_tweak, 'ecdsa');
|
|
54
|
+
return (ext_key.hex === tweaked_key.hex);
|
|
55
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Buff } from '@vbyte/buff';
|
|
2
|
+
export declare function encode_tapscript(script: string | Uint8Array, version?: number): Buff;
|
|
3
|
+
export declare function encode_tapleaf(data: string | Uint8Array, version?: number): Buff;
|
|
4
|
+
export declare function encode_tapbranch(leaf_a: string, leaf_b: string): Buff;
|
|
5
|
+
export declare function encode_leaf_version(version?: number): number;
|
|
6
|
+
export declare function encode_taptweak(pubkey: string | Uint8Array, data?: string | Uint8Array): Buff;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { hash340 } from '@vbyte/micro-lib/hash';
|
|
2
|
+
import { Assert } from '@vbyte/micro-lib';
|
|
3
|
+
import { prefix_script_size } from '../../lib/script/index.js';
|
|
4
|
+
import { TAPLEAF_DEFAULT_VERSION } from '../../const.js';
|
|
5
|
+
const DEFAULT_VERSION = TAPLEAF_DEFAULT_VERSION;
|
|
6
|
+
export function encode_tapscript(script, version = DEFAULT_VERSION) {
|
|
7
|
+
const preimg = prefix_script_size(script);
|
|
8
|
+
return encode_tapleaf(preimg, version);
|
|
9
|
+
}
|
|
10
|
+
export function encode_tapleaf(data, version = DEFAULT_VERSION) {
|
|
11
|
+
const vbyte = encode_leaf_version(version);
|
|
12
|
+
return hash340('TapLeaf', vbyte, data);
|
|
13
|
+
}
|
|
14
|
+
export function encode_tapbranch(leaf_a, leaf_b) {
|
|
15
|
+
if (leaf_b < leaf_a) {
|
|
16
|
+
[leaf_a, leaf_b] = [leaf_b, leaf_a];
|
|
17
|
+
}
|
|
18
|
+
return hash340('TapBranch', leaf_a, leaf_b);
|
|
19
|
+
}
|
|
20
|
+
export function encode_leaf_version(version = 0xc0) {
|
|
21
|
+
return version & 0xfe;
|
|
22
|
+
}
|
|
23
|
+
export function encode_taptweak(pubkey, data = new Uint8Array()) {
|
|
24
|
+
Assert.size(pubkey, 32);
|
|
25
|
+
return hash340('TapTweak', pubkey, data);
|
|
26
|
+
}
|