witness: Improve Witness::tapscript

This commit is contained in:
Steven Roose 2023-10-12 13:45:44 +01:00
parent e48a2e4225
commit ef336e1387
No known key found for this signature in database
GPG Key ID: 2F2A88D7F8D68E87
1 changed files with 15 additions and 28 deletions

View File

@ -394,24 +394,19 @@ impl Witness {
/// [Script::is_p2tr](crate::blockdata::script::Script::is_p2tr) to /// [Script::is_p2tr](crate::blockdata::script::Script::is_p2tr) to
/// check whether this is actually a Taproot witness. /// check whether this is actually a Taproot witness.
pub fn tapscript(&self) -> Option<&Script> { pub fn tapscript(&self) -> Option<&Script> {
let len = self.len(); self.last().and_then(|last| {
self.last() // From BIP341:
.map(|last_elem| { // If there are at least two witness elements, and the first byte of
// From BIP341: // the last element is 0x50, this last element is called annex a
// If there are at least two witness elements, and the first byte of // and is removed from the witness stack.
// the last element is 0x50, this last element is called annex a if self.len() >= 3 && last.first() == Some(&TAPROOT_ANNEX_PREFIX) {
// and is removed from the witness stack. self.nth(self.len() - 3).map(Script::from_bytes)
if len >= 2 && last_elem.first() == Some(&TAPROOT_ANNEX_PREFIX) { } else if self.len() >= 2 {
// account for the extra item removed from the end self.nth(self.len() - 2).map(Script::from_bytes)
3 } else {
} else { None
// otherwise script is 2nd from last }
2 })
}
})
.filter(|&script_pos_from_last| len >= script_pos_from_last)
.and_then(|script_pos_from_last| self.nth(len - script_pos_from_last))
.map(Script::from_bytes)
} }
} }
@ -702,16 +697,8 @@ mod test {
let witness_serialized: Vec<u8> = serialize(&witness_vec); let witness_serialized: Vec<u8> = serialize(&witness_vec);
let witness_serialized_annex: Vec<u8> = serialize(&witness_vec_annex); let witness_serialized_annex: Vec<u8> = serialize(&witness_vec_annex);
let witness = Witness { let witness = deserialize::<Witness>(&witness_serialized[..]).unwrap();
content: append_u32_vec(witness_serialized[1..].to_vec(), &[0, 5]), let witness_annex = deserialize::<Witness>(&witness_serialized_annex[..]).unwrap();
witness_elements: 2,
indices_start: 7,
};
let witness_annex = Witness {
content: append_u32_vec(witness_serialized_annex[1..].to_vec(), &[0, 5, 7]),
witness_elements: 3,
indices_start: 9,
};
// With or without annex, the tapscript should be returned. // With or without annex, the tapscript should be returned.
assert_eq!(witness.tapscript(), Some(Script::from_bytes(&tapscript[..]))); assert_eq!(witness.tapscript(), Some(Script::from_bytes(&tapscript[..])));