Merge rust-bitcoin/rust-bitcoin#1380: `Witness` API improvements
d78a996bf6
Add `Witness::from_slice()` and depreciate `Witness:from_vec()` (Noah Lanson)d5bdf5d225
Add non-generic `Witness::push_slice()` method (Noah Lanson) Pull request description: Cleanup PR to improve the `Witness` API by: - Adding `Witness::from_slice()` and depreciating `Witness::from_vec()` methods (#1371). - Making `Witness::push()` not generic and take in `&[u8]` instead of `AsRef<[u8]>` (#1372). Note: `Witness::from_vec()` has been marked for depreciation from `0.30.0`. Let me know if this should be different. ACKs for top commit: tcharding: ACKd78a996bf6
apoelstra: ACKd78a996bf6
Tree-SHA512: 3a0b11b1ea77966a773cf7c9e9853822192897eac495fc0a23068bad3b0c46714fc839b20ceeb6e076aa10ea8ff0c023dfc418feff2f892cf11e8c057e5b0c7d
This commit is contained in:
commit
60f3a19acd
|
@ -1396,7 +1396,7 @@ mod tests {
|
||||||
// test that we get a failure if we corrupt a signature
|
// test that we get a failure if we corrupt a signature
|
||||||
let mut witness: Vec<_> = spending.input[1].witness.to_vec();
|
let mut witness: Vec<_> = spending.input[1].witness.to_vec();
|
||||||
witness[0][10] = 42;
|
witness[0][10] = 42;
|
||||||
spending.input[1].witness = Witness::from_vec(witness);
|
spending.input[1].witness = Witness::from_slice(&witness);
|
||||||
match spending.verify(|point: &OutPoint| {
|
match spending.verify(|point: &OutPoint| {
|
||||||
if let Some(tx) = spent3.remove(&point.txid) {
|
if let Some(tx) = spent3.remove(&point.txid) {
|
||||||
return tx.output.get(point.vout as usize).cloned();
|
return tx.output.get(point.vout as usize).cloned();
|
||||||
|
|
|
@ -20,15 +20,16 @@ use crate::util::taproot::TAPROOT_ANNEX_PREFIX;
|
||||||
|
|
||||||
/// The Witness is the data used to unlock bitcoins since the [segwit upgrade](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki)
|
/// The Witness is the data used to unlock bitcoins since the [segwit upgrade](https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki)
|
||||||
///
|
///
|
||||||
/// Can be logically seen as an array of byte-arrays `Vec<Vec<u8>>` and indeed you can convert from
|
/// Can be logically seen as an array of bytestrings, i.e. `Vec<Vec<u8>>`, and it is serialized on the wire
|
||||||
/// it [`Witness::from_vec`] and convert into it [`Witness::to_vec`].
|
/// in that format. You can convert between this type and `Vec<Vec<u8>>` by using [`Witness::from_slice`]
|
||||||
|
/// and [`Witness::to_vec`].
|
||||||
///
|
///
|
||||||
/// For serialization and deserialization performance it is stored internally as a single `Vec`,
|
/// For serialization and deserialization performance it is stored internally as a single `Vec`,
|
||||||
/// saving some allocations.
|
/// saving some allocations.
|
||||||
///
|
///
|
||||||
#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
#[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||||
pub struct Witness {
|
pub struct Witness {
|
||||||
/// contains the witness Vec<Vec<u8>> serialization without the initial varint indicating the
|
/// Contains the witness Vec<Vec<u8>> serialization without the initial varint indicating the
|
||||||
/// number of elements (which is stored in `witness_elements`)
|
/// number of elements (which is stored in `witness_elements`)
|
||||||
content: Vec<u8>,
|
content: Vec<u8>,
|
||||||
|
|
||||||
|
@ -167,26 +168,31 @@ impl Witness {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates [`Witness`] object from an array of byte-arrays
|
/// Creates [`Witness`] object from an array of byte-arrays
|
||||||
|
#[deprecated(since="0.30.0", note="use `Witness::from_slice()` instead")]
|
||||||
pub fn from_vec(vec: Vec<Vec<u8>>) -> Self {
|
pub fn from_vec(vec: Vec<Vec<u8>>) -> Self {
|
||||||
let witness_elements = vec.len();
|
Witness::from_slice(&vec)
|
||||||
let index_size = witness_elements * 4;
|
}
|
||||||
|
|
||||||
let content_size: usize = vec
|
/// Creates a [`Witness`] object from a slice of bytes slices where each slice is a witness item.
|
||||||
|
pub fn from_slice<T: AsRef<[u8]>>(slice: &[T]) -> Self {
|
||||||
|
let witness_elements = slice.len();
|
||||||
|
let index_size = witness_elements * 4;
|
||||||
|
let content_size = slice
|
||||||
.iter()
|
.iter()
|
||||||
.map(|el| el.len() + VarInt(el.len() as u64).len())
|
.map(|elem| elem.as_ref().len() + VarInt(elem.as_ref().len() as u64).len())
|
||||||
.sum();
|
.sum();
|
||||||
|
|
||||||
let mut content = vec![0u8; content_size + index_size];
|
let mut content = vec![0u8; content_size + index_size];
|
||||||
let mut cursor = 0usize;
|
let mut cursor = 0usize;
|
||||||
for (i, el) in vec.into_iter().enumerate() {
|
for (i, elem) in slice.iter().enumerate() {
|
||||||
encode_cursor(&mut content, content_size, i, cursor);
|
encode_cursor(&mut content, content_size, i, cursor);
|
||||||
|
let elem_len_varint = VarInt(elem.as_ref().len() as u64);
|
||||||
let el_len_varint = VarInt(el.len() as u64);
|
elem_len_varint
|
||||||
el_len_varint
|
.consensus_encode(&mut &mut content[cursor..cursor + elem_len_varint.len()])
|
||||||
.consensus_encode(&mut &mut content[cursor..cursor + el_len_varint.len()])
|
|
||||||
.expect("writers on vec don't errors, space granted by content_size");
|
.expect("writers on vec don't errors, space granted by content_size");
|
||||||
cursor += el_len_varint.len();
|
cursor += elem_len_varint.len();
|
||||||
content[cursor..cursor + el.len()].copy_from_slice(&el);
|
content[cursor..cursor + elem.as_ref().len()].copy_from_slice(elem.as_ref());
|
||||||
cursor += el.len();
|
cursor += elem.as_ref().len();
|
||||||
}
|
}
|
||||||
|
|
||||||
Witness {
|
Witness {
|
||||||
|
@ -237,7 +243,11 @@ impl Witness {
|
||||||
|
|
||||||
/// Push a new element on the witness, requires an allocation
|
/// Push a new element on the witness, requires an allocation
|
||||||
pub fn push<T: AsRef<[u8]>>(&mut self, new_element: T) {
|
pub fn push<T: AsRef<[u8]>>(&mut self, new_element: T) {
|
||||||
let new_element = new_element.as_ref();
|
self.push_slice(new_element.as_ref());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Push a new element slice onto the witness stack.
|
||||||
|
fn push_slice(&mut self, new_element: &[u8]) {
|
||||||
self.witness_elements += 1;
|
self.witness_elements += 1;
|
||||||
let previous_content_end = self.indices_start;
|
let previous_content_end = self.indices_start;
|
||||||
let element_len_varint = VarInt(new_element.len() as u64);
|
let element_len_varint = VarInt(new_element.len() as u64);
|
||||||
|
@ -434,7 +444,7 @@ impl<'de> serde::Deserialize<'de> for Witness {
|
||||||
})?;
|
})?;
|
||||||
ret.push(vec);
|
ret.push(vec);
|
||||||
}
|
}
|
||||||
Ok(Witness::from_vec(ret))
|
Ok(Witness::from_slice(&ret))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,7 +452,7 @@ impl<'de> serde::Deserialize<'de> for Witness {
|
||||||
deserializer.deserialize_seq(Visitor)
|
deserializer.deserialize_seq(Visitor)
|
||||||
} else {
|
} else {
|
||||||
let vec: Vec<Vec<u8>> = serde::Deserialize::deserialize(deserializer)?;
|
let vec: Vec<Vec<u8>> = serde::Deserialize::deserialize(deserializer)?;
|
||||||
Ok(Witness::from_vec(vec))
|
Ok(Witness::from_slice(&vec))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -572,7 +582,7 @@ mod test {
|
||||||
assert_eq!(&witness[0], &w0[..]);
|
assert_eq!(&witness[0], &w0[..]);
|
||||||
assert_eq!(&witness[1], &w1[..]);
|
assert_eq!(&witness[1], &w1[..]);
|
||||||
|
|
||||||
let w_into = Witness::from_vec(witness_vec);
|
let w_into = Witness::from_slice(&witness_vec);
|
||||||
assert_eq!(w_into, witness);
|
assert_eq!(w_into, witness);
|
||||||
|
|
||||||
assert_eq!(witness_serialized, serialize(&witness));
|
assert_eq!(witness_serialized, serialize(&witness));
|
||||||
|
@ -646,7 +656,7 @@ mod test {
|
||||||
use bincode;
|
use bincode;
|
||||||
|
|
||||||
let old_witness_format = vec![vec![0u8], vec![2]];
|
let old_witness_format = vec![vec![0u8], vec![2]];
|
||||||
let new_witness_format = Witness::from_vec(old_witness_format.clone());
|
let new_witness_format = Witness::from_slice(&old_witness_format);
|
||||||
|
|
||||||
let old = bincode::serialize(&old_witness_format).unwrap();
|
let old = bincode::serialize(&old_witness_format).unwrap();
|
||||||
let new = bincode::serialize(&new_witness_format).unwrap();
|
let new = bincode::serialize(&new_witness_format).unwrap();
|
||||||
|
@ -662,7 +672,7 @@ mod test {
|
||||||
fn test_serde_human() {
|
fn test_serde_human() {
|
||||||
use serde_json;
|
use serde_json;
|
||||||
|
|
||||||
let witness = Witness::from_vec(vec![vec![0u8, 123, 75], vec![2u8, 6, 3, 7, 8]]);
|
let witness = Witness::from_slice(&[vec![0u8, 123, 75], vec![2u8, 6, 3, 7, 8]]);
|
||||||
|
|
||||||
let json = serde_json::to_string(&witness).unwrap();
|
let json = serde_json::to_string(&witness).unwrap();
|
||||||
|
|
||||||
|
@ -681,8 +691,8 @@ mod benches {
|
||||||
|
|
||||||
#[bench]
|
#[bench]
|
||||||
pub fn bench_big_witness_to_vec(bh: &mut Bencher) {
|
pub fn bench_big_witness_to_vec(bh: &mut Bencher) {
|
||||||
let raw_witness = vec![vec![1u8]; 5];
|
let raw_witness = [[1u8]; 5];
|
||||||
let witness = Witness::from_vec(raw_witness);
|
let witness = Witness::from_slice(&raw_witness);
|
||||||
|
|
||||||
bh.iter(|| {
|
bh.iter(|| {
|
||||||
black_box(witness.to_vec());
|
black_box(witness.to_vec());
|
||||||
|
@ -692,7 +702,7 @@ mod benches {
|
||||||
#[bench]
|
#[bench]
|
||||||
pub fn bench_witness_to_vec(bh: &mut Bencher) {
|
pub fn bench_witness_to_vec(bh: &mut Bencher) {
|
||||||
let raw_witness = vec![vec![1u8]; 3];
|
let raw_witness = vec![vec![1u8]; 3];
|
||||||
let witness = Witness::from_vec(raw_witness);
|
let witness = Witness::from_slice(&raw_witness);
|
||||||
|
|
||||||
bh.iter(|| {
|
bh.iter(|| {
|
||||||
black_box(witness.to_vec());
|
black_box(witness.to_vec());
|
||||||
|
|
|
@ -1058,7 +1058,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
|
script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
witness: Witness::from_vec(vec![Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap()]),
|
witness: Witness::from_slice(&[Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap()]),
|
||||||
}],
|
}],
|
||||||
output: vec![
|
output: vec![
|
||||||
TxOut {
|
TxOut {
|
||||||
|
@ -1117,7 +1117,7 @@ mod tests {
|
||||||
"304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe701".parse().unwrap(),
|
"304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe701".parse().unwrap(),
|
||||||
)].into_iter().collect(),
|
)].into_iter().collect(),
|
||||||
bip32_derivation: keypaths.clone(),
|
bip32_derivation: keypaths.clone(),
|
||||||
final_script_witness: Some(Witness::from_vec(vec![vec![1, 3], vec![5]])),
|
final_script_witness: Some(Witness::from_slice(&[vec![1, 3], vec![5]])),
|
||||||
ripemd160_preimages: vec![(ripemd160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
|
ripemd160_preimages: vec![(ripemd160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
|
||||||
sha256_preimages: vec![(sha256::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
|
sha256_preimages: vec![(sha256::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
|
||||||
hash160_preimages: vec![(hash160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
|
hash160_preimages: vec![(hash160::Hash::hash(&[]), vec![1, 2])].into_iter().collect(),
|
||||||
|
@ -1279,7 +1279,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
|
script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
witness: Witness::from_vec(vec![
|
witness: Witness::from_slice(&[
|
||||||
Vec::from_hex("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").unwrap(),
|
Vec::from_hex("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").unwrap(),
|
||||||
Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap(),
|
Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap(),
|
||||||
]),
|
]),
|
||||||
|
@ -1293,7 +1293,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"),
|
script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"),
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
witness: Witness::from_vec(vec![
|
witness: Witness::from_slice(&[
|
||||||
Vec::from_hex("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").unwrap(),
|
Vec::from_hex("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").unwrap(),
|
||||||
Vec::from_hex("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").unwrap(),
|
Vec::from_hex("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").unwrap(),
|
||||||
]),
|
]),
|
||||||
|
@ -1591,7 +1591,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
|
script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"),
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
witness: Witness::from_vec(vec![
|
witness: Witness::from_slice(&[
|
||||||
Vec::from_hex("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").unwrap(),
|
Vec::from_hex("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").unwrap(),
|
||||||
Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap(),
|
Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap(),
|
||||||
]),
|
]),
|
||||||
|
@ -1605,7 +1605,7 @@ mod tests {
|
||||||
},
|
},
|
||||||
script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"),
|
script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"),
|
||||||
sequence: Sequence::MAX,
|
sequence: Sequence::MAX,
|
||||||
witness: Witness::from_vec(vec![
|
witness: Witness::from_slice(&[
|
||||||
Vec::from_hex("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").unwrap(),
|
Vec::from_hex("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").unwrap(),
|
||||||
Vec::from_hex("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").unwrap(),
|
Vec::from_hex("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").unwrap(),
|
||||||
]),
|
]),
|
||||||
|
|
Loading…
Reference in New Issue