X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fser.rs;h=77ee33c4fa099de78ef6bac9f7c1cfd210586f73;hb=8eb44bfaaf343478c51cce55a57f01f9f82b6791;hp=349105266e0aecaf7d4958c63dbe3f4f87103ae1;hpb=2d4bf974e5b588ce93cc8f1e133cda30ca1d91ee;p=rust-lightning diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index 34910526..77ee33c4 100644 --- a/lightning/src/util/ser.rs +++ b/lightning/src/util/ser.rs @@ -38,6 +38,8 @@ use bitcoin::hash_types::{Txid, BlockHash}; use core::marker::Sized; use core::time::Duration; use crate::ln::msgs::DecodeError; +#[cfg(taproot)] +use crate::ln::msgs::PartialSignatureWithNonce; use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret}; use crate::util::byte_utils::{be48_to_array, slice_to_be48}; @@ -574,6 +576,7 @@ impl_array!(16); // for IPv6 impl_array!(32); // for channel id & hmac impl_array!(PUBLIC_KEY_SIZE); // for PublicKey impl_array!(64); // for ecdsa::Signature and schnorr::Signature +impl_array!(66); // for MuSig2 nonces impl_array!(1300); // for OnionPacket.hop_data impl Writeable for [u16; 8] { @@ -593,7 +596,7 @@ impl Readable for [u16; 8] { r.read_exact(&mut buf)?; let mut res = [0u16; 8]; for (idx, v) in res.iter_mut().enumerate() { - *v = (buf[idx] as u16) << 8 | (buf[idx + 1] as u16) + *v = (buf[idx*2] as u16) << 8 | (buf[idx*2 + 1] as u16) } Ok(res) } @@ -746,7 +749,7 @@ where T: Readable + Eq + Hash } // Vectors -macro_rules! impl_for_vec { +macro_rules! impl_writeable_for_vec { ($ty: ty $(, $name: ident)*) => { impl<$($name : Writeable),*> Writeable for Vec<$ty> { #[inline] @@ -758,7 +761,10 @@ macro_rules! impl_for_vec { Ok(()) } } - + } +} +macro_rules! impl_readable_for_vec { + ($ty: ty $(, $name: ident)*) => { impl<$($name : Readable),*> Readable for Vec<$ty> { #[inline] fn read(r: &mut R) -> Result { @@ -774,6 +780,12 @@ macro_rules! impl_for_vec { } } } +macro_rules! impl_for_vec { + ($ty: ty $(, $name: ident)*) => { + impl_writeable_for_vec!($ty $(, $name)*); + impl_readable_for_vec!($ty $(, $name)*); + } +} impl Writeable for Vec { #[inline] @@ -802,6 +814,8 @@ impl Readable for Vec { impl_for_vec!(ecdsa::Signature); impl_for_vec!(crate::ln::channelmanager::MonitorUpdateCompletionAction); impl_for_vec!((A, B), A, B); +impl_writeable_for_vec!(&crate::routing::router::BlindedTail); +impl_readable_for_vec!(crate::routing::router::BlindedTail); impl Writeable for Script { fn write(&self, w: &mut W) -> Result<(), io::Error> { @@ -861,6 +875,39 @@ impl Readable for SecretKey { } } +#[cfg(taproot)] +impl Writeable for musig2::types::PublicNonce { + fn write(&self, w: &mut W) -> Result<(), io::Error> { + self.serialize().write(w) + } +} + +#[cfg(taproot)] +impl Readable for musig2::types::PublicNonce { + fn read(r: &mut R) -> Result { + let buf: [u8; PUBLIC_KEY_SIZE * 2] = Readable::read(r)?; + musig2::types::PublicNonce::from_slice(&buf).map_err(|_| DecodeError::InvalidValue) + } +} + +#[cfg(taproot)] +impl Writeable for PartialSignatureWithNonce { + fn write(&self, w: &mut W) -> Result<(), io::Error> { + self.0.serialize().write(w)?; + self.1.write(w) + } +} + +#[cfg(taproot)] +impl Readable for PartialSignatureWithNonce { + fn read(r: &mut R) -> Result { + let partial_signature_buf: [u8; SECRET_KEY_SIZE] = Readable::read(r)?; + let partial_signature = musig2::types::PartialSignature::from_slice(&partial_signature_buf).map_err(|_| DecodeError::InvalidValue)?; + let public_nonce: musig2::types::PublicNonce = Readable::read(r)?; + Ok(PartialSignatureWithNonce(partial_signature, public_nonce)) + } +} + impl Writeable for Sha256dHash { fn write(&self, w: &mut W) -> Result<(), io::Error> { w.write_all(&self[..]) @@ -1251,6 +1298,7 @@ impl Readable for Duration { #[cfg(test)] mod tests { use core::convert::TryFrom; + use bitcoin::secp256k1::ecdsa; use crate::util::ser::{Readable, Hostname, Writeable}; #[test] @@ -1273,11 +1321,22 @@ mod tests { assert_eq!(Hostname::read(&mut buf.as_slice()).unwrap().as_str(), "test"); } + #[test] + /// Taproot will likely fill legacy signature fields with all 0s. + /// This test ensures that doing so won't break serialization. + fn null_signature_codec() { + let buffer = vec![0u8; 64]; + let mut cursor = crate::io::Cursor::new(buffer.clone()); + let signature = ecdsa::Signature::read(&mut cursor).unwrap(); + let serialization = signature.serialize_compact(); + assert_eq!(buffer, serialization.to_vec()) + } + #[test] fn bigsize_encoding_decoding() { let values = vec![0, 252, 253, 65535, 65536, 4294967295, 4294967296, 18446744073709551615]; let bytes = vec![ - "00", + "00", "fc", "fd00fd", "fdffff", @@ -1286,7 +1345,7 @@ mod tests { "ff0000000100000000", "ffffffffffffffffff" ]; - for i in 0..=7 { + for i in 0..=7 { let mut stream = crate::io::Cursor::new(::hex::decode(bytes[i]).unwrap()); assert_eq!(super::BigSize::read(&mut stream).unwrap().0, values[i]); let mut stream = super::VecWriter(Vec::new());