use std::{hash,cmp, mem};
use std::ops::Deref;
+/// An update generated by the underlying Channel itself which contains some new information the
+/// ChannelMonitor should be made aware of.
+#[cfg_attr(test, derive(PartialEq))]
+#[derive(Clone)]
+#[must_use]
+pub struct ChannelMonitorUpdate {
+ pub(super) updates: Vec<ChannelMonitorUpdateStep>,
+ /// The sequence number of this update. Updates *must* be replayed in-order according to this
+ /// sequence number (and updates may panic if they are not). The update_id values are strictly
+ /// increasing and increase by one for each new update.
+ ///
+ /// This sequence number is also used to track up to which points updates which returned
+ /// ChannelMonitorUpdateErr::TemporaryFailure have been applied to all copies of a given
+ /// ChannelMonitor when ChannelManager::channel_monitor_updated is called.
+ pub update_id: u64,
+}
+
+impl Writeable for ChannelMonitorUpdate {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ self.update_id.write(w)?;
+ (self.updates.len() as u64).write(w)?;
+ for update_step in self.updates.iter() {
+ update_step.write(w)?;
+ }
+ Ok(())
+ }
+}
+impl<R: ::std::io::Read> Readable<R> for ChannelMonitorUpdate {
+ fn read(r: &mut R) -> Result<Self, DecodeError> {
+ let update_id: u64 = Readable::read(r)?;
+ let len: u64 = Readable::read(r)?;
+ let mut updates = Vec::with_capacity(cmp::min(len as usize, MAX_ALLOC_SIZE / ::std::mem::size_of::<ChannelMonitorUpdateStep>()));
+ for _ in 0..len {
+ updates.push(Readable::read(r)?);
+ }
+ Ok(Self { update_id, updates })
+ }
+}
+
/// An error enum representing a failure to persist a channel monitor update.
#[derive(Clone)]
pub enum ChannelMonitorUpdateErr {
/// our state failed, but is expected to succeed at some point in the future).
///
/// Such a failure will "freeze" a channel, preventing us from revoking old states or
- /// submitting new commitment transactions to the remote party.
- /// ChannelManager::test_restore_channel_monitor can be used to retry the update(s) and restore
- /// the channel to an operational state.
+ /// submitting new commitment transactions to the remote party. Once the update(s) which failed
+ /// have been successfully applied, ChannelManager::channel_monitor_updated can be used to
+ /// restore the channel to an operational state.
///
- /// Note that continuing to operate when no copy of the updated ChannelMonitor could be
- /// persisted is unsafe - if you failed to store the update on your own local disk you should
- /// instead return PermanentFailure to force closure of the channel ASAP.
+ /// Note that a given ChannelManager will *never* re-generate a given ChannelMonitorUpdate. If
+ /// you return a TemporaryFailure you must ensure that it is written to disk safely before
+ /// writing out the latest ChannelManager state.
///
/// Even when a channel has been "frozen" updates to the ChannelMonitor can continue to occur
/// (eg if an inbound HTLC which we forwarded was claimed upstream resulting in us attempting
/// been "frozen".
///
/// Note that even if updates made after TemporaryFailure succeed you must still call
- /// test_restore_channel_monitor to ensure you have the latest monitor and re-enable normal
- /// channel operation.
+ /// channel_monitor_updated to ensure you have the latest monitor and re-enable normal channel
+ /// operation.
+ ///
+ /// Note that the update being processed here will not be replayed for you when you call
+ /// ChannelManager::channel_monitor_updated, so you must store the update itself along
+ /// with the persisted ChannelMonitor on your own local disk prior to returning a
+ /// TemporaryFailure. You may, of course, employ a journaling approach, storing only the
+ /// ChannelMonitorUpdate on disk without updating the monitor itself, replaying the journal at
+ /// reload-time.
///
/// For deployments where a copy of ChannelMonitors and other local state are backed up in a
/// remote location (with local copies persisted immediately), it is anticipated that all
/// any spends of any of the outputs.
///
/// Any spends of outputs which should have been registered which aren't passed to
- /// ChannelMonitors via block_connected may result in funds loss.
+ /// ChannelMonitors via block_connected may result in FUNDS LOSS.
fn add_update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr>;
+ /// Updates a monitor for the given `funding_txo`.
+ ///
+ /// Implementer must also ensure that the funding_txo txid *and* outpoint are registered with
+ /// any relevant ChainWatchInterfaces such that the provided monitor receives block_connected
+ /// callbacks with the funding transaction, or any spends of it.
+ ///
+ /// Further, the implementer must also ensure that each output returned in
+ /// monitor.get_watch_outputs() is registered to ensure that the provided monitor learns about
+ /// any spends of any of the outputs.
+ ///
+ /// Any spends of outputs which should have been registered which aren't passed to
+ /// ChannelMonitors via block_connected may result in FUNDS LOSS.
+ fn update_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr>;
+
/// Used by ChannelManager to get list of HTLC resolved onchain and which needed to be updated
/// with success or failure.
///
monitors.insert(key, monitor);
Ok(())
}
+
+ /// Updates the monitor which monitors the channel referred to by the given key.
+ pub fn update_monitor_by_key(&self, key: Key, update: ChannelMonitorUpdate) -> Result<(), MonitorUpdateError> {
+ let mut monitors = self.monitors.lock().unwrap();
+ match monitors.get_mut(&key) {
+ Some(orig_monitor) => {
+ log_trace!(self, "Updating Channel Monitor for channel {}", log_funding_info!(orig_monitor.key_storage));
+ orig_monitor.update_monitor(update)
+ },
+ None => Err(MonitorUpdateError("No such monitor registered"))
+ }
+ }
}
impl<ChanSigner: ChannelKeys, T: Deref + Sync + Send> ManyChannelMonitor<ChanSigner> for SimpleManyChannelMonitor<OutPoint, ChanSigner, T>
}
}
+ fn update_monitor(&self, funding_txo: OutPoint, update: ChannelMonitorUpdate) -> Result<(), ChannelMonitorUpdateErr> {
+ match self.update_monitor_by_key(funding_txo, update) {
+ Ok(_) => Ok(()),
+ Err(_) => Err(ChannelMonitorUpdateErr::PermanentFailure),
+ }
+ }
+
fn get_and_clear_pending_htlcs_updated(&self) -> Vec<HTLCUpdate> {
let mut pending_htlcs_updated = Vec::new();
for chan in self.monitors.lock().unwrap().values_mut() {
const SERIALIZATION_VERSION: u8 = 1;
const MIN_SERIALIZATION_VERSION: u8 = 1;
+#[cfg_attr(test, derive(PartialEq))]
+#[derive(Clone)]
+pub(super) enum ChannelMonitorUpdateStep {
+ LatestLocalCommitmentTXInfo {
+ // TODO: We really need to not be generating a fully-signed transaction in Channel and
+ // passing it here, we need to hold off so that the ChanSigner can enforce a
+ // only-sign-local-state-for-broadcast once invariant:
+ commitment_tx: LocalCommitmentTransaction,
+ local_keys: chan_utils::TxCreationKeys,
+ feerate_per_kw: u64,
+ htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>,
+ },
+ LatestRemoteCommitmentTXInfo {
+ unsigned_commitment_tx: Transaction, // TODO: We should actually only need the txid here
+ htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>,
+ commitment_number: u64,
+ their_revocation_point: PublicKey,
+ },
+ PaymentPreimage {
+ payment_preimage: PaymentPreimage,
+ },
+ CommitmentSecret {
+ idx: u64,
+ secret: [u8; 32],
+ },
+}
+
+impl Writeable for ChannelMonitorUpdateStep {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ match self {
+ &ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { ref commitment_tx, ref local_keys, ref feerate_per_kw, ref htlc_outputs } => {
+ 0u8.write(w)?;
+ commitment_tx.write(w)?;
+ local_keys.write(w)?;
+ feerate_per_kw.write(w)?;
+ (htlc_outputs.len() as u64).write(w)?;
+ for &(ref output, ref signature, ref source) in htlc_outputs.iter() {
+ output.write(w)?;
+ signature.write(w)?;
+ source.write(w)?;
+ }
+ }
+ &ChannelMonitorUpdateStep::LatestRemoteCommitmentTXInfo { ref unsigned_commitment_tx, ref htlc_outputs, ref commitment_number, ref their_revocation_point } => {
+ 1u8.write(w)?;
+ unsigned_commitment_tx.write(w)?;
+ commitment_number.write(w)?;
+ their_revocation_point.write(w)?;
+ (htlc_outputs.len() as u64).write(w)?;
+ for &(ref output, ref source) in htlc_outputs.iter() {
+ output.write(w)?;
+ match source {
+ &None => 0u8.write(w)?,
+ &Some(ref s) => {
+ 1u8.write(w)?;
+ s.write(w)?;
+ },
+ }
+ }
+ },
+ &ChannelMonitorUpdateStep::PaymentPreimage { ref payment_preimage } => {
+ 2u8.write(w)?;
+ payment_preimage.write(w)?;
+ },
+ &ChannelMonitorUpdateStep::CommitmentSecret { ref idx, ref secret } => {
+ 3u8.write(w)?;
+ idx.write(w)?;
+ secret.write(w)?;
+ },
+ }
+ Ok(())
+ }
+}
+impl<R: ::std::io::Read> Readable<R> for ChannelMonitorUpdateStep {
+ fn read(r: &mut R) -> Result<Self, DecodeError> {
+ match Readable::read(r)? {
+ 0u8 => {
+ Ok(ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo {
+ commitment_tx: Readable::read(r)?,
+ local_keys: Readable::read(r)?,
+ feerate_per_kw: Readable::read(r)?,
+ htlc_outputs: {
+ let len: u64 = Readable::read(r)?;
+ let mut res = Vec::new();
+ for _ in 0..len {
+ res.push((Readable::read(r)?, Readable::read(r)?, Readable::read(r)?));
+ }
+ res
+ },
+ })
+ },
+ 1u8 => {
+ Ok(ChannelMonitorUpdateStep::LatestRemoteCommitmentTXInfo {
+ unsigned_commitment_tx: Readable::read(r)?,
+ commitment_number: Readable::read(r)?,
+ their_revocation_point: Readable::read(r)?,
+ htlc_outputs: {
+ let len: u64 = Readable::read(r)?;
+ let mut res = Vec::new();
+ for _ in 0..len {
+ res.push((Readable::read(r)?, <Option<HTLCSource> as Readable<R>>::read(r)?.map(|o| Box::new(o))));
+ }
+ res
+ },
+ })
+ },
+ 2u8 => {
+ Ok(ChannelMonitorUpdateStep::PaymentPreimage {
+ payment_preimage: Readable::read(r)?,
+ })
+ },
+ 3u8 => {
+ Ok(ChannelMonitorUpdateStep::CommitmentSecret {
+ idx: Readable::read(r)?,
+ secret: Readable::read(r)?,
+ })
+ },
+ _ => Err(DecodeError::InvalidValue),
+ }
+ }
+}
+
/// A ChannelMonitor handles chain events (blocks connected and disconnected) and generates
/// on-chain transactions to ensure no loss of funds occurs.
///
/// information and are actively monitoring the chain.
#[derive(Clone)]
pub struct ChannelMonitor<ChanSigner: ChannelKeys> {
+ latest_update_id: u64,
commitment_transaction_number_obscure_factor: u64,
key_storage: Storage<ChanSigner>,
/// underlying object
impl<ChanSigner: ChannelKeys> PartialEq for ChannelMonitor<ChanSigner> {
fn eq(&self, other: &Self) -> bool {
- if self.commitment_transaction_number_obscure_factor != other.commitment_transaction_number_obscure_factor ||
+ if self.latest_update_id != other.latest_update_id ||
+ self.commitment_transaction_number_obscure_factor != other.commitment_transaction_number_obscure_factor ||
self.key_storage != other.key_storage ||
self.their_htlc_base_key != other.their_htlc_base_key ||
self.their_delayed_payment_base_key != other.their_delayed_payment_base_key ||
writer.write_all(&[SERIALIZATION_VERSION; 1])?;
writer.write_all(&[MIN_SERIALIZATION_VERSION; 1])?;
+ self.latest_update_id.write(writer)?;
+
// Set in initial Channel-object creation, so should always be set by now:
U48(self.commitment_transaction_number_obscure_factor).write(writer)?;
impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
pub(super) fn new(keys: ChanSigner, funding_key: &SecretKey, revocation_base_key: &SecretKey, delayed_payment_base_key: &SecretKey, htlc_base_key: &SecretKey, payment_base_key: &SecretKey, shutdown_pubkey: &PublicKey, our_to_self_delay: u16, destination_script: Script, logger: Arc<Logger>) -> ChannelMonitor<ChanSigner> {
ChannelMonitor {
+ latest_update_id: 0,
commitment_transaction_number_obscure_factor: 0,
key_storage: Storage::Local {
/// is important that any clones of this channel monitor (including remote clones) by kept
/// up-to-date as our local commitment transaction is updated.
/// Panics if set_their_to_self_delay has never been called.
- pub(super) fn provide_latest_local_commitment_tx_info(&mut self, commitment_tx: LocalCommitmentTransaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) {
- assert!(self.their_to_self_delay.is_some());
+ pub(super) fn provide_latest_local_commitment_tx_info(&mut self, commitment_tx: LocalCommitmentTransaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), MonitorUpdateError> {
+ if self.their_to_self_delay.is_none() {
+ return Err(MonitorUpdateError("Got a local commitment tx info update before we'd set basic information about the channel"));
+ }
self.prev_local_signed_commitment_tx = self.current_local_signed_commitment_tx.take();
self.current_local_signed_commitment_tx = Some(LocalSignedTx {
txid: commitment_tx.txid(),
feerate_per_kw,
htlc_outputs,
});
+ Ok(())
}
/// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all
self.payment_preimages.insert(payment_hash.clone(), payment_preimage.clone());
}
+ /// Used in Channel to cheat wrt the update_ids since it plays games, will be removed soon!
+ pub(super) fn update_monitor_ooo(&mut self, mut updates: ChannelMonitorUpdate) -> Result<(), MonitorUpdateError> {
+ for update in updates.updates.drain(..) {
+ match update {
+ ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx, local_keys, feerate_per_kw, htlc_outputs } =>
+ self.provide_latest_local_commitment_tx_info(commitment_tx, local_keys, feerate_per_kw, htlc_outputs)?,
+ ChannelMonitorUpdateStep::LatestRemoteCommitmentTXInfo { unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point } =>
+ self.provide_latest_remote_commitment_tx_info(&unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point),
+ ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } =>
+ self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage),
+ ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } =>
+ self.provide_secret(idx, secret)?
+ }
+ }
+ self.latest_update_id = updates.update_id;
+ Ok(())
+ }
+
+ /// Updates a ChannelMonitor on the basis of some new information provided by the Channel
+ /// itself.
+ ///
+ /// panics if the given update is not the next update by update_id.
+ pub fn update_monitor(&mut self, mut updates: ChannelMonitorUpdate) -> Result<(), MonitorUpdateError> {
+ if self.latest_update_id + 1 != updates.update_id {
+ panic!("Attempted to apply ChannelMonitorUpdates out of order, check the update_id before passing an update to update_monitor!");
+ }
+ for update in updates.updates.drain(..) {
+ match update {
+ ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx, local_keys, feerate_per_kw, htlc_outputs } =>
+ self.provide_latest_local_commitment_tx_info(commitment_tx, local_keys, feerate_per_kw, htlc_outputs)?,
+ ChannelMonitorUpdateStep::LatestRemoteCommitmentTXInfo { unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point } =>
+ self.provide_latest_remote_commitment_tx_info(&unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point),
+ ChannelMonitorUpdateStep::PaymentPreimage { payment_preimage } =>
+ self.provide_payment_preimage(&PaymentHash(Sha256::hash(&payment_preimage.0[..]).into_inner()), &payment_preimage),
+ ChannelMonitorUpdateStep::CommitmentSecret { idx, secret } =>
+ self.provide_secret(idx, secret)?
+ }
+ }
+ self.latest_update_id = updates.update_id;
+ Ok(())
+ }
+
/// Combines this ChannelMonitor with the information contained in the other ChannelMonitor.
/// After a successful call this ChannelMonitor is up-to-date and is safe to use to monitor the
/// chain for new blocks/transactions.
/// Allows this monitor to scan only for transactions which are applicable. Note that this is
/// optional, without it this monitor cannot be used in an SPV client, but you may wish to
- /// avoid this (or call unset_funding_info) on a monitor you wish to send to a watchtower as it
- /// provides slightly better privacy.
+ /// avoid this on a monitor you wish to send to a watchtower as it provides slightly better
+ /// privacy.
/// It's the responsibility of the caller to register outpoint and script with passing the former
/// value as key to add_update_monitor.
pub(super) fn set_funding_info(&mut self, new_funding_info: (OutPoint, Script)) {
self.commitment_transaction_number_obscure_factor = commitment_transaction_number_obscure_factor;
}
- pub(super) fn unset_funding_info(&mut self) {
- match self.key_storage {
- Storage::Local { ref mut funding_info, .. } => {
- *funding_info = None;
- },
- Storage::Watchtower { .. } => {
- panic!("Channel somehow ended up with its internal ChannelMonitor being in Watchtower mode?");
- },
- }
+ /// Gets the update_id from the latest ChannelMonitorUpdate which was applied to this
+ /// ChannelMonitor.
+ pub fn get_latest_update_id(&self) -> u64 {
+ self.latest_update_id
}
/// Gets the funding transaction outpoint of the channel this ChannelMonitor is monitoring for.
return Err(DecodeError::UnknownVersion);
}
+ let latest_update_id: u64 = Readable::read(reader)?;
let commitment_transaction_number_obscure_factor = <U48 as Readable<R>>::read(reader)?.0;
let key_storage = match <u8 as Readable<R>>::read(reader)? {
}
Ok((last_block_hash.clone(), ChannelMonitor {
+ latest_update_id,
commitment_transaction_number_obscure_factor,
key_storage,
let mut monitor = ChannelMonitor::new(keys, &SecretKey::from_slice(&[41; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
monitor.their_to_self_delay = Some(10);
- monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..10]));
+ monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..10])).unwrap();
monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key);
monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[15..20]), 281474976710654, dummy_key);
monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key);
// Now update local commitment tx info, pruning only element 18 as we still care about the
// previous commitment tx's preimages too
- monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..5]));
+ monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..5])).unwrap();
secret[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
monitor.provide_secret(281474976710653, secret.clone()).unwrap();
assert_eq!(monitor.payment_preimages.len(), 12);
test_preimages_exist!(&preimages[18..20], monitor);
// But if we do it again, we'll prune 5-10
- monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..3]));
+ monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..3])).unwrap();
secret[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
monitor.provide_secret(281474976710652, secret.clone()).unwrap();
assert_eq!(monitor.payment_preimages.len(), 5);