1
1
import { bitcoin as BITCOIN_NETWORK } from '../networks' ;
2
2
import * as bscript from '../script' ;
3
3
import { typeforce as typef } from '../types' ;
4
- import { computeMastRoot , leafHash , rootHash , tweakKey , liftX } from '../taproot' ;
4
+ import {
5
+ computeMastRoot ,
6
+ leafHash ,
7
+ rootHash ,
8
+ tweakKey ,
9
+ liftX ,
10
+ } from '../taproot' ;
5
11
import { Payment , PaymentOpts } from './index' ;
6
12
import * as lazy from './lazy' ;
7
13
import { bech32m } from 'bech32' ;
@@ -14,7 +20,14 @@ const ANNEX_PREFIX = 0x50;
14
20
// input: <>
15
21
// output: OP_1 {pubKey}
16
22
export function p2tr ( a : Payment , opts ?: PaymentOpts ) : Payment {
17
- if ( ! a . address && ! a . output && ! a . pubkey && ! a . output && ! a . internalPubkey && ! ( a . witness && a . witness . length > 1 ) )
23
+ if (
24
+ ! a . address &&
25
+ ! a . output &&
26
+ ! a . pubkey &&
27
+ ! a . output &&
28
+ ! a . internalPubkey &&
29
+ ! ( a . witness && a . witness . length > 1 )
30
+ )
18
31
throw new TypeError ( 'Not enough data' ) ;
19
32
opts = Object . assign ( { validate : true } , opts || { } ) ;
20
33
@@ -46,13 +59,16 @@ export function p2tr(a: Payment, opts?: PaymentOpts): Payment {
46
59
} ) ;
47
60
48
61
const _witness = lazy . value ( ( ) => {
49
- if ( ! a . witness || ! a . witness . length ) return
50
- if ( a . witness . length >= 2 && ( a . witness [ a . witness . length - 1 ] [ 0 ] === ANNEX_PREFIX ) ) {
62
+ if ( ! a . witness || ! a . witness . length ) return ;
63
+ if (
64
+ a . witness . length >= 2 &&
65
+ a . witness [ a . witness . length - 1 ] [ 0 ] === ANNEX_PREFIX
66
+ ) {
51
67
// remove annex, ignored by taproot
52
68
return a . witness . slice ( 0 , - 1 ) ;
53
69
}
54
- return a . witness . slice ( )
55
- } )
70
+ return a . witness . slice ( ) ;
71
+ } ) ;
56
72
57
73
const network = a . network || BITCOIN_NETWORK ;
58
74
const o : Payment = { name : 'p2tr' , network } ;
@@ -65,48 +81,47 @@ export function p2tr(a: Payment, opts?: PaymentOpts): Payment {
65
81
return bech32m . encode ( network . bech32 , words ) ;
66
82
} ) ;
67
83
68
-
69
84
lazy . prop ( o , 'hash' , ( ) => {
70
85
if ( a . hash ) return a . hash ;
71
- if ( a . scriptsTree ) return computeMastRoot ( a . scriptsTree )
72
- const w = _witness ( )
86
+ if ( a . scriptsTree ) return computeMastRoot ( a . scriptsTree ) ;
87
+ const w = _witness ( ) ;
73
88
if ( w && w . length > 1 ) {
74
89
const controlBlock = w [ w . length - 1 ] ;
75
90
const leafVersion = controlBlock [ 0 ] & 0b11111110 ;
76
91
const script = w [ w . length - 2 ] ;
77
- const tapLeafHash = leafHash ( script , leafVersion )
78
- return rootHash ( controlBlock , tapLeafHash )
92
+ const tapLeafHash = leafHash ( script , leafVersion ) ;
93
+ return rootHash ( controlBlock , tapLeafHash ) ;
79
94
}
80
- return null
95
+ return null ;
81
96
} ) ;
82
97
lazy . prop ( o , 'output' , ( ) => {
83
98
if ( ! o . pubkey ) return ;
84
99
return bscript . compile ( [ OPS . OP_1 , o . pubkey ] ) ;
85
100
} ) ;
86
101
lazy . prop ( o , 'pubkey' , ( ) => {
87
102
if ( a . pubkey ) return a . pubkey ;
88
- if ( a . output ) return a . output . slice ( 2 )
103
+ if ( a . output ) return a . output . slice ( 2 ) ;
89
104
if ( a . address ) return _address ( ) . data ;
90
105
if ( o . internalPubkey ) {
91
- const tweakedKey = tweakKey ( o . internalPubkey , o . hash )
92
- if ( tweakedKey ) return tweakedKey . x
106
+ const tweakedKey = tweakKey ( o . internalPubkey , o . hash ) ;
107
+ if ( tweakedKey ) return tweakedKey . x ;
93
108
}
94
109
} ) ;
95
110
lazy . prop ( o , 'internalPubkey' , ( ) => {
96
111
if ( a . internalPubkey ) return a . internalPubkey ;
97
- const witness = _witness ( )
112
+ const witness = _witness ( ) ;
98
113
if ( witness && witness . length > 1 )
99
114
return witness [ witness . length - 1 ] . slice ( 1 , 33 ) ;
100
115
} ) ;
101
116
lazy . prop ( o , 'signature' , ( ) => {
102
- if ( a . witness ? .length !== 1 ) return ;
117
+ if ( ! a . witness || a . witness . length !== 1 ) return ;
103
118
return a . witness [ 0 ] ;
104
119
} ) ;
105
120
lazy . prop ( o , 'input' , ( ) => {
106
121
// todo: not sure
107
122
} ) ;
108
123
lazy . prop ( o , 'witness' , ( ) => {
109
- if ( a . witness ) return a . witness
124
+ if ( a . witness ) return a . witness ;
110
125
if ( ! a . signature ) return ;
111
126
return [ a . signature ] ;
112
127
} ) ;
@@ -143,26 +158,26 @@ export function p2tr(a: Payment, opts?: PaymentOpts): Payment {
143
158
}
144
159
145
160
if ( a . internalPubkey ) {
146
- const tweakedKey = tweakKey ( a . internalPubkey , o . hash )
147
- if ( tweakedKey === null ) throw new TypeError ( 'Invalid internalPubkey for p2tr' ) ;
161
+ const tweakedKey = tweakKey ( a . internalPubkey , o . hash ) ;
162
+ if ( tweakedKey === null )
163
+ throw new TypeError ( 'Invalid internalPubkey for p2tr' ) ;
148
164
if ( pubkey . length > 0 && ! pubkey . equals ( tweakedKey . x ) )
149
165
throw new TypeError ( 'Pubkey mismatch' ) ;
150
166
else pubkey = tweakedKey . x ;
151
167
}
152
168
153
- if ( pubkey ? .length ) {
169
+ if ( pubkey && pubkey . length ) {
154
170
if ( liftX ( pubkey ) === null )
155
171
throw new TypeError ( 'Invalid pubkey for p2tr' ) ;
156
172
}
157
173
158
174
if ( a . hash && a . scriptsTree ) {
159
- const hash = computeMastRoot ( a . scriptsTree )
160
- if ( ! a . hash . equals ( hash ) )
161
- throw new TypeError ( 'Hash mismatch' ) ;
175
+ const hash = computeMastRoot ( a . scriptsTree ) ;
176
+ if ( ! a . hash . equals ( hash ) ) throw new TypeError ( 'Hash mismatch' ) ;
162
177
}
163
178
164
179
// todo: review cache
165
- const witness = _witness ( )
180
+ const witness = _witness ( ) ;
166
181
167
182
if ( witness && witness . length ) {
168
183
if ( witness . length === 1 ) {
@@ -176,14 +191,22 @@ export function p2tr(a: Payment, opts?: PaymentOpts): Payment {
176
191
// script path spending
177
192
const controlBlock = witness [ witness . length - 1 ] ;
178
193
if ( controlBlock . length < 33 )
179
- throw new TypeError ( `The control-block length is too small. Got ${ controlBlock . length } , expected min 33.` ) ;
194
+ throw new TypeError (
195
+ `The control-block length is too small. Got ${
196
+ controlBlock . length
197
+ } , expected min 33.`,
198
+ ) ;
180
199
181
200
if ( ( controlBlock . length - 33 ) % 32 !== 0 )
182
- throw new TypeError ( `The control-block length of ${ controlBlock . length } is incorrect!` ) ;
201
+ throw new TypeError (
202
+ `The control-block length of ${ controlBlock . length } is incorrect!` ,
203
+ ) ;
183
204
184
205
const m = ( controlBlock . length - 33 ) / 32 ;
185
206
if ( m > 128 )
186
- throw new TypeError ( `The script path is too long. Got ${ m } , expected max 128.` ) ;
207
+ throw new TypeError (
208
+ `The script path is too long. Got ${ m } , expected max 128.` ,
209
+ ) ;
187
210
188
211
const internalPubkey = controlBlock . slice ( 1 , 33 ) ;
189
212
if ( a . internalPubkey && ! a . internalPubkey . equals ( internalPubkey ) )
@@ -196,23 +219,21 @@ export function p2tr(a: Payment, opts?: PaymentOpts): Payment {
196
219
const leafVersion = controlBlock [ 0 ] & 0b11111110 ;
197
220
const script = witness [ witness . length - 2 ] ;
198
221
199
- const tapLeafHash = leafHash ( script , leafVersion )
200
- const hash = rootHash ( controlBlock , tapLeafHash )
222
+ const tapLeafHash = leafHash ( script , leafVersion ) ;
223
+ const hash = rootHash ( controlBlock , tapLeafHash ) ;
201
224
202
- const outputKey = tweakKey ( internalPubkey , hash )
225
+ const outputKey = tweakKey ( internalPubkey , hash ) ;
203
226
if ( ! outputKey )
204
227
// todo: needs test data
205
228
throw new TypeError ( 'Invalid outputKey for p2tr witness' ) ;
206
229
207
230
if ( pubkey . length && ! pubkey . equals ( outputKey . x ) )
208
231
throw new TypeError ( 'Pubkey mismatch for p2tr witness' ) ;
209
232
210
- const controlBlockOddParity = ( controlBlock [ 0 ] & 1 ) === 1
233
+ const controlBlockOddParity = ( controlBlock [ 0 ] & 1 ) === 1 ;
211
234
if ( outputKey . isOdd !== controlBlockOddParity )
212
- throw new Error ( 'Incorrect parity' )
213
-
235
+ throw new Error ( 'Incorrect parity' ) ;
214
236
}
215
-
216
237
}
217
238
}
218
239
0 commit comments