From 99dd7e7903ffdb13a3cc90fbee778a20f2a53768 Mon Sep 17 00:00:00 2001 From: Arik Sosman Date: Mon, 12 Aug 2024 11:52:12 -0700 Subject: [PATCH] Fixes + BufReader experimentation. --- lightning/src/lib.rs | 24 +++++++++++ lightning/src/ln/msgs.rs | 8 ++-- lightning/src/offers/invoice.rs | 8 ++-- lightning/src/util/ser.rs | 70 ++++++++++++++++++++++++++++---- lightning/src/util/test_utils.rs | 4 +- 5 files changed, 96 insertions(+), 18 deletions(-) diff --git a/lightning/src/lib.rs b/lightning/src/lib.rs index 7cc540af3..431fee5a0 100644 --- a/lightning/src/lib.rs +++ b/lightning/src/lib.rs @@ -155,6 +155,30 @@ pub mod io { Current(i64), } + /// Adaptor to chain together two readers. + /// + /// This struct is generally created by calling [`chain`] on a reader. + /// Please see the documentation of [`chain`] for more details. + /// + /// [`chain`]: Read::chain + pub struct Chain { + first: T, + second: U, + done_first: bool, + } + + impl Read for Chain { + fn read(&mut self, buf: &mut [u8]) -> Result { + if !self.done_first { + match self.first.read(buf)? { + 0 if !buf.is_empty() => self.done_first = true, + n => return Ok(n), + } + } + self.second.read(buf) + } + } + /// Emulation of std::io::Cursor #[derive(Clone, Debug, Default, Eq, PartialEq)] pub struct Cursor { diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index d1fdb2e20..3d606f4b9 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -3958,11 +3958,11 @@ mod tests { output: vec![ TxOut { value: Amount::from_sat(12704566), - script_pubkey: Address::from_str("bc1qzlffunw52jav8vwdu5x3jfk6sr8u22rmq3xzw2").unwrap().payload().script_pubkey(), + script_pubkey: Address::from_str("bc1qzlffunw52jav8vwdu5x3jfk6sr8u22rmq3xzw2").unwrap().assume_checked().script_pubkey(), }, TxOut { value: Amount::from_sat(245148), - script_pubkey: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().payload().script_pubkey(), + script_pubkey: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().assume_checked().script_pubkey(), }, ], }).unwrap(), @@ -3981,7 +3981,7 @@ mod tests { channel_id: ChannelId::from_bytes([2; 32]), serial_id: 4886718345, sats: 4886718345, - script: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().payload().script_pubkey(), + script: Address::from_str("bc1qxmk834g5marzm227dgqvynd23y2nvt2ztwcw2z").unwrap().assume_checked().script_pubkey(), }; let encoded_value = tx_add_output.encode(); let target_value = >::from_hex("0202020202020202020202020202020202020202020202020202020202020202000000012345678900000001234567890016001436ec78d514df462da95e6a00c24daa8915362d42").unwrap(); @@ -4130,7 +4130,7 @@ mod tests { scriptpubkey: if script_type == 1 { Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey() } else if script_type == 2 { Address::p2sh(&script, Network::Testnet).unwrap().script_pubkey() } - else if script_type == 3 { Address::p2wpkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).unwrap().script_pubkey() } + else if script_type == 3 { Address::p2wpkh(&::bitcoin::CompressedPublicKey(pubkey_1), Network::Testnet).script_pubkey() } else { Address::p2wsh(&script, Network::Testnet).script_pubkey() }, }; let encoded_value = shutdown.encode(); diff --git a/lightning/src/offers/invoice.rs b/lightning/src/offers/invoice.rs index 6077043b4..df8acec95 100644 --- a/lightning/src/offers/invoice.rs +++ b/lightning/src/offers/invoice.rs @@ -1934,7 +1934,7 @@ mod tests { invoice.fallbacks(), vec![ Address::p2wsh(&script, Network::Bitcoin), - Address::p2wpkh(&pubkey, Network::Bitcoin).unwrap(), + Address::p2wpkh(&CompressedPublicKey(pubkey.inner), Network::Bitcoin), Address::p2tr_tweaked(tweaked_pubkey, Network::Bitcoin), ], ); @@ -2248,10 +2248,10 @@ mod tests { invoice.fallbacks(), vec![ Address::p2wsh(&script, Network::Bitcoin), - Address::p2wpkh(&CompressedPublicKey(pubkey.inner), Network::Bitcoin).unwrap(), + Address::p2wpkh(&CompressedPublicKey(pubkey.inner), Network::Bitcoin), Address::p2tr_tweaked(tweaked_pubkey, Network::Bitcoin), - Address::from_witness_program(v1_witness_program, Network::Bitcoin.into()), - Address::from_witness_program(v2_witness_program, Network::Bitcoin.into()), + Address::from_witness_program(v1_witness_program, Network::Bitcoin), + Address::from_witness_program(v2_witness_program, Network::Bitcoin), ], ); }, diff --git a/lightning/src/util/ser.rs b/lightning/src/util/ser.rs index 83c80e804..35baf71e5 100644 --- a/lightning/src/util/ser.rs +++ b/lightning/src/util/ser.rs @@ -64,24 +64,78 @@ impl Writer for W { } } -pub(crate) struct ReadBufReadAdapter(pub R); +// pub(crate) struct ReadBufReadAdapter(pub R); +pub struct BufReader { + inner: R, + buf: [u8; S], + pos: usize, + cap: usize, +} + +impl BufReader { + pub fn new(inner: R) -> BufReader { + BufReader { + inner, + buf: [0; S], + pos: 0, + cap: 0, + } + } +} -impl Read for ReadBufReadAdapter { +impl Read for BufReader { fn read(&mut self, buf: &mut [u8]) -> io::Result { - self.0.read(buf) + // If we don't have any buffered data and we're doing a massive read + // (larger than our internal buffer), bypass our internal buffer + // entirely. + if self.pos == self.cap && buf.len() >= S { + self.discard_buffer(); + return self.inner.read(buf); + } + let nread = { + let mut rem = self.fill_buf()?; + rem.read(buf)? + }; + self.consume(nread); + Ok(nread) } } -impl BufRead for ReadBufReadAdapter { +impl BufRead for BufReader { fn fill_buf(&mut self) -> io::Result<&[u8]> { - todo!() + // If we've reached the end of our internal buffer then we need to fetch + // some more data from the underlying reader. + // Branch using `>=` instead of the more correct `==` + // to tell the compiler that the pos..cap slice is always valid. + if self.pos >= self.cap { + debug_assert!(self.pos == self.cap); + self.cap = self.inner.read(&mut self.buf)?; + self.pos = 0; + } + Ok(&self.buf[self.pos..self.cap]) } - fn consume(&mut self, amount: usize) { - todo!() + fn consume(&mut self, amt: usize) { + self.pos = cmp::min(self.pos + amt, self.cap); } } +// impl Read for ReadBufReadAdapter { +// fn read(&mut self, buf: &mut [u8]) -> io::Result { +// self.0.read(buf) +// } +// } +// +// impl BufRead for ReadBufReadAdapter { +// fn fill_buf(&mut self) -> io::Result<&[u8]> { +// todo!() +// } +// +// fn consume(&mut self, amount: usize) { +// todo!() +// } +// } + pub(crate) struct WriterWriteAdaptor<'a, W: Writer + 'a>(pub &'a mut W); impl<'a, W: Writer + 'a> Write for WriterWriteAdaptor<'a, W> { #[inline] @@ -1290,7 +1344,7 @@ macro_rules! impl_consensus_ser { impl Readable for $bitcoin_type { fn read(r: &mut R) -> Result { - match consensus::encode::Decodable::consensus_decode(&mut ReadBufReadAdapter(r)) { + match consensus::encode::Decodable::consensus_decode(&mut BufReader::new(r)) { Ok(t) => Ok(t), Err(consensus::encode::Error::Io(ref e)) if e.kind() == io::ErrorKind::UnexpectedEof => Err(DecodeError::ShortRead), Err(consensus::encode::Error::Io(e)) => Err(DecodeError::Io(e.kind().into())), diff --git a/lightning/src/util/test_utils.rs b/lightning/src/util/test_utils.rs index 74a7f769d..91e659009 100644 --- a/lightning/src/util/test_utils.rs +++ b/lightning/src/util/test_utils.rs @@ -1591,8 +1591,8 @@ impl WalletSource for TestWalletSource { let sighash = SighashCache::new(&tx) .legacy_signature_hash(i, &utxo.output.script_pubkey, EcdsaSighashType::All as u32) .map_err(|_| ())?; - let sig = self.secp.sign_ecdsa(&secp256k1::Message::from_digest(sighash.to_byte_array()), &self.secret_key); - let bitcoin_sig = bitcoin::ecdsa::Signature { sig, hash_ty: EcdsaSighashType::All }; + let signature = self.secp.sign_ecdsa(&secp256k1::Message::from_digest(sighash.to_byte_array()), &self.secret_key); + let bitcoin_sig = bitcoin::ecdsa::Signature { signature, sighash_type: EcdsaSighashType::All }; tx.input[i].script_sig = Builder::new() .push_slice(&bitcoin_sig.serialize()) .push_slice(&self.secret_key.public_key(&self.secp).serialize()) -- 2.39.5