@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.
- package/CHANGELOG.md +94 -0
- package/README.md +260 -3
- package/dist/const.d.ts +3 -0
- package/dist/const.js +23 -22
- package/dist/index.d.ts +11 -11
- package/dist/index.js +10 -10
- package/dist/lib/address/api.d.ts +2 -2
- package/dist/lib/address/api.js +12 -12
- package/dist/lib/address/encode.d.ts +1 -1
- package/dist/lib/address/encode.js +24 -24
- package/dist/lib/address/index.d.ts +6 -6
- package/dist/lib/address/index.js +6 -6
- package/dist/lib/address/p2pkh.d.ts +2 -2
- package/dist/lib/address/p2pkh.js +14 -14
- package/dist/lib/address/p2sh.d.ts +2 -2
- package/dist/lib/address/p2sh.js +13 -13
- package/dist/lib/address/p2tr.d.ts +2 -2
- package/dist/lib/address/p2tr.js +13 -13
- package/dist/lib/address/p2wpkh.d.ts +2 -2
- package/dist/lib/address/p2wpkh.js +14 -14
- package/dist/lib/address/p2wsh.d.ts +2 -2
- package/dist/lib/address/p2wsh.js +13 -13
- package/dist/lib/address/script.d.ts +1 -1
- package/dist/lib/address/script.js +16 -16
- package/dist/lib/address/util.d.ts +1 -1
- package/dist/lib/address/util.js +22 -22
- package/dist/lib/meta/index.d.ts +4 -4
- package/dist/lib/meta/index.js +4 -4
- package/dist/lib/meta/locktime.d.ts +1 -1
- package/dist/lib/meta/locktime.js +12 -12
- package/dist/lib/meta/ref.js +9 -6
- package/dist/lib/meta/scribe.d.ts +2 -2
- package/dist/lib/meta/scribe.js +48 -53
- package/dist/lib/meta/sequence.d.ts +1 -1
- package/dist/lib/meta/sequence.js +16 -15
- package/dist/lib/script/decode.d.ts +2 -2
- package/dist/lib/script/decode.js +50 -15
- package/dist/lib/script/encode.d.ts +1 -1
- package/dist/lib/script/encode.js +20 -16
- package/dist/lib/script/index.d.ts +5 -13
- package/dist/lib/script/index.js +5 -14
- package/dist/lib/script/lock.d.ts +2 -2
- package/dist/lib/script/lock.js +15 -12
- package/dist/lib/script/util.js +4 -4
- package/dist/lib/script/words.js +129 -129
- package/dist/lib/sighash/index.d.ts +3 -3
- package/dist/lib/sighash/index.js +3 -3
- package/dist/lib/sighash/segwit.d.ts +2 -2
- package/dist/lib/sighash/segwit.js +15 -14
- package/dist/lib/sighash/taproot.d.ts +2 -2
- package/dist/lib/sighash/taproot.js +24 -23
- package/dist/lib/sighash/util.d.ts +2 -2
- package/dist/lib/sighash/util.js +7 -7
- package/dist/lib/signer/index.d.ts +2 -2
- package/dist/lib/signer/index.js +2 -2
- package/dist/lib/signer/sign.d.ts +1 -1
- package/dist/lib/signer/sign.js +42 -7
- package/dist/lib/signer/verify.d.ts +17 -3
- package/dist/lib/signer/verify.js +233 -3
- package/dist/lib/taproot/cblock.d.ts +1 -1
- package/dist/lib/taproot/cblock.js +14 -16
- package/dist/lib/taproot/encode.d.ts +1 -1
- package/dist/lib/taproot/encode.js +7 -7
- package/dist/lib/taproot/index.d.ts +4 -4
- package/dist/lib/taproot/index.js +4 -4
- package/dist/lib/taproot/parse.d.ts +1 -1
- package/dist/lib/taproot/parse.js +12 -14
- package/dist/lib/taproot/tree.d.ts +2 -2
- package/dist/lib/taproot/tree.js +11 -7
- package/dist/lib/tx/create.d.ts +1 -1
- package/dist/lib/tx/create.js +28 -12
- package/dist/lib/tx/decode.d.ts +2 -2
- package/dist/lib/tx/decode.js +50 -17
- package/dist/lib/tx/encode.d.ts +2 -2
- package/dist/lib/tx/encode.js +13 -16
- package/dist/lib/tx/index.d.ts +7 -7
- package/dist/lib/tx/index.js +7 -7
- package/dist/lib/tx/parse.d.ts +1 -1
- package/dist/lib/tx/parse.js +9 -9
- package/dist/lib/tx/size.d.ts +2 -2
- package/dist/lib/tx/size.js +9 -9
- package/dist/lib/tx/util.d.ts +2 -2
- package/dist/lib/tx/util.js +23 -20
- package/dist/lib/tx/validate.d.ts +1 -1
- package/dist/lib/tx/validate.js +3 -3
- package/dist/lib/witness/index.d.ts +2 -2
- package/dist/lib/witness/index.js +2 -2
- package/dist/lib/witness/parse.d.ts +2 -2
- package/dist/lib/witness/parse.js +24 -23
- package/dist/lib/witness/util.d.ts +2 -2
- package/dist/lib/witness/util.js +5 -5
- package/dist/main.cjs +2308 -1005
- package/dist/main.cjs.map +1 -1
- package/dist/module.mjs +2308 -1005
- package/dist/module.mjs.map +1 -1
- package/dist/package.json +20 -17
- package/dist/schema/base.d.ts +1 -1
- package/dist/schema/base.js +17 -13
- package/dist/schema/index.d.ts +2 -2
- package/dist/schema/index.js +2 -2
- package/dist/schema/taproot.d.ts +1 -1
- package/dist/schema/taproot.js +2 -2
- package/dist/schema/tx.d.ts +1 -1
- package/dist/schema/tx.js +4 -4
- package/dist/script.js +8 -8
- package/dist/script.js.map +1 -1
- package/dist/types/address.d.ts +4 -4
- package/dist/types/index.d.ts +8 -8
- package/dist/types/index.js +8 -8
- package/dist/types/meta.d.ts +4 -4
- package/dist/types/psbt.d.ts +2 -2
- package/dist/types/script.d.ts +2 -2
- package/dist/types/sighash.d.ts +2 -2
- package/dist/types/witness.d.ts +5 -5
- package/package.json +20 -17
- package/src/const.ts +0 -61
- package/src/index.ts +0 -13
- package/src/lib/address/api.ts +0 -50
- package/src/lib/address/encode.ts +0 -183
- package/src/lib/address/index.ts +0 -7
- package/src/lib/address/p2pkh.ts +0 -94
- package/src/lib/address/p2sh.ts +0 -96
- package/src/lib/address/p2tr.ts +0 -91
- package/src/lib/address/p2wpkh.ts +0 -94
- package/src/lib/address/p2wsh.ts +0 -92
- package/src/lib/address/script.ts +0 -63
- package/src/lib/address/util.ts +0 -87
- package/src/lib/meta/index.ts +0 -4
- package/src/lib/meta/locktime.ts +0 -57
- package/src/lib/meta/ref.ts +0 -107
- package/src/lib/meta/scribe.ts +0 -256
- package/src/lib/meta/sequence.ts +0 -146
- package/src/lib/script/decode.ts +0 -85
- package/src/lib/script/encode.ts +0 -129
- package/src/lib/script/index.ts +0 -20
- package/src/lib/script/lock.ts +0 -73
- package/src/lib/script/util.ts +0 -78
- package/src/lib/script/words.ts +0 -182
- package/src/lib/sighash/index.ts +0 -3
- package/src/lib/sighash/segwit.ts +0 -152
- package/src/lib/sighash/taproot.ts +0 -206
- package/src/lib/sighash/util.ts +0 -51
- package/src/lib/signer/index.ts +0 -2
- package/src/lib/signer/sign.ts +0 -39
- package/src/lib/signer/verify.ts +0 -88
- package/src/lib/taproot/cblock.ts +0 -96
- package/src/lib/taproot/encode.ts +0 -49
- package/src/lib/taproot/index.ts +0 -4
- package/src/lib/taproot/parse.ts +0 -65
- package/src/lib/taproot/tree.ts +0 -94
- package/src/lib/tx/create.ts +0 -90
- package/src/lib/tx/decode.ts +0 -123
- package/src/lib/tx/encode.ts +0 -155
- package/src/lib/tx/index.ts +0 -7
- package/src/lib/tx/parse.ts +0 -69
- package/src/lib/tx/size.ts +0 -68
- package/src/lib/tx/util.ts +0 -111
- package/src/lib/tx/validate.ts +0 -49
- package/src/lib/witness/index.ts +0 -2
- package/src/lib/witness/parse.ts +0 -127
- package/src/lib/witness/util.ts +0 -18
- package/src/schema/base.ts +0 -57
- package/src/schema/index.ts +0 -2
- package/src/schema/taproot.ts +0 -12
- package/src/schema/tx.ts +0 -48
- package/src/types/address.ts +0 -35
- package/src/types/index.ts +0 -8
- package/src/types/meta.ts +0 -48
- package/src/types/psbt.ts +0 -15
- package/src/types/script.ts +0 -18
- package/src/types/sighash.ts +0 -16
- package/src/types/taproot.ts +0 -41
- package/src/types/txdata.ts +0 -85
- package/src/types/witness.ts +0 -42
package/src/lib/script/util.ts
DELETED
|
@@ -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
|
-
// }
|
package/src/lib/script/words.ts
DELETED
|
@@ -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
|
-
}
|
package/src/lib/sighash/index.ts
DELETED
|
@@ -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
|
-
}
|
package/src/lib/sighash/util.ts
DELETED
|
@@ -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
|
-
}
|
package/src/lib/signer/index.ts
DELETED