Fix bug in witness stack getters
In #2646 we introduced a bug in the taproot witness stack getter functions, of which we have three: - `tapscript` - `taproot_control_block` - `taproot_annex` Each returns `Some` if a possible bytes slice is found (with no other guarantees). Use `taproot_annex` combined with getters from `primitives` to implement the other two getters. This simplifies the code and fixes the bug. Add an additional getter to `primitives` `Witness::third_from_last`. Fix: #3598
This commit is contained in:
parent
73e33e5808
commit
195615c14d
|
@ -147,19 +147,15 @@ crate::internal_macros::define_extension_trait! {
|
||||||
///
|
///
|
||||||
/// See [`Script::is_p2tr`] to check whether this is actually a Taproot witness.
|
/// See [`Script::is_p2tr`] to check whether this is actually a Taproot witness.
|
||||||
fn tapscript(&self) -> Option<&Script> {
|
fn tapscript(&self) -> Option<&Script> {
|
||||||
self.last().and_then(|last| {
|
if self.is_empty() {
|
||||||
// From BIP341:
|
return None;
|
||||||
// If there are at least two witness elements, and the first byte of
|
}
|
||||||
// the last element is 0x50, this last element is called annex a
|
|
||||||
// and is removed from the witness stack.
|
if self.taproot_annex().is_some() {
|
||||||
if self.len() >= 3 && last.first() == Some(&TAPROOT_ANNEX_PREFIX) {
|
self.third_to_last().map(Script::from_bytes)
|
||||||
self.nth(self.len() - 3).map(Script::from_bytes)
|
} else {
|
||||||
} else if self.len() >= 2 {
|
self.second_to_last().map(Script::from_bytes)
|
||||||
self.nth(self.len() - 2).map(Script::from_bytes)
|
}
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the taproot control block following BIP341 rules.
|
/// Get the taproot control block following BIP341 rules.
|
||||||
|
@ -170,19 +166,15 @@ crate::internal_macros::define_extension_trait! {
|
||||||
///
|
///
|
||||||
/// See [`Script::is_p2tr`] to check whether this is actually a Taproot witness.
|
/// See [`Script::is_p2tr`] to check whether this is actually a Taproot witness.
|
||||||
fn taproot_control_block(&self) -> Option<&[u8]> {
|
fn taproot_control_block(&self) -> Option<&[u8]> {
|
||||||
self.last().and_then(|last| {
|
if self.is_empty() {
|
||||||
// From BIP341:
|
return None;
|
||||||
// If there are at least two witness elements, and the first byte of
|
}
|
||||||
// the last element is 0x50, this last element is called annex a
|
|
||||||
// and is removed from the witness stack.
|
if self.taproot_annex().is_some() {
|
||||||
if self.len() >= 3 && last.first() == Some(&TAPROOT_ANNEX_PREFIX) {
|
self.second_to_last()
|
||||||
self.nth(self.len() - 2)
|
} else {
|
||||||
} else if self.len() >= 2 {
|
self.last()
|
||||||
Some(last)
|
}
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the taproot annex following BIP341 rules.
|
/// Get the taproot annex following BIP341 rules.
|
||||||
|
|
|
@ -192,6 +192,15 @@ impl Witness {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the third-to-last element in the witness, if any.
|
||||||
|
pub fn third_to_last(&self) -> Option<&[u8]> {
|
||||||
|
if self.witness_elements <= 2 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
self.nth(self.witness_elements - 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the nth element in the witness, if any
|
/// Return the nth element in the witness, if any
|
||||||
pub fn nth(&self, index: usize) -> Option<&[u8]> {
|
pub fn nth(&self, index: usize) -> Option<&[u8]> {
|
||||||
let pos = decode_cursor(&self.content, self.indices_start, index)?;
|
let pos = decode_cursor(&self.content, self.indices_start, index)?;
|
||||||
|
|
Loading…
Reference in New Issue