From ef01f4d0f6d5051e28593c4d2427537be56b7c7b Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 2 Dec 2022 14:37:50 +1100 Subject: [PATCH 01/16] consensus: Introduce local variables In preparation for running the formatter introduce a couple of local variables to reduce the line length and inhibit function call from being split over multiple lines. Refactor only, no logic changes. --- bitcoin/src/consensus/encode.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/bitcoin/src/consensus/encode.rs b/bitcoin/src/consensus/encode.rs index c6c83717..d8619578 100644 --- a/bitcoin/src/consensus/encode.rs +++ b/bitcoin/src/consensus/encode.rs @@ -652,7 +652,8 @@ impl Decodable for Vec { fn consensus_decode_from_finite_reader(r: &mut R) -> Result { let len = VarInt::consensus_decode(r)?.0 as usize; // most real-world vec of bytes data, wouldn't be larger than 128KiB - read_bytes_from_finite_reader(r, ReadBytesFromFiniteReaderOpts { len, chunk_size: 128 * 1024 }) + let opts = ReadBytesFromFiniteReaderOpts { len, chunk_size: 128 * 1024 }; + read_bytes_from_finite_reader(r, opts) } } @@ -693,7 +694,8 @@ impl Decodable for CheckedData { let len = u32::consensus_decode_from_finite_reader(r)? as usize; let checksum = <[u8; 4]>::consensus_decode_from_finite_reader(r)?; - let ret = read_bytes_from_finite_reader(r, ReadBytesFromFiniteReaderOpts { len, chunk_size: MAX_VEC_SIZE })?; + let opts = ReadBytesFromFiniteReaderOpts { len, chunk_size: MAX_VEC_SIZE }; + let ret = read_bytes_from_finite_reader(r, opts)?; let expected_checksum = sha2_checksum(&ret); if expected_checksum != checksum { Err(self::Error::InvalidChecksum { From ce773af20f77046483ee36ad92e91cf33cfda01e Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 2 Dec 2022 14:39:52 +1100 Subject: [PATCH 02/16] tests: Remove useless use of super imports We already import `super::*`, these other imports are useless. --- bitcoin/src/consensus/encode.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/bitcoin/src/consensus/encode.rs b/bitcoin/src/consensus/encode.rs index d8619578..b07d0384 100644 --- a/bitcoin/src/consensus/encode.rs +++ b/bitcoin/src/consensus/encode.rs @@ -809,8 +809,6 @@ impl Decodable for TapLeafHash { mod tests { use super::*; use core::{mem::{self, discriminant}, fmt}; - use super::{deserialize, serialize, Error, CheckedData, VarInt}; - use super::{Transaction, BlockHash, FilterHash, TxMerkleNode, TxOut, TxIn}; use crate::consensus::{Encodable, deserialize_partial, Decodable}; #[cfg(feature = "std")] use crate::network::{Address, message_blockdata::Inventory}; From 89143205f900108755f939101c92cb1c74fbbf16 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 2 Dec 2022 14:40:49 +1100 Subject: [PATCH 03/16] Enable formatting for consensus Remove the exclude for the `consensus` module. Do not run the formatter, that will be done as a separate patch to aid review. --- rustfmt.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index 5290e495..3018b339 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,7 +1,6 @@ # Eventually this shoud be: ignore = [] ignore = [ "bitcoin/src/blockdata", - "bitcoin/src/consensus", "bitcoin/src/crypto", "bitcoin/src/psbt", "bitcoin/src/util", From 450a84f6e81315237821b27bee383380a46316ee Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 6 Dec 2022 10:38:48 +1100 Subject: [PATCH 04/16] consensus: Run the formatter Run `cargo +nightly fmt`, no other manual changes. --- bitcoin/src/consensus/encode.rs | 302 ++++++++++++++++++++------------ bitcoin/src/consensus/mod.rs | 5 +- bitcoin/src/consensus/params.rs | 2 +- bitcoin/src/consensus/serde.rs | 140 +++++++++------ 4 files changed, 277 insertions(+), 172 deletions(-) diff --git a/bitcoin/src/consensus/encode.rs b/bitcoin/src/consensus/encode.rs index b07d0384..7a523b69 100644 --- a/bitcoin/src/consensus/encode.rs +++ b/bitcoin/src/consensus/encode.rs @@ -16,22 +16,23 @@ //! typically big-endian decimals, etc.) //! -use crate::prelude::*; - -use core::{fmt, mem, u32, convert::From}; +use core::convert::From; +use core::{fmt, mem, u32}; use bitcoin_internals::write_err; -use crate::hashes::{sha256d, Hash, sha256}; -use crate::hash_types::{BlockHash, FilterHash, TxMerkleNode, FilterHeader}; +use crate::bip152::{PrefilledTransaction, ShortId}; +use crate::blockdata::transaction::{Transaction, TxIn, TxOut}; +use crate::hash_types::{BlockHash, FilterHash, FilterHeader, TxMerkleNode}; +use crate::hashes::{sha256, sha256d, Hash}; use crate::io::{self, Cursor, Read}; - -use crate::bip152::{ShortId, PrefilledTransaction}; -use crate::taproot::TapLeafHash; - -use crate::blockdata::transaction::{TxOut, Transaction, TxIn}; #[cfg(feature = "std")] -use crate::network::{message_blockdata::Inventory, address::{Address, AddrV2Message}}; +use crate::network::{ + address::{AddrV2Message, Address}, + message_blockdata::Inventory, +}; +use crate::prelude::*; +use crate::taproot::TapLeafHash; /// Encoding error. #[derive(Debug)] @@ -65,14 +66,14 @@ impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { Error::Io(ref e) => write_err!(f, "IO error"; e), - Error::OversizedVectorAllocation { requested: ref r, max: ref m } => write!(f, - "allocation of oversized vector: requested {}, maximum {}", r, m), - Error::InvalidChecksum { expected: ref e, actual: ref a } => write!(f, - "invalid checksum: expected {:x}, actual {:x}", e.as_hex(), a.as_hex()), + Error::OversizedVectorAllocation { requested: ref r, max: ref m } => + write!(f, "allocation of oversized vector: requested {}, maximum {}", r, m), + Error::InvalidChecksum { expected: ref e, actual: ref a } => + write!(f, "invalid checksum: expected {:x}, actual {:x}", e.as_hex(), a.as_hex()), Error::NonMinimalVarInt => write!(f, "non-minimal varint"), Error::ParseFailed(ref s) => write!(f, "parse failed: {}", s), - Error::UnsupportedSegwitFlag(ref swflag) => write!(f, - "unsupported segwit version: {}", swflag), + Error::UnsupportedSegwitFlag(ref swflag) => + write!(f, "unsupported segwit version: {}", swflag), } } } @@ -96,9 +97,7 @@ impl std::error::Error for Error { #[doc(hidden)] impl From for Error { - fn from(error: io::Error) -> Self { - Error::Io(error) - } + fn from(error: io::Error) -> Self { Error::Io(error) } } /// Encodes an object into a vector. @@ -137,9 +136,8 @@ pub fn deserialize_partial(data: &[u8]) -> Result<(T, usize), Erro Ok((rv, consumed)) } - /// Extensions of `Write` to encode data as per Bitcoin consensus. -pub trait WriteExt : io::Write { +pub trait WriteExt: io::Write { /// Outputs a 64-bit unsigned integer. fn emit_u64(&mut self, v: u64) -> Result<(), io::Error>; /// Outputs a 32-bit unsigned integer. @@ -166,7 +164,7 @@ pub trait WriteExt : io::Write { } /// Extensions of `Read` to decode data as per Bitcoin consensus. -pub trait ReadExt : io::Read { +pub trait ReadExt: io::Read { /// Reads a 64-bit unsigned integer. fn read_u64(&mut self) -> Result; /// Reads a 32-bit unsigned integer. @@ -198,7 +196,7 @@ macro_rules! encoder_fn { fn $name(&mut self, v: $val_type) -> Result<(), io::Error> { self.write_all(&v.to_le_bytes()) } - } + }; } macro_rules! decoder_fn { @@ -209,7 +207,7 @@ macro_rules! decoder_fn { self.read_exact(&mut val[..]).map_err(Error::Io)?; Ok(<$val_type>::from_le_bytes(val)) } - } + }; } impl WriteExt for W { @@ -221,21 +219,13 @@ impl WriteExt for W { encoder_fn!(emit_i16, i16); #[inline] - fn emit_i8(&mut self, v: i8) -> Result<(), io::Error> { - self.write_all(&[v as u8]) - } + fn emit_i8(&mut self, v: i8) -> Result<(), io::Error> { self.write_all(&[v as u8]) } #[inline] - fn emit_u8(&mut self, v: u8) -> Result<(), io::Error> { - self.write_all(&[v]) - } + fn emit_u8(&mut self, v: u8) -> Result<(), io::Error> { self.write_all(&[v]) } #[inline] - fn emit_bool(&mut self, v: bool) -> Result<(), io::Error> { - self.write_all(&[v as u8]) - } + fn emit_bool(&mut self, v: bool) -> Result<(), io::Error> { self.write_all(&[v as u8]) } #[inline] - fn emit_slice(&mut self, v: &[u8]) -> Result<(), io::Error> { - self.write_all(v) - } + fn emit_slice(&mut self, v: &[u8]) -> Result<(), io::Error> { self.write_all(v) } } impl ReadExt for R { @@ -259,9 +249,7 @@ impl ReadExt for R { Ok(slice[0] as i8) } #[inline] - fn read_bool(&mut self) -> Result { - ReadExt::read_i8(self).map(|bit| bit != 0) - } + fn read_bool(&mut self) -> Result { ReadExt::read_i8(self).map(|bit| bit != 0) } #[inline] fn read_slice(&mut self, slice: &mut [u8]) -> Result<(), Error> { self.read_exact(slice).map_err(Error::Io) @@ -313,7 +301,9 @@ pub trait Decodable: Sized { /// avoid creating redundant `Take` wrappers. Failure to do so might result only in a tiny /// performance hit. #[inline] - fn consensus_decode_from_finite_reader(reader: &mut R) -> Result { + fn consensus_decode_from_finite_reader( + reader: &mut R, + ) -> Result { // This method is always strictly less general than, `consensus_decode`, so it's safe and // make sense to default to just calling it. This way most types, that don't care about // protecting against resource exhaustion due to malicious input, can just ignore it. @@ -353,19 +343,22 @@ macro_rules! impl_int_encodable { } impl Encodable for $ty { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode( + &self, + w: &mut W, + ) -> Result { w.$meth_enc(*self)?; Ok(mem::size_of::<$ty>()) } } - } + }; } -impl_int_encodable!(u8, read_u8, emit_u8); +impl_int_encodable!(u8, read_u8, emit_u8); impl_int_encodable!(u16, read_u16, emit_u16); impl_int_encodable!(u32, read_u32, emit_u32); impl_int_encodable!(u64, read_u64, emit_u64); -impl_int_encodable!(i8, read_i8, emit_i8); +impl_int_encodable!(i8, read_i8, emit_i8); impl_int_encodable!(i16, read_i16, emit_i16); impl_int_encodable!(i32, read_i32, emit_i32); impl_int_encodable!(i64, read_i64, emit_i64); @@ -398,22 +391,22 @@ impl Encodable for VarInt { 0..=0xFC => { (self.0 as u8).consensus_encode(w)?; Ok(1) - }, + } 0xFD..=0xFFFF => { w.emit_u8(0xFD)?; (self.0 as u16).consensus_encode(w)?; Ok(3) - }, + } 0x10000..=0xFFFFFFFF => { w.emit_u8(0xFE)?; (self.0 as u32).consensus_encode(w)?; Ok(5) - }, + } _ => { w.emit_u8(0xFF)?; self.0.consensus_encode(w)?; Ok(9) - }, + } } } } @@ -447,7 +440,7 @@ impl Decodable for VarInt { Ok(VarInt(x as u64)) } } - n => Ok(VarInt(n as u64)) + n => Ok(VarInt(n as u64)), } } } @@ -508,7 +501,10 @@ macro_rules! impl_array { ( $size:literal ) => { impl Encodable for [u8; $size] { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode( + &self, + w: &mut W, + ) -> Result { w.emit_slice(&self[..])?; Ok(self.len()) } @@ -549,7 +545,9 @@ impl Decodable for [u16; 8] { impl Encodable for [u16; 8] { #[inline] fn consensus_encode(&self, w: &mut W) -> Result { - for c in self.iter() { c.consensus_encode(w)?; } + for c in self.iter() { + c.consensus_encode(w)?; + } Ok(16) } } @@ -558,7 +556,10 @@ macro_rules! impl_vec { ($type: ty) => { impl Encodable for Vec<$type> { #[inline] - fn consensus_encode(&self, w: &mut W) -> Result { + fn consensus_encode( + &self, + w: &mut W, + ) -> Result { let mut len = 0; len += VarInt(self.len() as u64).consensus_encode(w)?; for c in self.iter() { @@ -570,7 +571,9 @@ macro_rules! impl_vec { impl Decodable for Vec<$type> { #[inline] - fn consensus_decode_from_finite_reader(r: &mut R) -> Result { + fn consensus_decode_from_finite_reader( + r: &mut R, + ) -> Result { let len = VarInt::consensus_decode_from_finite_reader(r)?.0; // Do not allocate upfront more items than if the sequnce of type // occupied roughly quarter a block. This should never be the case @@ -586,7 +589,7 @@ macro_rules! impl_vec { Ok(ret) } } - } + }; } impl_vec!(BlockHash); impl_vec!(FilterHash); @@ -602,17 +605,22 @@ impl_vec!(VarInt); impl_vec!(ShortId); impl_vec!(PrefilledTransaction); -#[cfg(feature = "std")] impl_vec!(Inventory); -#[cfg(feature = "std")] impl_vec!((u32, Address)); -#[cfg(feature = "std")] impl_vec!(AddrV2Message); +#[cfg(feature = "std")] +impl_vec!(Inventory); +#[cfg(feature = "std")] +impl_vec!((u32, Address)); +#[cfg(feature = "std")] +impl_vec!(AddrV2Message); -pub(crate) fn consensus_encode_with_size(data: &[u8], mut s: S) -> Result { +pub(crate) fn consensus_encode_with_size( + data: &[u8], + mut s: S, +) -> Result { let vi_len = VarInt(data.len() as u64).consensus_encode(&mut s)?; s.emit_slice(data)?; Ok(vi_len + data.len()) } - struct ReadBytesFromFiniteReaderOpts { len: usize, chunk_size: usize, @@ -623,7 +631,10 @@ struct ReadBytesFromFiniteReaderOpts { /// This function relies on reader being bound in amount of data /// it returns for OOM protection. See [`Decodable::consensus_decode_from_finite_reader`]. #[inline] -fn read_bytes_from_finite_reader(mut d: D, mut opts: ReadBytesFromFiniteReaderOpts) -> Result, Error> { +fn read_bytes_from_finite_reader( + mut d: D, + mut opts: ReadBytesFromFiniteReaderOpts, +) -> Result, Error> { let mut ret = vec![]; assert_ne!(opts.chunk_size, 0); @@ -671,7 +682,6 @@ impl Decodable for Box<[u8]> { } } - /// Does a double-SHA256 on `data` and returns the first 4 bytes. fn sha2_checksum(data: &[u8]) -> [u8; 4] { let checksum = ::hash(data); @@ -698,10 +708,7 @@ impl Decodable for CheckedData { let ret = read_bytes_from_finite_reader(r, opts)?; let expected_checksum = sha2_checksum(&ret); if expected_checksum != checksum { - Err(self::Error::InvalidChecksum { - expected: expected_checksum, - actual: checksum, - }) + Err(self::Error::InvalidChecksum { expected: expected_checksum, actual: checksum }) } else { Ok(CheckedData(ret)) } @@ -807,11 +814,13 @@ impl Decodable for TapLeafHash { #[cfg(test)] mod tests { + use core::fmt; + use core::mem::{self, discriminant}; + use super::*; - use core::{mem::{self, discriminant}, fmt}; - use crate::consensus::{Encodable, deserialize_partial, Decodable}; + use crate::consensus::{deserialize_partial, Decodable, Encodable}; #[cfg(feature = "std")] - use crate::network::{Address, message_blockdata::Inventory}; + use crate::network::{message_blockdata::Inventory, Address}; #[test] fn serialize_int_test() { @@ -854,7 +863,10 @@ mod tests { assert_eq!(serialize(&-256i64), vec![0u8, 255, 255, 255, 255, 255, 255, 255]); assert_eq!(serialize(&-5000i64), vec![120u8, 236, 255, 255, 255, 255, 255, 255]); assert_eq!(serialize(&-500000i64), vec![224u8, 94, 248, 255, 255, 255, 255, 255]); - assert_eq!(serialize(&-723401728380766730i64), vec![246u8, 245, 245, 245, 245, 245, 245, 245]); + assert_eq!( + serialize(&-723401728380766730i64), + vec![246u8, 245, 245, 245, 245, 245, 245, 245] + ); assert_eq!(serialize(&1i64), vec![1u8, 0, 0, 0, 0, 0, 0, 0]); assert_eq!(serialize(&256i64), vec![0u8, 1, 0, 0, 0, 0, 0, 0]); assert_eq!(serialize(&5000i64), vec![136u8, 19, 0, 0, 0, 0, 0, 0]); @@ -869,8 +881,14 @@ mod tests { assert_eq!(serialize(&VarInt(0xFD)), vec![0xFDu8, 0xFD, 0]); assert_eq!(serialize(&VarInt(0xFFF)), vec![0xFDu8, 0xFF, 0xF]); assert_eq!(serialize(&VarInt(0xF0F0F0F)), vec![0xFEu8, 0xF, 0xF, 0xF, 0xF]); - assert_eq!(serialize(&VarInt(0xF0F0F0F0F0E0)), vec![0xFFu8, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0, 0]); - assert_eq!(test_varint_encode(0xFF, &0x100000000_u64.to_le_bytes()).unwrap(), VarInt(0x100000000)); + assert_eq!( + serialize(&VarInt(0xF0F0F0F0F0E0)), + vec![0xFFu8, 0xE0, 0xF0, 0xF0, 0xF0, 0xF0, 0xF0, 0, 0] + ); + assert_eq!( + test_varint_encode(0xFF, &0x100000000_u64.to_le_bytes()).unwrap(), + VarInt(0x100000000) + ); assert_eq!(test_varint_encode(0xFE, &0x10000_u64.to_le_bytes()).unwrap(), VarInt(0x10000)); assert_eq!(test_varint_encode(0xFD, &0xFD_u64.to_le_bytes()).unwrap(), VarInt(0xFD)); @@ -881,7 +899,7 @@ mod tests { test_varint_len(VarInt(0xFFFF), 3); test_varint_len(VarInt(0x10000), 5); test_varint_len(VarInt(0xFFFFFFFF), 5); - test_varint_len(VarInt(0xFFFFFFFF+1), 9); + test_varint_len(VarInt(0xFFFFFFFF + 1), 9); test_varint_len(VarInt(u64::max_value()), 9); } @@ -894,35 +912,62 @@ mod tests { fn test_varint_encode(n: u8, x: &[u8]) -> Result { let mut input = [0u8; 9]; input[0] = n; - input[1..x.len()+1].copy_from_slice(x); - deserialize_partial::(&input).map(|t|t.0) + input[1..x.len() + 1].copy_from_slice(x); + deserialize_partial::(&input).map(|t| t.0) } #[test] fn deserialize_nonminimal_vec() { // Check the edges for variant int - assert_eq!(discriminant(&test_varint_encode(0xFF, &(0x100000000_u64-1).to_le_bytes()).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&test_varint_encode(0xFE, &(0x10000_u64-1).to_le_bytes()).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&test_varint_encode(0xFD, &(0xFD_u64-1).to_le_bytes()).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - - assert_eq!(discriminant(&deserialize::>(&[0xfd, 0x00, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&deserialize::>(&[0xfd, 0xfc, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&deserialize::>(&[0xfd, 0xfc, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&deserialize::>(&[0xfe, 0xff, 0x00, 0x00, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&deserialize::>(&[0xfe, 0xff, 0xff, 0x00, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&deserialize::>(&[0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); - assert_eq!(discriminant(&deserialize::>(&[0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00]).unwrap_err()), - discriminant(&Error::NonMinimalVarInt)); + assert_eq!( + discriminant( + &test_varint_encode(0xFF, &(0x100000000_u64 - 1).to_le_bytes()).unwrap_err() + ), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&test_varint_encode(0xFE, &(0x10000_u64 - 1).to_le_bytes()).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&test_varint_encode(0xFD, &(0xFD_u64 - 1).to_le_bytes()).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfd, 0x00, 0x00]).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfd, 0xfc, 0x00]).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfd, 0xfc, 0x00]).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfe, 0xff, 0x00, 0x00, 0x00]).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant(&deserialize::>(&[0xfe, 0xff, 0xff, 0x00, 0x00]).unwrap_err()), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant( + &deserialize::>(&[0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + .unwrap_err() + ), + discriminant(&Error::NonMinimalVarInt) + ); + assert_eq!( + discriminant( + &deserialize::>(&[0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00]) + .unwrap_err() + ), + discriminant(&Error::NonMinimalVarInt) + ); let mut vec_256 = vec![0; 259]; vec_256[0] = 0xfd; @@ -1003,21 +1048,38 @@ mod tests { // u64 assert_eq!(deserialize(&[0xABu8, 0xCD, 0, 0, 0, 0, 0, 0]).ok(), Some(0xCDABu64)); - assert_eq!(deserialize(&[0xA0u8, 0x0D, 0xAB, 0xCD, 0x99, 0, 0, 0x99]).ok(), Some(0x99000099CDAB0DA0u64)); + assert_eq!( + deserialize(&[0xA0u8, 0x0D, 0xAB, 0xCD, 0x99, 0, 0, 0x99]).ok(), + Some(0x99000099CDAB0DA0u64) + ); let failure64: Result = deserialize(&[1u8, 2, 3, 4, 5, 6, 7]); assert!(failure64.is_err()); // i64 assert_eq!(deserialize(&[0xABu8, 0xCD, 0, 0, 0, 0, 0, 0]).ok(), Some(0xCDABi64)); - assert_eq!(deserialize(&[0xA0u8, 0x0D, 0xAB, 0xCD, 0x99, 0, 0, 0x99]).ok(), Some(-0x66ffff663254f260i64)); - assert_eq!(deserialize(&[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).ok(), Some(-1_i64)); - assert_eq!(deserialize(&[0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).ok(), Some(-2_i64)); - assert_eq!(deserialize(&[0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).ok(), Some(-255_i64)); - assert_eq!(deserialize(&[0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).ok(), Some(-254_i64)); + assert_eq!( + deserialize(&[0xA0u8, 0x0D, 0xAB, 0xCD, 0x99, 0, 0, 0x99]).ok(), + Some(-0x66ffff663254f260i64) + ); + assert_eq!( + deserialize(&[0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).ok(), + Some(-1_i64) + ); + assert_eq!( + deserialize(&[0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).ok(), + Some(-2_i64) + ); + assert_eq!( + deserialize(&[0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).ok(), + Some(-255_i64) + ); + assert_eq!( + deserialize(&[0x02, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]).ok(), + Some(-254_i64) + ); let failurei64: Result = deserialize(&[1u8, 2, 3, 4, 5, 6, 7]); assert!(failurei64.is_err()); - } #[test] @@ -1025,13 +1087,18 @@ mod tests { assert_eq!(deserialize(&[3u8, 2, 3, 4]).ok(), Some(vec![2u8, 3, 4])); assert!((deserialize(&[4u8, 2, 3, 4, 5, 6]) as Result, _>).is_err()); // found by cargo fuzz - assert!(deserialize::>(&[0xff,0xff,0xff,0xff,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0x6b,0xa,0xa,0x3a]).is_err()); + assert!(deserialize::>(&[ + 0xff, 0xff, 0xff, 0xff, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, 0x6b, + 0x6b, 0x6b, 0xa, 0xa, 0x3a + ]) + .is_err()); let rand_io_err = Error::Io(io::Error::new(io::ErrorKind::Other, "")); // Check serialization that `if len > MAX_VEC_SIZE {return err}` isn't inclusive, // by making sure it fails with IO Error and not an `OversizedVectorAllocation` Error. - let err = deserialize::(&serialize(&(super::MAX_VEC_SIZE as u32))).unwrap_err(); + let err = + deserialize::(&serialize(&(super::MAX_VEC_SIZE as u32))).unwrap_err(); assert_eq!(discriminant(&err), discriminant(&rand_io_err)); test_len_is_max_vec::(); @@ -1049,7 +1116,11 @@ mod tests { test_len_is_max_vec::(); } - fn test_len_is_max_vec() where Vec: Decodable, T: fmt::Debug { + fn test_len_is_max_vec() + where + Vec: Decodable, + T: fmt::Debug, + { let rand_io_err = Error::Io(io::Error::new(io::ErrorKind::Other, "")); let varint = VarInt((super::MAX_VEC_SIZE / mem::size_of::()) as u64); let err = deserialize::>(&serialize(&varint)).unwrap_err(); @@ -1058,7 +1129,10 @@ mod tests { #[test] fn deserialize_strbuf_test() { - assert_eq!(deserialize(&[6u8, 0x41, 0x6e, 0x64, 0x72, 0x65, 0x77]).ok(), Some("Andrew".to_string())); + assert_eq!( + deserialize(&[6u8, 0x41, 0x6e, 0x64, 0x72, 0x65, 0x77]).ok(), + Some("Andrew".to_string()) + ); assert_eq!( deserialize(&[6u8, 0x41, 0x6e, 0x64, 0x72, 0x65, 0x77]).ok(), Some(Cow::Borrowed("Andrew")) @@ -1067,7 +1141,8 @@ mod tests { #[test] fn deserialize_checkeddata_test() { - let cd: Result = deserialize(&[5u8, 0, 0, 0, 162, 107, 175, 90, 1, 2, 3, 4, 5]); + let cd: Result = + deserialize(&[5u8, 0, 0, 0, 162, 107, 175, 90, 1, 2, 3, 4, 5]); assert_eq!(cd.ok(), Some(CheckedData(vec![1u8, 2, 3, 4, 5]))); } @@ -1105,7 +1180,7 @@ mod tests { let mut data = Vec::with_capacity(256); let mut data64 = Vec::with_capacity(256); for _ in 0..10 { - round_trip!{bool, i8, u8, i16, u16, i32, u32, i64, u64, + round_trip! {bool, i8, u8, i16, u16, i32, u32, i64, u64, (bool, i8, u16, i32), (u64, i64, u32, i32, u16, i16), (i8, u8, i16, u16, i32, u32, i64, u64), [u8; 2], [u8; 4], [u8; 8], [u8; 12], [u8; 16], [u8; 32]}; @@ -1116,22 +1191,21 @@ mod tests { data64.resize(len, 0u64); let mut arr33 = [0u8; 33]; let mut arr16 = [0u16; 8]; - round_trip_bytes!{(Vec, data), ([u8; 33], arr33), ([u16; 8], arr16), (Vec, data64)}; - - + round_trip_bytes! {(Vec, data), ([u8; 33], arr33), ([u16; 8], arr16), (Vec, data64)}; } } #[test] fn test_read_bytes_from_finite_reader() { - let data : Vec = (0..10).collect(); + let data: Vec = (0..10).collect(); for chunk_size in 1..20 { assert_eq!( read_bytes_from_finite_reader( io::Cursor::new(&data), ReadBytesFromFiniteReaderOpts { len: data.len(), chunk_size } - ).unwrap(), + ) + .unwrap(), data ); } diff --git a/bitcoin/src/consensus/mod.rs b/bitcoin/src/consensus/mod.rs index 9ccae25f..0759358f 100644 --- a/bitcoin/src/consensus/mod.rs +++ b/bitcoin/src/consensus/mod.rs @@ -9,8 +9,9 @@ pub mod encode; pub mod params; -pub use self::encode::{Encodable, Decodable, WriteExt, ReadExt}; -pub use self::encode::{serialize, deserialize, deserialize_partial}; +pub use self::encode::{ + deserialize, deserialize_partial, serialize, Decodable, Encodable, ReadExt, WriteExt, +}; pub use self::params::Params; #[cfg(feature = "serde")] diff --git a/bitcoin/src/consensus/params.rs b/bitcoin/src/consensus/params.rs index dc4909d4..07b5ff8d 100644 --- a/bitcoin/src/consensus/params.rs +++ b/bitcoin/src/consensus/params.rs @@ -83,7 +83,7 @@ impl Params { }, Network::Signet => Params { network: Network::Signet, - bip16_time: 1333238400, // Apr 1 2012 + bip16_time: 1333238400, // Apr 1 2012 bip34_height: 1, bip65_height: 1, bip66_height: 1, diff --git a/bitcoin/src/consensus/serde.rs b/bitcoin/src/consensus/serde.rs index cbae90cd..7b411d01 100644 --- a/bitcoin/src/consensus/serde.rs +++ b/bitcoin/src/consensus/serde.rs @@ -9,20 +9,22 @@ use core::fmt; use core::marker::PhantomData; -use crate::io; -use serde::{Serializer, Deserializer}; -use serde::de::{Visitor, SeqAccess, Unexpected}; + +use serde::de::{SeqAccess, Unexpected, Visitor}; use serde::ser::SerializeSeq; -use super::{Encodable, Decodable}; +use serde::{Deserializer, Serializer}; + use super::encode::Error as ConsensusError; +use super::{Decodable, Encodable}; +use crate::io; /// Hex-encoding strategy -pub struct Hex(PhantomData) where Case: hex::Case; +pub struct Hex(PhantomData) +where + Case: hex::Case; impl Default for Hex { - fn default() -> Self { - Hex(Default::default()) - } + fn default() -> Self { Hex(Default::default()) } } impl ByteEncoder for Hex { @@ -33,6 +35,7 @@ impl ByteEncoder for Hex { pub mod hex { use core::fmt; use core::marker::PhantomData; + use bitcoin_internals as internals; use internals::hex::BufEncoder; @@ -131,9 +134,7 @@ pub mod hex { type DecodeError = DecodeError; type Decoder = Decoder<'a>; - fn from_str(s: &'a str) -> Result { - Decoder::new(s) - } + fn from_str(s: &'a str) -> Result { Decoder::new(s) } } impl super::IntoDeError for DecodeInitError { @@ -141,7 +142,8 @@ pub mod hex { use bitcoin_hashes::hex::Error; match self.0 { - Error::OddLengthString(len) => E::invalid_length(len, &"an even number of ASCII-encoded hex digits"), + Error::OddLengthString(len) => + E::invalid_length(len, &"an even number of ASCII-encoded hex digits"), error => panic!("unexpected error: {:?}", error), } } @@ -155,8 +157,10 @@ pub mod hex { const EXPECTED_CHAR: &str = "an ASCII-encoded hex digit"; match self.0 { - Error::InvalidChar(c) if c.is_ascii() => E::invalid_value(Unexpected::Char(c as _), &EXPECTED_CHAR), - Error::InvalidChar(c) => E::invalid_value(Unexpected::Unsigned(c.into()), &EXPECTED_CHAR), + Error::InvalidChar(c) if c.is_ascii() => + E::invalid_value(Unexpected::Char(c as _), &EXPECTED_CHAR), + Error::InvalidChar(c) => + E::invalid_value(Unexpected::Unsigned(c.into()), &EXPECTED_CHAR), error => panic!("unexpected error: {:?}", error), } } @@ -173,8 +177,15 @@ impl<'a, T: 'a + Encodable, E: ByteEncoder> fmt::Display for DisplayWrapper<'a, { use crate::StdError; - if error.kind() != io::ErrorKind::Other || error.source().is_some() || !writer.writer.was_error { - panic!("{} returned an unexpected error: {:?}", core::any::type_name::(), error); + if error.kind() != io::ErrorKind::Other + || error.source().is_some() + || !writer.writer.was_error + { + panic!( + "{} returned an unexpected error: {:?}", + core::any::type_name::(), + error + ); } } fmt::Error @@ -255,15 +266,10 @@ struct IoWrapper<'a, W: fmt::Write, E: EncodeBytes> { impl<'a, W: fmt::Write, E: EncodeBytes> IoWrapper<'a, W, E> { fn new(writer: &'a mut W, encoder: E) -> Self { - IoWrapper { - writer: ErrorTrackingWriter::new(writer), - encoder, - } + IoWrapper { writer: ErrorTrackingWriter::new(writer), encoder } } - fn actually_flush(&mut self) -> fmt::Result { - self.encoder.flush(&mut self.writer) - } + fn actually_flush(&mut self) -> fmt::Result { self.encoder.flush(&mut self.writer) } } impl<'a, W: fmt::Write, E: EncodeBytes> io::Write for IoWrapper<'a, W, E> { @@ -319,7 +325,7 @@ pub trait ByteDecoder<'a> { type DecodeError: IntoDeError + fmt::Debug; /// The decoder state. - type Decoder: Iterator>; + type Decoder: Iterator>; /// Constructs the decoder from string. fn from_str(s: &'a str) -> Result; @@ -331,15 +337,13 @@ pub trait IntoDeError { fn into_de_error(self) -> E; } -struct BinWriter{ +struct BinWriter { serializer: S, error: Option, } impl io::Write for BinWriter { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.write_all(buf).map(|_| buf.len()) - } + fn write(&mut self, buf: &[u8]) -> io::Result { self.write_all(buf).map(|_| buf.len()) } fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { for byte in buf { @@ -372,15 +376,29 @@ enum DecodeError { fn consensus_error_into_serde(error: ConsensusError) -> E { match error { ConsensusError::Io(error) => panic!("unexpected IO error {:?}", error), - ConsensusError::OversizedVectorAllocation { requested, max } => E::custom(format_args!("the requested allocation of {} items exceeds maximum of {}", requested, max)), - ConsensusError::InvalidChecksum { expected, actual } => E::invalid_value(Unexpected::Bytes(&actual), &DisplayExpected(format_args!("checksum {:02x}{:02x}{:02x}{:02x}", expected[0], expected[1], expected[2], expected[3]))), - ConsensusError::NonMinimalVarInt => E::custom(format_args!("compact size was not encoded minimally")), + ConsensusError::OversizedVectorAllocation { requested, max } => E::custom(format_args!( + "the requested allocation of {} items exceeds maximum of {}", + requested, max + )), + ConsensusError::InvalidChecksum { expected, actual } => E::invalid_value( + Unexpected::Bytes(&actual), + &DisplayExpected(format_args!( + "checksum {:02x}{:02x}{:02x}{:02x}", + expected[0], expected[1], expected[2], expected[3] + )), + ), + ConsensusError::NonMinimalVarInt => + E::custom(format_args!("compact size was not encoded minimally")), ConsensusError::ParseFailed(msg) => E::custom(msg), - ConsensusError::UnsupportedSegwitFlag(flag) => E::invalid_value(Unexpected::Unsigned(flag.into()), &"segwit version 1 flag"), + ConsensusError::UnsupportedSegwitFlag(flag) => + E::invalid_value(Unexpected::Unsigned(flag.into()), &"segwit version 1 flag"), } } -impl DecodeError where E: serde::de::Error { +impl DecodeError +where + E: serde::de::Error, +{ fn unify(self) -> E { match self { DecodeError::Other(error) => error, @@ -390,7 +408,10 @@ impl DecodeError where E: serde::de::Error { } } -impl IntoDeError for DecodeError where E: IntoDeError { +impl IntoDeError for DecodeError +where + E: IntoDeError, +{ fn into_de_error(self) -> DE { match self { DecodeError::Other(error) => error.into_de_error(), @@ -400,18 +421,13 @@ impl IntoDeError for DecodeError where E: IntoDeError { } } -struct IterReader>> { +struct IterReader>> { iterator: core::iter::Fuse, error: Option, } -impl>> IterReader { - fn new(iterator: I) -> Self { - IterReader { - iterator: iterator.fuse(), - error: None, - } - } +impl>> IterReader { + fn new(iterator: I) -> Self { IterReader { iterator: iterator.fuse(), error: None } } fn decode(mut self) -> Result> { use crate::StdError; @@ -431,7 +447,7 @@ impl>> IterReader { } } -impl>> io::Read for IterReader { +impl>> io::Read for IterReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { let mut count = 0; for (dst, src) in buf.iter_mut().zip(&mut self.iterator) { @@ -469,30 +485,46 @@ pub struct With(PhantomData); impl With { /// Serializes the value as consensus-encoded - pub fn serialize(value: &T, serializer: S) -> Result where E: ByteEncoder { + pub fn serialize( + value: &T, + serializer: S, + ) -> Result + where + E: ByteEncoder, + { if serializer.is_human_readable() { serializer.collect_str(&DisplayWrapper::<'_, _, E>(value, Default::default())) } else { use crate::StdError; let serializer = serializer.serialize_seq(None)?; - let mut writer = BinWriter { - serializer, - error: None, - }; + let mut writer = BinWriter { serializer, error: None }; let result = value.consensus_encode(&mut writer); match (result, writer.error) { (Ok(_), None) => writer.serializer.end(), - (Ok(_), Some(error)) => panic!("{} silently ate an IO error: {:?}", core::any::type_name::(), error), - (Err(io_error), Some(ser_error)) if io_error.kind() == io::ErrorKind::Other && io_error.source().is_none() => Err(ser_error), - (Err(io_error), ser_error) => panic!("{} returned an unexpected IO error: {:?} serialization error: {:?}", core::any::type_name::(), io_error, ser_error), + (Ok(_), Some(error)) => + panic!("{} silently ate an IO error: {:?}", core::any::type_name::(), error), + (Err(io_error), Some(ser_error)) + if io_error.kind() == io::ErrorKind::Other && io_error.source().is_none() => + Err(ser_error), + (Err(io_error), ser_error) => panic!( + "{} returned an unexpected IO error: {:?} serialization error: {:?}", + core::any::type_name::(), + io_error, + ser_error + ), } } } /// Deserializes the value as consensus-encoded - pub fn deserialize<'d, T: Decodable, D: Deserializer<'d>>(deserializer: D) -> Result where for<'a> E: ByteDecoder<'a> { + pub fn deserialize<'d, T: Decodable, D: Deserializer<'d>>( + deserializer: D, + ) -> Result + where + for<'a> E: ByteDecoder<'a>, + { if deserializer.is_human_readable() { deserializer.deserialize_str(HRVisitor::<_, E>(Default::default())) } else { @@ -535,7 +567,5 @@ struct SeqIterator<'a, S: serde::de::SeqAccess<'a>>(S, PhantomData<&'a ()>); impl<'a, S: serde::de::SeqAccess<'a>> Iterator for SeqIterator<'a, S> { type Item = Result; - fn next(&mut self) -> Option { - self.0.next_element::().transpose() - } + fn next(&mut self) -> Option { self.0.next_element::().transpose() } } From 314e6786b46623c90b407cf33c56a5cc40781148 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 2 Dec 2022 14:44:31 +1100 Subject: [PATCH 05/16] crypto: Add rustfmt::skip attributes In preparation for formatting the `crypto` module add a couple of `skip` attributes to keep arrays formatted 8 bytes per line. --- bitcoin/src/crypto/key.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs index e1646864..4c7158da 100644 --- a/bitcoin/src/crypto/key.rs +++ b/bitcoin/src/crypto/key.rs @@ -835,6 +835,7 @@ mod tests { 9b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef\ 87288ed73ce47fc4f5c79d19ebfa57da7cff3aff6e819e4ee971d86b5e61875d\ "; + #[rustfmt::skip] static PK_BYTES: [u8; 33] = [ 0x03, 0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec, @@ -842,6 +843,7 @@ mod tests { 0x66, 0xc0, 0x28, 0x3e, 0xe9, 0xbe, 0x98, 0x0e, 0x29, 0xce, 0x32, 0x5a, 0x0f, 0x46, 0x79, 0xef, ]; + #[rustfmt::skip] static PK_BYTES_U: [u8; 65] = [ 0x04, 0x9b, 0x63, 0x47, 0x39, 0x85, 0x05, 0xf5, 0xec, From c8a3c58786ad8a76c9a084a953accef22ff35d19 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 2 Dec 2022 14:45:50 +1100 Subject: [PATCH 06/16] Enable formatting for crypto Remove the exclude for the `crypto` module. Do not run the formatter, that will be done as a separate patch to aid review. --- rustfmt.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index 3018b339..53fb3127 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,7 +1,6 @@ # Eventually this shoud be: ignore = [] ignore = [ "bitcoin/src/blockdata", - "bitcoin/src/crypto", "bitcoin/src/psbt", "bitcoin/src/util", "hashes", From 3ec8a12428170891b7227ba7c61ba6e1f6133b46 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 6 Dec 2022 10:39:56 +1100 Subject: [PATCH 07/16] crypto: Run the formatter Run `cargo +nightly fmt`, no other manual changes. --- bitcoin/src/crypto/ecdsa.rs | 94 ++++---------- bitcoin/src/crypto/key.rs | 238 +++++++++++++++------------------- bitcoin/src/crypto/sighash.rs | 107 +++++++++------ bitcoin/src/crypto/taproot.rs | 28 ++-- 4 files changed, 205 insertions(+), 262 deletions(-) diff --git a/bitcoin/src/crypto/ecdsa.rs b/bitcoin/src/crypto/ecdsa.rs index 58ee6644..664a2d09 100644 --- a/bitcoin/src/crypto/ecdsa.rs +++ b/bitcoin/src/crypto/ecdsa.rs @@ -8,14 +8,14 @@ use core::str::FromStr; use core::{fmt, iter}; -use bitcoin_internals::write_err; use bitcoin_internals::hex::display::DisplayHex; +use bitcoin_internals::write_err; use secp256k1; -use crate::prelude::*; use crate::hashes::hex::{self, FromHex}; -use crate::sighash::{EcdsaSighashType, NonStandardSighashType}; +use crate::prelude::*; use crate::script::PushBytes; +use crate::sighash::{EcdsaSighashType, NonStandardSighashType}; const MAX_SIG_LEN: usize = 73; @@ -33,20 +33,15 @@ pub struct Signature { impl Signature { /// Constructs an ECDSA bitcoin signature for [`EcdsaSighashType::All`]. pub fn sighash_all(sig: secp256k1::ecdsa::Signature) -> Signature { - Signature { - sig, - hash_ty: EcdsaSighashType::All - } + Signature { sig, hash_ty: EcdsaSighashType::All } } /// Deserializes from slice following the standardness rules for [`EcdsaSighashType`]. pub fn from_slice(sl: &[u8]) -> Result { - let (hash_ty, sig) = sl.split_last() - .ok_or(Error::EmptySignature)?; + let (hash_ty, sig) = sl.split_last().ok_or(Error::EmptySignature)?; let hash_ty = EcdsaSighashType::from_standard(*hash_ty as u32) .map_err(|_| Error::NonStandardSighashType(*hash_ty as u32))?; - let sig = secp256k1::ecdsa::Signature::from_der(sig) - .map_err(Error::Secp256k1)?; + let sig = secp256k1::ecdsa::Signature::from_der(sig).map_err(Error::Secp256k1)?; Ok(Signature { sig, hash_ty }) } @@ -58,10 +53,7 @@ impl Signature { let signature = self.sig.serialize_der(); buf[..signature.len()].copy_from_slice(&signature); buf[signature.len()] = self.hash_ty as u8; - SerializedSignature { - data: buf, - len: signature.len() + 1, - } + SerializedSignature { data: buf, len: signature.len() + 1 } } /// Serializes an ECDSA signature (inner secp256k1 signature in DER format) into `Vec`. @@ -70,10 +62,7 @@ impl Signature { /// [`serialize`](Self::serialize) method instead. pub fn to_vec(self) -> Vec { // TODO: add support to serialize to a writer to SerializedSig - self.sig.serialize_der() - .iter().copied() - .chain(iter::once(self.hash_ty as u8)) - .collect() + self.sig.serialize_der().iter().copied().chain(iter::once(self.hash_ty as u8)).collect() } } @@ -89,11 +78,10 @@ impl FromStr for Signature { fn from_str(s: &str) -> Result { let bytes = Vec::from_hex(s)?; - let (sighash_byte, signature) = bytes.split_last() - .ok_or(Error::EmptySignature)?; + let (sighash_byte, signature) = bytes.split_last().ok_or(Error::EmptySignature)?; Ok(Signature { sig: secp256k1::ecdsa::Signature::from_der(signature)?, - hash_ty: EcdsaSighashType::from_standard(*sighash_byte as u32)? + hash_ty: EcdsaSighashType::from_standard(*sighash_byte as u32)?, }) } } @@ -114,60 +102,44 @@ pub struct SerializedSignature { impl SerializedSignature { /// Returns an iterator over bytes of the signature. #[inline] - pub fn iter(&self) -> core::slice::Iter<'_, u8> { - self.into_iter() - } + pub fn iter(&self) -> core::slice::Iter<'_, u8> { self.into_iter() } } impl core::ops::Deref for SerializedSignature { type Target = [u8]; #[inline] - fn deref(&self) -> &Self::Target { - &self.data[..self.len] - } + fn deref(&self) -> &Self::Target { &self.data[..self.len] } } impl core::ops::DerefMut for SerializedSignature { #[inline] - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.data[..self.len] - } + fn deref_mut(&mut self) -> &mut Self::Target { &mut self.data[..self.len] } } impl AsRef<[u8]> for SerializedSignature { #[inline] - fn as_ref(&self) -> &[u8] { - self - } + fn as_ref(&self) -> &[u8] { self } } impl AsMut<[u8]> for SerializedSignature { #[inline] - fn as_mut(&mut self) -> &mut [u8] { - self - } + fn as_mut(&mut self) -> &mut [u8] { self } } impl AsRef for SerializedSignature { #[inline] - fn as_ref(&self) -> &PushBytes { - &<&PushBytes>::from(&self.data)[..self.len()] - } + fn as_ref(&self) -> &PushBytes { &<&PushBytes>::from(&self.data)[..self.len()] } } impl core::borrow::Borrow<[u8]> for SerializedSignature { #[inline] - fn borrow(&self) -> &[u8] { - self - } + fn borrow(&self) -> &[u8] { self } } impl core::borrow::BorrowMut<[u8]> for SerializedSignature { #[inline] - fn borrow_mut(&mut self) -> &mut [u8] { - self - } + fn borrow_mut(&mut self) -> &mut [u8] { self } } impl fmt::Debug for SerializedSignature { @@ -202,9 +174,7 @@ impl PartialEq for SerializedSignature { impl Eq for SerializedSignature {} impl core::hash::Hash for SerializedSignature { - fn hash(&self, state: &mut H) { - core::hash::Hash::hash(&**self, state) - } + fn hash(&self, state: &mut H) { core::hash::Hash::hash(&**self, state) } } impl<'a> IntoIterator for &'a SerializedSignature { @@ -212,9 +182,7 @@ impl<'a> IntoIterator for &'a SerializedSignature { type Item = &'a u8; #[inline] - fn into_iter(self) -> Self::IntoIter { - (*self).iter() - } + fn into_iter(self) -> Self::IntoIter { (*self).iter() } } /// A key-related error. @@ -231,18 +199,14 @@ pub enum Error { Secp256k1(secp256k1::Error), } - impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - Error::HexEncoding(ref e) => - write_err!(f, "Signature hex encoding error"; e), + Error::HexEncoding(ref e) => write_err!(f, "Signature hex encoding error"; e), Error::NonStandardSighashType(hash_ty) => write!(f, "Non standard signature hash type {}", hash_ty), - Error::EmptySignature => - write!(f, "Empty ECDSA signature"), - Error::Secp256k1(ref e) => - write_err!(f, "invalid ECDSA signature"; e), + Error::EmptySignature => write!(f, "Empty ECDSA signature"), + Error::Secp256k1(ref e) => write_err!(f, "invalid ECDSA signature"; e), } } } @@ -262,19 +226,13 @@ impl std::error::Error for Error { } impl From for Error { - fn from(e: secp256k1::Error) -> Error { - Error::Secp256k1(e) - } + fn from(e: secp256k1::Error) -> Error { Error::Secp256k1(e) } } impl From for Error { - fn from(err: NonStandardSighashType) -> Self { - Error::NonStandardSighashType(err.0) - } + fn from(err: NonStandardSighashType) -> Self { Error::NonStandardSighashType(err.0) } } impl From for Error { - fn from(err: hex::Error) -> Self { - Error::HexEncoding(err) - } + fn from(err: hex::Error) -> Self { Error::HexEncoding(err) } } diff --git a/bitcoin/src/crypto/key.rs b/bitcoin/src/crypto/key.rs index 4c7158da..1ac38b5a 100644 --- a/bitcoin/src/crypto/key.rs +++ b/bitcoin/src/crypto/key.rs @@ -6,20 +6,20 @@ //! This module provides keys used in Bitcoin that can be roundtrip //! (de)serialized. -use crate::prelude::*; - -use core::{ops, str::FromStr}; use core::fmt::{self, Write}; +use core::ops; +use core::str::FromStr; use bitcoin_internals::write_err; +pub use secp256k1::{self, constants, KeyPair, Parity, Secp256k1, Verification, XOnlyPublicKey}; -pub use secp256k1::{self, constants, Secp256k1, KeyPair, XOnlyPublicKey, Verification, Parity}; - -use crate::{base58, io}; -use crate::network::constants::Network; -use crate::hashes::{Hash, hash160, hex, hex::FromHex}; use crate::hash_types::{PubkeyHash, WPubkeyHash}; +use crate::hashes::hex::FromHex; +use crate::hashes::{hash160, hex, Hash}; +use crate::network::constants::Network; +use crate::prelude::*; use crate::taproot::{TapNodeHash, TapTweakHash}; +use crate::{base58, io}; /// A key-related error. #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] @@ -44,7 +44,8 @@ impl fmt::Display for Error { Error::Secp256k1(ref e) => write_err!(f, "key secp256k1 error"; e), Error::InvalidKeyPrefix(ref b) => write!(f, "key prefix invalid: {}", b), Error::Hex(ref e) => write_err!(f, "key hex decoding error"; e), - Error::InvalidHexLength(got) => write!(f, "PublicKey hex should be 66 or 130 digits long, got: {}", got), + Error::InvalidHexLength(got) => + write!(f, "PublicKey hex should be 66 or 130 digits long, got: {}", got), } } } @@ -66,26 +67,19 @@ impl std::error::Error for Error { #[doc(hidden)] impl From for Error { - fn from(e: base58::Error) -> Error { - Error::Base58(e) - } + fn from(e: base58::Error) -> Error { Error::Base58(e) } } #[doc(hidden)] impl From for Error { - fn from(e: secp256k1::Error) -> Error { - Error::Secp256k1(e) - } + fn from(e: secp256k1::Error) -> Error { Error::Secp256k1(e) } } #[doc(hidden)] impl From for Error { - fn from(e: hex::Error) -> Self { - Error::Hex(e) - } + fn from(e: hex::Error) -> Self { Error::Hex(e) } } - /// A Bitcoin ECDSA public key #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] pub struct PublicKey { @@ -98,19 +92,13 @@ pub struct PublicKey { impl PublicKey { /// Constructs compressed ECDSA public key from the provided generic Secp256k1 public key pub fn new(key: impl Into) -> PublicKey { - PublicKey { - compressed: true, - inner: key.into(), - } + PublicKey { compressed: true, inner: key.into() } } /// Constructs uncompressed (legacy) ECDSA public key from the provided generic Secp256k1 /// public key pub fn new_uncompressed(key: impl Into) -> PublicKey { - PublicKey { - compressed: false, - inner: key.into(), - } + PublicKey { compressed: false, inner: key.into() } } fn with_serialized R>(&self, f: F) -> R { @@ -122,15 +110,13 @@ impl PublicKey { } /// Returns bitcoin 160-bit hash of the public key - pub fn pubkey_hash(&self) -> PubkeyHash { - self.with_serialized(PubkeyHash::hash) - } + pub fn pubkey_hash(&self) -> PubkeyHash { self.with_serialized(PubkeyHash::hash) } /// Returns bitcoin 160-bit hash of the public key for witness program pub fn wpubkey_hash(&self) -> Option { if self.compressed { Some(WPubkeyHash::from_byte_array( - hash160::Hash::hash(&self.inner.serialize()).to_byte_array() + hash160::Hash::hash(&self.inner.serialize()).to_byte_array(), )) } else { // We can't create witness pubkey hashes for an uncompressed @@ -249,26 +235,25 @@ impl PublicKey { let compressed = match data.len() { 33 => true, 65 => false, - len => { + len => { return Err(base58::Error::InvalidLength(len).into()); - }, + } }; if !compressed && data[0] != 0x04 { - return Err(Error::InvalidKeyPrefix(data[0])) + return Err(Error::InvalidKeyPrefix(data[0])); } - Ok(PublicKey { - compressed, - inner: secp256k1::PublicKey::from_slice(data)?, - }) + Ok(PublicKey { compressed, inner: secp256k1::PublicKey::from_slice(data)? }) } /// Computes the public key as supposed to be used with this secret - pub fn from_private_key(secp: &Secp256k1, sk: &PrivateKey) -> PublicKey { + pub fn from_private_key( + secp: &Secp256k1, + sk: &PrivateKey, + ) -> PublicKey { sk.public_key(secp) } - } /// An opaque return type for PublicKey::to_sort_key @@ -299,9 +284,7 @@ impl FromStr for PublicKey { } impl From for PubkeyHash { - fn from(key: PublicKey) -> PubkeyHash { - key.pubkey_hash() - } + fn from(key: PublicKey) -> PubkeyHash { key.pubkey_hash() } } /// A Bitcoin ECDSA private key @@ -320,35 +303,25 @@ impl PrivateKey { /// Constructs compressed ECDSA private key from the provided generic Secp256k1 private key /// and the specified network pub fn new(key: secp256k1::SecretKey, network: Network) -> PrivateKey { - PrivateKey { - compressed: true, - network, - inner: key, - } + PrivateKey { compressed: true, network, inner: key } } /// Constructs uncompressed (legacy) ECDSA private key from the provided generic Secp256k1 /// private key and the specified network pub fn new_uncompressed(key: secp256k1::SecretKey, network: Network) -> PrivateKey { - PrivateKey { - compressed: false, - network, - inner: key, - } + PrivateKey { compressed: false, network, inner: key } } /// Creates a public key from this private key pub fn public_key(&self, secp: &Secp256k1) -> PublicKey { PublicKey { compressed: self.compressed, - inner: secp256k1::PublicKey::from_secret_key(secp, &self.inner) + inner: secp256k1::PublicKey::from_secret_key(secp, &self.inner), } } /// Serialize the private key to bytes - pub fn to_bytes(self) -> Vec { - self.inner[..].to_vec() - } + pub fn to_bytes(self) -> Vec { self.inner[..].to_vec() } /// Deserialize a private key from a slice pub fn from_slice(data: &[u8], network: Network) -> Result { @@ -395,7 +368,7 @@ impl PrivateKey { let network = match data[0] { 128 => Network::Bitcoin, 239 => Network::Testnet, - x => { + x => { return Err(Error::Base58(base58::Error::InvalidAddressVersion(x))); } }; @@ -409,30 +382,22 @@ impl PrivateKey { } impl fmt::Display for PrivateKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.fmt_wif(f) - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_wif(f) } } #[cfg(not(feature = "std"))] impl fmt::Debug for PrivateKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - write!(f, "[private key data]") - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "[private key data]") } } impl FromStr for PrivateKey { type Err = Error; - fn from_str(s: &str) -> Result { - PrivateKey::from_wif(s) - } + fn from_str(s: &str) -> Result { PrivateKey::from_wif(s) } } impl ops::Index for PrivateKey { type Output = [u8]; - fn index(&self, _: ops::RangeFull) -> &[u8] { - &self.inner[..] - } + fn index(&self, _: ops::RangeFull) -> &[u8] { &self.inner[..] } } #[cfg(feature = "serde")] @@ -559,15 +524,11 @@ pub type UntweakedPublicKey = XOnlyPublicKey; pub struct TweakedPublicKey(XOnlyPublicKey); impl fmt::LowerHex for TweakedPublicKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::LowerHex::fmt(&self.0, f) - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::LowerHex::fmt(&self.0, f) } } impl fmt::Display for TweakedPublicKey { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.0, f) - } + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fmt::Display::fmt(&self.0, f) } } /// Untweaked BIP-340 key pair @@ -613,7 +574,11 @@ pub trait TapTweak { /// /// # Returns /// The tweaked key and its parity. - fn tap_tweak(self, secp: &Secp256k1, merkle_root: Option) -> Self::TweakedAux; + fn tap_tweak( + self, + secp: &Secp256k1, + merkle_root: Option, + ) -> Self::TweakedAux; /// Directly converts an [`UntweakedPublicKey`] to a [`TweakedPublicKey`] /// @@ -638,7 +603,11 @@ impl TapTweak for UntweakedPublicKey { /// /// # Returns /// The tweaked key and its parity. - fn tap_tweak(self, secp: &Secp256k1, merkle_root: Option) -> (TweakedPublicKey, Parity) { + fn tap_tweak( + self, + secp: &Secp256k1, + merkle_root: Option, + ) -> (TweakedPublicKey, Parity) { let tweak = TapTweakHash::from_key_and_tweak(self, merkle_root).to_scalar(); let (output_key, parity) = self.add_tweak(secp, &tweak).expect("Tap tweak failed"); @@ -646,9 +615,7 @@ impl TapTweak for UntweakedPublicKey { (TweakedPublicKey(output_key), parity) } - fn dangerous_assume_tweaked(self) -> TweakedPublicKey { - TweakedPublicKey(self) - } + fn dangerous_assume_tweaked(self) -> TweakedPublicKey { TweakedPublicKey(self) } } impl TapTweak for UntweakedKeyPair { @@ -667,16 +634,18 @@ impl TapTweak for UntweakedKeyPair { /// /// # Returns /// The tweaked key and its parity. - fn tap_tweak(self, secp: &Secp256k1, merkle_root: Option) -> TweakedKeyPair { + fn tap_tweak( + self, + secp: &Secp256k1, + merkle_root: Option, + ) -> TweakedKeyPair { let (pubkey, _parity) = XOnlyPublicKey::from_keypair(&self); let tweak = TapTweakHash::from_key_and_tweak(pubkey, merkle_root).to_scalar(); let tweaked = self.add_xonly_tweak(secp, &tweak).expect("Tap tweak failed"); TweakedKeyPair(tweaked) } - fn dangerous_assume_tweaked(self) -> TweakedKeyPair { - TweakedKeyPair(self) - } + fn dangerous_assume_tweaked(self) -> TweakedKeyPair { TweakedKeyPair(self) } } impl TweakedPublicKey { @@ -698,17 +667,13 @@ impl TweakedPublicKey { } /// Returns the underlying public key. - pub fn to_inner(self) -> XOnlyPublicKey { - self.0 - } + pub fn to_inner(self) -> XOnlyPublicKey { self.0 } /// Serialize the key as a byte-encoded pair of values. In compressed form /// the y-coordinate is represented by only a single bit, as x determines /// it up to one bit. #[inline] - pub fn serialize(&self) -> [u8; constants::SCHNORR_PUBLIC_KEY_SIZE] { - self.0.serialize() - } + pub fn serialize(&self) -> [u8; constants::SCHNORR_PUBLIC_KEY_SIZE] { self.0.serialize() } } impl TweakedKeyPair { @@ -718,15 +683,11 @@ impl TweakedKeyPair { /// This method is dangerous and can lead to loss of funds if used incorrectly. /// Specifically, in multi-party protocols a peer can provide a value that allows them to steal. #[inline] - pub fn dangerous_assume_tweaked(pair: KeyPair) -> TweakedKeyPair { - TweakedKeyPair(pair) - } + pub fn dangerous_assume_tweaked(pair: KeyPair) -> TweakedKeyPair { TweakedKeyPair(pair) } /// Returns the underlying key pair. #[inline] - pub fn to_inner(self) -> KeyPair { - self.0 - } + pub fn to_inner(self) -> KeyPair { self.0 } /// Returns the [`TweakedPublicKey`] and its [`Parity`] for this [`TweakedKeyPair`]. #[inline] @@ -738,43 +699,36 @@ impl TweakedKeyPair { impl From for XOnlyPublicKey { #[inline] - fn from(pair: TweakedPublicKey) -> Self { - pair.0 - } + fn from(pair: TweakedPublicKey) -> Self { pair.0 } } impl From for KeyPair { #[inline] - fn from(pair: TweakedKeyPair) -> Self { - pair.0 - } + fn from(pair: TweakedKeyPair) -> Self { pair.0 } } impl From for TweakedPublicKey { #[inline] - fn from(pair: TweakedKeyPair) -> Self { - TweakedPublicKey::from_keypair(pair) - } + fn from(pair: TweakedKeyPair) -> Self { TweakedPublicKey::from_keypair(pair) } } #[cfg(test)] mod tests { - use super::*; - use std::str::FromStr; use secp256k1::Secp256k1; + use super::*; use crate::address::Address; use crate::hashes::hex::FromHex; use crate::io; - use crate::network::constants::Network::Testnet; - use crate::network::constants::Network::Bitcoin; + use crate::network::constants::Network::{Bitcoin, Testnet}; #[test] fn test_key_derivation() { // testnet compressed - let sk = PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); + let sk = + PrivateKey::from_wif("cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy").unwrap(); assert_eq!(sk.network, Testnet); assert!(sk.compressed); assert_eq!(&sk.to_wif(), "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"); @@ -790,7 +744,8 @@ mod tests { assert_eq!(&sk.to_wif(), &sk_str.to_wif()); // mainnet uncompressed - let sk = PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap(); + let sk = + PrivateKey::from_wif("5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3").unwrap(); assert_eq!(sk.network, Bitcoin); assert!(!sk.compressed); assert_eq!(&sk.to_wif(), "5JYkZjmN7PVMjJUfJWfRFwtuXTGB439XV6faajeHPAM9Z2PT2R3"); @@ -803,13 +758,25 @@ mod tests { let addr = Address::p2pkh(&pk, sk.network); assert_eq!(&addr.to_string(), "1GhQvF6dL8xa6wBxLnWmHcQsurx9RxiMc8"); pk.compressed = true; - assert_eq!(&pk.to_string(), "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af"); - assert_eq!(pk, PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap()); + assert_eq!( + &pk.to_string(), + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af" + ); + assert_eq!( + pk, + PublicKey::from_str( + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af" + ) + .unwrap() + ); } #[test] fn test_pubkey_hash() { - let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap(); + let pk = PublicKey::from_str( + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", + ) + .unwrap(); let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap(); assert_eq!(pk.pubkey_hash().to_string(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4"); assert_eq!(upk.pubkey_hash().to_string(), "ac2e7daf42d2c97418fd9f78af2de552bb9c6a7a"); @@ -817,16 +784,22 @@ mod tests { #[test] fn test_wpubkey_hash() { - let pk = PublicKey::from_str("032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af").unwrap(); + let pk = PublicKey::from_str( + "032e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af", + ) + .unwrap(); let upk = PublicKey::from_str("042e58afe51f9ed8ad3cc7897f634d881fdbe49a81564629ded8156bebd2ffd1af191923a2964c177f5b5923ae500fca49e99492d534aa3759d6b25a8bc971b133").unwrap(); - assert_eq!(pk.wpubkey_hash().unwrap().to_string(), "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4"); + assert_eq!( + pk.wpubkey_hash().unwrap().to_string(), + "9511aa27ef39bbfa4e4f3dd15f4d66ea57f475b4" + ); assert_eq!(upk.wpubkey_hash(), None); } #[cfg(feature = "serde")] #[test] fn test_key_serde() { - use serde_test::{Configure, Token, assert_tokens}; + use serde_test::{assert_tokens, Configure, Token}; static KEY_WIF: &str = "cVt4o7BGAig1UXywgGSmARhxMdzP5qvQsxKkSsc1XEkw3tDTQFpy"; static PK_STR: &str = "039b6347398505f5ec93826dc61c19f47c66c0283ee9be980e29ce325a0f4679ef"; @@ -859,10 +832,7 @@ mod tests { let s = Secp256k1::new(); let sk = PrivateKey::from_str(KEY_WIF).unwrap(); let pk = PublicKey::from_private_key(&s, &sk); - let pk_u = PublicKey { - inner: pk.inner, - compressed: false, - }; + let pk_u = PublicKey { inner: pk.inner, compressed: false }; assert_tokens(&sk, &[Token::BorrowedStr(KEY_WIF)]); assert_tokens(&pk.compact(), &[Token::BorrowedBytes(&PK_BYTES[..])]); @@ -922,26 +892,29 @@ mod tests { #[test] fn pubkey_to_sort_key() { - let key1 = PublicKey::from_str("02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8").unwrap(); - let key2 = PublicKey { - inner: key1.inner, - compressed: false, - }; + let key1 = PublicKey::from_str( + "02ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8", + ) + .unwrap(); + let key2 = PublicKey { inner: key1.inner, compressed: false }; let expected1 = SortKey( 2, <[u8; 32]>::from_hex( "ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8", - ).unwrap(), + ) + .unwrap(), [0_u8; 32], ); let expected2 = SortKey( 4, <[u8; 32]>::from_hex( "ff12471208c14bd580709cb2358d98975247d8765f92bc25eab3b2763ed605f8", - ).unwrap(), + ) + .unwrap(), <[u8; 32]>::from_hex( "1794e7f3d5e420641a3bc690067df5541470c966cbca8c694bf39aa16d836918", - ).unwrap(), + ) + .unwrap(), ); assert_eq!(key1.to_sort_key(), expected1); assert_eq!(key2.to_sort_key(), expected2); @@ -953,9 +926,8 @@ mod tests { input: Vec, expect: Vec, } - let fmt = |v: Vec<_>| v.into_iter() - .map(|s| PublicKey::from_str(s).unwrap()) - .collect::>(); + let fmt = + |v: Vec<_>| v.into_iter().map(|s| PublicKey::from_str(s).unwrap()).collect::>(); let vectors = vec![ // Start BIP67 vectors // Vector 1 diff --git a/bitcoin/src/crypto/sighash.rs b/bitcoin/src/crypto/sighash.rs index 5390bc82..866aebf6 100644 --- a/bitcoin/src/crypto/sighash.rs +++ b/bitcoin/src/crypto/sighash.rs @@ -14,14 +14,14 @@ use core::borrow::{Borrow, BorrowMut}; use core::{fmt, str}; -use crate::{io, Script, ScriptBuf, Transaction, TxIn, TxOut, Sequence}; use crate::blockdata::transaction::EncodeSigningDataResult; use crate::blockdata::witness::Witness; use crate::consensus::{encode, Encodable}; use crate::error::impl_std_error; -use crate::hashes::{hash_newtype, sha256, sha256t_hash_newtype, sha256d, Hash}; +use crate::hashes::{hash_newtype, sha256, sha256d, sha256t_hash_newtype, Hash}; use crate::prelude::*; use crate::taproot::{LeafVersion, TapLeafHash, TAPROOT_ANNEX_PREFIX}; +use crate::{io, Script, ScriptBuf, Sequence, Transaction, TxIn, TxOut}; /// Used for signature hash for invalid use of SIGHASH_SINGLE. #[rustfmt::skip] @@ -44,7 +44,7 @@ macro_rules! impl_thirty_two_byte_hash { impl secp256k1::ThirtyTwoByteHash for $ty { fn into_32(self) -> [u8; 32] { self.to_byte_array() } } - } + }; } hash_newtype! { @@ -60,10 +60,15 @@ hash_newtype! { impl_thirty_two_byte_hash!(LegacySighash); impl_thirty_two_byte_hash!(SegwitV0Sighash); -sha256t_hash_newtype!(TapSighash, TapSighashTag, MIDSTATE_TAPSIGHASH, 64, - doc="Taproot-tagged hash with tag \"TapSighash\". +sha256t_hash_newtype!( + TapSighash, + TapSighashTag, + MIDSTATE_TAPSIGHASH, + 64, + doc = "Taproot-tagged hash with tag \"TapSighash\". -This hash type is used for computing taproot signature hash.", forward +This hash type is used for computing taproot signature hash.", + forward ); impl_thirty_two_byte_hash!(TapSighash); @@ -559,14 +564,10 @@ impl> SighashCache { } /// Returns the reference to the cached transaction. - pub fn transaction(&self) -> &Transaction { - self.tx.borrow() - } + pub fn transaction(&self) -> &Transaction { self.tx.borrow() } /// Destroys the cache and recovers the stored transaction. - pub fn into_transaction(self) -> R { - self.tx - } + pub fn into_transaction(self) -> R { self.tx } /// Encodes the BIP341 signing data for any flag type into a given object implementing a /// [`io::Write`] trait. @@ -633,10 +634,11 @@ impl> SighashCache { // scriptPubKey (35): scriptPubKey of the previous output spent by this input, serialized as script inside CTxOut. Its size is always 35 bytes. // nSequence (4): nSequence of this input. if anyone_can_pay { - let txin = &self.tx.borrow().input.get(input_index).ok_or(Error::IndexOutOfInputsBounds { - index: input_index, - inputs_size: self.tx.borrow().input.len(), - })?; + let txin = + &self.tx.borrow().input.get(input_index).ok_or(Error::IndexOutOfInputsBounds { + index: input_index, + inputs_size: self.tx.borrow().input.len(), + })?; let previous_output = prevouts.get(input_index)?; txin.previous_output.consensus_encode(&mut writer)?; previous_output.value.consensus_encode(&mut writer)?; @@ -782,10 +784,11 @@ impl> SighashCache { } { - let txin = &self.tx.borrow().input.get(input_index).ok_or(Error::IndexOutOfInputsBounds { - index: input_index, - inputs_size: self.tx.borrow().input.len(), - })?; + let txin = + &self.tx.borrow().input.get(input_index).ok_or(Error::IndexOutOfInputsBounds { + index: input_index, + inputs_size: self.tx.borrow().input.len(), + })?; txin.previous_output.consensus_encode(&mut writer)?; script_code.consensus_encode(&mut writer)?; @@ -795,7 +798,8 @@ impl> SighashCache { if sighash != EcdsaSighashType::Single && sighash != EcdsaSighashType::None { self.segwit_cache().outputs.consensus_encode(&mut writer)?; - } else if sighash == EcdsaSighashType::Single && input_index < self.tx.borrow().output.len() { + } else if sighash == EcdsaSighashType::Single && input_index < self.tx.borrow().output.len() + { let mut single_enc = LegacySighash::engine(); self.tx.borrow().output[input_index].consensus_encode(&mut single_enc)?; let hash = LegacySighash::from_engine(single_enc); @@ -865,7 +869,11 @@ impl> SighashCache { } let sighash_type: u32 = sighash_type.into(); - if is_invalid_use_of_sighash_single(sighash_type, input_index, self.tx.borrow().output.len()) { + if is_invalid_use_of_sighash_single( + sighash_type, + input_index, + self.tx.borrow().output.len(), + ) { // We cannot correctly handle the SIGHASH_SINGLE bug here because usage of this function // will result in the data written to the writer being hashed, however the correct // handling of the SIGHASH_SINGLE bug is to return the 'one array' - either implement @@ -1197,8 +1205,7 @@ mod tests { #[test] fn test_tap_sighash_hash() { let bytes = hex!("00011b96877db45ffa23b307e9f0ac87b80ef9a80b4c5f0db3fbe734422453e83cc5576f3d542c5d4898fb2b696c15d43332534a7c1d1255fda38993545882df92c3e353ff6d36fbfadc4d168452afd8467f02fe53d71714fcea5dfe2ea759bd00185c4cb02bc76d42620393ca358a1a713f4997f9fc222911890afb3fe56c6a19b202df7bffdcfad08003821294279043746631b00e2dc5e52a111e213bbfe6ef09a19428d418dab0d50000000000"); - let expected = - hex!("04e808aad07a40b3767a1442fead79af6ef7e7c9316d82dec409bb31e77699b0"); + let expected = hex!("04e808aad07a40b3767a1442fead79af6ef7e7c9316d82dec409bb31e77699b0"); let mut enc = TapSighash::engine(); enc.input(&bytes); let hash = TapSighash::from_engine(enc); @@ -1690,22 +1697,27 @@ mod tests { let mut cache = SighashCache::new(&tx); assert_eq!( cache.segwit_signature_hash(1, &witness_script, value, EcdsaSighashType::All).unwrap(), - "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670".parse::().unwrap(), + "c37af31116d1b27caf68aae9e3ac82f1477929014d5b917657d0eb49478cb670" + .parse::() + .unwrap(), ); let cache = cache.segwit_cache(); // Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards. assert_eq!( cache.prevouts.as_byte_array(), - &Vec::from_hex("96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37").unwrap()[..], + &Vec::from_hex("96b827c8483d4e9b96712b6713a7b68d6e8003a781feba36c31143470b4efd37") + .unwrap()[..], ); assert_eq!( cache.sequences.as_byte_array(), - &Vec::from_hex("52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b").unwrap()[..], + &Vec::from_hex("52b0a642eea2fb7ae638c36f6252b6750293dbe574a806984b8e4d8548339a3b") + .unwrap()[..], ); assert_eq!( cache.outputs.as_byte_array(), - &Vec::from_hex("863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5").unwrap()[..], + &Vec::from_hex("863ef3e1a92afbfdb97f31ad0fc7683ee943e9abcf2501590ff8f6551f47e5e5") + .unwrap()[..], ); } @@ -1726,33 +1738,38 @@ mod tests { let mut cache = SighashCache::new(&tx); assert_eq!( cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(), - "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6".parse::().unwrap(), + "64f3b0f4dd2bb3aa1ce8566d220cc74dda9df97d8490cc81d89d735c92e59fb6" + .parse::() + .unwrap(), ); let cache = cache.segwit_cache(); // Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards. assert_eq!( cache.prevouts.as_byte_array(), - &Vec::from_hex("b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a").unwrap()[..], + &Vec::from_hex("b0287b4a252ac05af83d2dcef00ba313af78a3e9c329afa216eb3aa2a7b4613a") + .unwrap()[..], ); assert_eq!( cache.sequences.as_byte_array(), - &Vec::from_hex("18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198").unwrap()[..], + &Vec::from_hex("18606b350cd8bf565266bc352f0caddcf01e8fa789dd8a15386327cf8cabe198") + .unwrap()[..], ); assert_eq!( cache.outputs.as_byte_array(), - &Vec::from_hex("de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83").unwrap()[..], + &Vec::from_hex("de984f44532e2173ca0d64314fcefe6d30da6f8cf27bafa706da61df8a226c83") + .unwrap()[..], ); } #[test] fn bip143_p2wsh_nested_in_p2sh() { - let tx = deserialize::( - &hex!( + let tx = deserialize::(&hex!( "010000000136641869ca081e70f394c6948e8af409e18b619df2ed74aa106c1ca29787b96e0100000000\ ffffffff0200e9a435000000001976a914389ffce9cd9ae88dcc0631e88a821ffdbe9bfe2688acc0832f\ - 05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000"), - ).unwrap(); + 05000000001976a9147480a33f950689af511e6e84c138dbbd3c3ee41588ac00000000" + )) + .unwrap(); let witness_script = ScriptBuf::from_hex( "56210307b8ae49ac90a048e9b53357a2354b3334e9c8bee813ecb98e99a7e07e8c3ba32103b28f0c28\ @@ -1760,29 +1777,35 @@ mod tests { 9781957b8c0ac1dfe69f492580ca4195f50376ba4a21033400f6afecb833092a9a21cfdf1ed1376e58\ c5d1f47de74683123987e967a8f42103a6d48b1131e94ba04d9737d61acdaa1322008af9602b3b1486\ 2c07a1789aac162102d8b661b0b3302ee2f162b09e07a55ad5dfbe673a9f01d9f0c19617681024306b\ - 56ae" - ).unwrap(); + 56ae", + ) + .unwrap(); let value = 987654321; let mut cache = SighashCache::new(&tx); assert_eq!( cache.segwit_signature_hash(0, &witness_script, value, EcdsaSighashType::All).unwrap(), - "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c".parse::().unwrap(), + "185c0be5263dce5b4bb50a047973c1b6272bfbd0103a89444597dc40b248ee7c" + .parse::() + .unwrap(), ); let cache = cache.segwit_cache(); // Parse hex into Vec because BIP143 test vector displays forwards but our sha256d::Hash displays backwards. assert_eq!( cache.prevouts.as_byte_array(), - &Vec::from_hex("74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0").unwrap()[..], + &Vec::from_hex("74afdc312af5183c4198a40ca3c1a275b485496dd3929bca388c4b5e31f7aaa0") + .unwrap()[..], ); assert_eq!( cache.sequences.as_byte_array(), - &Vec::from_hex("3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044").unwrap()[..], + &Vec::from_hex("3bb13029ce7b1f559ef5e747fcac439f1455a2ec7c5f09b72290795e70665044") + .unwrap()[..], ); assert_eq!( cache.outputs.as_byte_array(), - &Vec::from_hex("bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc").unwrap()[..], + &Vec::from_hex("bc4d309071414bed932f98832b27b4d76dad7e6c1346f487a8fdbb8eb90307cc") + .unwrap()[..], ); } } diff --git a/bitcoin/src/crypto/taproot.rs b/bitcoin/src/crypto/taproot.rs index 93f62ef5..ceba2a03 100644 --- a/bitcoin/src/crypto/taproot.rs +++ b/bitcoin/src/crypto/taproot.rs @@ -9,11 +9,9 @@ use core::fmt; use bitcoin_internals::write_err; - -pub use secp256k1::{self, constants, Secp256k1, KeyPair, XOnlyPublicKey, Verification, Parity}; +pub use secp256k1::{self, constants, KeyPair, Parity, Secp256k1, Verification, XOnlyPublicKey}; use crate::prelude::*; - use crate::sighash::TapSighashType; /// A BIP340-341 serialized taproot signature with the corresponding hash type. @@ -33,21 +31,19 @@ impl Signature { match sl.len() { 64 => { // default type - let sig = secp256k1::schnorr::Signature::from_slice(sl) - .map_err(Error::Secp256k1)?; + let sig = + secp256k1::schnorr::Signature::from_slice(sl).map_err(Error::Secp256k1)?; Ok(Signature { sig, hash_ty: TapSighashType::Default }) - }, + } 65 => { let (hash_ty, sig) = sl.split_last().expect("Slice len checked == 65"); let hash_ty = TapSighashType::from_consensus_u8(*hash_ty) .map_err(|_| Error::InvalidSighashType(*hash_ty))?; - let sig = secp256k1::schnorr::Signature::from_slice(sig) - .map_err(Error::Secp256k1)?; + let sig = + secp256k1::schnorr::Signature::from_slice(sig).map_err(Error::Secp256k1)?; Ok(Signature { sig, hash_ty }) } - len => { - Err(Error::InvalidSignatureSize(len)) - } + len => Err(Error::InvalidSignatureSize(len)), } } @@ -62,7 +58,6 @@ impl Signature { } ser_sig } - } /// A taproot sig related error. @@ -77,7 +72,6 @@ pub enum Error { InvalidSignatureSize(usize), } - impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -85,8 +79,7 @@ impl fmt::Display for Error { write!(f, "invalid signature hash type {}", hash_ty), Error::Secp256k1(ref e) => write_err!(f, "taproot signature has correct len but is malformed"; e), - Error::InvalidSignatureSize(sz) => - write!(f, "invalid taproot signature size: {}", sz), + Error::InvalidSignatureSize(sz) => write!(f, "invalid taproot signature size: {}", sz), } } } @@ -105,8 +98,5 @@ impl std::error::Error for Error { } impl From for Error { - - fn from(e: secp256k1::Error) -> Error { - Error::Secp256k1(e) - } + fn from(e: secp256k1::Error) -> Error { Error::Secp256k1(e) } } From 296f2ed82c638c121d9a24a8cbe45ddb85865994 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 6 Dec 2022 10:52:11 +1100 Subject: [PATCH 08/16] Make test panic instead of using code comment Currently we have a code comment that is supposed to assist devs in maintaining the `network::constants::Network` type by failing to build if a new variant is added. This plays havoc with the formatter because the comment is hanging at the bottom of a match block and the formatting thinks its for the proceeding line of code. Instead of using a code comment add a panic so the unit test fails if a new variant is added to `network::constants::Network`. --- bitcoin/src/blockdata/constants.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bitcoin/src/blockdata/constants.rs b/bitcoin/src/blockdata/constants.rs index eb0534c8..0de5503c 100644 --- a/bitcoin/src/blockdata/constants.rs +++ b/bitcoin/src/blockdata/constants.rs @@ -271,12 +271,13 @@ mod test { // Compare strings because the spec specifically states how the chain hash must encode to hex. assert_eq!(got, want); + #[allow(unreachable_patterns)] // This is specifically trying to catch later added variants. match network { Network::Bitcoin => {}, Network::Testnet => {}, Network::Signet => {}, Network::Regtest => {}, - // Update ChainHash::using_genesis_block and chain_hash_genesis_block with new variants. + _ => panic!("Update ChainHash::using_genesis_block and chain_hash_genesis_block with new variants"), } } From ef306db5e2b1ee9c79d3a94e2befaa7ba29a5fab Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 2 Dec 2022 14:52:46 +1100 Subject: [PATCH 09/16] Enable formatting for psbt Remove the exclude for the `psbt` module. Do not run the formatter, that will be done as a separate patch to aid review. --- rustfmt.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/rustfmt.toml b/rustfmt.toml index 53fb3127..3d9a166e 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,7 +1,6 @@ # Eventually this shoud be: ignore = [] ignore = [ "bitcoin/src/blockdata", - "bitcoin/src/psbt", "bitcoin/src/util", "hashes", ] From a52746d01cc1ae26aab8caa4b41043a83d5ea993 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Tue, 6 Dec 2022 10:03:19 +1100 Subject: [PATCH 10/16] psbt: Run the formatter Run `cargo +nightly fmt`, no other manual changes. --- bitcoin/src/psbt/error.rs | 70 +++--- bitcoin/src/psbt/macros.rs | 22 +- bitcoin/src/psbt/map/global.rs | 97 ++++----- bitcoin/src/psbt/map/input.rs | 80 +++---- bitcoin/src/psbt/map/mod.rs | 2 - bitcoin/src/psbt/map/output.rs | 45 ++-- bitcoin/src/psbt/mod.rs | 380 ++++++++++++++++++--------------- bitcoin/src/psbt/raw.rs | 56 ++--- bitcoin/src/psbt/serialize.rs | 186 +++++++--------- 9 files changed, 470 insertions(+), 468 deletions(-) diff --git a/bitcoin/src/psbt/error.rs b/bitcoin/src/psbt/error.rs index f6511f02..75a17222 100644 --- a/bitcoin/src/psbt/error.rs +++ b/bitcoin/src/psbt/error.rs @@ -1,18 +1,15 @@ // SPDX-License-Identifier: CC0-1.0 -use crate::prelude::*; - use core::fmt; use bitcoin_internals::write_err; +use crate::bip32::ExtendedPubKey; use crate::blockdata::transaction::Transaction; use crate::consensus::encode; +use crate::prelude::*; use crate::psbt::raw; - -use crate::hashes; -use crate::io; -use crate::bip32::ExtendedPubKey; +use crate::{hashes, io}; /// Enum for marking psbt hash error. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] @@ -113,29 +110,41 @@ impl fmt::Display for Error { Error::InvalidMagic => f.write_str("invalid magic"), Error::MissingUtxo => f.write_str("UTXO information is not present in PSBT"), Error::InvalidSeparator => f.write_str("invalid separator"), - Error::PsbtUtxoOutOfbounds => f.write_str("output index is out of bounds of non witness script output array"), + Error::PsbtUtxoOutOfbounds => + f.write_str("output index is out of bounds of non witness script output array"), Error::InvalidKey(ref rkey) => write!(f, "invalid key: {}", rkey), - Error::InvalidProprietaryKey => write!(f, "non-proprietary key type found when proprietary key was expected"), + Error::InvalidProprietaryKey => + write!(f, "non-proprietary key type found when proprietary key was expected"), Error::DuplicateKey(ref rkey) => write!(f, "duplicate key: {}", rkey), - Error::UnsignedTxHasScriptSigs => f.write_str("the unsigned transaction has script sigs"), - Error::UnsignedTxHasScriptWitnesses => f.write_str("the unsigned transaction has script witnesses"), - Error::MustHaveUnsignedTx => { - f.write_str("partially signed transactions must have an unsigned transaction") - } + Error::UnsignedTxHasScriptSigs => + f.write_str("the unsigned transaction has script sigs"), + Error::UnsignedTxHasScriptWitnesses => + f.write_str("the unsigned transaction has script witnesses"), + Error::MustHaveUnsignedTx => + f.write_str("partially signed transactions must have an unsigned transaction"), Error::NoMorePairs => f.write_str("no more key-value pairs for this psbt map"), - Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!(f, "different unsigned transaction: expected {}, actual {}", e.txid(), a.txid()), - Error::NonStandardSighashType(ref sht) => write!(f, "non-standard sighash type: {}", sht), + Error::UnexpectedUnsignedTx { expected: ref e, actual: ref a } => write!( + f, + "different unsigned transaction: expected {}, actual {}", + e.txid(), + a.txid() + ), + Error::NonStandardSighashType(ref sht) => + write!(f, "non-standard sighash type: {}", sht), Error::HashParse(ref e) => write_err!(f, "hash parse error"; e), - Error::InvalidPreimageHashPair{ref preimage, ref hash, ref hash_type} => { + Error::InvalidPreimageHashPair { ref preimage, ref hash, ref hash_type } => { // directly using debug forms of psbthash enums - write!(f, "Preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash ) - }, - Error::CombineInconsistentKeySources(ref s) => { write!(f, "combine conflict: {}", s) }, + write!(f, "Preimage {:?} does not match {:?} hash {:?}", preimage, hash_type, hash) + } + Error::CombineInconsistentKeySources(ref s) => { + write!(f, "combine conflict: {}", s) + } Error::ConsensusEncoding(ref e) => write_err!(f, "bitcoin consensus encoding error"; e), Error::NegativeFee => f.write_str("PSBT has a negative fee which is not allowed"), Error::FeeOverflow => f.write_str("integer overflow in fee calculation"), Error::InvalidPublicKey(ref e) => write_err!(f, "invalid public key"; e), - Error::InvalidSecp256k1PublicKey(ref e) => write_err!(f, "invalid secp256k1 public key"; e), + Error::InvalidSecp256k1PublicKey(ref e) => + write_err!(f, "invalid secp256k1 public key"; e), Error::InvalidXOnlyPublicKey => f.write_str("invalid xonly public key"), Error::InvalidEcdsaSignature(ref e) => write_err!(f, "invalid ECDSA signature"; e), Error::InvalidTaprootSignature(ref e) => write_err!(f, "invalid taproot signature"; e), @@ -145,7 +154,8 @@ impl fmt::Display for Error { Error::TapTree(ref e) => write_err!(f, "taproot tree error"; e), Error::XPubKey(s) => write!(f, "xpub key error - {}", s), Error::Version(s) => write!(f, "version error {}", s), - Error::PartialDataConsumption => f.write_str("data not consumed entirely when explicitly deserializing"), + Error::PartialDataConsumption => + f.write_str("data not consumed entirely when explicitly deserializing"), Error::Io(ref e) => write_err!(f, "I/O error"; e), } } @@ -161,7 +171,7 @@ impl std::error::Error for Error { HashParse(e) => Some(e), ConsensusEncoding(e) => Some(e), Io(e) => Some(e), - | InvalidMagic + InvalidMagic | MissingUtxo | InvalidSeparator | PsbtUtxoOutOfbounds @@ -174,7 +184,7 @@ impl std::error::Error for Error { | NoMorePairs | UnexpectedUnsignedTx { .. } | NonStandardSighashType(_) - | InvalidPreimageHashPair{ .. } + | InvalidPreimageHashPair { .. } | CombineInconsistentKeySources(_) | NegativeFee | FeeOverflow @@ -189,26 +199,20 @@ impl std::error::Error for Error { | TapTree(_) | XPubKey(_) | Version(_) - | PartialDataConsumption=> None, + | PartialDataConsumption => None, } } } #[doc(hidden)] impl From for Error { - fn from(e: hashes::Error) -> Error { - Error::HashParse(e) - } + fn from(e: hashes::Error) -> Error { Error::HashParse(e) } } impl From for Error { - fn from(e: encode::Error) -> Self { - Error::ConsensusEncoding(e) - } + fn from(e: encode::Error) -> Self { Error::ConsensusEncoding(e) } } impl From for Error { - fn from(e: io::Error) -> Self { - Error::Io(e) - } + fn from(e: io::Error) -> Self { Error::Io(e) } } diff --git a/bitcoin/src/psbt/macros.rs b/bitcoin/src/psbt/macros.rs index 77da1679..187d0eef 100644 --- a/bitcoin/src/psbt/macros.rs +++ b/bitcoin/src/psbt/macros.rs @@ -2,7 +2,11 @@ #[allow(unused_macros)] macro_rules! hex_psbt { - ($s:expr) => { <$crate::psbt::PartiallySignedTransaction>::deserialize(&<$crate::prelude::Vec as $crate::hashes::hex::FromHex>::from_hex($s).unwrap()) }; + ($s:expr) => { + <$crate::psbt::PartiallySignedTransaction>::deserialize( + &<$crate::prelude::Vec as $crate::hashes::hex::FromHex>::from_hex($s).unwrap(), + ) + }; } macro_rules! combine { @@ -33,9 +37,7 @@ macro_rules! impl_psbt_deserialize { macro_rules! impl_psbt_serialize { ($thing:ty) => { impl $crate::psbt::serialize::Serialize for $thing { - fn serialize(&self) -> $crate::prelude::Vec { - $crate::consensus::serialize(self) - } + fn serialize(&self) -> $crate::prelude::Vec { $crate::consensus::serialize(self) } } }; } @@ -43,9 +45,7 @@ macro_rules! impl_psbt_serialize { macro_rules! impl_psbtmap_serialize { ($thing:ty) => { impl $crate::psbt::serialize::Serialize for $thing { - fn serialize(&self) -> Vec { - self.serialize_map() - } + fn serialize(&self) -> Vec { self.serialize_map() } } }; } @@ -157,9 +157,7 @@ macro_rules! impl_psbt_hash_deserialize { ($hash_type:ty) => { impl $crate::psbt::serialize::Deserialize for $hash_type { fn deserialize(bytes: &[u8]) -> Result { - <$hash_type>::from_slice(&bytes[..]).map_err(|e| { - $crate::psbt::Error::from(e) - }) + <$hash_type>::from_slice(&bytes[..]).map_err(|e| $crate::psbt::Error::from(e)) } } }; @@ -168,9 +166,7 @@ macro_rules! impl_psbt_hash_deserialize { macro_rules! impl_psbt_hash_serialize { ($hash_type:ty) => { impl $crate::psbt::serialize::Serialize for $hash_type { - fn serialize(&self) -> $crate::prelude::Vec { - self.as_byte_array().to_vec() - } + fn serialize(&self) -> $crate::prelude::Vec { self.as_byte_array().to_vec() } } }; } diff --git a/bitcoin/src/psbt/map/global.rs b/bitcoin/src/psbt/map/global.rs index 908b2a7c..1add4f8d 100644 --- a/bitcoin/src/psbt/map/global.rs +++ b/bitcoin/src/psbt/map/global.rs @@ -2,16 +2,14 @@ use core::convert::TryFrom; -use crate::prelude::*; - -use crate::io::{self, Cursor, Read}; - +use crate::bip32::{ChildNumber, DerivationPath, ExtendedPubKey, Fingerprint}; use crate::blockdata::transaction::Transaction; use crate::consensus::encode::MAX_VEC_SIZE; use crate::consensus::{encode, Decodable}; +use crate::io::{self, Cursor, Read}; +use crate::prelude::*; use crate::psbt::map::Map; use crate::psbt::{raw, Error, PartiallySignedTransaction}; -use crate::bip32::{ExtendedPubKey, Fingerprint, DerivationPath, ChildNumber}; /// Type: Unsigned Transaction PSBT_GLOBAL_UNSIGNED_TX = 0x00 const PSBT_GLOBAL_UNSIGNED_TX: u8 = 0x00; @@ -27,10 +25,7 @@ impl Map for PartiallySignedTransaction { let mut rv: Vec = Default::default(); rv.push(raw::Pair { - key: raw::Key { - type_value: PSBT_GLOBAL_UNSIGNED_TX, - key: vec![], - }, + key: raw::Key { type_value: PSBT_GLOBAL_UNSIGNED_TX, key: vec![] }, value: { // Manually serialized to ensure 0-input txs are serialized // without witnesses. @@ -45,42 +40,30 @@ impl Map for PartiallySignedTransaction { for (xpub, (fingerprint, derivation)) in &self.xpub { rv.push(raw::Pair { - key: raw::Key { - type_value: PSBT_GLOBAL_XPUB, - key: xpub.encode().to_vec(), - }, + key: raw::Key { type_value: PSBT_GLOBAL_XPUB, key: xpub.encode().to_vec() }, value: { let mut ret = Vec::with_capacity(4 + derivation.len() * 4); ret.extend(fingerprint.as_bytes()); derivation.into_iter().for_each(|n| ret.extend(&u32::from(*n).to_le_bytes())); ret - } + }, }); } // Serializing version only for non-default value; otherwise test vectors fail if self.version > 0 { rv.push(raw::Pair { - key: raw::Key { - type_value: PSBT_GLOBAL_VERSION, - key: vec![], - }, - value: self.version.to_le_bytes().to_vec() + key: raw::Key { type_value: PSBT_GLOBAL_VERSION, key: vec![] }, + value: self.version.to_le_bytes().to_vec(), }); } for (key, value) in self.proprietary.iter() { - rv.push(raw::Pair { - key: key.to_key(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.to_key(), value: value.clone() }); } for (key, value) in self.unknown.iter() { - rv.push(raw::Pair { - key: key.clone(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.clone(), value: value.clone() }); } rv @@ -93,7 +76,8 @@ impl PartiallySignedTransaction { let mut tx: Option = None; let mut version: Option = None; let mut unknowns: BTreeMap> = Default::default(); - let mut xpub_map: BTreeMap = Default::default(); + let mut xpub_map: BTreeMap = + Default::default(); let mut proprietary: BTreeMap> = Default::default(); loop { @@ -119,13 +103,13 @@ impl PartiallySignedTransaction { }); if decoder.position() != vlen as u64 { - return Err(Error::PartialDataConsumption) + return Err(Error::PartialDataConsumption); } } else { - return Err(Error::DuplicateKey(pair.key)) + return Err(Error::DuplicateKey(pair.key)); } } else { - return Err(Error::InvalidKey(pair.key)) + return Err(Error::InvalidKey(pair.key)); } } PSBT_GLOBAL_XPUB => { @@ -136,24 +120,33 @@ impl PartiallySignedTransaction { ))?; if pair.value.is_empty() || pair.value.len() % 4 != 0 { - return Err(Error::XPubKey("Incorrect length of global xpub derivation data")) + return Err(Error::XPubKey( + "Incorrect length of global xpub derivation data", + )); } let child_count = pair.value.len() / 4 - 1; let mut decoder = Cursor::new(pair.value); let mut fingerprint = [0u8; 4]; - decoder.read_exact(&mut fingerprint[..]).map_err(|_| Error::XPubKey("Can't read global xpub fingerprint"))?; + decoder.read_exact(&mut fingerprint[..]).map_err(|_| { + Error::XPubKey("Can't read global xpub fingerprint") + })?; let mut path = Vec::::with_capacity(child_count); while let Ok(index) = u32::consensus_decode(&mut decoder) { path.push(ChildNumber::from(index)) } let derivation = DerivationPath::from(path); // Keys, according to BIP-174, must be unique - if xpub_map.insert(xpub, (Fingerprint::from(fingerprint), derivation)).is_some() { - return Err(Error::XPubKey("Repeated global xpub key")) + if xpub_map + .insert(xpub, (Fingerprint::from(fingerprint), derivation)) + .is_some() + { + return Err(Error::XPubKey("Repeated global xpub key")); } } else { - return Err(Error::XPubKey("Xpub global key must contain serialized Xpub data")) + return Err(Error::XPubKey( + "Xpub global key must contain serialized Xpub data", + )); } } PSBT_GLOBAL_VERSION => { @@ -164,33 +157,41 @@ impl PartiallySignedTransaction { let vlen: usize = pair.value.len(); let mut decoder = Cursor::new(pair.value); if vlen != 4 { - return Err(Error::Version("invalid global version value length (must be 4 bytes)")) + return Err(Error::Version( + "invalid global version value length (must be 4 bytes)", + )); } version = Some(Decodable::consensus_decode(&mut decoder)?); // We only understand version 0 PSBTs. According to BIP-174 we // should throw an error if we see anything other than version 0. if version != Some(0) { - return Err(Error::Version("PSBT versions greater than 0 are not supported")) + return Err(Error::Version( + "PSBT versions greater than 0 are not supported", + )); } } else { - return Err(Error::DuplicateKey(pair.key)) + return Err(Error::DuplicateKey(pair.key)); } } else { - return Err(Error::InvalidKey(pair.key)) + return Err(Error::InvalidKey(pair.key)); } } - PSBT_GLOBAL_PROPRIETARY => match proprietary.entry(raw::ProprietaryKey::try_from(pair.key.clone())?) { + PSBT_GLOBAL_PROPRIETARY => match proprietary + .entry(raw::ProprietaryKey::try_from(pair.key.clone())?) + { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(pair.value); - }, - btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(pair.key)), - } + } + btree_map::Entry::Occupied(_) => + return Err(Error::DuplicateKey(pair.key)), + }, _ => match unknowns.entry(pair.key) { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(pair.value); - }, - btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone())), - } + } + btree_map::Entry::Occupied(k) => + return Err(Error::DuplicateKey(k.key().clone())), + }, } } Err(crate::psbt::Error::NoMorePairs) => break, @@ -206,7 +207,7 @@ impl PartiallySignedTransaction { proprietary, unknown: unknowns, inputs: vec![], - outputs: vec![] + outputs: vec![], }) } else { Err(Error::MustHaveUnsignedTx) diff --git a/bitcoin/src/psbt/map/input.rs b/bitcoin/src/psbt/map/input.rs index 20882b07..723ce407 100644 --- a/bitcoin/src/psbt/map/input.rs +++ b/bitcoin/src/psbt/map/input.rs @@ -1,24 +1,25 @@ // SPDX-License-Identifier: CC0-1.0 -use crate::prelude::*; - +use core::convert::TryFrom; use core::fmt; use core::str::FromStr; -use core::convert::TryFrom; use secp256k1::XOnlyPublicKey; -use crate::blockdata::script::ScriptBuf; -use crate::blockdata::witness::Witness; -use crate::blockdata::transaction::{Transaction, TxOut}; -use crate::crypto::{ecdsa, taproot}; -use crate::crypto::key::PublicKey; -use crate::hashes::{self, hash160, ripemd160, sha256, sha256d}; use crate::bip32::KeySource; +use crate::blockdata::script::ScriptBuf; +use crate::blockdata::transaction::{Transaction, TxOut}; +use crate::blockdata::witness::Witness; +use crate::crypto::key::PublicKey; +use crate::crypto::{ecdsa, taproot}; +use crate::hashes::{self, hash160, ripemd160, sha256, sha256d}; +use crate::prelude::*; use crate::psbt::map::Map; use crate::psbt::serialize::Deserialize; use crate::psbt::{self, error, raw, Error}; -use crate::sighash::{self, NonStandardSighashType, SighashTypeParseError, EcdsaSighashType, TapSighashType}; +use crate::sighash::{ + self, EcdsaSighashType, NonStandardSighashType, SighashTypeParseError, TapSighashType, +}; use crate::taproot::{ControlBlock, LeafVersion, TapLeafHash, TapNodeHash}; /// Type: Non-Witness UTXO PSBT_IN_NON_WITNESS_UTXO = 0x00 @@ -132,7 +133,6 @@ pub struct Input { pub unknown: BTreeMap>, } - /// A Signature hash type for the corresponding input. As of taproot upgrade, the signature hash /// type can be either [`EcdsaSighashType`] or [`TapSighashType`] but it is not possible to know /// directly which signature hash type the user is dealing with. Therefore, the user is responsible @@ -141,7 +141,7 @@ pub struct Input { #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] pub struct PsbtSighashType { - pub (in crate::psbt) inner: u32, + pub(in crate::psbt) inner: u32, } impl fmt::Display for PsbtSighashType { @@ -172,7 +172,7 @@ impl FromStr for PsbtSighashType { return Ok(PsbtSighashType { inner }); } - Err(SighashTypeParseError{ unrecognized: s.to_owned() }) + Err(SighashTypeParseError { unrecognized: s.to_owned() }) } } impl From for PsbtSighashType { @@ -208,17 +208,12 @@ impl PsbtSighashType { /// /// Allows construction of a non-standard or non-valid sighash flag /// ([`EcdsaSighashType`], [`TapSighashType`] respectively). - pub fn from_u32(n: u32) -> PsbtSighashType { - PsbtSighashType { inner: n } - } - + pub fn from_u32(n: u32) -> PsbtSighashType { PsbtSighashType { inner: n } } /// Converts [`PsbtSighashType`] to a raw `u32` sighash flag. /// /// No guarantees are made as to the standardness or validity of the returned value. - pub fn to_u32(self) -> u32 { - self.inner - } + pub fn to_u32(self) -> u32 { self.inner } } impl Input { @@ -247,10 +242,7 @@ impl Input { } pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), Error> { - let raw::Pair { - key: raw_key, - value: raw_value, - } = pair; + let raw::Pair { key: raw_key, value: raw_value } = pair; match raw_key.type_value { PSBT_IN_NON_WITNESS_UTXO => { @@ -299,16 +291,36 @@ impl Input { } } PSBT_IN_RIPEMD160 => { - psbt_insert_hash_pair(&mut self.ripemd160_preimages, raw_key, raw_value, error::PsbtHash::Ripemd)?; + psbt_insert_hash_pair( + &mut self.ripemd160_preimages, + raw_key, + raw_value, + error::PsbtHash::Ripemd, + )?; } PSBT_IN_SHA256 => { - psbt_insert_hash_pair(&mut self.sha256_preimages, raw_key, raw_value, error::PsbtHash::Sha256)?; + psbt_insert_hash_pair( + &mut self.sha256_preimages, + raw_key, + raw_value, + error::PsbtHash::Sha256, + )?; } PSBT_IN_HASH160 => { - psbt_insert_hash_pair(&mut self.hash160_preimages, raw_key, raw_value, error::PsbtHash::Hash160)?; + psbt_insert_hash_pair( + &mut self.hash160_preimages, + raw_key, + raw_value, + error::PsbtHash::Hash160, + )?; } PSBT_IN_HASH256 => { - psbt_insert_hash_pair(&mut self.hash256_preimages, raw_key, raw_value, error::PsbtHash::Hash256)?; + psbt_insert_hash_pair( + &mut self.hash256_preimages, + raw_key, + raw_value, + error::PsbtHash::Hash256, + )?; } PSBT_IN_TAP_KEY_SIG => { impl_psbt_insert_pair! { @@ -345,7 +357,7 @@ impl Input { match self.proprietary.entry(key) { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(raw_value); - }, + } btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key)), } } @@ -471,17 +483,11 @@ impl Map for Input { rv.push(self.tap_merkle_root, PSBT_IN_TAP_MERKLE_ROOT) } for (key, value) in self.proprietary.iter() { - rv.push(raw::Pair { - key: key.to_key(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.to_key(), value: value.clone() }); } for (key, value) in self.unknown.iter() { - rv.push(raw::Pair { - key: key.clone(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.clone(), value: value.clone() }); } rv diff --git a/bitcoin/src/psbt/map/mod.rs b/bitcoin/src/psbt/map/mod.rs index 4a2a3d94..91d455e0 100644 --- a/bitcoin/src/psbt/map/mod.rs +++ b/bitcoin/src/psbt/map/mod.rs @@ -1,7 +1,6 @@ // SPDX-License-Identifier: CC0-1.0 use crate::prelude::*; - use crate::psbt::raw; mod global; @@ -10,7 +9,6 @@ mod output; pub use self::input::{Input, PsbtSighashType}; pub use self::output::Output; - use super::serialize::Serialize; /// A trait that describes a PSBT key-value map. diff --git a/bitcoin/src/psbt/map/output.rs b/bitcoin/src/psbt/map/output.rs index 4621bc79..4f032019 100644 --- a/bitcoin/src/psbt/map/output.rs +++ b/bitcoin/src/psbt/map/output.rs @@ -1,18 +1,16 @@ // SPDX-License-Identifier: CC0-1.0 -use crate::prelude::*; -use core; use core::convert::TryFrom; -use crate::blockdata::script::ScriptBuf; use secp256k1::XOnlyPublicKey; -use crate::bip32::KeySource; -use secp256k1; -use crate::psbt::map::Map; -use crate::psbt::raw; -use crate::psbt::Error; +use {core, secp256k1}; -use crate::taproot::{TapTree, TapLeafHash}; +use crate::bip32::KeySource; +use crate::blockdata::script::ScriptBuf; +use crate::prelude::*; +use crate::psbt::map::Map; +use crate::psbt::{raw, Error}; +use crate::taproot::{TapLeafHash, TapTree}; /// Type: Redeem ScriptBuf PSBT_OUT_REDEEM_SCRIPT = 0x00 const PSBT_OUT_REDEEM_SCRIPT: u8 = 0x00; @@ -51,25 +49,16 @@ pub struct Output { #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq"))] pub tap_key_origins: BTreeMap, KeySource)>, /// Proprietary key-value pairs for this output. - #[cfg_attr( - feature = "serde", - serde(with = "crate::serde_utils::btreemap_as_seq_byte_values") - )] + #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))] pub proprietary: BTreeMap>, /// Unknown key-value pairs for this output. - #[cfg_attr( - feature = "serde", - serde(with = "crate::serde_utils::btreemap_as_seq_byte_values") - )] + #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::btreemap_as_seq_byte_values"))] pub unknown: BTreeMap>, } impl Output { pub(super) fn insert_pair(&mut self, pair: raw::Pair) -> Result<(), Error> { - let raw::Pair { - key: raw_key, - value: raw_value, - } = pair; + let raw::Pair { key: raw_key, value: raw_value } = pair; match raw_key.type_value { PSBT_OUT_REDEEM_SCRIPT => { @@ -92,7 +81,7 @@ impl Output { match self.proprietary.entry(key) { btree_map::Entry::Vacant(empty_key) => { empty_key.insert(raw_value); - }, + } btree_map::Entry::Occupied(_) => return Err(Error::DuplicateKey(raw_key)), } } @@ -116,7 +105,7 @@ impl Output { empty_key.insert(raw_value); } btree_map::Entry::Occupied(k) => return Err(Error::DuplicateKey(k.key().clone())), - } + }, } Ok(()) @@ -165,17 +154,11 @@ impl Map for Output { } for (key, value) in self.proprietary.iter() { - rv.push(raw::Pair { - key: key.to_key(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.to_key(), value: value.clone() }); } for (key, value) in self.unknown.iter() { - rv.push(raw::Pair { - key: key.clone(), - value: value.clone(), - }); + rv.push(raw::Pair { key: key.clone(), value: value.clone() }); } rv diff --git a/bitcoin/src/psbt/mod.rs b/bitcoin/src/psbt/mod.rs index e2bf4f54..ee5a0c7d 100644 --- a/bitcoin/src/psbt/mod.rs +++ b/bitcoin/src/psbt/mod.rs @@ -7,24 +7,22 @@ //! except we define PSBTs containing non-standard sighash types as invalid. //! +use core::{cmp, fmt}; #[cfg(feature = "std")] use std::collections::{HashMap, HashSet}; -use core::{fmt, cmp}; - -use secp256k1::{Message, Secp256k1, Signing}; use bitcoin_internals::write_err; +use secp256k1::{Message, Secp256k1, Signing}; -use crate::{prelude::*, Amount}; - +use crate::bip32::{self, ExtendedPrivKey, ExtendedPubKey, KeySource}; use crate::blockdata::script::ScriptBuf; use crate::blockdata::transaction::{Transaction, TxOut}; -use crate::bip32::{self, ExtendedPrivKey, ExtendedPubKey, KeySource}; use crate::crypto::ecdsa; -use crate::crypto::key::{PublicKey, PrivateKey}; -use crate::sighash::{self, EcdsaSighashType, SighashCache}; - +use crate::crypto::key::{PrivateKey, PublicKey}; +use crate::prelude::*; pub use crate::sighash::Prevouts; +use crate::sighash::{self, EcdsaSighashType, SighashCache}; +use crate::Amount; #[macro_use] mod macros; @@ -86,7 +84,7 @@ impl PartiallySignedTransaction { (None, Some(non_witness_utxo)) => { let vout = tx_input.previous_output.vout as usize; non_witness_utxo.output.get(vout).ok_or(Error::PsbtUtxoOutOfbounds) - }, + } (None, None) => Err(Error::MissingUtxo), } }) @@ -161,7 +159,7 @@ impl PartiallySignedTransaction { match self.xpub.entry(xpub) { btree_map::Entry::Vacant(entry) => { entry.insert((fingerprint1, derivation1)); - }, + } btree_map::Entry::Occupied(mut entry) => { // Here in case of the conflict we select the version with algorithm: // 1) if everything is equal we do nothing @@ -174,15 +172,17 @@ impl PartiallySignedTransaction { let (fingerprint2, derivation2) = entry.get().clone(); - if (derivation1 == derivation2 && fingerprint1 == fingerprint2) || - (derivation1.len() < derivation2.len() && derivation1[..] == derivation2[derivation2.len() - derivation1.len()..]) + if (derivation1 == derivation2 && fingerprint1 == fingerprint2) + || (derivation1.len() < derivation2.len() + && derivation1[..] + == derivation2[derivation2.len() - derivation1.len()..]) { - continue - } - else if derivation2[..] == derivation1[derivation1.len() - derivation2.len()..] + continue; + } else if derivation2[..] + == derivation1[derivation1.len() - derivation2.len()..] { entry.insert((fingerprint1, derivation1)); - continue + continue; } return Err(Error::CombineInconsistentKeySources(Box::new(xpub))); } @@ -237,8 +237,12 @@ impl PartiallySignedTransaction { for i in 0..self.inputs.len() { if let Ok(SigningAlgorithm::Ecdsa) = self.signing_algorithm(i) { match self.bip32_sign_ecdsa(k, i, &mut cache, secp) { - Ok(v) => { used.insert(i, v); }, - Err(e) => { errors.insert(i, e); }, + Ok(v) => { + used.insert(i, v); + } + Err(e) => { + errors.insert(i, e); + } } }; } @@ -272,7 +276,7 @@ impl PartiallySignedTransaction { let input = &mut self.inputs[input_index]; // Index checked in call to `sighash_ecdsa`. - let mut used = vec![]; // List of pubkeys used to sign the input. + let mut used = vec![]; // List of pubkeys used to sign the input. for (pk, key_source) in input.bip32_derivation.iter() { let sk = if let Ok(Some(sk)) = k.get_key(KeyRequest::Bip32(key_source.clone()), secp) { @@ -289,10 +293,8 @@ impl PartiallySignedTransaction { Ok((msg, sighash_ty)) => (msg, sighash_ty), }; - let sig = ecdsa::Signature { - sig: secp.sign_ecdsa(&msg, &sk.inner), - hash_ty: sighash_ty, - }; + let sig = + ecdsa::Signature { sig: secp.sign_ecdsa(&msg, &sk.inner), hash_ty: sighash_ty }; let pk = sk.public_key(secp); @@ -323,35 +325,42 @@ impl PartiallySignedTransaction { let utxo = self.spend_utxo(input_index)?; let spk = &utxo.script_pubkey; // scriptPubkey for input spend utxo. - let hash_ty = input.ecdsa_hash_ty() - .map_err(|_| SignError::InvalidSighashType)?; // Only support standard sighash types. + let hash_ty = input.ecdsa_hash_ty().map_err(|_| SignError::InvalidSighashType)?; // Only support standard sighash types. match self.output_type(input_index)? { Bare => { let sighash = cache.legacy_signature_hash(input_index, spk, hash_ty.to_u32())?; Ok((Message::from(sighash), hash_ty)) - }, + } Sh => { - let script_code = input.redeem_script.as_ref().ok_or(SignError::MissingRedeemScript)?; - let sighash = cache.legacy_signature_hash(input_index, script_code, hash_ty.to_u32())?; + let script_code = + input.redeem_script.as_ref().ok_or(SignError::MissingRedeemScript)?; + let sighash = + cache.legacy_signature_hash(input_index, script_code, hash_ty.to_u32())?; Ok((Message::from(sighash), hash_ty)) - }, + } Wpkh => { let script_code = ScriptBuf::p2wpkh_script_code(spk).ok_or(SignError::NotWpkh)?; - let sighash = cache.segwit_signature_hash(input_index, &script_code, utxo.value, hash_ty)?; + let sighash = + cache.segwit_signature_hash(input_index, &script_code, utxo.value, hash_ty)?; Ok((Message::from(sighash), hash_ty)) - }, + } ShWpkh => { - let script_code = ScriptBuf::p2wpkh_script_code(input.redeem_script.as_ref().expect("checked above")) - .ok_or(SignError::NotWpkh)?; - let sighash = cache.segwit_signature_hash(input_index, &script_code, utxo.value, hash_ty)?; + let script_code = ScriptBuf::p2wpkh_script_code( + input.redeem_script.as_ref().expect("checked above"), + ) + .ok_or(SignError::NotWpkh)?; + let sighash = + cache.segwit_signature_hash(input_index, &script_code, utxo.value, hash_ty)?; Ok((Message::from(sighash), hash_ty)) - }, + } Wsh | ShWsh => { - let script_code = input.witness_script.as_ref().ok_or(SignError::MissingWitnessScript)?; - let sighash = cache.segwit_signature_hash(input_index, script_code, utxo.value, hash_ty)?; + let script_code = + input.witness_script.as_ref().ok_or(SignError::MissingWitnessScript)?; + let sighash = + cache.segwit_signature_hash(input_index, script_code, utxo.value, hash_ty)?; Ok((Message::from(sighash), hash_ty)) - }, + } Tr => { // This PSBT signing API is WIP, taproot to come shortly. Err(SignError::Unsupported) @@ -368,7 +377,7 @@ impl PartiallySignedTransaction { let vout = self.unsigned_tx.input[input_index].previous_output.vout; &non_witness_utxo.output[vout as usize] } else { - return Err(SignError::MissingSpendUtxo); + return Err(SignError::MissingSpendUtxo); }; Ok(utxo) } @@ -481,13 +490,21 @@ pub trait GetKey { /// - `Some(key)` if the key is found. /// - `None` if the key was not found but no error was encountered. /// - `Err` if an error was encountered while looking for the key. - fn get_key(&self, key_request: KeyRequest, secp: &Secp256k1) -> Result, Self::Error>; + fn get_key( + &self, + key_request: KeyRequest, + secp: &Secp256k1, + ) -> Result, Self::Error>; } impl GetKey for ExtendedPrivKey { type Error = GetKeyError; - fn get_key(&self, key_request: KeyRequest, secp: &Secp256k1) -> Result, Self::Error> { + fn get_key( + &self, + key_request: KeyRequest, + secp: &Secp256k1, + ) -> Result, Self::Error> { match key_request { KeyRequest::Pubkey(_) => Err(GetKeyError::NotSupported), KeyRequest::Bip32((fingerprint, path)) => { @@ -577,7 +594,8 @@ impl fmt::Display for GetKeyError { match *self { Bip32(ref e) => write_err!(f, "a bip23 error"; e), - NotSupported => f.write_str("the GetKey operation is not supported for this key request"), + NotSupported => + f.write_str("the GetKey operation is not supported for this key request"), } } } @@ -596,9 +614,7 @@ impl std::error::Error for GetKeyError { } impl From for GetKeyError { - fn from(e: bip32::Error) -> Self { - GetKeyError::Bip32(e) - } + fn from(e: bip32::Error) -> Self { GetKeyError::Bip32(e) } } /// The various output types supported by the Bitcoin network. @@ -676,7 +692,7 @@ pub enum SignError { /// Attempt to sign an input with the wrong signing algorithm. WrongSigningAlgorithm, /// Signing request currently unsupported. - Unsupported + Unsupported, } impl fmt::Display for SignError { @@ -698,7 +714,8 @@ impl fmt::Display for SignError { SighashComputation(e) => write!(f, "sighash: {}", e), UnknownOutputType => write!(f, "unable to determine the output type"), KeyNotFound => write!(f, "unable to find key"), - WrongSigningAlgorithm => write!(f, "attempt to sign an input with the wrong signing algorithm"), + WrongSigningAlgorithm => + write!(f, "attempt to sign an input with the wrong signing algorithm"), Unsupported => write!(f, "signing request currently unsupported"), } } @@ -712,37 +729,37 @@ impl std::error::Error for SignError { match *self { IndexOutOfBounds(_, _) - | InvalidSighashType - | MissingInputUtxo - | MissingRedeemScript - | MissingSpendUtxo - | MissingWitnessScript - | MismatchedAlgoKey - | NotEcdsa - | NotWpkh - | UnknownOutputType - | KeyNotFound - | WrongSigningAlgorithm - | Unsupported => None, + | InvalidSighashType + | MissingInputUtxo + | MissingRedeemScript + | MissingSpendUtxo + | MissingWitnessScript + | MismatchedAlgoKey + | NotEcdsa + | NotWpkh + | UnknownOutputType + | KeyNotFound + | WrongSigningAlgorithm + | Unsupported => None, SighashComputation(ref e) => Some(e), } } } impl From for SignError { - fn from(e: sighash::Error) -> Self { - SignError::SighashComputation(e) - } + fn from(e: sighash::Error) -> Self { SignError::SighashComputation(e) } } #[cfg(feature = "base64")] mod display_from_str { - use super::{PartiallySignedTransaction, Error}; - use core::fmt::{Display, Formatter, self}; + use core::fmt::{self, Display, Formatter}; use core::str::FromStr; + use base64::display::Base64Display; use bitcoin_internals::write_err; + use super::{Error, PartiallySignedTransaction}; + /// Error encountered during PSBT decoding from Base64 string. #[derive(Debug)] #[cfg_attr(docsrs, doc(cfg(feature = "base64")))] @@ -751,7 +768,7 @@ mod display_from_str { /// Error in internal PSBT data structure. PsbtEncoding(Error), /// Error in PSBT Base64 encoding. - Base64Encoding(::base64::DecodeError) + Base64Encoding(::base64::DecodeError), } impl Display for PsbtParseError { @@ -801,26 +818,24 @@ pub use self::display_from_str::PsbtParseError; #[cfg(test)] mod tests { - use super::*; + use std::collections::BTreeMap; - use crate::blockdata::locktime::absolute; - use crate::hashes::{sha256, hash160, Hash, ripemd160}; - use crate::psbt::serialize::{Serialize, Deserialize}; - - use secp256k1::{Secp256k1, self}; + use secp256k1::{self, Secp256k1}; #[cfg(feature = "rand-std")] use secp256k1::{All, SecretKey}; - use crate::blockdata::script::ScriptBuf; - use crate::blockdata::transaction::{Transaction, TxIn, TxOut, OutPoint, Sequence}; - use crate::network::constants::Network::Bitcoin; + use super::*; use crate::bip32::{ChildNumber, ExtendedPrivKey, ExtendedPubKey, KeySource}; - use crate::psbt::map::{Output, Input}; - use crate::psbt::raw; - use crate::internal_macros::hex; - - use std::collections::BTreeMap; + use crate::blockdata::locktime::absolute; + use crate::blockdata::script::ScriptBuf; + use crate::blockdata::transaction::{OutPoint, Sequence, Transaction, TxIn, TxOut}; use crate::blockdata::witness::Witness; + use crate::hashes::{hash160, ripemd160, sha256, Hash}; + use crate::internal_macros::hex; + use crate::network::constants::Network::Bitcoin; + use crate::psbt::map::{Input, Output}; + use crate::psbt::raw; + use crate::psbt::serialize::{Deserialize, Serialize}; #[test] fn trivial_psbt() { @@ -843,14 +858,13 @@ mod tests { } #[test] - fn psbt_uncompressed_key() { + fn psbt_uncompressed_key() { + let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff01003302000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff000000000000420204bb0d5d0cca36e7b9c80f63bc04c1240babb83bcd2803ef7ac8b6e2af594291daec281e856c98d210c5ab14dfd5828761f8ee7d5f45ca21ad3e4c4b41b747a3a047304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe70100").unwrap(); - let psbt: PartiallySignedTransaction = hex_psbt!("70736274ff01003302000000010000000000000000000000000000000000000000000000000000000000000000ffffffff00ffffffff000000000000420204bb0d5d0cca36e7b9c80f63bc04c1240babb83bcd2803ef7ac8b6e2af594291daec281e856c98d210c5ab14dfd5828761f8ee7d5f45ca21ad3e4c4b41b747a3a047304402204f67e2afb76142d44fae58a2495d33a3419daa26cd0db8d04f3452b63289ac0f022010762a9fb67e94cc5cad9026f6dc99ff7f070f4278d30fbc7d0c869dd38c7fe70100").unwrap(); - - assert!(psbt.inputs[0].partial_sigs.len() == 1); - let pk = psbt.inputs[0].partial_sigs.iter().next().unwrap().0; - assert!(!pk.compressed); - } + assert!(psbt.inputs[0].partial_sigs.len() == 1); + let pk = psbt.inputs[0].partial_sigs.iter().next().unwrap().0; + assert!(!pk.compressed); + } #[test] fn serialize_then_deserialize_output() { @@ -881,8 +895,12 @@ mod tests { hd_keypaths.insert(pk.public_key, (fprint, dpath.into())); let expected: Output = Output { - redeem_script: Some(ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap()), - witness_script: Some(ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap()), + redeem_script: Some( + ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(), + ), + witness_script: Some( + ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(), + ), bip32_derivation: hd_keypaths, ..Default::default() }; @@ -898,25 +916,31 @@ mod tests { unsigned_tx: Transaction { version: 2, lock_time: absolute::LockTime::from_consensus(1257139), - input: vec![ - TxIn { - previous_output: OutPoint { - txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126".parse().unwrap(), - vout: 0, - }, - script_sig: ScriptBuf::new(), - sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, - witness: Witness::default(), - } - ], + input: vec![TxIn { + previous_output: OutPoint { + txid: "f61b1742ca13176464adb3cb66050c00787bb3a4eead37e985f2df1e37718126" + .parse() + .unwrap(), + vout: 0, + }, + script_sig: ScriptBuf::new(), + sequence: Sequence::ENABLE_LOCKTIME_NO_RBF, + witness: Witness::default(), + }], output: vec![ TxOut { value: 99999699, - script_pubkey: ScriptBuf::from_hex("76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac").unwrap(), + script_pubkey: ScriptBuf::from_hex( + "76a914d0c59903c5bac2868760e90fd521a4665aa7652088ac", + ) + .unwrap(), }, TxOut { value: 100000000, - script_pubkey: ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(), + script_pubkey: ScriptBuf::from_hex( + "a9143545e6e33b832c47050f24d3eeb93c9c03948bc787", + ) + .unwrap(), }, ], }, @@ -935,10 +959,7 @@ mod tests { #[test] fn serialize_then_deserialize_psbtkvpair() { let expected = raw::Pair { - key: raw::Key { - type_value: 0u8, - key: vec![42u8, 69u8], - }, + key: raw::Key { type_value: 0u8, key: vec![42u8, 69u8] }, value: vec![69u8, 42u8, 4u8], }; @@ -965,33 +986,39 @@ mod tests { let tx = Transaction { version: 1, lock_time: absolute::LockTime::ZERO, - input: vec![ - TxIn { - previous_output: OutPoint { - txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389".parse().unwrap(), - vout: 1, - }, - script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985").unwrap(), - sequence: Sequence::MAX, - witness: Witness::from_slice(&[hex!("03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105")]), - } - ], - output: vec![ - TxOut { - value: 190303501938, - script_pubkey: ScriptBuf::from_hex("a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587").unwrap(), + input: vec![TxIn { + previous_output: OutPoint { + txid: "e567952fb6cc33857f392efa3a46c995a28f69cca4bb1b37e0204dab1ec7a389" + .parse() + .unwrap(), + vout: 1, }, - ], + script_sig: ScriptBuf::from_hex("160014be18d152a9b012039daf3da7de4f53349eecb985") + .unwrap(), + sequence: Sequence::MAX, + witness: Witness::from_slice(&[hex!( + "03d2e15674941bad4a996372cb87e1856d3652606d98562fe39c5e9e7e413f2105" + )]), + }], + output: vec![TxOut { + value: 190303501938, + script_pubkey: ScriptBuf::from_hex( + "a914339725ba21efd62ac753a9bcd067d6c7a6a39d0587", + ) + .unwrap(), + }], }; - let unknown: BTreeMap> = vec![( - raw::Key { type_value: 1, key: vec![0, 1] }, - vec![3, 4 ,5], - )].into_iter().collect(); + let unknown: BTreeMap> = + vec![(raw::Key { type_value: 1, key: vec![0, 1] }, vec![3, 4, 5])] + .into_iter() + .collect(); let key_source = ("deadbeef".parse().unwrap(), "m/0'/1".parse().unwrap()); let keypaths: BTreeMap = vec![( "0339880dc92394b7355e3d0439fa283c31de7590812ea011c4245c0674a685e883".parse().unwrap(), key_source.clone(), - )].into_iter().collect(); + )] + .into_iter() + .collect(); let proprietary: BTreeMap> = vec![( raw::ProprietaryKey { @@ -1000,7 +1027,9 @@ mod tests { key: "test_key".as_bytes().to_vec(), }, vec![5, 6, 7], - )].into_iter().collect(); + )] + .into_iter() + .collect(); let psbt = PartiallySignedTransaction { version: 0, @@ -1059,19 +1088,18 @@ mod tests { } mod bip_vectors { - use super::*; - + use std::collections::BTreeMap; #[cfg(feature = "base64")] use std::str::FromStr; - use crate::blockdata::script::ScriptBuf; - use crate::blockdata::transaction::{Transaction, TxIn, TxOut, OutPoint, Sequence}; + use super::*; use crate::blockdata::locktime::absolute; - use crate::psbt::map::{Map, Input, Output}; - use crate::psbt::{raw, PartiallySignedTransaction, Error}; - use crate::sighash::EcdsaSighashType; - use std::collections::BTreeMap; + use crate::blockdata::script::ScriptBuf; + use crate::blockdata::transaction::{OutPoint, Sequence, Transaction, TxIn, TxOut}; use crate::blockdata::witness::Witness; + use crate::psbt::map::{Input, Map, Output}; + use crate::psbt::{raw, Error, PartiallySignedTransaction}; + use crate::sighash::EcdsaSighashType; #[test] #[should_panic(expected = "InvalidMagic")] @@ -1242,11 +1270,15 @@ mod tests { assert_eq!(unserialized.serialize_hex(), base16str); assert_eq!(unserialized, hex_psbt!(base16str).unwrap()); - #[cfg(feature = "base64")] { + #[cfg(feature = "base64")] + { let base64str = "cHNidP8BAHUCAAAAASaBcTce3/KF6Tet7qSze3gADAVmy7OtZGQXE8pCFxv2AAAAAAD+////AtPf9QUAAAAAGXapFNDFmQPFusKGh2DpD9UhpGZap2UgiKwA4fUFAAAAABepFDVF5uM7gyxHBQ8k0+65PJwDlIvHh7MuEwAAAQD9pQEBAAAAAAECiaPHHqtNIOA3G7ukzGmPopXJRjr6Ljl/hTPMti+VZ+UBAAAAFxYAFL4Y0VKpsBIDna89p95PUzSe7LmF/////4b4qkOnHf8USIk6UwpyN+9rRgi7st0tAXHmOuxqSJC0AQAAABcWABT+Pp7xp0XpdNkCxDVZQ6vLNL1TU/////8CAMLrCwAAAAAZdqkUhc/xCX/Z4Ai7NK9wnGIZeziXikiIrHL++E4sAAAAF6kUM5cluiHv1irHU6m80GfWx6ajnQWHAkcwRAIgJxK+IuAnDzlPVoMR3HyppolwuAJf3TskAinwf4pfOiQCIAGLONfc0xTnNMkna9b7QPZzMlvEuqFEyADS8vAtsnZcASED0uFWdJQbrUqZY3LLh+GFbTZSYG2YVi/jnF6efkE/IQUCSDBFAiEA0SuFLYXc2WHS9fSrZgZU327tzHlMDDPOXMMJ/7X85Y0CIGczio4OFyXBl/saiK9Z9R5E5CVbIBZ8hoQDHAXR8lkqASECI7cr7vCWXRC+B3jv7NYfysb3mk6haTkzgHNEZPhPKrMAAAAAAAAA"; assert_eq!(PartiallySignedTransaction::from_str(base64str).unwrap(), unserialized); assert_eq!(base64str, unserialized.to_string()); - assert_eq!(PartiallySignedTransaction::from_str(base64str).unwrap(), hex_psbt!(base16str).unwrap()); + assert_eq!( + PartiallySignedTransaction::from_str(base64str).unwrap(), + hex_psbt!(base16str).unwrap() + ); } } @@ -1260,7 +1292,8 @@ mod tests { assert!(&psbt.inputs[0].final_script_sig.is_some()); let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap(); - let expected_out = ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(); + let expected_out = + ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(); assert!(redeem_script.is_v0_p2wpkh()); assert_eq!( @@ -1286,9 +1319,8 @@ mod tests { assert_eq!(tx_input.previous_output.txid, psbt_non_witness_utxo.txid()); assert!(psbt_non_witness_utxo.output[tx_input.previous_output.vout as usize] - .script_pubkey - .is_p2pkh() - ); + .script_pubkey + .is_p2pkh()); assert_eq!( psbt.inputs[0].sighash_type.as_ref().unwrap().ecdsa_hash_ty().unwrap(), EcdsaSighashType::All @@ -1306,7 +1338,8 @@ mod tests { assert!(&psbt.inputs[1].final_script_sig.is_none()); let redeem_script = psbt.inputs[1].redeem_script.as_ref().unwrap(); - let expected_out = ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(); + let expected_out = + ScriptBuf::from_hex("a9143545e6e33b832c47050f24d3eeb93c9c03948bc787").unwrap(); assert!(redeem_script.is_v0_p2wpkh()); assert_eq!( @@ -1330,7 +1363,8 @@ mod tests { assert!(&psbt.inputs[0].final_script_sig.is_none()); let redeem_script = psbt.inputs[0].redeem_script.as_ref().unwrap(); - let expected_out = ScriptBuf::from_hex("a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87").unwrap(); + let expected_out = + ScriptBuf::from_hex("a9146345200f68d189e1adc0df1c4d16ea8f14c0dbeb87").unwrap(); assert!(redeem_script.is_v0_p2wsh()); assert_eq!( @@ -1355,10 +1389,7 @@ mod tests { ); let mut unknown: BTreeMap> = BTreeMap::new(); - let key: raw::Key = raw::Key { - type_value: 0x0fu8, - key: hex!("010203040506070809"), - }; + let key: raw::Key = raw::Key { type_value: 0x0fu8, key: hex!("010203040506070809") }; let value: Vec = hex!("0102030405060708090a0b0c0d0e0f"); unknown.insert(key, value); @@ -1378,7 +1409,10 @@ mod tests { #[cfg(feature = "std")] assert_eq!(err.to_string(), "invalid taproot signature"); #[cfg(not(feature = "std"))] - assert_eq!(err.to_string(), "invalid taproot signature: invalid taproot signature size: 66"); + assert_eq!( + err.to_string(), + "invalid taproot signature: invalid taproot signature size: 66" + ); let err = hex_psbt!("70736274ff010071020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02787c01000000000016001483a7e34bd99ff03a4962ef8a1a101bb295461ece606b042a010000001600147ac369df1b20e033d6116623957b0ac49f3c52e8000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757221602fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa2321900772b2da75600008001000080000000800100000000000000000000").unwrap_err(); assert_eq!(err.to_string(), "invalid xonly public key"); let err = hex_psbt!("70736274ff01007d020000000127744ababf3027fe0d6cf23a96eee2efb188ef52301954585883e69b6624b2420000000000ffffffff02887b0100000000001600142382871c7e8421a00093f754d91281e675874b9f606b042a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000000000001012b00f2052a010000002251205a2c2cf5b52cf31f83ad2e8da63ff03183ecd8f609c7510ae8a48e03910a0757000001052102fe349064c98d6e2a853fa3c9b12bd8b304a19c195c60efa7ee2393046d3fa23200").unwrap_err(); @@ -1394,12 +1428,18 @@ mod tests { #[cfg(feature = "std")] assert_eq!(err.to_string(), "invalid taproot signature"); #[cfg(not(feature = "std"))] - assert_eq!(err.to_string(), "invalid taproot signature: invalid taproot signature size: 66"); + assert_eq!( + err.to_string(), + "invalid taproot signature: invalid taproot signature size: 66" + ); let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b69241142cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2cd970e15f53fc0c82f950fd560ffa919b76172be017368a89913af074f400b093989756aa3739ccc689ec0fcf3a360be32cc0b59b16e93a1e8bb4605726b2ca7a3ff706c4176649632b2cc68e1f912b8a578e3719ce7710885c7a966f49bcd43cb0000").unwrap_err(); #[cfg(feature = "std")] assert_eq!(err.to_string(), "invalid taproot signature"); #[cfg(not(feature = "std"))] - assert_eq!(err.to_string(), "invalid taproot signature: invalid taproot signature size: 57"); + assert_eq!( + err.to_string(), + "invalid taproot signature: invalid taproot signature size: 57" + ); let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926315c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e1f80023202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err(); assert_eq!(err.to_string(), "invalid control block"); let err = hex_psbt!("70736274ff01005e02000000019bd48765230bf9a72e662001f972556e54f0c6f97feb56bcb5600d817f6995260100000000ffffffff0148e6052a01000000225120030da4fce4f7db28c2cb2951631e003713856597fe963882cb500e68112cca63000000000001012b00f2052a01000000225120c2247efbfd92ac47f6f40b8d42d169175a19fa9fa10e4a25d7f35eb4dd85b6926115c150929b74c1a04954b78b4b6035e97a5e078a5a0f28ec96d547bfee9ace803ac06f7d62059e9497a1a4a267569d9876da60101aff38e3529b9b939ce7f91ae970115f2e490af7cc45c4f78511f36057ce5c5a5c56325a29fb44dfc203f356e123202cb13ac68248de806aa6a3659cf3c03eb6821d09c8114a4e868febde865bb6d2acc00000").unwrap_err(); @@ -1575,11 +1615,10 @@ mod tests { #[test] fn serialize_and_deserialize_proprietary() { let mut psbt: PartiallySignedTransaction = hex_psbt!("70736274ff0100a00200000002ab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40000000000feffffffab0949a08c5af7c49b8212f417e2f15ab3f5c33dcf153821a8139f877a5b7be40100000000feffffff02603bea0b000000001976a914768a40bbd740cbe81d988e71de2a4d5c71396b1d88ac8e240000000000001976a9146f4620b553fa095e721b9ee0efe9fa039cca459788ac000000000001076a47304402204759661797c01b036b25928948686218347d89864b719e1f7fcf57d1e511658702205309eabf56aa4d8891ffd111fdf1336f3a29da866d7f8486d75546ceedaf93190121035cdc61fc7ba971c0b501a646a2a83b102cb43881217ca682dc86e2d73fa882920001012000e1f5050000000017a9143545e6e33b832c47050f24d3eeb93c9c03948bc787010416001485d13537f2e265405a34dbafa9e3dda01fb82308000000").unwrap(); - psbt.proprietary.insert(raw::ProprietaryKey { - prefix: b"test".to_vec(), - subtype: 0u8, - key: b"test".to_vec(), - }, b"test".to_vec()); + psbt.proprietary.insert( + raw::ProprietaryKey { prefix: b"test".to_vec(), subtype: 0u8, key: b"test".to_vec() }, + b"test".to_vec(), + ); assert!(!psbt.proprietary.is_empty()); let rtt: PartiallySignedTransaction = hex_psbt!(&psbt.serialize_hex()).unwrap(); assert!(!rtt.proprietary.is_empty()); @@ -1725,31 +1764,31 @@ mod tests { let mut t2 = t.clone(); t2.inputs[0].non_witness_utxo = None; match t2.fee().unwrap_err() { - Error::MissingUtxo => {}, - e => panic!("unexpected error: {:?}", e) + Error::MissingUtxo => {} + e => panic!("unexpected error: {:?}", e), } // negative fee let mut t3 = t.clone(); t3.unsigned_tx.output[0].value = prev_output_val; match t3.fee().unwrap_err() { - Error::NegativeFee => {}, - e => panic!("unexpected error: {:?}", e) + Error::NegativeFee => {} + e => panic!("unexpected error: {:?}", e), } // overflow t.unsigned_tx.output[0].value = u64::max_value(); t.unsigned_tx.output[1].value = u64::max_value(); match t.fee().unwrap_err() { - Error::FeeOverflow => {}, - e => panic!("unexpected error: {:?}", e) + Error::FeeOverflow => {} + e => panic!("unexpected error: {:?}", e), } } #[test] #[cfg(feature = "rand-std")] fn sign_psbt() { - use crate::WPubkeyHash; use crate::address::WitnessProgram; - use crate::bip32::{Fingerprint, DerivationPath}; + use crate::bip32::{DerivationPath, Fingerprint}; + use crate::WPubkeyHash; let unsigned_tx = Transaction { version: 2, @@ -1767,7 +1806,7 @@ mod tests { key_map.insert(pk, priv_key); // First input we can spend. See comment above on key_map for why we use defaults here. - let txout_wpkh = TxOut{ + let txout_wpkh = TxOut { value: 10, script_pubkey: ScriptBuf::new_v0_p2wpkh(&WPubkeyHash::hash(&pk.to_bytes())), }; @@ -1778,13 +1817,10 @@ mod tests { psbt.inputs[0].bip32_derivation = map; // Second input is unspendable by us e.g., from another wallet that supports future upgrades. - let unknown_prog = WitnessProgram::new( - crate::address::WitnessVersion::V4, vec![0xaa; 34] - ).unwrap(); - let txout_unknown_future = TxOut{ - value: 10, - script_pubkey: ScriptBuf::new_witness_program(&unknown_prog), - }; + let unknown_prog = + WitnessProgram::new(crate::address::WitnessVersion::V4, vec![0xaa; 34]).unwrap(); + let txout_unknown_future = + TxOut { value: 10, script_pubkey: ScriptBuf::new_witness_program(&unknown_prog) }; psbt.inputs[1].witness_utxo = Some(txout_unknown_future); let sigs = psbt.sign(&key_map, &secp).unwrap(); diff --git a/bitcoin/src/psbt/raw.rs b/bitcoin/src/psbt/raw.rs index 94ab4eab..aa312413 100644 --- a/bitcoin/src/psbt/raw.rs +++ b/bitcoin/src/psbt/raw.rs @@ -6,16 +6,17 @@ //! . //! -use crate::prelude::*; -use core::fmt; use core::convert::TryFrom; +use core::fmt; +use super::serialize::{Deserialize, Serialize}; +use crate::consensus::encode::{ + self, deserialize, serialize, Decodable, Encodable, ReadExt, VarInt, WriteExt, MAX_VEC_SIZE, +}; use crate::io; -use crate::consensus::encode::{self, ReadExt, WriteExt, Decodable, Encodable, VarInt, serialize, deserialize, MAX_VEC_SIZE}; +use crate::prelude::*; use crate::psbt::Error; -use super::serialize::{Serialize, Deserialize}; - /// A PSBT key in its raw byte form. #[derive(Debug, PartialEq, Hash, Eq, Clone, Ord, PartialOrd)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] @@ -51,7 +52,10 @@ pub type ProprietaryType = u8; #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] #[cfg_attr(feature = "serde", serde(crate = "actual_serde"))] -pub struct ProprietaryKey where Subtype: Copy + From + Into { +pub struct ProprietaryKey +where + Subtype: Copy + From + Into, +{ /// Proprietary type prefix used for grouping together keys under some /// application and avoid namespace collision #[cfg_attr(feature = "serde", serde(with = "crate::serde_utils::hex_bytes"))] @@ -83,7 +87,7 @@ impl Key { return Err(encode::Error::OversizedVectorAllocation { requested: key_byte_size as usize, max: MAX_VEC_SIZE, - })? + })?; } let type_value: u8 = Decodable::consensus_decode(r)?; @@ -100,7 +104,9 @@ impl Key { impl Serialize for Key { fn serialize(&self) -> Vec { let mut buf = Vec::new(); - VarInt((self.key.len() + 1) as u64).consensus_encode(&mut buf).expect("in-memory writers don't error"); + VarInt((self.key.len() + 1) as u64) + .consensus_encode(&mut buf) + .expect("in-memory writers don't error"); self.type_value.consensus_encode(&mut buf).expect("in-memory writers don't error"); @@ -131,14 +137,14 @@ impl Deserialize for Pair { impl Pair { pub(crate) fn decode(r: &mut R) -> Result { - Ok(Pair { - key: Key::decode(r)?, - value: Decodable::consensus_decode(r)?, - }) + Ok(Pair { key: Key::decode(r)?, value: Decodable::consensus_decode(r)? }) } } -impl Encodable for ProprietaryKey where Subtype: Copy + From + Into { +impl Encodable for ProprietaryKey +where + Subtype: Copy + From + Into, +{ fn consensus_encode(&self, w: &mut W) -> Result { let mut len = self.prefix.consensus_encode(w)? + 1; w.emit_u8(self.subtype.into())?; @@ -148,7 +154,10 @@ impl Encodable for ProprietaryKey where Subtype: Copy + From Decodable for ProprietaryKey where Subtype: Copy + From + Into { +impl Decodable for ProprietaryKey +where + Subtype: Copy + From + Into, +{ fn consensus_decode(r: &mut R) -> Result { let prefix = Vec::::consensus_decode(r)?; let subtype = Subtype::from(r.read_u8()?); @@ -158,19 +167,18 @@ impl Decodable for ProprietaryKey where Subtype: Copy + From ProprietaryKey where Subtype: Copy + From + Into { +impl ProprietaryKey +where + Subtype: Copy + From + Into, +{ /// Constructs full [Key] corresponding to this proprietary key type - pub fn to_key(&self) -> Key { - Key { - type_value: 0xFC, - key: serialize(self) - } - } + pub fn to_key(&self) -> Key { Key { type_value: 0xFC, key: serialize(self) } } } impl TryFrom for ProprietaryKey where - Subtype:Copy + From + Into { + Subtype: Copy + From + Into, +{ type Error = Error; /// Constructs a [`ProprietaryKey`] from a [`Key`]. @@ -179,7 +187,7 @@ where /// Returns [`Error::InvalidProprietaryKey`] if `key` does not start with `0xFC` byte. fn try_from(key: Key) -> Result { if key.type_value != 0xFC { - return Err(Error::InvalidProprietaryKey) + return Err(Error::InvalidProprietaryKey); } Ok(deserialize(&key.key)?) @@ -194,7 +202,7 @@ pub(crate) fn read_to_end(mut d: D) -> Result, io::Error> { match d.read(&mut buf) { Ok(0) => break, Ok(n) => result.extend_from_slice(&buf[0..n]), - Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}, + Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {} Err(e) => return Err(e), }; } diff --git a/bitcoin/src/psbt/serialize.rs b/bitcoin/src/psbt/serialize.rs index 5f965824..c3a21d54 100644 --- a/bitcoin/src/psbt/serialize.rs +++ b/bitcoin/src/psbt/serialize.rs @@ -6,31 +6,26 @@ //! according to the BIP-174 specification. //! -use core::convert::TryFrom; -use core::convert::TryInto; +use core::convert::{TryFrom, TryInto}; -use crate::VarInt; -use crate::prelude::*; - -use crate::io; - -use crate::blockdata::script::ScriptBuf; -use crate::blockdata::witness::Witness; -use crate::blockdata::transaction::{Transaction, TxOut}; -use crate::consensus::encode::{self, serialize, Decodable, Encodable, deserialize_partial}; -use crate::taproot::TapTree; use secp256k1::{self, XOnlyPublicKey}; -use crate::bip32::{ChildNumber, Fingerprint, KeySource}; -use crate::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; -use crate::crypto::{ecdsa, taproot}; -use crate::psbt::{Error, PartiallySignedTransaction}; -use crate::taproot::{TapNodeHash, TapLeafHash, ControlBlock, LeafVersion}; -use crate::crypto::key::PublicKey; -use super::map::{Map, Input, Output, PsbtSighashType}; +use super::map::{Input, Map, Output, PsbtSighashType}; use super::Psbt; - -use crate::taproot::TaprootBuilder; +use crate::bip32::{ChildNumber, Fingerprint, KeySource}; +use crate::blockdata::script::ScriptBuf; +use crate::blockdata::transaction::{Transaction, TxOut}; +use crate::blockdata::witness::Witness; +use crate::consensus::encode::{self, deserialize_partial, serialize, Decodable, Encodable}; +use crate::crypto::key::PublicKey; +use crate::crypto::{ecdsa, taproot}; +use crate::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; +use crate::prelude::*; +use crate::psbt::{Error, PartiallySignedTransaction}; +use crate::taproot::{ + ControlBlock, LeafVersion, TapLeafHash, TapNodeHash, TapTree, TaprootBuilder, +}; +use crate::{io, VarInt}; /// A trait for serializing a value as raw data for insertion into PSBT /// key-value maps. pub(crate) trait Serialize { @@ -46,9 +41,7 @@ pub(crate) trait Deserialize: Sized { impl PartiallySignedTransaction { /// Serialize a value as bytes in hex. - pub fn serialize_hex(&self) -> String { - self.serialize().to_lower_hex_string() - } + pub fn serialize_hex(&self) -> String { self.serialize().to_lower_hex_string() } /// Serialize as raw binary data pub fn serialize(&self) -> Vec { @@ -72,7 +65,6 @@ impl PartiallySignedTransaction { buf } - /// Deserialize a value from raw binary data. pub fn deserialize(bytes: &[u8]) -> Result { const MAGIC_BYTES: &[u8] = b"psbt"; @@ -133,15 +125,11 @@ impl_psbt_hash_de_serialize!(sha256d::Hash); impl_psbt_de_serialize!(Vec); impl Serialize for ScriptBuf { - fn serialize(&self) -> Vec { - self.to_bytes() - } + fn serialize(&self) -> Vec { self.to_bytes() } } impl Deserialize for ScriptBuf { - fn deserialize(bytes: &[u8]) -> Result { - Ok(Self::from(bytes.to_vec())) - } + fn deserialize(bytes: &[u8]) -> Result { Ok(Self::from(bytes.to_vec())) } } impl Serialize for PublicKey { @@ -154,28 +142,22 @@ impl Serialize for PublicKey { impl Deserialize for PublicKey { fn deserialize(bytes: &[u8]) -> Result { - PublicKey::from_slice(bytes) - .map_err(Error::InvalidPublicKey) + PublicKey::from_slice(bytes).map_err(Error::InvalidPublicKey) } } impl Serialize for secp256k1::PublicKey { - fn serialize(&self) -> Vec { - self.serialize().to_vec() - } + fn serialize(&self) -> Vec { self.serialize().to_vec() } } impl Deserialize for secp256k1::PublicKey { fn deserialize(bytes: &[u8]) -> Result { - secp256k1::PublicKey::from_slice(bytes) - .map_err(Error::InvalidSecp256k1PublicKey) + secp256k1::PublicKey::from_slice(bytes).map_err(Error::InvalidSecp256k1PublicKey) } } impl Serialize for ecdsa::Signature { - fn serialize(&self) -> Vec { - self.to_vec() - } + fn serialize(&self) -> Vec { self.to_vec() } } impl Deserialize for ecdsa::Signature { @@ -193,21 +175,14 @@ impl Deserialize for ecdsa::Signature { // also has a field sighash_u32 (See BIP141). For example, when signing with non-standard // 0x05, the sighash message would have the last field as 0x05u32 while, the verification // would use check the signature assuming sighash_u32 as `0x01`. - ecdsa::Signature::from_slice(bytes) - .map_err(|e| match e { - ecdsa::Error::EmptySignature => { - Error::InvalidEcdsaSignature(e) - } - ecdsa::Error::NonStandardSighashType(flag) => { - Error::NonStandardSighashType(flag) - } - ecdsa::Error::Secp256k1(..) => { - Error::InvalidEcdsaSignature(e) - } - ecdsa::Error::HexEncoding(..) => { - unreachable!("Decoding from slice, not hex") - } - }) + ecdsa::Signature::from_slice(bytes).map_err(|e| match e { + ecdsa::Error::EmptySignature => Error::InvalidEcdsaSignature(e), + ecdsa::Error::NonStandardSighashType(flag) => Error::NonStandardSighashType(flag), + ecdsa::Error::Secp256k1(..) => Error::InvalidEcdsaSignature(e), + ecdsa::Error::HexEncoding(..) => { + unreachable!("Decoding from slice, not hex") + } + }) } } @@ -228,7 +203,7 @@ impl Serialize for KeySource { impl Deserialize for KeySource { fn deserialize(bytes: &[u8]) -> Result { if bytes.len() < 4 { - return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); } let fprint: Fingerprint = bytes[0..4].try_into().expect("4 is the fingerprint length"); @@ -248,21 +223,15 @@ impl Deserialize for KeySource { // partial sigs impl Serialize for Vec { - fn serialize(&self) -> Vec { - self.clone() - } + fn serialize(&self) -> Vec { self.clone() } } impl Deserialize for Vec { - fn deserialize(bytes: &[u8]) -> Result { - Ok(bytes.to_vec()) - } + fn deserialize(bytes: &[u8]) -> Result { Ok(bytes.to_vec()) } } impl Serialize for PsbtSighashType { - fn serialize(&self) -> Vec { - serialize(&self.to_u32()) - } + fn serialize(&self) -> Vec { serialize(&self.to_u32()) } } impl Deserialize for PsbtSighashType { @@ -274,38 +243,26 @@ impl Deserialize for PsbtSighashType { // Taproot related ser/deser impl Serialize for XOnlyPublicKey { - fn serialize(&self) -> Vec { - XOnlyPublicKey::serialize(self).to_vec() - } + fn serialize(&self) -> Vec { XOnlyPublicKey::serialize(self).to_vec() } } impl Deserialize for XOnlyPublicKey { fn deserialize(bytes: &[u8]) -> Result { - XOnlyPublicKey::from_slice(bytes) - .map_err(|_| Error::InvalidXOnlyPublicKey) + XOnlyPublicKey::from_slice(bytes).map_err(|_| Error::InvalidXOnlyPublicKey) } } -impl Serialize for taproot::Signature { - fn serialize(&self) -> Vec { - self.to_vec() - } +impl Serialize for taproot::Signature { + fn serialize(&self) -> Vec { self.to_vec() } } impl Deserialize for taproot::Signature { fn deserialize(bytes: &[u8]) -> Result { - taproot::Signature::from_slice(bytes) - .map_err(|e| match e { - taproot::Error::InvalidSighashType(flag) => { - Error::NonStandardSighashType(flag as u32) - } - taproot::Error::InvalidSignatureSize(_) => { - Error::InvalidTaprootSignature(e) - } - taproot::Error::Secp256k1(..) => { - Error::InvalidTaprootSignature(e) - } - }) + taproot::Signature::from_slice(bytes).map_err(|e| match e { + taproot::Error::InvalidSighashType(flag) => Error::NonStandardSighashType(flag as u32), + taproot::Error::InvalidSignatureSize(_) => Error::InvalidTaprootSignature(e), + taproot::Error::Secp256k1(..) => Error::InvalidTaprootSignature(e), + }) } } @@ -322,7 +279,7 @@ impl Serialize for (XOnlyPublicKey, TapLeafHash) { impl Deserialize for (XOnlyPublicKey, TapLeafHash) { fn deserialize(bytes: &[u8]) -> Result { if bytes.len() < 32 { - return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); } let a: XOnlyPublicKey = Deserialize::deserialize(&bytes[..32])?; let b: TapLeafHash = Deserialize::deserialize(&bytes[32..])?; @@ -331,15 +288,12 @@ impl Deserialize for (XOnlyPublicKey, TapLeafHash) { } impl Serialize for ControlBlock { - fn serialize(&self) -> Vec { - ControlBlock::serialize(self) - } + fn serialize(&self) -> Vec { ControlBlock::serialize(self) } } impl Deserialize for ControlBlock { fn deserialize(bytes: &[u8]) -> Result { - Self::decode(bytes) - .map_err(|_| Error::InvalidControlBlock) + Self::decode(bytes).map_err(|_| Error::InvalidControlBlock) } } @@ -356,7 +310,7 @@ impl Serialize for (ScriptBuf, LeafVersion) { impl Deserialize for (ScriptBuf, LeafVersion) { fn deserialize(bytes: &[u8]) -> Result { if bytes.is_empty() { - return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()) + return Err(io::Error::from(io::ErrorKind::UnexpectedEof).into()); } // The last byte is LeafVersion. let script = ScriptBuf::deserialize(&bytes[..bytes.len() - 1])?; @@ -366,10 +320,9 @@ impl Deserialize for (ScriptBuf, LeafVersion) { } } - impl Serialize for (Vec, KeySource) { fn serialize(&self) -> Vec { - let mut buf = Vec::with_capacity( 32 * self.0.len() + key_source_len(&self.1)); + let mut buf = Vec::with_capacity(32 * self.0.len() + key_source_len(&self.1)); self.0.consensus_encode(&mut buf).expect("Vecs don't error allocation"); // TODO: Add support for writing into a writer for key-source buf.extend(self.1.serialize()); @@ -387,11 +340,14 @@ impl Deserialize for (Vec, KeySource) { impl Serialize for TapTree { fn serialize(&self) -> Vec { - let capacity = self.script_leaves().map(|l| { - l.script().len() + VarInt(l.script().len() as u64).len() // script version + let capacity = self + .script_leaves() + .map(|l| { + l.script().len() + VarInt(l.script().len() as u64).len() // script version + 1 // merkle branch + 1 // leaf version - }).sum::(); + }) + .sum::(); let mut buf = Vec::with_capacity(capacity); for leaf_info in self.script_leaves() { // # Cast Safety: @@ -416,9 +372,10 @@ impl Deserialize for TapTree { if consumed > 0 { bytes_iter.nth(consumed - 1); } - let leaf_version = LeafVersion::from_consensus(*version) - .map_err(|_| Error::InvalidLeafVersion)?; - builder = builder.add_leaf_with_ver(*depth, script, leaf_version) + let leaf_version = + LeafVersion::from_consensus(*version).map_err(|_| Error::InvalidLeafVersion)?; + builder = builder + .add_leaf_with_ver(*depth, script, leaf_version) .map_err(|_| Error::Taproot("Tree not in DFS order"))?; } TapTree::try_from(builder).map_err(Error::TapTree) @@ -426,9 +383,7 @@ impl Deserialize for TapTree { } // Helper function to compute key source len -fn key_source_len(key_source: &KeySource) -> usize { - 4 + 4 * (key_source.1).as_ref().len() -} +fn key_source_len(key_source: &KeySource) -> usize { 4 + 4 * (key_source.1).as_ref().len() } #[cfg(test)] mod tests { @@ -439,7 +394,10 @@ mod tests { // Composes tree matching a given depth map, filled with dumb script leafs, // each of which consists of a single push-int op code, with int value // increased for each consecutive leaf. - pub fn compose_taproot_builder<'map>(opcode: u8, depth_map: impl IntoIterator) -> TaprootBuilder { + pub fn compose_taproot_builder<'map>( + opcode: u8, + depth_map: impl IntoIterator, + ) -> TaprootBuilder { let mut val = opcode; let mut builder = TaprootBuilder::new(); for depth in depth_map { @@ -454,7 +412,13 @@ mod tests { #[test] fn taptree_hidden() { let mut builder = compose_taproot_builder(0x51, &[2, 2, 2]); - builder = builder.add_leaf_with_ver(3, ScriptBuf::from_hex("b9").unwrap(), LeafVersion::from_consensus(0xC2).unwrap()).unwrap(); + builder = builder + .add_leaf_with_ver( + 3, + ScriptBuf::from_hex("b9").unwrap(), + LeafVersion::from_consensus(0xC2).unwrap(), + ) + .unwrap(); builder = builder.add_hidden_node(3, TapNodeHash::all_zeros()).unwrap(); assert!(TapTree::try_from(builder).is_err()); } @@ -462,7 +426,13 @@ mod tests { #[test] fn taptree_roundtrip() { let mut builder = compose_taproot_builder(0x51, &[2, 2, 2, 3]); - builder = builder.add_leaf_with_ver(3, ScriptBuf::from_hex("b9").unwrap(), LeafVersion::from_consensus(0xC2).unwrap()).unwrap(); + builder = builder + .add_leaf_with_ver( + 3, + ScriptBuf::from_hex("b9").unwrap(), + LeafVersion::from_consensus(0xC2).unwrap(), + ) + .unwrap(); let tree = TapTree::try_from(builder).unwrap(); let tree_prime = TapTree::deserialize(&tree.serialize()).unwrap(); assert_eq!(tree, tree_prime); From 0dcbed3c7b5662bbaba6595306ca4b8a075d0277 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 22 Feb 2023 09:49:06 +1100 Subject: [PATCH 11/16] Enable formatting for blockdata Add `rustfmt::skip` attribute in a couple of places and then remove the exclude for the `blockdata` module. Do not run the formatter, that will be done as a separate patch to aid review. --- bitcoin/src/blockdata/opcodes.rs | 1 + bitcoin/src/blockdata/script/tests.rs | 1 + rustfmt.toml | 1 - 3 files changed, 2 insertions(+), 1 deletion(-) diff --git a/bitcoin/src/blockdata/opcodes.rs b/bitcoin/src/blockdata/opcodes.rs index 36120248..f78c315e 100644 --- a/bitcoin/src/blockdata/opcodes.rs +++ b/bitcoin/src/blockdata/opcodes.rs @@ -351,6 +351,7 @@ impl All { (OP_VERIF, _) | (OP_VERNOTIF, _) | (OP_INVALIDOPCODE, _) => Class::IllegalOp, // 15 opcodes illegal in Legacy context + #[rustfmt::skip] (OP_CAT, ctx) | (OP_SUBSTR, ctx) | (OP_LEFT, ctx) | (OP_RIGHT, ctx) | (OP_INVERT, ctx) diff --git a/bitcoin/src/blockdata/script/tests.rs b/bitcoin/src/blockdata/script/tests.rs index fdd528e9..36aed97e 100644 --- a/bitcoin/src/blockdata/script/tests.rs +++ b/bitcoin/src/blockdata/script/tests.rs @@ -11,6 +11,7 @@ use crate::psbt::serialize::Serialize; use hex_lit::hex; #[test] +#[rustfmt::skip] fn script() { let mut comp = vec![]; let mut script = Builder::new(); diff --git a/rustfmt.toml b/rustfmt.toml index 3d9a166e..2e5d6794 100644 --- a/rustfmt.toml +++ b/rustfmt.toml @@ -1,6 +1,5 @@ # Eventually this shoud be: ignore = [] ignore = [ - "bitcoin/src/blockdata", "bitcoin/src/util", "hashes", ] From 5973dce9db50b735172983af173f1b34b4223531 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Wed, 22 Feb 2023 10:01:26 +1100 Subject: [PATCH 12/16] blockdata: Run the formatter Run `cargo +nightly fmt`, no other manual changes. --- bitcoin/src/blockdata/block.rs | 148 +++-- bitcoin/src/blockdata/constants.rs | 187 +++--- bitcoin/src/blockdata/fee_rate.rs | 51 +- bitcoin/src/blockdata/locktime/absolute.rs | 90 +-- bitcoin/src/blockdata/locktime/relative.rs | 49 +- bitcoin/src/blockdata/mod.rs | 8 +- bitcoin/src/blockdata/opcodes.rs | 75 +-- bitcoin/src/blockdata/script/borrowed.rs | 157 +++-- bitcoin/src/blockdata/script/builder.rs | 44 +- bitcoin/src/blockdata/script/instruction.rs | 70 +-- bitcoin/src/blockdata/script/mod.rs | 204 +++---- bitcoin/src/blockdata/script/owned.rs | 107 ++-- bitcoin/src/blockdata/script/push_bytes.rs | 166 ++---- bitcoin/src/blockdata/script/tests.rs | 286 +++++----- bitcoin/src/blockdata/transaction.rs | 597 +++++++++++--------- bitcoin/src/blockdata/weight.rs | 100 +--- bitcoin/src/blockdata/witness.rs | 167 +++--- 17 files changed, 1181 insertions(+), 1325 deletions(-) diff --git a/bitcoin/src/blockdata/block.rs b/bitcoin/src/blockdata/block.rs index 45ab355c..9f737eb6 100644 --- a/bitcoin/src/blockdata/block.rs +++ b/bitcoin/src/blockdata/block.rs @@ -9,24 +9,20 @@ //! these blocks and the blockchain. //! -use crate::prelude::*; - use core::fmt; -use crate::merkle_tree; -use crate::error::Error::{self, BlockBadTarget, BlockBadProofOfWork}; -use crate::hashes::{Hash, HashEngine}; -use crate::hash_types::{Wtxid, TxMerkleNode, WitnessMerkleNode, WitnessCommitment}; -use crate::consensus::{encode, Encodable, Decodable}; -use crate::blockdata::transaction::Transaction; -use crate::blockdata::script; -use crate::pow::{CompactTarget, Target, Work}; -use crate::VarInt; -use crate::internal_macros::impl_consensus_encoding; -use crate::io; use super::Weight; - +use crate::blockdata::script; +use crate::blockdata::transaction::Transaction; +use crate::consensus::{encode, Decodable, Encodable}; +use crate::error::Error::{self, BlockBadProofOfWork, BlockBadTarget}; pub use crate::hash_types::BlockHash; +use crate::hash_types::{TxMerkleNode, WitnessCommitment, WitnessMerkleNode, Wtxid}; +use crate::hashes::{Hash, HashEngine}; +use crate::internal_macros::impl_consensus_encoding; +use crate::pow::{CompactTarget, Target, Work}; +use crate::prelude::*; +use crate::{io, merkle_tree, VarInt}; /// Bitcoin block header. /// @@ -67,14 +63,10 @@ impl Header { } /// Computes the target (range [0, T] inclusive) that a blockhash must land in to be valid. - pub fn target(&self) -> Target { - self.bits.into() - } + pub fn target(&self) -> Target { self.bits.into() } /// Computes the popular "difficulty" measure for mining. - pub fn difficulty(&self) -> u128 { - self.target().difficulty() - } + pub fn difficulty(&self) -> u128 { self.target().difficulty() } /// Checks that the proof-of-work for the block is valid, returning the block hash. pub fn validate_pow(&self, required_target: Target) -> Result { @@ -91,9 +83,7 @@ impl Header { } /// Returns the total work of the block. - pub fn work(&self) -> Work { - self.target().to_work() - } + pub fn work(&self) -> Work { self.target().to_work() } } /// Bitcoin block version number. @@ -135,16 +125,12 @@ impl Version { /// Creates a [`Version`] from a signed 32 bit integer value. /// /// This is the data type used in consensus code in Bitcoin Core. - pub fn from_consensus(v: i32) -> Self { - Version(v) - } + pub fn from_consensus(v: i32) -> Self { Version(v) } /// Returns the inner `i32` value. /// /// This is the data type used in consensus code in Bitcoin Core. - pub fn to_consensus(self) -> i32 { - self.0 - } + pub fn to_consensus(self) -> i32 { self.0 } /// Checks whether the version number is signalling a soft fork at the given bit. /// @@ -167,9 +153,7 @@ impl Version { } impl Default for Version { - fn default() -> Version { - Self::NO_SOFT_FORK_SIGNALLING - } + fn default() -> Version { Self::NO_SOFT_FORK_SIGNALLING } } impl Encodable for Version { @@ -202,16 +186,14 @@ pub struct Block { /// The block header pub header: Header, /// List of transactions contained in the block - pub txdata: Vec + pub txdata: Vec, } impl_consensus_encoding!(Block, header, txdata); impl Block { /// Returns the block hash. - pub fn block_hash(&self) -> BlockHash { - self.header.block_hash() - } + pub fn block_hash(&self) -> BlockHash { self.header.block_hash() } /// Checks if merkle root of header matches merkle root of the transaction list. pub fn check_merkle_root(&self) -> bool { @@ -239,15 +221,21 @@ impl Block { } // Commitment is in the last output that starts with magic bytes. - if let Some(pos) = coinbase.output.iter() - .rposition(|o| o.script_pubkey.len () >= 38 && o.script_pubkey.as_bytes()[0..6] == MAGIC) + if let Some(pos) = coinbase + .output + .iter() + .rposition(|o| o.script_pubkey.len() >= 38 && o.script_pubkey.as_bytes()[0..6] == MAGIC) { - let commitment = WitnessCommitment::from_slice(&coinbase.output[pos].script_pubkey.as_bytes()[6..38]).unwrap(); + let commitment = WitnessCommitment::from_slice( + &coinbase.output[pos].script_pubkey.as_bytes()[6..38], + ) + .unwrap(); // Witness reserved value is in coinbase input witness. let witness_vec: Vec<_> = coinbase.input[0].witness.iter().collect(); if witness_vec.len() == 1 && witness_vec[0].len() == 32 { if let Some(witness_root) = self.witness_root() { - return commitment == Self::compute_witness_commitment(&witness_root, witness_vec[0]); + return commitment + == Self::compute_witness_commitment(&witness_root, witness_vec[0]); } } } @@ -262,7 +250,10 @@ impl Block { } /// Computes the witness commitment for the block's transaction list. - pub fn compute_witness_commitment(witness_root: &WitnessMerkleNode, witness_reserved_value: &[u8]) -> WitnessCommitment { + pub fn compute_witness_commitment( + witness_root: &WitnessMerkleNode, + witness_reserved_value: &[u8], + ) -> WitnessCommitment { let mut encoder = WitnessCommitment::engine(); witness_root.consensus_encode(&mut encoder).expect("engines don't error"); encoder.input(witness_reserved_value); @@ -283,9 +274,7 @@ impl Block { } /// base_size == size of header + size of encoded transaction count. - fn base_size(&self) -> usize { - 80 + VarInt(self.txdata.len() as u64).len() - } + fn base_size(&self) -> usize { 80 + VarInt(self.txdata.len() as u64).len() } /// Returns the size of the block. /// @@ -309,9 +298,7 @@ impl Block { } /// Returns the coinbase transaction, if one is present. - pub fn coinbase(&self) -> Option<&Transaction> { - self.txdata.first() - } + pub fn coinbase(&self) -> Option<&Transaction> { self.txdata.first() } /// Returns the block height, as encoded in the coinbase transaction according to BIP34. pub fn bip34_block_height(&self) -> Result { @@ -334,7 +321,8 @@ impl Block { match push.map_err(|_| Bip34Error::NotPresent)? { script::Instruction::PushBytes(b) => { // Check that the number is encoded in the minimal way. - let h = script::read_scriptint(b.as_bytes()).map_err(|_e| Bip34Error::UnexpectedPush(b.as_bytes().to_vec()))?; + let h = script::read_scriptint(b.as_bytes()) + .map_err(|_e| Bip34Error::UnexpectedPush(b.as_bytes().to_vec()))?; if h < 0 { Err(Bip34Error::NegativeHeight) } else { @@ -380,44 +368,32 @@ impl std::error::Error for Bip34Error { use self::Bip34Error::*; match self { - Unsupported | - NotPresent | - UnexpectedPush(_) | - NegativeHeight => None, + Unsupported | NotPresent | UnexpectedPush(_) | NegativeHeight => None, } } } impl From
for BlockHash { - fn from(header: Header) -> BlockHash { - header.block_hash() - } + fn from(header: Header) -> BlockHash { header.block_hash() } } impl From<&Header> for BlockHash { - fn from(header: &Header) -> BlockHash { - header.block_hash() - } + fn from(header: &Header) -> BlockHash { header.block_hash() } } impl From for BlockHash { - fn from(block: Block) -> BlockHash { - block.block_hash() - } + fn from(block: Block) -> BlockHash { block.block_hash() } } impl From<&Block> for BlockHash { - fn from(block: &Block) -> BlockHash { - block.block_hash() - } + fn from(block: &Block) -> BlockHash { block.block_hash() } } #[cfg(test)] mod tests { use super::*; - - use crate::hashes::hex::FromHex; use crate::consensus::encode::{deserialize, serialize}; + use crate::hashes::hex::FromHex; use crate::internal_macros::hex; #[test] @@ -431,7 +407,6 @@ mod tests { assert_eq!(block.bip34_block_height(), Ok(100_000)); - // block with 9-byte bip34 push const BAD_HEX: &str = "0200000035ab154183570282ce9afc0b494c9fc6a3cfea05aa8c1add2ecc56490000000038ba3d78e4500a5a7570dbe61960398add4410d278b21cd9708e6d9743f374d544fc055227f1001c29c1ea3b0101000000010000000000000000000000000000000000000000000000000000000000000000ffffffff3d09a08601112233445566000427f1001c046a510100522cfabe6d6d0000000000000000000068692066726f6d20706f6f6c7365727665726aac1eeeed88ffffffff0100f2052a010000001976a914912e2b234f941f30b18afbb4fa46171214bf66c888ac00000000"; let bad: Block = deserialize(&hex!(BAD_HEX)).unwrap(); @@ -464,13 +439,19 @@ mod tests { assert_eq!(real_decode.header.bits, CompactTarget::from_consensus(486604799)); assert_eq!(real_decode.header.nonce, 2067413810); assert_eq!(real_decode.header.work(), work); - assert_eq!(real_decode.header.validate_pow(real_decode.header.target()).unwrap(), real_decode.block_hash()); + assert_eq!( + real_decode.header.validate_pow(real_decode.header.target()).unwrap(), + real_decode.block_hash() + ); assert_eq!(real_decode.header.difficulty(), 1); // [test] TODO: check the transaction data assert_eq!(real_decode.size(), some_block.len()); assert_eq!(real_decode.strippedsize(), some_block.len()); - assert_eq!(real_decode.weight(), Weight::from_non_witness_data_size(some_block.len() as u64)); + assert_eq!( + real_decode.weight(), + Weight::from_non_witness_data_size(some_block.len() as u64) + ); // should be also ok for a non-witness block as commitment is optional in that case assert!(real_decode.check_witness_commitment()); @@ -491,7 +472,7 @@ mod tests { assert!(decode.is_ok()); let real_decode = decode.unwrap(); - assert_eq!(real_decode.header.version, Version(Version::USE_VERSION_BITS as i32)); // VERSIONBITS but no bits set + assert_eq!(real_decode.header.version, Version(Version::USE_VERSION_BITS as i32)); // VERSIONBITS but no bits set assert_eq!(serialize(&real_decode.header.prev_blockhash), prevhash); assert_eq!(serialize(&real_decode.header.merkle_root), merkle); assert_eq!(real_decode.header.merkle_root, real_decode.compute_merkle_root().unwrap()); @@ -499,7 +480,10 @@ mod tests { assert_eq!(real_decode.header.bits, CompactTarget::from_consensus(0x1a06d450)); assert_eq!(real_decode.header.nonce, 1879759182); assert_eq!(real_decode.header.work(), work); - assert_eq!(real_decode.header.validate_pow(real_decode.header.target()).unwrap(), real_decode.block_hash()); + assert_eq!( + real_decode.header.validate_pow(real_decode.header.target()).unwrap(), + real_decode.block_hash() + ); assert_eq!(real_decode.header.difficulty(), 2456598); // [test] TODO: check the transaction data @@ -530,8 +514,12 @@ mod tests { #[test] fn validate_pow_test() { let some_header = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b"); - let some_header: Header = deserialize(&some_header).expect("Can't deserialize correct block header"); - assert_eq!(some_header.validate_pow(some_header.target()).unwrap(), some_header.block_hash()); + let some_header: Header = + deserialize(&some_header).expect("Can't deserialize correct block header"); + assert_eq!( + some_header.validate_pow(some_header.target()).unwrap(), + some_header.block_hash() + ); // test with zero target match some_header.validate_pow(Target::ZERO) { @@ -552,7 +540,8 @@ mod tests { fn compact_roundrtip_test() { let some_header = hex!("010000004ddccd549d28f385ab457e98d1b11ce80bfea2c5ab93015ade4973e400000000bf4473e53794beae34e64fccc471dace6ae544180816f89591894e0f417a914cd74d6e49ffff001d323b3a7b"); - let header: Header = deserialize(&some_header).expect("Can't deserialize correct block header"); + let header: Header = + deserialize(&some_header).expect("Can't deserialize correct block header"); assert_eq!(header.bits, header.target().to_compact_lossy()); } @@ -560,7 +549,7 @@ mod tests { #[test] fn soft_fork_signalling() { for i in 0..31 { - let version_int = (0x20000000u32 ^ 1< Transaction { }; // Inputs - let in_script = script::Builder::new().push_int(486604799) - .push_int_non_minimal(4) - .push_slice(b"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks") - .into_script(); + let in_script = script::Builder::new() + .push_int(486604799) + .push_int_non_minimal(4) + .push_slice(b"The Times 03/Jan/2009 Chancellor on brink of second bailout for banks") + .into_script(); ret.input.push(TxIn { previous_output: OutPoint::null(), script_sig: in_script, @@ -86,14 +87,9 @@ fn bitcoin_genesis_tx() -> Transaction { // Outputs let script_bytes = hex!("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f"); - let out_script = script::Builder::new() - .push_slice(script_bytes) - .push_opcode(OP_CHECKSIG) - .into_script(); - ret.output.push(TxOut { - value: 50 * COIN_VALUE, - script_pubkey: out_script - }); + let out_script = + script::Builder::new().push_slice(script_bytes).push_opcode(OP_CHECKSIG).into_script(); + ret.output.push(TxOut { value: 50 * COIN_VALUE, script_pubkey: out_script }); // end ret @@ -105,58 +101,50 @@ pub fn genesis_block(network: Network) -> Block { let hash: sha256d::Hash = txdata[0].txid().into(); let merkle_root = hash.into(); match network { - Network::Bitcoin => { - Block { - header: block::Header { - version: block::Version::ONE, - prev_blockhash: Hash::all_zeros(), - merkle_root, - time: 1231006505, - bits: CompactTarget::from_consensus(0x1d00ffff), - nonce: 2083236893 - }, - txdata, - } - } - Network::Testnet => { - Block { - header: block::Header { - version: block::Version::ONE, - prev_blockhash: Hash::all_zeros(), - merkle_root, - time: 1296688602, - bits: CompactTarget::from_consensus(0x1d00ffff), - nonce: 414098458 - }, - txdata, - } - } - Network::Signet => { - Block { - header: block::Header { - version: block::Version::ONE, - prev_blockhash: Hash::all_zeros(), - merkle_root, - time: 1598918400, - bits: CompactTarget::from_consensus(0x1e0377ae), - nonce: 52613770 - }, - txdata, - } - } - Network::Regtest => { - Block { - header: block::Header { - version: block::Version::ONE, - prev_blockhash: Hash::all_zeros(), - merkle_root, - time: 1296688602, - bits: CompactTarget::from_consensus(0x207fffff), - nonce: 2 - }, - txdata, - } - } + Network::Bitcoin => Block { + header: block::Header { + version: block::Version::ONE, + prev_blockhash: Hash::all_zeros(), + merkle_root, + time: 1231006505, + bits: CompactTarget::from_consensus(0x1d00ffff), + nonce: 2083236893, + }, + txdata, + }, + Network::Testnet => Block { + header: block::Header { + version: block::Version::ONE, + prev_blockhash: Hash::all_zeros(), + merkle_root, + time: 1296688602, + bits: CompactTarget::from_consensus(0x1d00ffff), + nonce: 414098458, + }, + txdata, + }, + Network::Signet => Block { + header: block::Header { + version: block::Version::ONE, + prev_blockhash: Hash::all_zeros(), + merkle_root, + time: 1598918400, + bits: CompactTarget::from_consensus(0x1e0377ae), + nonce: 52613770, + }, + txdata, + }, + Network::Regtest => Block { + header: block::Header { + version: block::Version::ONE, + prev_blockhash: Hash::all_zeros(), + merkle_root, + time: 1296688602, + bits: CompactTarget::from_consensus(0x207fffff), + nonce: 2, + }, + txdata, + }, } } @@ -169,13 +157,25 @@ impl_bytes_newtype!(ChainHash, 32); impl ChainHash { // Mainnet value can be verified at https://github.com/lightning/bolts/blob/master/00-introduction.md /// `ChainHash` for mainnet bitcoin. - pub const BITCOIN: Self = Self([111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, 79, 147, 30, 131, 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0]); + pub const BITCOIN: Self = Self([ + 111, 226, 140, 10, 182, 241, 179, 114, 193, 166, 162, 70, 174, 99, 247, 79, 147, 30, 131, + 101, 225, 90, 8, 156, 104, 214, 25, 0, 0, 0, 0, 0, + ]); /// `ChainHash` for testnet bitcoin. - pub const TESTNET: Self = Self([67, 73, 127, 215, 248, 38, 149, 113, 8, 244, 163, 15, 217, 206, 195, 174, 186, 121, 151, 32, 132, 233, 14, 173, 1, 234, 51, 9, 0, 0, 0, 0]); + pub const TESTNET: Self = Self([ + 67, 73, 127, 215, 248, 38, 149, 113, 8, 244, 163, 15, 217, 206, 195, 174, 186, 121, 151, + 32, 132, 233, 14, 173, 1, 234, 51, 9, 0, 0, 0, 0, + ]); /// `ChainHash` for signet bitcoin. - pub const SIGNET: Self = Self([246, 30, 238, 59, 99, 163, 128, 164, 119, 160, 99, 175, 50, 178, 187, 201, 124, 159, 249, 240, 31, 44, 66, 37, 233, 115, 152, 129, 8, 0, 0, 0]); + pub const SIGNET: Self = Self([ + 246, 30, 238, 59, 99, 163, 128, 164, 119, 160, 99, 175, 50, 178, 187, 201, 124, 159, 249, + 240, 31, 44, 66, 37, 233, 115, 152, 129, 8, 0, 0, 0, + ]); /// `ChainHash` for regtest bitcoin. - pub const REGTEST: Self = Self([6, 34, 110, 70, 17, 26, 11, 89, 202, 175, 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94, 51, 42, 31, 199, 178, 183, 60, 241, 136, 145, 15]); + pub const REGTEST: Self = Self([ + 6, 34, 110, 70, 17, 26, 11, 89, 202, 175, 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94, + 51, 42, 31, 199, 178, 183, 60, 241, 136, 145, 15, + ]); /// Returns the hash of the `network` genesis block for use as a chain hash. /// @@ -190,10 +190,10 @@ impl ChainHash { #[cfg(test)] mod test { use super::*; - use crate::network::constants::Network; - use crate::consensus::encode::serialize; use crate::blockdata::locktime::absolute; + use crate::consensus::encode::serialize; use crate::internal_macros::hex; + use crate::network::constants::Network; #[test] fn bitcoin_genesis_first_transaction() { @@ -213,7 +213,10 @@ mod test { assert_eq!(gen.output[0].value, 50 * COIN_VALUE); assert_eq!(gen.lock_time, absolute::LockTime::ZERO); - assert_eq!(gen.wtxid().to_string(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + assert_eq!( + gen.wtxid().to_string(), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" + ); } #[test] @@ -222,12 +225,18 @@ mod test { assert_eq!(gen.header.version, block::Version::ONE); assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); - assert_eq!(gen.header.merkle_root.to_string(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + assert_eq!( + gen.header.merkle_root.to_string(), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" + ); assert_eq!(gen.header.time, 1231006505); assert_eq!(gen.header.bits, CompactTarget::from_consensus(0x1d00ffff)); assert_eq!(gen.header.nonce, 2083236893); - assert_eq!(gen.header.block_hash().to_string(), "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f"); + assert_eq!( + gen.header.block_hash().to_string(), + "000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f" + ); } #[test] @@ -235,11 +244,17 @@ mod test { let gen = genesis_block(Network::Testnet); assert_eq!(gen.header.version, block::Version::ONE); assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); - assert_eq!(gen.header.merkle_root.to_string(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + assert_eq!( + gen.header.merkle_root.to_string(), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" + ); assert_eq!(gen.header.time, 1296688602); assert_eq!(gen.header.bits, CompactTarget::from_consensus(0x1d00ffff)); assert_eq!(gen.header.nonce, 414098458); - assert_eq!(gen.header.block_hash().to_string(), "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943"); + assert_eq!( + gen.header.block_hash().to_string(), + "000000000933ea01ad0ee984209779baaec3ced90fa3f408719526f8d77f4943" + ); } #[test] @@ -247,11 +262,17 @@ mod test { let gen = genesis_block(Network::Signet); assert_eq!(gen.header.version, block::Version::ONE); assert_eq!(gen.header.prev_blockhash, Hash::all_zeros()); - assert_eq!(gen.header.merkle_root.to_string(), "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b"); + assert_eq!( + gen.header.merkle_root.to_string(), + "4a5e1e4baab89f3a32518a88c31bc87f618f76673e2cc77ab2127b7afdeda33b" + ); assert_eq!(gen.header.time, 1598918400); assert_eq!(gen.header.bits, CompactTarget::from_consensus(0x1e0377ae)); assert_eq!(gen.header.nonce, 52613770); - assert_eq!(gen.header.block_hash().to_string(), "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6"); + assert_eq!( + gen.header.block_hash().to_string(), + "00000008819873e925422c1ff0f99f7cc9bbb232af63a077a480a3633bee1ef6" + ); } // The *_chain_hash tests are sanity/regression tests, they verify that the const byte array diff --git a/bitcoin/src/blockdata/fee_rate.rs b/bitcoin/src/blockdata/fee_rate.rs index 23e986b1..a0686bda 100644 --- a/bitcoin/src/blockdata/fee_rate.rs +++ b/bitcoin/src/blockdata/fee_rate.rs @@ -1,11 +1,11 @@ //! Implements `FeeRate` and assoctiated features. use core::fmt; -use core::ops::{Mul, Div}; +use core::ops::{Div, Mul}; +use super::Weight; use crate::prelude::*; use crate::Amount; -use super::Weight; /// Represents fee rate. /// @@ -40,9 +40,7 @@ impl FeeRate { pub const DUST: FeeRate = FeeRate::from_sat_per_vb_unchecked(3); /// Constructs `FeeRate` from satoshis per 1000 weight units. - pub const fn from_sat_per_kwu(sat_kwu: u64) -> Self { - FeeRate(sat_kwu) - } + pub const fn from_sat_per_kwu(sat_kwu: u64) -> Self { FeeRate(sat_kwu) } /// Constructs `FeeRate` from satoshis per virtual bytes. /// @@ -57,40 +55,28 @@ impl FeeRate { } /// Constructs `FeeRate` from satoshis per virtual bytes without overflow check. - pub const fn from_sat_per_vb_unchecked(sat_vb: u64) -> Self { - FeeRate(sat_vb * (1000 / 4)) - } + pub const fn from_sat_per_vb_unchecked(sat_vb: u64) -> Self { FeeRate(sat_vb * (1000 / 4)) } /// Returns raw fee rate. /// /// Can be used instead of `into()` to avoid inference issues. - pub const fn to_sat_per_kwu(self) -> u64 { - self.0 - } + pub const fn to_sat_per_kwu(self) -> u64 { self.0 } /// Converts to sat/vB rounding down. - pub const fn to_sat_per_vb_floor(self) -> u64 { - self.0 / (1000 / 4) - } + pub const fn to_sat_per_vb_floor(self) -> u64 { self.0 / (1000 / 4) } /// Converts to sat/vB rounding up. - pub const fn to_sat_per_vb_ceil(self) -> u64 { - (self.0 + (1000 / 4 - 1)) / (1000 / 4) - } + pub const fn to_sat_per_vb_ceil(self) -> u64 { (self.0 + (1000 / 4 - 1)) / (1000 / 4) } /// Checked multiplication. /// /// Computes `self * rhs` returning `None` if overflow occurred. - pub fn checked_mul(self, rhs: u64) -> Option { - self.0.checked_mul(rhs).map(Self) - } + pub fn checked_mul(self, rhs: u64) -> Option { self.0.checked_mul(rhs).map(Self) } /// Checked division. /// /// Computes `self / rhs` returning `None` if `rhs == 0`. - pub fn checked_div(self, rhs: u64) -> Option { - self.0.checked_div(rhs).map(Self) - } + pub fn checked_div(self, rhs: u64) -> Option { self.0.checked_div(rhs).map(Self) } } /// Alternative will display the unit. @@ -105,9 +91,7 @@ impl fmt::Display for FeeRate { } impl From for u64 { - fn from(value: FeeRate) -> Self { - value.to_sat_per_kwu() - } + fn from(value: FeeRate) -> Self { value.to_sat_per_kwu() } } /// Computes ceiling so that fee computation is conservative. @@ -122,26 +106,23 @@ impl Mul for Weight { impl Mul for FeeRate { type Output = Amount; - fn mul(self, rhs: Weight) -> Self::Output { - rhs * self - } + fn mul(self, rhs: Weight) -> Self::Output { rhs * self } } impl Div for Amount { type Output = FeeRate; - fn div(self, rhs: Weight) -> Self::Output { - FeeRate(self.to_sat() * 1000 / rhs.to_wu()) - } + fn div(self, rhs: Weight) -> Self::Output { FeeRate(self.to_sat() * 1000 / rhs.to_wu()) } } crate::parse::impl_parse_str_from_int_infallible!(FeeRate, u64, from_sat_per_kwu); #[cfg(test)] mod tests { - use super::*; use std::u64; + use super::*; + #[test] fn fee_rate_const_test() { assert_eq!(0, FeeRate::ZERO.to_sat_per_kwu()); @@ -171,9 +152,7 @@ mod tests { #[test] #[should_panic] - fn from_sat_per_vb_unchecked_panic_test() { - FeeRate::from_sat_per_vb_unchecked(u64::MAX); - } + fn from_sat_per_vb_unchecked_panic_test() { FeeRate::from_sat_per_vb_unchecked(u64::MAX); } #[test] fn raw_feerate_test() { diff --git a/bitcoin/src/blockdata/locktime/absolute.rs b/bitcoin/src/blockdata/locktime/absolute.rs index 1f2fad50..53546093 100644 --- a/bitcoin/src/blockdata/locktime/absolute.rs +++ b/bitcoin/src/blockdata/locktime/absolute.rs @@ -7,24 +7,22 @@ //! whether `LockTime < LOCKTIME_THRESHOLD`. //! -use core::{mem, fmt}; -use core::cmp::{PartialOrd, Ordering}; +use core::cmp::{Ordering, PartialOrd}; +use core::{fmt, mem}; use bitcoin_internals::write_err; - #[cfg(all(test, mutate))] use mutagen::mutate; +#[cfg(doc)] +use crate::absolute; use crate::consensus::encode::{self, Decodable, Encodable}; use crate::error::ParseIntError; use crate::io::{self, Read, Write}; -use crate::parse::{impl_parse_str_from_int_infallible, impl_parse_str_from_int_fallible}; +use crate::parse::{impl_parse_str_from_int_fallible, impl_parse_str_from_int_infallible}; use crate::prelude::*; use crate::string::FromHexStr; -#[cfg(doc)] -use crate::absolute; - /// The Threshold for deciding whether a lock time value is a height or a time (see [Bitcoin Core]). /// /// `LockTime` values _below_ the threshold are interpreted as block heights, values _above_ (or @@ -173,9 +171,7 @@ impl LockTime { /// Returns true if this lock time value is a block time (UNIX timestamp). #[inline] - pub fn is_block_time(&self) -> bool { - !self.is_block_height() - } + pub fn is_block_time(&self) -> bool { !self.is_block_height() } /// Returns true if this timelock constraint is satisfied by the respective `height`/`time`. /// @@ -278,16 +274,12 @@ impl_parse_str_from_int_infallible!(LockTime, u32, from_consensus); impl From for LockTime { #[inline] - fn from(h: Height) -> Self { - LockTime::Blocks(h) - } + fn from(h: Height) -> Self { LockTime::Blocks(h) } } impl From