X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Futil%2Fser.rs;h=366e6c8cb1efaef3767b0e8d4232c3763915eb20;hb=a5ecb851716bc0819586894232653ec4b5e2c67f;hp=349105266e0aecaf7d4958c63dbe3f4f87103ae1;hpb=2223e92ac6b1ef0b11ac7448ed35f5d0adf77aaa;p=rust-lightning diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index 34910526..366e6c8c 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] { @@ -861,6 +864,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 +1287,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 +1310,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 +1334,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());