X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchannel.rs;h=08faea160bb193a0d652a03211d4d2039942f500;hb=c7ddcd3867757c74d8a3a2997604edf52aa0a536;hp=10b6b28b7737b7851b0667f1c6508cbbf23af07b;hpb=caa16e0fb549db56e432f84cc902cf1835a8e360;p=rust-lightning diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index 10b6b28b..08faea16 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -33,7 +33,7 @@ use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitor use chain::transaction::{OutPoint, TransactionData}; use chain::keysinterface::{ChannelKeys, KeysInterface}; use util::transaction_utils; -use util::ser::{Readable, Writeable, Writer}; +use util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter}; use util::logger::Logger; use util::errors::APIError; use util::config::{UserConfig,ChannelConfig}; @@ -4055,7 +4055,7 @@ impl Readable for InboundHTLCRemovalReason { } } -impl Writeable for Channel { +impl Writeable for Channel { fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { // Note that we write out as if remove_uncommitted_htlcs_and_mark_paused had just been // called but include holding cell updates (and obviously we don't modify self). @@ -4072,7 +4072,13 @@ impl Writeable for Channel { self.latest_monitor_update_id.write(writer)?; - self.holder_keys.write(writer)?; + let mut key_data = VecWriter(Vec::new()); + self.holder_keys.write(&mut key_data)?; + assert!(key_data.0.len() < std::usize::MAX); + assert!(key_data.0.len() < std::u32::MAX as usize); + (key_data.0.len() as u32).write(writer)?; + writer.write_all(&key_data.0[..])?; + self.shutdown_pubkey.write(writer)?; self.destination_script.write(writer)?; @@ -4237,8 +4243,10 @@ impl Writeable for Channel { } } -impl Readable for Channel { - fn read(reader: &mut R) -> Result { +const MAX_ALLOC_SIZE: usize = 64*1024; +impl<'a, ChanSigner: ChannelKeys, K: Deref> ReadableArgs<&'a K> for Channel + where K::Target: KeysInterface { + fn read(reader: &mut R, keys_source: &'a K) -> Result { let _ver: u8 = Readable::read(reader)?; let min_ver: u8 = Readable::read(reader)?; if min_ver > SERIALIZATION_VERSION { @@ -4254,7 +4262,17 @@ impl Readable for Channel { let latest_monitor_update_id = Readable::read(reader)?; - let holder_keys = Readable::read(reader)?; + let keys_len: u32 = Readable::read(reader)?; + let mut keys_data = Vec::with_capacity(cmp::min(keys_len as usize, MAX_ALLOC_SIZE)); + while keys_data.len() != keys_len as usize { + // Read 1KB at a time to avoid accidentally allocating 4GB on corrupted channel keys + let mut data = [0; 1024]; + let read_slice = &mut data[0..cmp::min(1024, keys_len as usize - keys_data.len())]; + reader.read_exact(read_slice)?; + keys_data.extend_from_slice(read_slice); + } + let holder_keys = keys_source.read_chan_signer(&keys_data)?; + let shutdown_pubkey = Readable::read(reader)?; let destination_script = Readable::read(reader)?; @@ -4472,7 +4490,7 @@ mod tests { use ln::channel::{Channel,ChannelKeys,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,TxCreationKeys}; use ln::channel::MAX_FUNDING_SATOSHIS; use ln::features::InitFeatures; - use ln::msgs::{OptionalField, DataLossProtect}; + use ln::msgs::{OptionalField, DataLossProtect, DecodeError}; use ln::chan_utils; use ln::chan_utils::{ChannelPublicKeys, HolderCommitmentTransaction, CounterpartyChannelTransactionParameters}; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; @@ -4528,6 +4546,7 @@ mod tests { self.chan_keys.clone() } fn get_secure_random_bytes(&self) -> [u8; 32] { [0; 32] } + fn read_chan_signer(&self, _data: &[u8]) -> Result { panic!(); } } fn public_from_secret_hex(secp_ctx: &Secp256k1, hex: &str) -> PublicKey { @@ -4723,15 +4742,13 @@ mod tests { &chan.holder_keys.pubkeys().funding_pubkey, chan.counterparty_funding_pubkey() ); - let holder_sig = chan_keys.sign_holder_commitment(&holder_commitment_tx, &secp_ctx).unwrap(); + let (holder_sig, htlc_sigs) = chan_keys.sign_holder_commitment_and_htlcs(&holder_commitment_tx, &secp_ctx).unwrap(); assert_eq!(Signature::from_der(&hex::decode($sig_hex).unwrap()[..]).unwrap(), holder_sig, "holder_sig"); let funding_redeemscript = chan.get_funding_redeemscript(); let tx = holder_commitment_tx.add_holder_sig(&funding_redeemscript, holder_sig); assert_eq!(serialize(&tx)[..], hex::decode($tx_hex).unwrap()[..], "tx"); - let htlc_sigs = chan_keys.sign_holder_commitment_htlc_transactions(&holder_commitment_tx, &secp_ctx).unwrap(); - // ((htlc, counterparty_sig), (index, holder_sig)) let mut htlc_sig_iter = holder_commitment_tx.htlcs().iter().zip(&holder_commitment_tx.counterparty_htlc_sigs).zip(htlc_sigs.iter().enumerate());