@vbyte/btc-dev 1.1.8 → 2.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.
Files changed (174) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +260 -3
  3. package/dist/const.d.ts +3 -0
  4. package/dist/const.js +23 -22
  5. package/dist/index.d.ts +11 -11
  6. package/dist/index.js +10 -10
  7. package/dist/lib/address/api.d.ts +2 -2
  8. package/dist/lib/address/api.js +12 -12
  9. package/dist/lib/address/encode.d.ts +1 -1
  10. package/dist/lib/address/encode.js +24 -24
  11. package/dist/lib/address/index.d.ts +6 -6
  12. package/dist/lib/address/index.js +6 -6
  13. package/dist/lib/address/p2pkh.d.ts +2 -2
  14. package/dist/lib/address/p2pkh.js +14 -14
  15. package/dist/lib/address/p2sh.d.ts +2 -2
  16. package/dist/lib/address/p2sh.js +13 -13
  17. package/dist/lib/address/p2tr.d.ts +2 -2
  18. package/dist/lib/address/p2tr.js +13 -13
  19. package/dist/lib/address/p2wpkh.d.ts +2 -2
  20. package/dist/lib/address/p2wpkh.js +14 -14
  21. package/dist/lib/address/p2wsh.d.ts +2 -2
  22. package/dist/lib/address/p2wsh.js +13 -13
  23. package/dist/lib/address/script.d.ts +1 -1
  24. package/dist/lib/address/script.js +16 -16
  25. package/dist/lib/address/util.d.ts +1 -1
  26. package/dist/lib/address/util.js +22 -22
  27. package/dist/lib/meta/index.d.ts +4 -4
  28. package/dist/lib/meta/index.js +4 -4
  29. package/dist/lib/meta/locktime.d.ts +1 -1
  30. package/dist/lib/meta/locktime.js +12 -12
  31. package/dist/lib/meta/ref.js +9 -6
  32. package/dist/lib/meta/scribe.d.ts +2 -2
  33. package/dist/lib/meta/scribe.js +48 -53
  34. package/dist/lib/meta/sequence.d.ts +1 -1
  35. package/dist/lib/meta/sequence.js +16 -15
  36. package/dist/lib/script/decode.d.ts +2 -2
  37. package/dist/lib/script/decode.js +50 -15
  38. package/dist/lib/script/encode.d.ts +1 -1
  39. package/dist/lib/script/encode.js +20 -16
  40. package/dist/lib/script/index.d.ts +5 -13
  41. package/dist/lib/script/index.js +5 -14
  42. package/dist/lib/script/lock.d.ts +2 -2
  43. package/dist/lib/script/lock.js +15 -12
  44. package/dist/lib/script/util.js +4 -4
  45. package/dist/lib/script/words.js +129 -129
  46. package/dist/lib/sighash/index.d.ts +3 -3
  47. package/dist/lib/sighash/index.js +3 -3
  48. package/dist/lib/sighash/segwit.d.ts +2 -2
  49. package/dist/lib/sighash/segwit.js +15 -14
  50. package/dist/lib/sighash/taproot.d.ts +2 -2
  51. package/dist/lib/sighash/taproot.js +24 -23
  52. package/dist/lib/sighash/util.d.ts +2 -2
  53. package/dist/lib/sighash/util.js +7 -7
  54. package/dist/lib/signer/index.d.ts +2 -2
  55. package/dist/lib/signer/index.js +2 -2
  56. package/dist/lib/signer/sign.d.ts +1 -1
  57. package/dist/lib/signer/sign.js +42 -7
  58. package/dist/lib/signer/verify.d.ts +17 -3
  59. package/dist/lib/signer/verify.js +233 -3
  60. package/dist/lib/taproot/cblock.d.ts +1 -1
  61. package/dist/lib/taproot/cblock.js +14 -16
  62. package/dist/lib/taproot/encode.d.ts +1 -1
  63. package/dist/lib/taproot/encode.js +7 -7
  64. package/dist/lib/taproot/index.d.ts +4 -4
  65. package/dist/lib/taproot/index.js +4 -4
  66. package/dist/lib/taproot/parse.d.ts +1 -1
  67. package/dist/lib/taproot/parse.js +12 -14
  68. package/dist/lib/taproot/tree.d.ts +2 -2
  69. package/dist/lib/taproot/tree.js +11 -7
  70. package/dist/lib/tx/create.d.ts +1 -1
  71. package/dist/lib/tx/create.js +28 -12
  72. package/dist/lib/tx/decode.d.ts +2 -2
  73. package/dist/lib/tx/decode.js +50 -17
  74. package/dist/lib/tx/encode.d.ts +2 -2
  75. package/dist/lib/tx/encode.js +13 -16
  76. package/dist/lib/tx/index.d.ts +7 -7
  77. package/dist/lib/tx/index.js +7 -7
  78. package/dist/lib/tx/parse.d.ts +1 -1
  79. package/dist/lib/tx/parse.js +9 -9
  80. package/dist/lib/tx/size.d.ts +2 -2
  81. package/dist/lib/tx/size.js +9 -9
  82. package/dist/lib/tx/util.d.ts +2 -2
  83. package/dist/lib/tx/util.js +23 -20
  84. package/dist/lib/tx/validate.d.ts +1 -1
  85. package/dist/lib/tx/validate.js +3 -3
  86. package/dist/lib/witness/index.d.ts +2 -2
  87. package/dist/lib/witness/index.js +2 -2
  88. package/dist/lib/witness/parse.d.ts +2 -2
  89. package/dist/lib/witness/parse.js +24 -23
  90. package/dist/lib/witness/util.d.ts +2 -2
  91. package/dist/lib/witness/util.js +5 -5
  92. package/dist/main.cjs +2308 -1005
  93. package/dist/main.cjs.map +1 -1
  94. package/dist/module.mjs +2308 -1005
  95. package/dist/module.mjs.map +1 -1
  96. package/dist/package.json +20 -17
  97. package/dist/schema/base.d.ts +1 -1
  98. package/dist/schema/base.js +17 -13
  99. package/dist/schema/index.d.ts +2 -2
  100. package/dist/schema/index.js +2 -2
  101. package/dist/schema/taproot.d.ts +1 -1
  102. package/dist/schema/taproot.js +2 -2
  103. package/dist/schema/tx.d.ts +1 -1
  104. package/dist/schema/tx.js +4 -4
  105. package/dist/script.js +8 -8
  106. package/dist/script.js.map +1 -1
  107. package/dist/types/address.d.ts +4 -4
  108. package/dist/types/index.d.ts +8 -8
  109. package/dist/types/index.js +8 -8
  110. package/dist/types/meta.d.ts +4 -4
  111. package/dist/types/psbt.d.ts +2 -2
  112. package/dist/types/script.d.ts +2 -2
  113. package/dist/types/sighash.d.ts +2 -2
  114. package/dist/types/witness.d.ts +5 -5
  115. package/package.json +20 -17
  116. package/src/const.ts +0 -61
  117. package/src/index.ts +0 -13
  118. package/src/lib/address/api.ts +0 -50
  119. package/src/lib/address/encode.ts +0 -183
  120. package/src/lib/address/index.ts +0 -7
  121. package/src/lib/address/p2pkh.ts +0 -94
  122. package/src/lib/address/p2sh.ts +0 -96
  123. package/src/lib/address/p2tr.ts +0 -91
  124. package/src/lib/address/p2wpkh.ts +0 -94
  125. package/src/lib/address/p2wsh.ts +0 -92
  126. package/src/lib/address/script.ts +0 -63
  127. package/src/lib/address/util.ts +0 -87
  128. package/src/lib/meta/index.ts +0 -4
  129. package/src/lib/meta/locktime.ts +0 -57
  130. package/src/lib/meta/ref.ts +0 -107
  131. package/src/lib/meta/scribe.ts +0 -256
  132. package/src/lib/meta/sequence.ts +0 -146
  133. package/src/lib/script/decode.ts +0 -85
  134. package/src/lib/script/encode.ts +0 -129
  135. package/src/lib/script/index.ts +0 -20
  136. package/src/lib/script/lock.ts +0 -73
  137. package/src/lib/script/util.ts +0 -78
  138. package/src/lib/script/words.ts +0 -182
  139. package/src/lib/sighash/index.ts +0 -3
  140. package/src/lib/sighash/segwit.ts +0 -152
  141. package/src/lib/sighash/taproot.ts +0 -206
  142. package/src/lib/sighash/util.ts +0 -51
  143. package/src/lib/signer/index.ts +0 -2
  144. package/src/lib/signer/sign.ts +0 -39
  145. package/src/lib/signer/verify.ts +0 -88
  146. package/src/lib/taproot/cblock.ts +0 -96
  147. package/src/lib/taproot/encode.ts +0 -49
  148. package/src/lib/taproot/index.ts +0 -4
  149. package/src/lib/taproot/parse.ts +0 -65
  150. package/src/lib/taproot/tree.ts +0 -94
  151. package/src/lib/tx/create.ts +0 -90
  152. package/src/lib/tx/decode.ts +0 -123
  153. package/src/lib/tx/encode.ts +0 -155
  154. package/src/lib/tx/index.ts +0 -7
  155. package/src/lib/tx/parse.ts +0 -69
  156. package/src/lib/tx/size.ts +0 -68
  157. package/src/lib/tx/util.ts +0 -111
  158. package/src/lib/tx/validate.ts +0 -49
  159. package/src/lib/witness/index.ts +0 -2
  160. package/src/lib/witness/parse.ts +0 -127
  161. package/src/lib/witness/util.ts +0 -18
  162. package/src/schema/base.ts +0 -57
  163. package/src/schema/index.ts +0 -2
  164. package/src/schema/taproot.ts +0 -12
  165. package/src/schema/tx.ts +0 -48
  166. package/src/types/address.ts +0 -35
  167. package/src/types/index.ts +0 -8
  168. package/src/types/meta.ts +0 -48
  169. package/src/types/psbt.ts +0 -15
  170. package/src/types/script.ts +0 -18
  171. package/src/types/sighash.ts +0 -16
  172. package/src/types/taproot.ts +0 -41
  173. package/src/types/txdata.ts +0 -85
  174. package/src/types/witness.ts +0 -42
@@ -1,78 +0,0 @@
1
- import { Buff } from '@vbyte/buff'
2
-
3
- export function prefix_script_size (script: string | Uint8Array): string {
4
- return Buff.bytes(script).prefix_varint('le').hex
5
- }
6
-
7
- export function parse_script_pubkeys (script: string | Uint8Array): string[] {
8
- // Convert the script to a string if it's a Uint8Array
9
- const scriptHex = typeof script === 'string' ? script : Buff.bytes(script).hex
10
-
11
- // Define the regex pattern to match the specified pattern
12
- // 20 = pushdata byte for 32 bytes (0x20)
13
- // [0-9a-f]{64} = 32-byte hex string (64 hex characters)
14
- // (ac|ad|ba) = OP_CHECKSIG (0xac), OP_CHECKSIGVERIFY (0xad), or OP_CHECKSIGADD (0xba)
15
- const pubkeyPattern = /20([0-9a-f]{64})(ac|ad|ba)/gi
16
-
17
- // Find all matches in the script
18
- const matches = [...scriptHex.matchAll(pubkeyPattern)]
19
-
20
- // Extract the public keys from the matches
21
- return matches.map(match => match[1])
22
- }
23
-
24
- // export function parse_witness_pubkeys (
25
- // witness : string[] | TxWitnessData
26
- // ) : string[] {
27
- // // Parse the witness data if it is an array.
28
- // if (witness instanceof Array) {
29
- // witness = parse_witness_data(witness)
30
- // }
31
- // // Define the set of pubkeys.
32
- // const pubkeys = new Set<string>()
33
- // // Get the witness type.
34
- // const type = witness.type
35
- // // If the witness type is a p2tr-ts:
36
- // if (type === 'p2tr-ts') {
37
- // // Parse the internal pubkey from the cblock.
38
- // const int_pk = witness.cblock?.slice(2, 66)
39
- // // If the internal pubkey is present, add it to the list.
40
- // if (int_pk !== undefined) pubkeys.add(int_pk)
41
- // // Parse any pubkeys witness parameters.
42
- // witness.params
43
- // .filter(p => p.length === 64)
44
- // .forEach(p => pubkeys.add(p))
45
- // // Parse any pubkeys from the script.
46
- // parse_taproot_pubkeys(witness.script!)
47
- // .forEach(p => pubkeys.add(p))
48
- // // If the witness type is a p2w-pkh:
49
- // } else if (type === 'p2w-pkh') {
50
- // // Parse the witness parameter pubkey.
51
- // const params_pk = witness.params.find(p => p.length === 66)
52
- // // If the parameter pubkey is present, add it to the list.
53
- // if (params_pk !== undefined) pubkeys.add(params_pk)
54
- // // If the witness type is a p2w-sh:
55
- // } else if (type === 'p2w-sh') {
56
- // // Parse any witness parameter pubkeys.
57
- // witness.params
58
- // .filter(p => p.length === 66)
59
- // .forEach(p => pubkeys.add(p))
60
- // // Parse any script pubkeys.
61
- // parse_segwit_pubkeys(witness.script!)
62
- // .forEach(p => pubkeys.add(p))
63
- // }
64
- // // Return the list of pubkeys.
65
- // return Array.from(pubkeys)
66
- // }
67
-
68
- // function parse_segwit_pubkeys (script : string) : string[] {
69
- // const regex = /21([0-9a-f]{66})(ac|ad)/gi
70
- // const matches = [...script.matchAll(regex)]
71
- // return matches.map(match => match[1])
72
- // }
73
-
74
- // function parse_taproot_pubkeys (script : string) : string[] {
75
- // const regex = /20([0-9a-f]{64})(ac|ad|ba)/gi
76
- // const matches = [...script.matchAll(regex)]
77
- // return matches.map(match => match[1])
78
- // }
@@ -1,182 +0,0 @@
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
-
114
- /**
115
- * Get the sting-representation of an opcode
116
- * based on its number value.
117
- */
118
- export function get_op_code (num : number) : string {
119
- if (num > 186 && num < 255) {
120
- return 'OP_SUCCESS' + String(num)
121
- }
122
- for (const [ k, v ] of Object.entries(OPCODE_MAP)) {
123
- if (v === num) return k
124
- }
125
- throw new Error('OPCODE not found:' + String(num))
126
- }
127
-
128
- /**
129
- * Get the number-representation of an opcode
130
- * based on its asm string value.
131
- */
132
- export function get_asm_code (string : string) : number {
133
- for (const [ k, v ] of Object.entries(OPCODE_MAP)) {
134
- if (k === string) return Number(v)
135
- }
136
- throw new Error('OPCODE not found:' + string)
137
- }
138
-
139
- /**
140
- * Get the type of word based on its number value.
141
- */
142
- export function get_op_type (word : number) : string {
143
- switch (true) {
144
- case (word === 0):
145
- return 'opcode'
146
- case (word >= 1 && word <= 75):
147
- return 'varint'
148
- case (word === 76):
149
- return 'pushdata1'
150
- case (word === 77):
151
- return 'pushdata2'
152
- case (word === 78):
153
- return 'pushdata4'
154
- case (word <= 254):
155
- return 'opcode'
156
- default:
157
- throw new Error(`Invalid word range: ${word}`)
158
- }
159
- }
160
-
161
- /**
162
- * Check if the provided value is a valid script opcode.
163
- */
164
- export function is_valid_op (word : number) : boolean {
165
- const MIN_RANGE = 75
166
- const MAX_RANGE = 254
167
-
168
- const DISABLED_OPCODES : number[] = []
169
-
170
- switch (true) {
171
- case (typeof (word) !== 'number'):
172
- return false
173
- case (word === 0):
174
- return true
175
- case (DISABLED_OPCODES.includes(word)):
176
- return false
177
- case (MIN_RANGE < word && word < MAX_RANGE):
178
- return true
179
- default:
180
- return false
181
- }
182
- }
@@ -1,3 +0,0 @@
1
- export * from './segwit.js'
2
- export * from './taproot.js'
3
- export * from './util.js'
@@ -1,152 +0,0 @@
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
-
6
- import {
7
- prefix_script_size,
8
- decode_script
9
- } from '@/lib/script/index.js'
10
-
11
- import {
12
- encode_txin_vout,
13
- encode_tx_locktime,
14
- encode_txin_sequence,
15
- encode_txin_txid,
16
- encode_vout_value,
17
- encode_tx_version,
18
- parse_tx
19
- } from '@/lib/tx/index.js'
20
-
21
- import {
22
- SigHashOptions,
23
- TxData,
24
- TxInput,
25
- TxOutput
26
- } from '@/types/index.js'
27
-
28
- import * as CONST from '@/const.js'
29
-
30
- export function hash_segwit_tx (
31
- txdata : TxData,
32
- options : SigHashOptions = {}
33
- ) : Buff {
34
- // Unpack the sigflag from our config object.
35
- const { sigflag = 0x01, txindex } = options
36
- // Normalize the tx into JSON format.
37
- const tx = parse_tx(txdata)
38
- // Check if the ANYONECANPAY flag is set.
39
- const is_anypay = (sigflag & 0x80) === 0x80
40
- // Save a normalized version of the sigflag.
41
- const flag = sigflag % 0x80
42
- // Check if the sigflag exists as a valid type.
43
- if (!CONST.SIGHASH_SEGWIT.includes(flag)) {
44
- throw new Error('Invalid hash type: ' + String(sigflag))
45
- }
46
- // Unpack the tx object.
47
- const { version, vin, vout, locktime } = tx
48
- // Parse the input we are signing from the config.
49
- const txinput = parse_txinput(tx, options)
50
- // Unpack the chosen input for signing.
51
- const { txid, vout: prevIdx, prevout, sequence } = txinput
52
- // Unpack the prevout for the chosen input.
53
- const { value } = prevout ?? {}
54
- // Check if a prevout value is provided.
55
- if (value === undefined) {
56
- throw new Error('Prevout value is empty!')
57
- }
58
- // Initialize our script variable from the config.
59
- let { pubkey, script } = options
60
- // Check if a pubkey is provided (instead of a script).
61
- if (script === undefined && pubkey !== undefined) {
62
- const pkhash = hash160(pubkey).hex
63
- script = `76a914${String(pkhash)}88ac`
64
- }
65
- // Make sure that some form of script has been provided.
66
- if (script === undefined) {
67
- throw new Error('No pubkey / script has been set!')
68
- }
69
- // Throw if OP_CODESEPARATOR is used in a script.
70
- if (decode_script(script).includes('OP_CODESEPARATOR')) {
71
- throw new Error('This library does not currently support the use of OP_CODESEPARATOR in segwit scripts.')
72
- }
73
-
74
- const sighash = [
75
- encode_tx_version(version),
76
- bip143_hash_prevouts(vin, is_anypay),
77
- bip143_hash_sequence(vin, flag, is_anypay),
78
- encode_txin_txid(txid),
79
- encode_txin_vout(prevIdx),
80
- prefix_script_size(script),
81
- encode_vout_value(value),
82
- encode_txin_sequence(sequence),
83
- bip143_hash_outputs(vout, flag, txindex),
84
- encode_tx_locktime(locktime),
85
- Buff.num(sigflag, 4).reverse()
86
- ]
87
-
88
- return hash256(Buff.join(sighash))
89
- }
90
-
91
- export function bip143_hash_prevouts (
92
- vin : TxInput[],
93
- isAnypay ?: boolean
94
- ) : Uint8Array {
95
- if (isAnypay === true) {
96
- return Buff.num(0, 32)
97
- }
98
-
99
- const stack = []
100
-
101
- for (const { txid, vout } of vin) {
102
- stack.push(encode_txin_txid(txid))
103
- stack.push(encode_txin_vout(vout))
104
- }
105
-
106
- return hash256(Buff.join(stack))
107
- }
108
-
109
- export function bip143_hash_sequence (
110
- vin : TxInput[],
111
- sigflag : number,
112
- isAnyPay : boolean
113
- ) : Uint8Array {
114
- if (isAnyPay || sigflag !== 0x01) {
115
- return Buff.num(0, 32)
116
- }
117
-
118
- const stack = []
119
-
120
- for (const { sequence } of vin) {
121
- stack.push(encode_txin_sequence(sequence))
122
- }
123
- return hash256(Buff.join(stack))
124
- }
125
-
126
- export function bip143_hash_outputs (
127
- vout : TxOutput[],
128
- sigflag : number,
129
- idx ?: number
130
- ) : Uint8Array {
131
- const stack = []
132
-
133
- if (sigflag === 0x01) {
134
- for (const { value, script_pk } of vout) {
135
- stack.push(encode_vout_value(value))
136
- stack.push(prefix_script_size(script_pk))
137
- }
138
- return hash256(Buff.join(stack))
139
- }
140
-
141
- if (sigflag === 0x03) {
142
- Assert.ok(idx !== undefined)
143
- if (idx < vout.length) {
144
- const { value, script_pk } = vout[idx]
145
- stack.push(encode_vout_value(value))
146
- stack.push(prefix_script_size(script_pk))
147
- return hash256(Buff.join(stack))
148
- }
149
- }
150
-
151
- return Buff.num(0, 32)
152
- }
@@ -1,206 +0,0 @@
1
- import { Buff } from '@vbyte/buff'
2
- import { Assert } from '@vbyte/micro-lib'
3
- import { hash340, sha256 } from '@vbyte/micro-lib/hash'
4
- import { encode_tapscript } from '@/lib/taproot/encode.js'
5
- import { parse_tx } from '@/lib/tx/parse.js'
6
- import * as CONST from '@/const.js'
7
-
8
- import {
9
- parse_txinput,
10
- get_annex_data,
11
- get_prevout
12
- } from './util.js'
13
-
14
- import {
15
- encode_txin_vout,
16
- encode_tx_locktime,
17
- encode_txin_sequence,
18
- encode_txin_txid,
19
- encode_vout_value,
20
- encode_tx_version,
21
- encode_script_data
22
- } from '@/lib/tx/encode.js'
23
-
24
- import type {
25
- SigHashOptions,
26
- TxData,
27
- TxInput,
28
- TxOutput
29
- } from '@/types/index.js'
30
-
31
- export function hash_taproot_tx (
32
- template : TxData | string,
33
- config : SigHashOptions = {}
34
- ) : Buff {
35
- const preimage = get_taproot_tx_preimage(template, config)
36
- return hash340('TapSighash', preimage)
37
- }
38
-
39
- export function get_taproot_tx_preimage (
40
- template : TxData | string,
41
- config : SigHashOptions = {}
42
- ) : Buff {
43
- // Unpack configuration.
44
- const {
45
- script,
46
- txindex,
47
- sigflag = 0x00,
48
- extflag = 0x00,
49
- key_version = 0x00,
50
- separator_pos = 0xFFFFFFFF
51
- } = config
52
-
53
- // Normalize the txdata object.
54
- const tx = parse_tx(template)
55
- // Unpack the txdata object.
56
- const { version, vin: input, vout: output, locktime } = tx
57
- // Parse the input we are signing from the config.
58
- const txinput = parse_txinput(tx, config)
59
- // Unpack the txinput object.
60
- const { txid, vout, sequence, witness = [] } = txinput
61
- // Check if we are using a valid hash type.
62
- if (!CONST.SIGHASH_TAPROOT.includes(sigflag)) {
63
- // If the sigflag is an invalid type, throw error.
64
- throw new Error('Invalid hash type: ' + String(sigflag))
65
- }
66
- if (extflag < 0 || extflag > 127) {
67
- // If the extflag is out of range, throw error.
68
- throw new Error('Extention flag out of range: ' + String(extflag))
69
- }
70
-
71
- let { extension } = config
72
-
73
- if (script !== undefined) {
74
- extension = encode_tapscript(script).hex
75
- }
76
-
77
- // Define the parameters of the transaction.
78
- const is_anypay = (sigflag & 0x80) === 0x80
79
- const annex = get_annex_data(witness)
80
- const annexBit = (annex !== undefined) ? 1 : 0
81
- const extendBit = (extension !== undefined) ? 1 : 0
82
- const spendType = ((extflag + extendBit) * 2) + annexBit
83
-
84
- // Begin building our preimage.
85
- const preimage : (string | Uint8Array)[] = [
86
- Buff.num(0x00, 1), // Add zero-byte.
87
- Buff.num(sigflag, 1), // Commit to signature flag.
88
- encode_tx_version(version), // Commit to tx version.
89
- encode_tx_locktime(locktime) // Commit to tx locktime.
90
- ]
91
-
92
- if (!is_anypay) {
93
- // If flag ANYONE_CAN_PAY is not set,
94
- // then commit to all inputs.
95
- const prevouts = input.map(e => get_prevout(e))
96
- preimage.push(
97
- bip341_hash_outpoints(input), // Commit to txid/vout for each input.
98
- bip341_hash_amounts(prevouts), // Commit to prevout amount for each input.
99
- bip341_hash_scripts(prevouts), // Commit to prevout script for each input.
100
- bip341_hash_sequence(input) // Commit to sequence value for each input.
101
- )
102
- }
103
-
104
- if ((sigflag & 0x03) < 2 || (sigflag & 0x03) > 3) {
105
- // If neither SINGLE or NONE flags are set,
106
- // include a commitment to all outputs.
107
- preimage.push(bip341_hash_outputs(output))
108
- }
109
-
110
- // At this step, we include the spend type.
111
- preimage.push(Buff.num(spendType, 1))
112
-
113
- if (is_anypay) {
114
- // If ANYONE_CAN_PAY flag is set, then we will
115
- // provide a commitment to the input being signed.
116
- const { value, script_pk } = get_prevout(txinput)
117
- preimage.push(
118
- encode_txin_txid(txid), // Commit to the input txid.
119
- encode_txin_vout(vout), // Commit to the input vout index.
120
- encode_vout_value(value), // Commit to the input's prevout value.
121
- encode_script_data(script_pk), // Commit to the input's prevout script.
122
- encode_txin_sequence(sequence) // Commit to the input's sequence value.
123
- )
124
- } else {
125
- // Otherwise, we must have already included a commitment
126
- // to all inputs in the tx, so simply add a commitment to
127
- // the index of the input we are signing for.
128
- Assert.ok(typeof txindex === 'number')
129
- preimage.push(Buff.num(txindex, 4).reverse())
130
- }
131
-
132
- if (annex !== undefined) {
133
- // If an annex has been set, include it here.
134
- preimage.push(annex)
135
- }
136
-
137
- if ((sigflag & 0x03) === 0x03) {
138
- // If the SINGLE flag is set, then include a
139
- // commitment to the output which is adjacent
140
- // to the input that we are signing for.
141
- Assert.ok(typeof txindex === 'number')
142
- preimage.push(bip341_hash_output(output[txindex]))
143
- }
144
-
145
- if (extension !== undefined) {
146
- // If we are extending this signature to include
147
- // other commitments (such as a tapleaf), then we
148
- // will add it to the preimage here.
149
- preimage.push(
150
- Buff.bytes(extension), // Extention data (in bytes).
151
- Buff.num(key_version), // Key version (reserved for future upgrades).
152
- Buff.num(separator_pos, 4,'le') // If OP_CODESEPARATOR is used, this must be set.
153
- )
154
- }
155
-
156
- return Buff.join(preimage)
157
- }
158
-
159
- export function bip341_hash_outpoints (
160
- vin : TxInput[]
161
- ) : Buff {
162
- const stack = []
163
- for (const { txid, vout } of vin) {
164
- stack.push(encode_txin_txid(txid))
165
- stack.push(encode_txin_vout(vout))
166
- }
167
- return sha256(Buff.join(stack))
168
- }
169
-
170
- export function bip341_hash_sequence (
171
- vin : TxInput[]
172
- ) : Buff {
173
- return sha256(...vin.map(vin => encode_txin_sequence(vin.sequence)))
174
- }
175
-
176
- export function bip341_hash_amounts (
177
- prevouts : TxOutput[]
178
- ) : Buff {
179
- return sha256(...prevouts.map(prevout => encode_vout_value(prevout.value)))
180
- }
181
-
182
- export function bip341_hash_scripts (
183
- prevouts : TxOutput[]
184
- ) : Buff {
185
- return sha256(...prevouts.map(prevout => encode_script_data(prevout.script_pk)))
186
- }
187
-
188
- export function bip341_hash_outputs (
189
- vout : TxOutput[]
190
- ) : Buff {
191
- const stack = []
192
- for (const { value, script_pk } of vout) {
193
- stack.push(encode_vout_value(value))
194
- stack.push(encode_script_data(script_pk))
195
- }
196
- return sha256(...stack)
197
- }
198
-
199
- export function bip341_hash_output (
200
- vout : TxOutput
201
- ) : Buff {
202
- return sha256(
203
- encode_vout_value(vout.value),
204
- encode_script_data(vout.script_pk)
205
- )
206
- }
@@ -1,51 +0,0 @@
1
- import { Buff } from '@vbyte/buff'
2
- import { Assert } from '@vbyte/micro-lib'
3
- import { sha256 } from '@vbyte/micro-lib/hash'
4
-
5
- import type {
6
- SigHashOptions,
7
- TxInput,
8
- TxData,
9
- TxOutput,
10
- } from '@/types/index.js'
11
-
12
- export function get_prevout (vin : TxInput) : TxOutput {
13
- Assert.exists(vin.prevout, 'Prevout data missing for input: ' + String(vin.txid))
14
- return vin.prevout
15
- }
16
-
17
- export function parse_txinput (
18
- txdata : TxData,
19
- config ?: SigHashOptions
20
- ) : TxInput {
21
- let { txindex, txinput } = config ?? {}
22
- if (txindex !== undefined) {
23
- if (txindex >= txdata.vin.length) {
24
- // If index is out of bounds, throw error.
25
- throw new Error('Input index out of bounds: ' + String(txindex))
26
- }
27
- txinput = txdata.vin.at(txindex)
28
- }
29
- Assert.ok(txinput !== undefined)
30
- return txinput
31
- }
32
-
33
- export function get_annex_data (
34
- witness ?: string[]
35
- ) : Buff | undefined {
36
- // If no witness exists, return undefined.
37
- if (witness === undefined) return
38
- // If there are less than two elements, return undefined.
39
- if (witness.length < 2) return
40
- // Define the last element as the annex.
41
- const annex = witness.at(-1)
42
- // If the annex is a string and starts with '50',
43
- if (typeof annex === 'string' && annex.startsWith('50')) {
44
- // Convert the annex to a buffer with a varint prefix.
45
- const bytes = Buff.hex(annex).prefix_varint('be')
46
- // Return the sha256 of the annex.
47
- return sha256(bytes)
48
- }
49
- // Else, return undefined.
50
- return undefined
51
- }
@@ -1,2 +0,0 @@
1
- export * from './sign.js'
2
- export * from './verify.js'