@@ -208,6 +208,18 @@ pub(super) fn from_txdata<'txin>(
208
208
} else {
209
209
let output_key = bitcoin:: XOnlyPublicKey :: from_slice ( & spk[ 2 ..] )
210
210
. map_err ( |_| Error :: XOnlyPublicKeyParseError ) ?;
211
+ if wit_stack. len ( ) >= 2 {
212
+ let has_annex = wit_stack
213
+ . last ( )
214
+ . and_then ( |x| x. as_push ( ) . ok ( ) )
215
+ . map ( |x| x. len ( ) > 0 && x[ 0 ] == TAPROOT_ANNEX_PREFIX )
216
+ . unwrap_or ( false ) ;
217
+ if has_annex {
218
+ wit_stack. pop ( ) ;
219
+ } else {
220
+ // no annex
221
+ }
222
+ }
211
223
if wit_stack. len ( ) == 1 {
212
224
// Key spend
213
225
Ok ( (
@@ -216,47 +228,36 @@ pub(super) fn from_txdata<'txin>(
216
228
None , // Tr script code None
217
229
) )
218
230
} else {
219
- // wit_stack.len() >=2
220
- // Check for annex
221
231
let ctrl_blk = wit_stack. pop ( ) . ok_or ( Error :: UnexpectedStackEnd ) ?;
222
232
let ctrl_blk = ctrl_blk. as_push ( ) ?;
223
233
let tap_script = wit_stack. pop ( ) . ok_or ( Error :: UnexpectedStackEnd ) ?;
224
- if ctrl_blk. len ( ) > 0 && ctrl_blk[ 0 ] == TAPROOT_ANNEX_PREFIX {
225
- // Annex is non-standard, bitcoin consensus rules ignore it.
226
- // Our sighash structure and signature verification
227
- // does not support annex, return error
228
- return Err ( Error :: TapAnnexUnsupported ) ;
229
- } else if wit_stack. len ( ) >= 2 {
230
- let ctrl_blk = ControlBlock :: from_slice ( ctrl_blk)
231
- . map_err ( |e| Error :: ControlBlockParse ( e) ) ?;
232
- let tap_script = script_from_stackelem :: < Tap > ( & tap_script) ?;
233
- let ms = tap_script. to_no_checks_ms ( ) ;
234
- // Creating new contexts is cheap
235
- let secp = bitcoin:: secp256k1:: Secp256k1 :: verification_only ( ) ;
236
- let tap_script = tap_script. encode ( ) ;
237
- // Should not really need to call dangerous assumed tweaked here.
238
- // Should be fixed after RC
239
- if ctrl_blk. verify_taproot_commitment (
240
- & secp,
241
- & output_key. dangerous_assume_tweaked ( ) ,
242
- & tap_script,
243
- ) {
244
- Ok ( (
245
- Inner :: Script ( ms, ScriptType :: Tr ) ,
246
- wit_stack,
247
- // Tapscript is returned as a "scriptcode". This is a hack, but avoids adding yet
248
- // another enum just for taproot, and this function is not a publicly exposed API,
249
- // so it's easy enough to keep track of all uses.
250
- //
251
- // In particular, this return value will be put into the `script_code` member of
252
- // the `Interpreter` script; the iterpreter logic does the right thing with it.
253
- Some ( tap_script) ,
254
- ) )
255
- } else {
256
- return Err ( Error :: ControlBlockVerificationError ) ;
257
- }
234
+ let ctrl_blk =
235
+ ControlBlock :: from_slice ( ctrl_blk) . map_err ( |e| Error :: ControlBlockParse ( e) ) ?;
236
+ let tap_script = script_from_stackelem :: < Tap > ( & tap_script) ?;
237
+ let ms = tap_script. to_no_checks_ms ( ) ;
238
+ // Creating new contexts is cheap
239
+ let secp = bitcoin:: secp256k1:: Secp256k1 :: verification_only ( ) ;
240
+ let tap_script = tap_script. encode ( ) ;
241
+ // Should not really need to call dangerous assumed tweaked here.
242
+ // Should be fixed after RC
243
+ if ctrl_blk. verify_taproot_commitment (
244
+ & secp,
245
+ & output_key. dangerous_assume_tweaked ( ) ,
246
+ & tap_script,
247
+ ) {
248
+ Ok ( (
249
+ Inner :: Script ( ms, ScriptType :: Tr ) ,
250
+ wit_stack,
251
+ // Tapscript is returned as a "scriptcode". This is a hack, but avoids adding yet
252
+ // another enum just for taproot, and this function is not a publicly exposed API,
253
+ // so it's easy enough to keep track of all uses.
254
+ //
255
+ // In particular, this return value will be put into the `script_code` member of
256
+ // the `Interpreter` script; the iterpreter logic does the right thing with it.
257
+ Some ( tap_script) ,
258
+ ) )
258
259
} else {
259
- return Err ( Error :: UnexpectedStackBoolean ) ;
260
+ return Err ( Error :: ControlBlockVerificationError ) ;
260
261
}
261
262
}
262
263
}
0 commit comments