diff --git a/fuzz/src/chanmon_consistency.rs b/fuzz/src/chanmon_consistency.rs index 18652d22120..dc811c3ba86 100644 --- a/fuzz/src/chanmon_consistency.rs +++ b/fuzz/src/chanmon_consistency.rs @@ -73,52 +73,55 @@ impl Writer for VecWriter { } } -static mut IN_RESTORE: bool = false; pub struct TestChannelMonitor { + pub logger: Arc, pub simple_monitor: Arc>>, pub update_ret: Mutex>, - pub latest_good_update: Mutex>>, - pub latest_update_good: Mutex>, - pub latest_updates_good_at_last_ser: Mutex>, + // If we reload a node with an old copy of ChannelMonitors, the ChannelManager deserialization + // logic will automatically force-close our channels for us (as we don't have an up-to-date + // monitor implying we are not able to punish misbehaving counterparties). Because this test + // "fails" if we ever force-close a channel, we avoid doing so, always saving the latest + // fully-serialized monitor state here, as well as the corresponding update_id. + pub latest_monitors: Mutex)>>, pub should_update_manager: atomic::AtomicBool, } impl TestChannelMonitor { pub fn new(chain_monitor: Arc, broadcaster: Arc, logger: Arc, feeest: Arc) -> Self { Self { - simple_monitor: Arc::new(channelmonitor::SimpleManyChannelMonitor::new(chain_monitor, broadcaster, logger, feeest)), + simple_monitor: Arc::new(channelmonitor::SimpleManyChannelMonitor::new(chain_monitor, broadcaster, logger.clone(), feeest)), + logger, update_ret: Mutex::new(Ok(())), - latest_good_update: Mutex::new(HashMap::new()), - latest_update_good: Mutex::new(HashMap::new()), - latest_updates_good_at_last_ser: Mutex::new(HashMap::new()), + latest_monitors: Mutex::new(HashMap::new()), should_update_manager: atomic::AtomicBool::new(false), } } } impl channelmonitor::ManyChannelMonitor for TestChannelMonitor { - fn add_update_monitor(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { - let ret = self.update_ret.lock().unwrap().clone(); - if let Ok(()) = ret { - let mut ser = VecWriter(Vec::new()); - monitor.write_for_disk(&mut ser).unwrap(); - self.latest_good_update.lock().unwrap().insert(funding_txo, ser.0); - match self.latest_update_good.lock().unwrap().entry(funding_txo) { - hash_map::Entry::Vacant(e) => { e.insert(true); }, - hash_map::Entry::Occupied(mut e) => { - if !e.get() && unsafe { IN_RESTORE } { - // Technically we can't consider an update to be "good" unless we're doing - // it in response to a test_restore_channel_monitor as the channel may - // still be waiting on such a call, so only set us to good if we're in the - // middle of a restore call. - e.insert(true); - } - }, - } - self.should_update_manager.store(true, atomic::Ordering::Relaxed); - } else { - self.latest_update_good.lock().unwrap().insert(funding_txo, false); + fn add_monitor(&self, funding_txo: OutPoint, monitor: channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { + let mut ser = VecWriter(Vec::new()); + monitor.write_for_disk(&mut ser).unwrap(); + if let Some(_) = self.latest_monitors.lock().unwrap().insert(funding_txo, (monitor.get_latest_update_id(), ser.0)) { + panic!("Already had monitor pre-add_monitor"); } - assert!(self.simple_monitor.add_update_monitor(funding_txo, monitor).is_ok()); - ret + self.should_update_manager.store(true, atomic::Ordering::Relaxed); + assert!(self.simple_monitor.add_monitor(funding_txo, monitor).is_ok()); + self.update_ret.lock().unwrap().clone() + } + + fn update_monitor(&self, funding_txo: OutPoint, update: channelmonitor::ChannelMonitorUpdate) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> { + let mut map_lock = self.latest_monitors.lock().unwrap(); + let mut map_entry = match map_lock.entry(funding_txo) { + hash_map::Entry::Occupied(entry) => entry, + hash_map::Entry::Vacant(_) => panic!("Didn't have monitor on update call"), + }; + let mut deserialized_monitor = <(Sha256d, channelmonitor::ChannelMonitor)>:: + read(&mut Cursor::new(&map_entry.get().1), Arc::clone(&self.logger)).unwrap().1; + deserialized_monitor.update_monitor(update.clone()).unwrap(); + let mut ser = VecWriter(Vec::new()); + deserialized_monitor.write_for_disk(&mut ser).unwrap(); + map_entry.insert((update.update_id, ser.0)); + self.should_update_manager.store(true, atomic::Ordering::Relaxed); + self.update_ret.lock().unwrap().clone() } fn get_and_clear_pending_htlcs_updated(&self) -> Vec { @@ -210,10 +213,10 @@ pub fn do_test(data: &[u8]) { config.peer_channel_config_limits.min_dust_limit_satoshis = 0; let mut monitors = HashMap::new(); - let mut old_monitors = $old_monitors.latest_good_update.lock().unwrap(); - for (outpoint, monitor_ser) in old_monitors.drain() { + let mut old_monitors = $old_monitors.latest_monitors.lock().unwrap(); + for (outpoint, (update_id, monitor_ser)) in old_monitors.drain() { monitors.insert(outpoint, <(Sha256d, ChannelMonitor)>::read(&mut Cursor::new(&monitor_ser), Arc::clone(&logger)).expect("Failed to read monitor").1); - monitor.latest_good_update.lock().unwrap().insert(outpoint, monitor_ser); + monitor.latest_monitors.lock().unwrap().insert(outpoint, (update_id, monitor_ser)); } let mut monitor_refs = HashMap::new(); for (outpoint, monitor) in monitors.iter_mut() { @@ -230,17 +233,7 @@ pub fn do_test(data: &[u8]) { channel_monitors: &mut monitor_refs, }; - let res = (<(Sha256d, ChannelManager, Arc>)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor); - for (_, was_good) in $old_monitors.latest_updates_good_at_last_ser.lock().unwrap().iter() { - if !was_good { - // If the last time we updated a monitor we didn't successfully update (and we - // have sense updated our serialized copy of the ChannelManager) we may - // force-close the channel on our counterparty cause we know we're missing - // something. Thus, we just return here since we can't continue to test. - return; - } - } - res + (<(Sha256d, ChannelManager, Arc>)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor) } } } @@ -266,6 +259,7 @@ pub fn do_test(data: &[u8]) { }; $source.handle_accept_channel(&$dest.get_our_node_id(), InitFeatures::supported(), &accept_channel); + let funding_output; { let events = $source.get_and_clear_pending_events(); assert_eq!(events.len(), 1); @@ -273,7 +267,7 @@ pub fn do_test(data: &[u8]) { let tx = Transaction { version: $chan_id, lock_time: 0, input: Vec::new(), output: vec![TxOut { value: *channel_value_satoshis, script_pubkey: output_script.clone(), }]}; - let funding_output = OutPoint::new(tx.txid(), 0); + funding_output = OutPoint::new(tx.txid(), 0); $source.funding_transaction_generated(&temporary_channel_id, funding_output); channel_txn.push(tx); } else { panic!("Wrong event type"); } @@ -303,6 +297,7 @@ pub fn do_test(data: &[u8]) { if let events::Event::FundingBroadcastSafe { .. } = events[0] { } else { panic!("Wrong event type"); } } + funding_output } } } @@ -359,8 +354,8 @@ pub fn do_test(data: &[u8]) { let mut nodes = [node_a, node_b, node_c]; - make_channel!(nodes[0], nodes[1], 0); - make_channel!(nodes[1], nodes[2], 1); + let chan_1_funding = make_channel!(nodes[0], nodes[1], 0); + let chan_2_funding = make_channel!(nodes[1], nodes[2], 1); for node in nodes.iter() { confirm_txn!(node); @@ -631,9 +626,26 @@ pub fn do_test(data: &[u8]) { 0x03 => *monitor_a.update_ret.lock().unwrap() = Ok(()), 0x04 => *monitor_b.update_ret.lock().unwrap() = Ok(()), 0x05 => *monitor_c.update_ret.lock().unwrap() = Ok(()), - 0x06 => { unsafe { IN_RESTORE = true }; nodes[0].test_restore_channel_monitor(); unsafe { IN_RESTORE = false }; }, - 0x07 => { unsafe { IN_RESTORE = true }; nodes[1].test_restore_channel_monitor(); unsafe { IN_RESTORE = false }; }, - 0x08 => { unsafe { IN_RESTORE = true }; nodes[2].test_restore_channel_monitor(); unsafe { IN_RESTORE = false }; }, + 0x06 => { + if let Some((id, _)) = monitor_a.latest_monitors.lock().unwrap().get(&chan_1_funding) { + nodes[0].channel_monitor_updated(&chan_1_funding, *id); + } + }, + 0x07 => { + if let Some((id, _)) = monitor_b.latest_monitors.lock().unwrap().get(&chan_1_funding) { + nodes[1].channel_monitor_updated(&chan_1_funding, *id); + } + }, + 0x24 => { + if let Some((id, _)) = monitor_b.latest_monitors.lock().unwrap().get(&chan_2_funding) { + nodes[1].channel_monitor_updated(&chan_2_funding, *id); + } + }, + 0x08 => { + if let Some((id, _)) = monitor_c.latest_monitors.lock().unwrap().get(&chan_2_funding) { + nodes[2].channel_monitor_updated(&chan_2_funding, *id); + } + }, 0x09 => send_payment!(nodes[0], (&nodes[1], chan_a)), 0x0a => send_payment!(nodes[1], (&nodes[0], chan_a)), 0x0b => send_payment!(nodes[1], (&nodes[2], chan_b)), @@ -722,27 +734,19 @@ pub fn do_test(data: &[u8]) { nodes[2] = node_c.clone(); monitor_c = new_monitor_c; }, + // 0x24 defined above _ => test_return!(), } - if monitor_a.should_update_manager.load(atomic::Ordering::Relaxed) { - node_a_ser.0.clear(); - nodes[0].write(&mut node_a_ser).unwrap(); - monitor_a.should_update_manager.store(false, atomic::Ordering::Relaxed); - *monitor_a.latest_updates_good_at_last_ser.lock().unwrap() = monitor_a.latest_update_good.lock().unwrap().clone(); - } - if monitor_b.should_update_manager.load(atomic::Ordering::Relaxed) { - node_b_ser.0.clear(); - nodes[1].write(&mut node_b_ser).unwrap(); - monitor_b.should_update_manager.store(false, atomic::Ordering::Relaxed); - *monitor_b.latest_updates_good_at_last_ser.lock().unwrap() = monitor_b.latest_update_good.lock().unwrap().clone(); - } - if monitor_c.should_update_manager.load(atomic::Ordering::Relaxed) { - node_c_ser.0.clear(); - nodes[2].write(&mut node_c_ser).unwrap(); - monitor_c.should_update_manager.store(false, atomic::Ordering::Relaxed); - *monitor_c.latest_updates_good_at_last_ser.lock().unwrap() = monitor_c.latest_update_good.lock().unwrap().clone(); - } + node_a_ser.0.clear(); + nodes[0].write(&mut node_a_ser).unwrap(); + monitor_a.should_update_manager.store(false, atomic::Ordering::Relaxed); + node_b_ser.0.clear(); + nodes[1].write(&mut node_b_ser).unwrap(); + monitor_b.should_update_manager.store(false, atomic::Ordering::Relaxed); + node_c_ser.0.clear(); + nodes[2].write(&mut node_c_ser).unwrap(); + monitor_c.should_update_manager.store(false, atomic::Ordering::Relaxed); } } diff --git a/lightning/src/chain/keysinterface.rs b/lightning/src/chain/keysinterface.rs index 158f71dba28..e2e4403b528 100644 --- a/lightning/src/chain/keysinterface.rs +++ b/lightning/src/chain/keysinterface.rs @@ -135,7 +135,8 @@ pub trait KeysInterface: Send + Sync { /// (TODO: We shouldn't require that, and should have an API to get them at deser time, due mostly /// to the possibility of reentrancy issues by calling the user's code during our deserialization /// routine). -/// TODO: remove Clone once we start returning ChannelUpdate objects instead of copying ChannelMonitor +/// TODO: We should remove Clone by instead requesting a new ChannelKeys copy when we create +/// ChannelMonitors instead of expecting to clone the one out of the Channel into the monitors. pub trait ChannelKeys : Send+Clone { /// Gets the private key for the anchor tx fn funding_key<'a>(&'a self) -> &'a SecretKey; diff --git a/lightning/src/chain/transaction.rs b/lightning/src/chain/transaction.rs index ce43984ebd4..0f479ff91ab 100644 --- a/lightning/src/chain/transaction.rs +++ b/lightning/src/chain/transaction.rs @@ -39,6 +39,8 @@ impl OutPoint { } } +impl_writeable!(OutPoint, 0, { txid, index }); + #[cfg(test)] mod tests { use chain::transaction::OutPoint; diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index e7bea90914e..3fd489fa1a9 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -17,6 +17,7 @@ use bitcoin_hashes::sha256d::Hash as Sha256dHash; use ln::channelmanager::{PaymentHash, PaymentPreimage}; use ln::msgs::DecodeError; use util::ser::{Readable, Writeable, Writer, WriterWriteAdaptor}; +use util::byte_utils; use secp256k1::key::{SecretKey, PublicKey}; use secp256k1::{Secp256k1, Signature}; @@ -59,6 +60,114 @@ pub(super) fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [ res } +/// Implements the per-commitment secret storage scheme from +/// [BOLT 3](https://github.com/lightningnetwork/lightning-rfc/blob/dcbf8583976df087c79c3ce0b535311212e6812d/03-transactions.md#efficient-per-commitment-secret-storage). +/// +/// Allows us to keep track of all of the revocation secrets of counterarties in just 50*32 bytes +/// or so. +#[derive(Clone)] +pub(super) struct CounterpartyCommitmentSecrets { + old_secrets: [([u8; 32], u64); 49], +} + +impl PartialEq for CounterpartyCommitmentSecrets { + fn eq(&self, other: &Self) -> bool { + for (&(ref secret, ref idx), &(ref o_secret, ref o_idx)) in self.old_secrets.iter().zip(other.old_secrets.iter()) { + if secret != o_secret || idx != o_idx { + return false + } + } + true + } +} + +impl CounterpartyCommitmentSecrets { + pub(super) fn new() -> Self { + Self { old_secrets: [([0; 32], 1 << 48); 49], } + } + + #[inline] + fn place_secret(idx: u64) -> u8 { + for i in 0..48 { + if idx & (1 << i) == (1 << i) { + return i + } + } + 48 + } + + pub(super) fn get_min_seen_secret(&self) -> u64 { + //TODO This can be optimized? + let mut min = 1 << 48; + for &(_, idx) in self.old_secrets.iter() { + if idx < min { + min = idx; + } + } + min + } + + #[inline] + pub(super) fn derive_secret(secret: [u8; 32], bits: u8, idx: u64) -> [u8; 32] { + let mut res: [u8; 32] = secret; + for i in 0..bits { + let bitpos = bits - 1 - i; + if idx & (1 << bitpos) == (1 << bitpos) { + res[(bitpos / 8) as usize] ^= 1 << (bitpos & 7); + res = Sha256::hash(&res).into_inner(); + } + } + res + } + + pub(super) fn provide_secret(&mut self, idx: u64, secret: [u8; 32]) -> Result<(), ()> { + let pos = Self::place_secret(idx); + for i in 0..pos { + let (old_secret, old_idx) = self.old_secrets[i as usize]; + if Self::derive_secret(secret, pos, old_idx) != old_secret { + return Err(()); + } + } + if self.get_min_seen_secret() <= idx { + return Ok(()); + } + self.old_secrets[pos as usize] = (secret, idx); + Ok(()) + } + + /// Can only fail if idx is < get_min_seen_secret + pub(super) fn get_secret(&self, idx: u64) -> Option<[u8; 32]> { + for i in 0..self.old_secrets.len() { + if (idx & (!((1 << i) - 1))) == self.old_secrets[i].1 { + return Some(Self::derive_secret(self.old_secrets[i].0, i as u8, idx)) + } + } + assert!(idx < self.get_min_seen_secret()); + None + } +} + +impl Writeable for CounterpartyCommitmentSecrets { + fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + for &(ref secret, ref idx) in self.old_secrets.iter() { + writer.write_all(secret)?; + writer.write_all(&byte_utils::be64_to_array(*idx))?; + } + Ok(()) + } +} +impl Readable for CounterpartyCommitmentSecrets { + fn read(reader: &mut R) -> Result { + let mut old_secrets = [([0; 32], 1 << 48); 49]; + for &mut (ref mut secret, ref mut idx) in old_secrets.iter_mut() { + *secret = Readable::read(reader)?; + *idx = Readable::read(reader)?; + } + + Ok(Self { old_secrets }) + } +} + /// Derives a per-commitment-transaction private key (eg an htlc key or payment key) from the base /// private key for that type of key and the per_commitment_point (available in TxCreationKeys) pub fn derive_private_key(secp_ctx: &Secp256k1, per_commitment_point: &PublicKey, base_secret: &SecretKey) -> Result { @@ -137,7 +246,7 @@ pub(super) fn derive_public_revocation_key(secp_ctx: /// The set of public keys which are used in the creation of one commitment transaction. /// These are derived from the channel base keys and per-commitment data. -#[derive(PartialEq)] +#[derive(PartialEq, Clone)] pub struct TxCreationKeys { /// The per-commitment public key which was used to derive the other keys. pub per_commitment_point: PublicKey, @@ -153,6 +262,8 @@ pub struct TxCreationKeys { /// B's Payment Key pub(crate) b_payment_key: PublicKey, } +impl_writeable!(TxCreationKeys, 33*6, + { per_commitment_point, revocation_key, a_htlc_key, b_htlc_key, a_delayed_payment_key, b_payment_key }); /// One counterparty's public keys which do not change over the life of a channel. #[derive(Clone, PartialEq)] @@ -235,6 +346,14 @@ pub struct HTLCOutputInCommitment { pub transaction_output_index: Option, } +impl_writeable!(HTLCOutputInCommitment, 1 + 8 + 4 + 32 + 5, { + offered, + amount_msat, + cltv_expiry, + payment_hash, + transaction_output_index +}); + #[inline] pub(super) fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, a_htlc_key: &PublicKey, b_htlc_key: &PublicKey, revocation_key: &PublicKey) -> Script { let payment_hash160 = Ripemd160::hash(&htlc.payment_hash.0[..]).into_inner(); @@ -505,3 +624,354 @@ impl Readable for LocalCommitmentTransaction { Ok(Self { tx }) } } + +#[cfg(test)] +mod tests { + use super::CounterpartyCommitmentSecrets; + use hex; + + #[test] + fn test_per_commitment_storage() { + // Test vectors from BOLT 3: + let mut secrets: Vec<[u8; 32]> = Vec::new(); + let mut monitor; + + macro_rules! test_secrets { + () => { + let mut idx = 281474976710655; + for secret in secrets.iter() { + assert_eq!(monitor.get_secret(idx).unwrap(), *secret); + idx -= 1; + } + assert_eq!(monitor.get_min_seen_secret(), idx + 1); + assert!(monitor.get_secret(idx).is_none()); + }; + } + + { + // insert_secret correct sequence + monitor = CounterpartyCommitmentSecrets::new(); + secrets.clear(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd").unwrap()); + monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap()); + monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32").unwrap()); + monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17").unwrap()); + monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + } + + { + // insert_secret #1 incorrect + monitor = CounterpartyCommitmentSecrets::new(); + secrets.clear(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap()); + monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + assert!(monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).is_err()); + } + + { + // insert_secret #2 incorrect (#1 derived from incorrect) + monitor = CounterpartyCommitmentSecrets::new(); + secrets.clear(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap()); + monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3").unwrap()); + monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + assert!(monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).is_err()); + } + + { + // insert_secret #3 incorrect + monitor = CounterpartyCommitmentSecrets::new(); + secrets.clear(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a").unwrap()); + monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + assert!(monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).is_err()); + } + + { + // insert_secret #4 incorrect (1,2,3 derived from incorrect) + monitor = CounterpartyCommitmentSecrets::new(); + secrets.clear(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("02a40c85b6f28da08dfdbe0926c53fab2de6d28c10301f8f7c4073d5e42e3148").unwrap()); + monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("dddc3a8d14fddf2b68fa8c7fbad2748274937479dd0f8930d5ebb4ab6bd866a3").unwrap()); + monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c51a18b13e8527e579ec56365482c62f180b7d5760b46e9477dae59e87ed423a").unwrap()); + monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("ba65d7b0ef55a3ba300d4e87af29868f394f8f138d78a7011669c79b37b936f4").unwrap()); + monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd").unwrap()); + monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap()); + monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32").unwrap()); + monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17").unwrap()); + assert!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).is_err()); + } + + { + // insert_secret #5 incorrect + monitor = CounterpartyCommitmentSecrets::new(); + secrets.clear(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("631373ad5f9ef654bb3dade742d09504c567edd24320d2fcd68e3cc47e2ff6a6").unwrap()); + monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap()); + assert!(monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).is_err()); + } + + { + // insert_secret #6 incorrect (5 derived from incorrect) + monitor = CounterpartyCommitmentSecrets::new(); + secrets.clear(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("631373ad5f9ef654bb3dade742d09504c567edd24320d2fcd68e3cc47e2ff6a6").unwrap()); + monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("b7e76a83668bde38b373970155c868a653304308f9896692f904a23731224bb1").unwrap()); + monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32").unwrap()); + monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17").unwrap()); + assert!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).is_err()); + } + + { + // insert_secret #7 incorrect + monitor = CounterpartyCommitmentSecrets::new(); + secrets.clear(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd").unwrap()); + monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap()); + monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("e7971de736e01da8ed58b94c2fc216cb1dca9e326f3a96e7194fe8ea8af6c0a3").unwrap()); + monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("05cde6323d949933f7f7b78776bcc1ea6d9b31447732e3802e1f7ac44b650e17").unwrap()); + assert!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).is_err()); + } + + { + // insert_secret #8 incorrect + monitor = CounterpartyCommitmentSecrets::new(); + secrets.clear(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("7cc854b54e3e0dcdb010d7a3fee464a9687be6e8db3be6854c475621e007a5dc").unwrap()); + monitor.provide_secret(281474976710655, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c7518c8ae4660ed02894df8976fa1a3659c1a8b4b5bec0c4b872abeba4cb8964").unwrap()); + monitor.provide_secret(281474976710654, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap()); + monitor.provide_secret(281474976710653, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap()); + monitor.provide_secret(281474976710652, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("c65716add7aa98ba7acb236352d665cab17345fe45b55fb879ff80e6bd0c41dd").unwrap()); + monitor.provide_secret(281474976710651, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("969660042a28f32d9be17344e09374b379962d03db1574df5a8a5a47e19ce3f2").unwrap()); + monitor.provide_secret(281474976710650, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("a5a64476122ca0925fb344bdc1854c1c0a59fc614298e50a33e331980a220f32").unwrap()); + monitor.provide_secret(281474976710649, secrets.last().unwrap().clone()).unwrap(); + test_secrets!(); + + secrets.push([0; 32]); + secrets.last_mut().unwrap()[0..32].clone_from_slice(&hex::decode("a7efbc61aac46d34f77778bac22c8a20c6a46ca460addc49009bda875ec88fa4").unwrap()); + assert!(monitor.provide_secret(281474976710648, secrets.last().unwrap().clone()).is_err()); + } + } +} diff --git a/lightning/src/ln/chanmon_update_fail_tests.rs b/lightning/src/ln/chanmon_update_fail_tests.rs index 995855427f7..562b21524fb 100644 --- a/lightning/src/ln/chanmon_update_fail_tests.rs +++ b/lightning/src/ln/chanmon_update_fail_tests.rs @@ -3,6 +3,7 @@ //! There are a bunch of these as their handling is relatively error-prone so they are split out //! here. See also the chanmon_fail_consistency fuzz test. +use chain::transaction::OutPoint; use ln::channelmanager::{RAACommitmentOrder, PaymentPreimage, PaymentHash}; use ln::channelmonitor::ChannelMonitorUpdateErr; use ln::features::InitFeatures; @@ -56,7 +57,7 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); + let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).2; let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap(); let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(&nodes[0]); @@ -76,8 +77,9 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) { } *nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[0].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[0], 1); + let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[0].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[0], 0); let mut events_2 = nodes[0].node.get_and_clear_pending_msg_events(); assert_eq!(events_2.len(), 1); @@ -116,10 +118,9 @@ fn do_test_simple_monitor_temporary_update_fail(disconnect: bool) { reconnect_nodes(&nodes[0], &nodes[1], (false, false), (0, 0), (0, 0), (0, 0), (0, 0), (false, false)); } - // ...and make sure we can force-close a TemporaryFailure channel with a PermanentFailure - *nodes[0].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::PermanentFailure); - nodes[0].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[0], 1); + // ...and make sure we can force-close a frozen channel + nodes[0].node.force_close_channel(&channel_id); + check_added_monitors!(nodes[0], 0); check_closed_broadcast!(nodes[0], false); // TODO: Once we hit the chain with the failure transaction we should check that we get a @@ -158,7 +159,7 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); + let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).2; let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); @@ -201,6 +202,7 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { } nodes[0].node.handle_commitment_signed(&nodes[1].node.get_our_node_id(), commitment_signed); + check_added_monitors!(nodes[0], 1); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Previous monitor update failure prevented generation of RAA".to_string(), 1); } @@ -217,8 +219,9 @@ fn do_test_monitor_temporary_update_fail(disconnect_count: usize) { // Now fix monitor updating... *nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[0].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[0], 1); + let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[0].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[0], 0); macro_rules! disconnect_reconnect_peers { () => { { nodes[0].node.peer_disconnected(&nodes[1].node.get_our_node_id(), false); @@ -487,7 +490,7 @@ fn test_monitor_update_fail_cs() { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); + let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).2; let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap(); let (payment_preimage, our_payment_hash) = get_payment_preimage_hash!(nodes[0]); @@ -505,8 +508,9 @@ fn test_monitor_update_fail_cs() { assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[1].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[1], 1); + let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[1], 0); let responses = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(responses.len(), 2); @@ -538,8 +542,9 @@ fn test_monitor_update_fail_cs() { } *nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[0].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[0], 1); + let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[0].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[0], 0); let final_raa = get_event_msg!(nodes[0], MessageSendEvent::SendRevokeAndACK, nodes[1].node.get_our_node_id()); nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &final_raa); @@ -563,13 +568,13 @@ fn test_monitor_update_fail_cs() { #[test] fn test_monitor_update_fail_no_rebroadcast() { // Tests handling of a monitor update failure when no message rebroadcasting on - // test_restore_channel_monitor() is required. Backported from - // chanmon_fail_consistency fuzz tests. + // channel_monitor_updated() is required. Backported from chanmon_fail_consistency + // fuzz tests. let chanmon_cfgs = create_chanmon_cfgs(2); let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); + let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).2; let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap(); let (payment_preimage_1, our_payment_hash) = get_payment_preimage_hash!(nodes[0]); @@ -589,9 +594,10 @@ fn test_monitor_update_fail_no_rebroadcast() { check_added_monitors!(nodes[1], 1); *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[1].node.test_restore_channel_monitor(); + let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&outpoint, latest_update); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); - check_added_monitors!(nodes[1], 1); + check_added_monitors!(nodes[1], 0); expect_pending_htlcs_forwardable!(nodes[1]); let events = nodes[1].node.get_and_clear_pending_events(); @@ -614,7 +620,7 @@ fn test_monitor_update_raa_while_paused() { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); + let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).2; send_payment(&nodes[0], &[&nodes[1]], 5000000, 5_000_000); @@ -648,8 +654,9 @@ fn test_monitor_update_raa_while_paused() { check_added_monitors!(nodes[0], 1); *nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[0].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[0], 1); + let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[0].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[0], 0); let as_update_raa = get_revoke_commit_msgs!(nodes[0], nodes[1].node.get_our_node_id()); nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_update_raa.0); @@ -791,6 +798,7 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { send_event = SendEvent::from_event(nodes[2].node.get_and_clear_pending_msg_events().remove(0)); nodes[1].node.handle_update_add_htlc(&nodes[2].node.get_our_node_id(), &send_event.msgs[0]); nodes[1].node.handle_commitment_signed(&nodes[2].node.get_our_node_id(), &send_event.commitment_msg); + check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Previous monitor update failure prevented generation of RAA".to_string(), 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); @@ -801,8 +809,9 @@ fn do_test_monitor_update_fail_raa(test_ignore_second_cs: bool) { // Restore monitor updating, ensuring we immediately get a fail-back update and a // update_add update. *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[1].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[1], 1); + let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_2.2).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[1], 0); expect_pending_htlcs_forwardable!(nodes[1]); check_added_monitors!(nodes[1], 1); @@ -940,7 +949,7 @@ fn test_monitor_update_fail_reestablish() { let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); + let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::supported(), InitFeatures::supported()); let (our_payment_preimage, _) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 1000000); @@ -991,8 +1000,9 @@ fn test_monitor_update_fail_reestablish() { assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[1].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[1], 1); + let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[1], 0); updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); assert!(updates.update_add_htlcs.is_empty()); @@ -1021,7 +1031,7 @@ fn raa_no_response_awaiting_raa_state() { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); + let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).2; let route = nodes[0].router.get_route(&nodes[1].node.get_our_node_id(), None, &Vec::new(), 1000000, TEST_FINAL_CLTV).unwrap(); let (payment_preimage_1, payment_hash_1) = get_payment_preimage_hash!(nodes[0]); @@ -1072,9 +1082,10 @@ fn raa_no_response_awaiting_raa_state() { check_added_monitors!(nodes[1], 1); *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[1].node.test_restore_channel_monitor(); + let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&outpoint, latest_update); // nodes[1] should be AwaitingRAA here! - check_added_monitors!(nodes[1], 1); + check_added_monitors!(nodes[1], 0); let bs_responses = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); expect_pending_htlcs_forwardable!(nodes[1]); expect_payment_received!(nodes[1], payment_hash_1, 1000000); @@ -1137,7 +1148,7 @@ fn claim_while_disconnected_monitor_update_fail() { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); + let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).2; // Forward a payment for B to claim let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); @@ -1177,16 +1188,18 @@ fn claim_while_disconnected_monitor_update_fail() { let as_updates = get_htlc_update_msgs!(nodes[0], nodes[1].node.get_our_node_id()); nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &as_updates.update_add_htlcs[0]); nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &as_updates.commitment_signed); + check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Previous monitor update failure prevented generation of RAA".to_string(), 1); // Note that nodes[1] not updating monitor here is OK - it wont take action on the new HTLC - // until we've test_restore_channel_monitor'd and updated for the new commitment transaction. + // until we've channel_monitor_update'd and updated for the new commitment transaction. // Now un-fail the monitor, which will result in B sending its original commitment update, // receiving the commitment update from A, and the resulting commitment dances. *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[1].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[1], 1); + let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[1], 0); let bs_msgs = nodes[1].node.get_and_clear_pending_msg_events(); assert_eq!(bs_msgs.len(), 2); @@ -1255,7 +1268,7 @@ fn monitor_failed_no_reestablish_response() { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); + let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).2; // Route the payment and deliver the initial commitment_signed (with a monitor update failure // on receipt). @@ -1289,8 +1302,9 @@ fn monitor_failed_no_reestablish_response() { nodes[0].node.handle_channel_reestablish(&nodes[1].node.get_our_node_id(), &bs_reconnect); *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[1].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[1], 1); + let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[1], 0); let bs_responses = get_revoke_commit_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_revoke_and_ack(&nodes[1].node.get_our_node_id(), &bs_responses.0); @@ -1324,7 +1338,7 @@ fn first_message_on_recv_ordering() { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); + let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).2; // Route the first payment outbound, holding the last RAA for B until we are set up so that we // can deliver it and fail the monitor update. @@ -1370,16 +1384,18 @@ fn first_message_on_recv_ordering() { check_added_monitors!(nodes[1], 1); // Now deliver the update_add_htlc/commitment_signed for the second payment, which does need an - // RAA/CS response, which should be generated when we call test_restore_channel_monitor (with - // the appropriate HTLC acceptance). + // RAA/CS response, which should be generated when we call channel_monitor_update (with the + // appropriate HTLC acceptance). nodes[1].node.handle_update_add_htlc(&nodes[0].node.get_our_node_id(), &payment_event.msgs[0]); nodes[1].node.handle_commitment_signed(&nodes[0].node.get_our_node_id(), &payment_event.commitment_msg); + check_added_monitors!(nodes[1], 1); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Previous monitor update failure prevented generation of RAA".to_string(), 1); *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[1].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[1], 1); + let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[1], 0); expect_pending_htlcs_forwardable!(nodes[1]); expect_payment_received!(nodes[1], payment_hash_1, 1000000); @@ -1430,7 +1446,7 @@ fn test_monitor_update_fail_claim() { check_added_monitors!(nodes[2], 1); // Successfully update the monitor on the 1<->2 channel, but the 0<->1 channel should still be - // paused, so forward shouldn't succeed until we call test_restore_channel_monitor(). + // paused, so forward shouldn't succeed until we call channel_monitor_updated(). *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); let mut events = nodes[2].node.get_and_clear_pending_msg_events(); @@ -1464,8 +1480,9 @@ fn test_monitor_update_fail_claim() { } else { panic!("Unexpected event!"); } // Now restore monitor updating on the 0<->1 channel and claim the funds on B. - nodes[1].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[1], 1); + let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[1], 0); let bs_fulfill_update = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_update_fulfill_htlc(&nodes[1].node.get_our_node_id(), &bs_fulfill_update.update_fulfill_htlcs[0]); @@ -1488,7 +1505,7 @@ fn test_monitor_update_on_pending_forwards() { let node_cfgs = create_node_cfgs(3, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(3, &node_cfgs, &[None, None, None]); let mut nodes = create_network(3, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); + let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); create_announced_chan_between_nodes(&nodes, 1, 2, InitFeatures::supported(), InitFeatures::supported()); // Rebalance a bit so that we can send backwards from 3 to 1. @@ -1522,8 +1539,9 @@ fn test_monitor_update_on_pending_forwards() { nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Failed to update ChannelMonitor".to_string(), 1); *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[1].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[1], 1); + let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&chan_1.2).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[1], 0); let bs_updates = get_htlc_update_msgs!(nodes[1], nodes[0].node.get_our_node_id()); nodes[0].node.handle_update_fail_htlc(&nodes[1].node.get_our_node_id(), &bs_updates.update_fail_htlcs[0]); @@ -1556,7 +1574,7 @@ fn monitor_update_claim_fail_no_response() { let node_cfgs = create_node_cfgs(2, &chanmon_cfgs); let node_chanmgrs = create_node_chanmgrs(2, &node_cfgs, &[None, None]); let mut nodes = create_network(2, &node_cfgs, &node_chanmgrs); - create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()); + let channel_id = create_announced_chan_between_nodes(&nodes, 0, 1, InitFeatures::supported(), InitFeatures::supported()).2; // Forward a payment for B to claim let (payment_preimage_1, _) = route_payment(&nodes[0], &[&nodes[1]], 1000000); @@ -1581,8 +1599,9 @@ fn monitor_update_claim_fail_no_response() { nodes[1].logger.assert_log("lightning::ln::channelmanager".to_string(), "Failed to update ChannelMonitor".to_string(), 1); *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[1].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[1], 1); + let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[1], 0); assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty()); nodes[1].node.handle_revoke_and_ack(&nodes[0].node.get_our_node_id(), &as_raa); @@ -1632,14 +1651,17 @@ fn do_during_funding_monitor_fail(fail_on_generate: bool, restore_between_fails: check_added_monitors!(nodes[0], 1); *nodes[1].chan_monitor.update_ret.lock().unwrap() = Err(ChannelMonitorUpdateErr::TemporaryFailure); - nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id())); + let funding_created_msg = get_event_msg!(nodes[0], MessageSendEvent::SendFundingCreated, nodes[1].node.get_our_node_id()); + let channel_id = OutPoint { txid: funding_created_msg.funding_txid, index: funding_created_msg.funding_output_index }.to_channel_id(); + nodes[1].node.handle_funding_created(&nodes[0].node.get_our_node_id(), &funding_created_msg); check_added_monitors!(nodes[1], 1); if restore_between_fails { assert!(fail_on_generate); *nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[0].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[0], 1); + let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[0].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[0], 0); assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); } @@ -1655,18 +1677,20 @@ fn do_during_funding_monitor_fail(fail_on_generate: bool, restore_between_fails: assert!(nodes[0].node.get_and_clear_pending_msg_events().is_empty()); if fail_on_generate && !restore_between_fails { nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Previous monitor update failure prevented funding_signed from allowing funding broadcast".to_string(), 1); - check_added_monitors!(nodes[0], 0); + check_added_monitors!(nodes[0], 1); } else { nodes[0].logger.assert_log("lightning::ln::channelmanager".to_string(), "Failed to update ChannelMonitor".to_string(), 1); check_added_monitors!(nodes[0], 1); } assert!(nodes[0].node.get_and_clear_pending_events().is_empty()); *nodes[0].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[0].node.test_restore_channel_monitor(); + let (outpoint, latest_update) = nodes[0].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[0].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[0], 0); + } else { + check_added_monitors!(nodes[0], 1); } - check_added_monitors!(nodes[0], 1); - let events = nodes[0].node.get_and_clear_pending_events(); assert_eq!(events.len(), 1); match events[0] { @@ -1700,8 +1724,9 @@ fn do_during_funding_monitor_fail(fail_on_generate: bool, restore_between_fails: } *nodes[1].chan_monitor.update_ret.lock().unwrap() = Ok(()); - nodes[1].node.test_restore_channel_monitor(); - check_added_monitors!(nodes[1], 1); + let (outpoint, latest_update) = nodes[1].chan_monitor.latest_monitor_update_id.lock().unwrap().get(&channel_id).unwrap().clone(); + nodes[1].node.channel_monitor_updated(&outpoint, latest_update); + check_added_monitors!(nodes[1], 0); let (channel_id, (announcement, as_update, bs_update)) = if !confirm_a_first { nodes[0].node.handle_funding_locked(&nodes[1].node.get_our_node_id(), &get_event_msg!(nodes[1], MessageSendEvent::SendFundingLocked, nodes[0].node.get_our_node_id())); diff --git a/lightning/src/ln/channel.rs b/lightning/src/ln/channel.rs index ff2a28b1fc3..c503aaea6c7 100644 --- a/lightning/src/ln/channel.rs +++ b/lightning/src/ln/channel.rs @@ -18,9 +18,9 @@ use secp256k1; use ln::features::{ChannelFeatures, InitFeatures}; use ln::msgs; use ln::msgs::{DecodeError, OptionalField, DataLossProtect}; -use ln::channelmonitor::ChannelMonitor; -use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingForwardHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT}; -use ln::chan_utils::{LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys}; +use ln::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep}; +use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT}; +use ln::chan_utils::{CounterpartyCommitmentSecrets, LocalCommitmentTransaction, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys}; use ln::chan_utils; use chain::chaininterface::{FeeEstimator,ConfirmationTarget}; use chain::transaction::OutPoint; @@ -240,11 +240,14 @@ pub(super) struct Channel { secp_ctx: Secp256k1, channel_value_satoshis: u64, + latest_monitor_update_id: u64, + #[cfg(not(test))] local_keys: ChanSigner, #[cfg(test)] pub(super) local_keys: ChanSigner, shutdown_pubkey: PublicKey, + destination_script: Script, // Our commitment numbers start at 2^48-1 and count down, whereas the ones used in transaction // generation start at 0 and count up...this simplifies some parts of implementation at the @@ -269,7 +272,7 @@ pub(super) struct Channel { monitor_pending_funding_locked: bool, monitor_pending_revoke_and_ack: bool, monitor_pending_commitment_signed: bool, - monitor_pending_forwards: Vec<(PendingForwardHTLCInfo, u64)>, + monitor_pending_forwards: Vec<(PendingHTLCInfo, u64)>, monitor_pending_failures: Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, // pending_update_fee is filled when sending and receiving update_fee @@ -303,6 +306,8 @@ pub(super) struct Channel { last_sent_closing_fee: Option<(u64, u64, Signature)>, // (feerate, fee, our_sig) + funding_txo: Option, + /// The hash of the block in which the funding transaction reached our CONF_TARGET. We use this /// to detect unconfirmation after a serialize-unserialize roundtrip where we may not see a full /// series of block_connected/block_disconnected calls. Obviously this is not a guarantee as we @@ -347,7 +352,10 @@ pub(super) struct Channel { their_shutdown_scriptpubkey: Option