use crate::io::{self, Read, Seek, Write};
use crate::io_extras::{copy, sink};
use core::hash::Hash;
-use crate::sync::Mutex;
+use crate::sync::{Mutex, RwLock};
use core::cmp;
use core::convert::TryFrom;
use core::ops::Deref;
use bitcoin::hash_types::{Txid, BlockHash};
use core::marker::Sized;
use core::time::Duration;
+use crate::chain::ClaimId;
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};
+use crate::util::string::UntrustedString;
/// serialization buffer size
pub const MAX_BUF_SIZE: usize = 64 * 1024;
/// Writes `self` out to a `Vec<u8>`.
fn encode(&self) -> Vec<u8> {
- let mut msg = VecWriter(Vec::new());
+ let len = self.serialized_length();
+ let mut msg = VecWriter(Vec::with_capacity(len));
self.write(&mut msg).unwrap();
+ // Note that objects with interior mutability may change size between when we called
+ // serialized_length and when we called write. That's okay, but shouldn't happen during
+ // testing as most of our tests are not threaded.
+ #[cfg(test)]
+ debug_assert_eq!(len, msg.0.len());
msg.0
}
0u16.write(&mut msg).unwrap();
self.write(&mut msg).unwrap();
let len = msg.0.len();
+ debug_assert_eq!(len - 2, self.serialized_length());
msg.0[..2].copy_from_slice(&(len as u16 - 2).to_be_bytes());
msg.0
}
/// encoded in several different ways, which we must check for at deserialization-time. Thus, if
/// you're looking for an example of a variable-length integer to use for your own project, move
/// along, this is a rather poor design.
+#[derive(Clone, Copy, Debug, Hash, PartialOrd, Ord, PartialEq, Eq)]
pub struct BigSize(pub u64);
impl Writeable for BigSize {
#[inline]
}
}
-// u8 arrays
macro_rules! impl_array {
- ( $size:expr ) => (
- impl Writeable for [u8; $size]
- {
+ ($size:expr, $ty: ty) => (
+ impl Writeable for [$ty; $size] {
#[inline]
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
- w.write_all(self)
+ let mut out = [0; $size * core::mem::size_of::<$ty>()];
+ for (idx, v) in self.iter().enumerate() {
+ let startpos = idx * core::mem::size_of::<$ty>();
+ out[startpos..startpos + core::mem::size_of::<$ty>()].copy_from_slice(&v.to_be_bytes());
+ }
+ w.write_all(&out)
}
}
- impl Readable for [u8; $size]
- {
+ impl Readable for [$ty; $size] {
#[inline]
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
- let mut buf = [0u8; $size];
+ let mut buf = [0u8; $size * core::mem::size_of::<$ty>()];
r.read_exact(&mut buf)?;
- Ok(buf)
+ let mut res = [0; $size];
+ for (idx, v) in res.iter_mut().enumerate() {
+ let startpos = idx * core::mem::size_of::<$ty>();
+ let mut arr = [0; core::mem::size_of::<$ty>()];
+ arr.copy_from_slice(&buf[startpos..startpos + core::mem::size_of::<$ty>()]);
+ *v = <$ty>::from_be_bytes(arr);
+ }
+ Ok(res)
}
}
);
}
-impl_array!(3); // for rgb, ISO 4712 code
-impl_array!(4); // for IPv4
-impl_array!(12); // for OnionV2
-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] {
- #[inline]
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
- for v in self.iter() {
- w.write_all(&v.to_be_bytes())?
- }
- Ok(())
- }
-}
+impl_array!(3, u8); // for rgb, ISO 4712 code
+impl_array!(4, u8); // for IPv4
+impl_array!(12, u8); // for OnionV2
+impl_array!(16, u8); // for IPv6
+impl_array!(32, u8); // for channel id & hmac
+impl_array!(PUBLIC_KEY_SIZE, u8); // for PublicKey
+impl_array!(64, u8); // for ecdsa::Signature and schnorr::Signature
+impl_array!(66, u8); // for MuSig2 nonces
+impl_array!(1300, u8); // for OnionPacket.hop_data
-impl Readable for [u16; 8] {
- #[inline]
- fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
- let mut buf = [0u8; 16];
- r.read_exact(&mut buf)?;
- let mut res = [0u16; 8];
- for (idx, v) in res.iter_mut().enumerate() {
- *v = (buf[idx*2] as u16) << 8 | (buf[idx*2 + 1] as u16)
- }
- Ok(res)
- }
-}
+impl_array!(8, u16);
+impl_array!(32, u16);
/// A type for variable-length values within TLV record where the length is encoded as part of the record.
/// Used to prevent encoding the length twice.
fn from(s: &'a String) -> Self { Self(s) }
}
+
+impl Writeable for WithoutLength<&UntrustedString> {
+ #[inline]
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+ WithoutLength(&self.0.0).write(w)
+ }
+}
+impl Readable for WithoutLength<UntrustedString> {
+ #[inline]
+ fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+ let s: WithoutLength<String> = Readable::read(r)?;
+ Ok(Self(UntrustedString(s.0)))
+ }
+}
+
impl<'a, T: Writeable> Writeable for WithoutLength<&'a Vec<T>> {
#[inline]
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
}
impl_for_vec!(ecdsa::Signature);
+impl_for_vec!(crate::chain::channelmonitor::ChannelMonitorUpdate);
impl_for_vec!(crate::ln::channelmanager::MonitorUpdateCompletionAction);
impl_for_vec!((A, B), A, B);
impl_writeable_for_vec!(&crate::routing::router::BlindedTail);
}
}
+impl<T: Readable> Readable for RwLock<T> {
+ fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+ let t: T = Readable::read(r)?;
+ Ok(RwLock::new(t))
+ }
+}
+impl<T: Writeable> Writeable for RwLock<T> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+ self.read().unwrap().write(w)
+ }
+}
+
impl<A: Readable, B: Readable> Readable for (A, B) {
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
let a: A = Readable::read(r)?;
/// This serialization is used by [`BOLT 7`] hostnames.
///
/// [`BOLT 7`]: https://github.com/lightning/bolts/blob/master/07-routing-gossip.md
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct Hostname(String);
impl Hostname {
/// Returns the length of the hostname.
(&self.0).len() as u8
}
}
+
+impl core::fmt::Display for Hostname {
+ fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
+ write!(f, "{}", self.0)?;
+ Ok(())
+ }
+}
impl Deref for Hostname {
type Target = String;
}
}
+/// This is not exported to bindings users as `Duration`s are simply mapped as ints.
impl Writeable for Duration {
#[inline]
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
self.subsec_nanos().write(w)
}
}
+/// This is not exported to bindings users as `Duration`s are simply mapped as ints.
impl Readable for Duration {
#[inline]
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
/// if the `Transaction`'s consensus-serialized length is <= u16::MAX.
///
/// Use [`TransactionU16LenLimited::into_transaction`] to convert into the contained `Transaction`.
-#[derive(Clone, Debug, PartialEq, Eq)]
+#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct TransactionU16LenLimited(Transaction);
impl TransactionU16LenLimited {
}
}
+impl Writeable for ClaimId {
+ fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+ self.0.write(writer)
+ }
+}
+
+impl Readable for ClaimId {
+ fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ Ok(Self(Readable::read(reader)?))
+ }
+}
+
#[cfg(test)]
mod tests {
use core::convert::TryFrom;