From d78a996bf69b730a0d09e2df0b9ba28f459eb872 Mon Sep 17 00:00:00 2001 From: Noah Lanson Date: Tue, 15 Nov 2022 04:50:17 +1100 Subject: [PATCH] Add `Witness::from_slice()` and depreciate `Witness:from_vec()` --- bitcoin/src/blockdata/transaction.rs | 2 +- bitcoin/src/blockdata/witness.rs | 52 ++++++++++++++++------------ bitcoin/src/util/psbt/mod.rs | 12 +++---- 3 files changed, 36 insertions(+), 30 deletions(-) diff --git a/bitcoin/src/blockdata/transaction.rs b/bitcoin/src/blockdata/transaction.rs index 1581587c..a43d6b12 100644 --- a/bitcoin/src/blockdata/transaction.rs +++ b/bitcoin/src/blockdata/transaction.rs @@ -1396,7 +1396,7 @@ mod tests { // test that we get a failure if we corrupt a signature let mut witness: Vec<_> = spending.input[1].witness.to_vec(); 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| { if let Some(tx) = spent3.remove(&point.txid) { return tx.output.get(point.vout as usize).cloned(); diff --git a/bitcoin/src/blockdata/witness.rs b/bitcoin/src/blockdata/witness.rs index 89855e55..42eb47b6 100644 --- a/bitcoin/src/blockdata/witness.rs +++ b/bitcoin/src/blockdata/witness.rs @@ -19,15 +19,16 @@ use crate::VarInt; /// 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>` and indeed you can convert from -/// it [`Witness::from_vec`] and convert into it [`Witness::to_vec`]. +/// Can be logically seen as an array of bytestrings, i.e. `Vec>`, and it is serialized on the wire +/// in that format. You can convert between this type and `Vec>` by using [`Witness::from_slice`] +/// and [`Witness::to_vec`]. /// /// For serialization and deserialization performance it is stored internally as a single `Vec`, /// saving some allocations. /// #[derive(Clone, Default, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)] pub struct Witness { - /// contains the witness Vec> serialization without the initial varint indicating the + /// Contains the witness Vec> serialization without the initial varint indicating the /// number of elements (which is stored in `witness_elements`) content: Vec, @@ -166,26 +167,31 @@ impl Witness { } /// 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>) -> Self { - let witness_elements = vec.len(); - let index_size = witness_elements * 4; + Witness::from_slice(&vec) + } - 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>(slice: &[T]) -> Self { + let witness_elements = slice.len(); + let index_size = witness_elements * 4; + let content_size = slice .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(); + let mut content = vec![0u8; content_size + index_size]; 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); - - let el_len_varint = VarInt(el.len() as u64); - el_len_varint - .consensus_encode(&mut &mut content[cursor..cursor + el_len_varint.len()]) + let elem_len_varint = VarInt(elem.as_ref().len() as u64); + elem_len_varint + .consensus_encode(&mut &mut content[cursor..cursor + elem_len_varint.len()]) .expect("writers on vec don't errors, space granted by content_size"); - cursor += el_len_varint.len(); - content[cursor..cursor + el.len()].copy_from_slice(&el); - cursor += el.len(); + cursor += elem_len_varint.len(); + content[cursor..cursor + elem.as_ref().len()].copy_from_slice(elem.as_ref()); + cursor += elem.as_ref().len(); } Witness { @@ -437,7 +443,7 @@ impl<'de> serde::Deserialize<'de> for Witness { })?; ret.push(vec); } - Ok(Witness::from_vec(ret)) + Ok(Witness::from_slice(&ret)) } } @@ -445,7 +451,7 @@ impl<'de> serde::Deserialize<'de> for Witness { deserializer.deserialize_seq(Visitor) } else { let vec: Vec> = serde::Deserialize::deserialize(deserializer)?; - Ok(Witness::from_vec(vec)) + Ok(Witness::from_slice(&vec)) } } } @@ -575,7 +581,7 @@ mod test { assert_eq!(&witness[0], &w0[..]); 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!(witness_serialized, serialize(&witness)); @@ -649,7 +655,7 @@ mod test { use bincode; 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 new = bincode::serialize(&new_witness_format).unwrap(); @@ -665,7 +671,7 @@ mod test { fn test_serde_human() { 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(); @@ -684,8 +690,8 @@ mod benches { #[bench] pub fn bench_big_witness_to_vec(bh: &mut Bencher) { - let raw_witness = vec![vec![1u8]; 5]; - let witness = Witness::from_vec(raw_witness); + let raw_witness = [[1u8]; 5]; + let witness = Witness::from_slice(&raw_witness); bh.iter(|| { black_box(witness.to_vec()); @@ -695,7 +701,7 @@ mod benches { #[bench] pub fn bench_witness_to_vec(bh: &mut Bencher) { let raw_witness = vec![vec![1u8]; 3]; - let witness = Witness::from_vec(raw_witness); + let witness = Witness::from_slice(&raw_witness); bh.iter(|| { black_box(witness.to_vec()); diff --git a/bitcoin/src/util/psbt/mod.rs b/bitcoin/src/util/psbt/mod.rs index 304e641d..d34bbce2 100644 --- a/bitcoin/src/util/psbt/mod.rs +++ b/bitcoin/src/util/psbt/mod.rs @@ -1058,7 +1058,7 @@ mod tests { }, script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), sequence: Sequence::MAX, - witness: Witness::from_vec(vec![Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap()]), + witness: Witness::from_slice(&[Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap()]), }], output: vec![ TxOut { @@ -1117,7 +1117,7 @@ mod tests { "304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe701".parse().unwrap(), )].into_iter().collect(), 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(), sha256_preimages: vec![(sha256::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"), sequence: Sequence::MAX, - witness: Witness::from_vec(vec![ + witness: Witness::from_slice(&[ Vec::from_hex("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").unwrap(), Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap(), ]), @@ -1293,7 +1293,7 @@ mod tests { }, script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"), sequence: Sequence::MAX, - witness: Witness::from_vec(vec![ + witness: Witness::from_slice(&[ Vec::from_hex("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").unwrap(), Vec::from_hex("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").unwrap(), ]), @@ -1591,7 +1591,7 @@ mod tests { }, script_sig: hex_script!("160014be18d152a9b012039daf3da7de4f53349eecb985"), sequence: Sequence::MAX, - witness: Witness::from_vec(vec![ + witness: Witness::from_slice(&[ Vec::from_hex("304402202712be22e0270f394f568311dc7ca9a68970b8025fdd3b240229f07f8a5f3a240220018b38d7dcd314e734c9276bd6fb40f673325bc4baa144c800d2f2f02db2765c01").unwrap(), Vec::from_hex("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105").unwrap(), ]), @@ -1605,7 +1605,7 @@ mod tests { }, script_sig: hex_script!("160014fe3e9ef1a745e974d902c4355943abcb34bd5353"), sequence: Sequence::MAX, - witness: Witness::from_vec(vec![ + witness: Witness::from_slice(&[ Vec::from_hex("3045022100d12b852d85dcd961d2f5f4ab660654df6eedcc794c0c33ce5cc309ffb5fce58d022067338a8e0e1725c197fb1a88af59f51e44e4255b20167c8684031c05d1f2592a01").unwrap(), Vec::from_hex("0223b72beef0965d10be0778efecd61fcac6f79a4ea169393380734464f84f2ab3").unwrap(), ]),