use prelude::*;
use core::{cmp, mem};
-use std::io::Error;
+use io::{self, Error};
use core::ops::Deref;
use sync::Mutex;
pub const CLOSED_CHANNEL_UPDATE_ID: u64 = core::u64::MAX;
impl Writeable for ChannelMonitorUpdate {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
write_ver_prefix!(w, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
self.update_id.write(w)?;
(self.updates.len() as u64).write(w)?;
}
}
impl Readable for ChannelMonitorUpdate {
- fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
+ fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
let _ver = read_ver_prefix!(r, SERIALIZATION_VERSION);
let update_id: u64 = Readable::read(r)?;
let len: u64 = Readable::read(r)?;
}
/// An error enum representing a failure to persist a channel monitor update.
-#[derive(Clone, Debug)]
+#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ChannelMonitorUpdateErr {
/// Used to indicate a temporary failure (eg connection to a watchtower or remote backup of
/// our state failed, but is expected to succeed at some point in the future).
pub struct HTLCUpdate {
pub(crate) payment_hash: PaymentHash,
pub(crate) payment_preimage: Option<PaymentPreimage>,
- pub(crate) source: HTLCSource
+ pub(crate) source: HTLCSource,
+ pub(crate) onchain_value_satoshis: Option<u64>,
}
impl_writeable_tlv_based!(HTLCUpdate, {
(0, payment_hash, required),
+ (1, onchain_value_satoshis, option),
(2, source, required),
(4, payment_preimage, option),
});
}
impl Writeable for CounterpartyCommitmentTransaction {
- fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
w.write_all(&byte_utils::be64_to_array(self.per_htlc.len() as u64))?;
for (ref txid, ref htlcs) in self.per_htlc.iter() {
w.write_all(&txid[..])?;
}
}
impl Readable for CounterpartyCommitmentTransaction {
- fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
+ fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
let counterparty_commitment_transaction = {
let per_htlc_len: u64 = Readable::read(r)?;
let mut per_htlc = HashMap::with_capacity(cmp::min(per_htlc_len as usize, MAX_ALLOC_SIZE / 64));
HTLCUpdate {
source: HTLCSource,
payment_hash: PaymentHash,
+ onchain_value_satoshis: Option<u64>,
},
MaturingOutput {
descriptor: SpendableOutputDescriptor,
impl_writeable_tlv_based_enum!(OnchainEvent,
(0, HTLCUpdate) => {
(0, source, required),
+ (1, onchain_value_satoshis, option),
(2, payment_hash, required),
},
(1, MaturingOutput) => {
event: OnchainEvent::HTLCUpdate {
source: (**source).clone(),
payment_hash: htlc.payment_hash.clone(),
+ onchain_value_satoshis: Some(htlc.amount_msat / 1000),
},
};
log_info!(logger, "Failing HTLC with payment_hash {} from {} counterparty commitment tx due to broadcast of revoked counterparty commitment transaction, waiting for confirmation (at height {})", log_bytes!(htlc.payment_hash.0), $commitment_tx, entry.confirmation_threshold());
event: OnchainEvent::HTLCUpdate {
source: (**source).clone(),
payment_hash: htlc.payment_hash.clone(),
+ onchain_value_satoshis: Some(htlc.amount_msat / 1000),
},
});
}
let mut claim_requests = Vec::new();
let mut watch_outputs = Vec::new();
- macro_rules! wait_threshold_conf {
- ($source: expr, $commitment_tx: expr, $payment_hash: expr) => {
- self.onchain_events_awaiting_threshold_conf.retain(|ref entry| {
- if entry.height != height { return true; }
- match entry.event {
- OnchainEvent::HTLCUpdate { source: ref update_source, .. } => {
- *update_source != $source
- },
- _ => true,
- }
- });
- let entry = OnchainEventEntry {
- txid: commitment_txid,
- height,
- event: OnchainEvent::HTLCUpdate { source: $source, payment_hash: $payment_hash },
- };
- log_trace!(logger, "Failing HTLC with payment_hash {} from {} holder commitment tx due to broadcast of transaction, waiting confirmation (at height{})", log_bytes!($payment_hash.0), $commitment_tx, entry.confirmation_threshold());
- self.onchain_events_awaiting_threshold_conf.push(entry);
- }
- }
-
macro_rules! append_onchain_update {
($updates: expr, $to_watch: expr) => {
claim_requests = $updates.0;
}
macro_rules! fail_dust_htlcs_after_threshold_conf {
- ($holder_tx: expr) => {
+ ($holder_tx: expr, $commitment_tx: expr) => {
for &(ref htlc, _, ref source) in &$holder_tx.htlc_outputs {
if htlc.transaction_output_index.is_none() {
if let &Some(ref source) = source {
- wait_threshold_conf!(source.clone(), "lastest", htlc.payment_hash.clone());
+ self.onchain_events_awaiting_threshold_conf.retain(|ref entry| {
+ if entry.height != height { return true; }
+ match entry.event {
+ OnchainEvent::HTLCUpdate { source: ref update_source, .. } => {
+ update_source != source
+ },
+ _ => true,
+ }
+ });
+ let entry = OnchainEventEntry {
+ txid: commitment_txid,
+ height,
+ event: OnchainEvent::HTLCUpdate {
+ source: source.clone(), payment_hash: htlc.payment_hash,
+ onchain_value_satoshis: Some(htlc.amount_msat / 1000)
+ },
+ };
+ log_trace!(logger, "Failing HTLC with payment_hash {} from {} holder commitment tx due to broadcast of transaction, waiting confirmation (at height{})",
+ log_bytes!(htlc.payment_hash.0), $commitment_tx, entry.confirmation_threshold());
+ self.onchain_events_awaiting_threshold_conf.push(entry);
}
}
}
}
if is_holder_tx {
- fail_dust_htlcs_after_threshold_conf!(self.current_holder_commitment_tx);
+ fail_dust_htlcs_after_threshold_conf!(self.current_holder_commitment_tx, "latest");
if let &Some(ref holder_tx) = &self.prev_holder_signed_commitment_tx {
- fail_dust_htlcs_after_threshold_conf!(holder_tx);
+ fail_dust_htlcs_after_threshold_conf!(holder_tx, "previous");
}
}
// Produce actionable events from on-chain events having reached their threshold.
for entry in onchain_events_reaching_threshold_conf.drain(..) {
match entry.event {
- OnchainEvent::HTLCUpdate { ref source, payment_hash } => {
+ OnchainEvent::HTLCUpdate { ref source, payment_hash, onchain_value_satoshis } => {
// Check for duplicate HTLC resolutions.
#[cfg(debug_assertions)]
{
log_debug!(logger, "HTLC {} failure update has got enough confirmations to be passed upstream", log_bytes!(payment_hash.0));
self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate {
- payment_hash: payment_hash,
+ payment_hash,
payment_preimage: None,
source: source.clone(),
+ onchain_value_satoshis,
}));
},
OnchainEvent::MaturingOutput { descriptor } => {
if pending_htlc.payment_hash == $htlc_output.payment_hash && pending_htlc.amount_msat == $htlc_output.amount_msat {
if let &Some(ref source) = pending_source {
log_claim!("revoked counterparty commitment tx", false, pending_htlc, true);
- payment_data = Some(((**source).clone(), $htlc_output.payment_hash));
+ payment_data = Some(((**source).clone(), $htlc_output.payment_hash, $htlc_output.amount_msat));
break;
}
}
// transaction. This implies we either learned a preimage, the HTLC
// has timed out, or we screwed up. In any case, we should now
// resolve the source HTLC with the original sender.
- payment_data = Some(((*source).clone(), htlc_output.payment_hash));
+ payment_data = Some(((*source).clone(), htlc_output.payment_hash, htlc_output.amount_msat));
} else if !$holder_tx {
check_htlc_valid_counterparty!(self.current_counterparty_commitment_txid, htlc_output);
if payment_data.is_none() {
// Check that scan_commitment, above, decided there is some source worth relaying an
// HTLC resolution backwards to and figure out whether we learned a preimage from it.
- if let Some((source, payment_hash)) = payment_data {
+ if let Some((source, payment_hash, amount_msat)) = payment_data {
let mut payment_preimage = PaymentPreimage([0; 32]);
if accepted_preimage_claim {
if !self.pending_monitor_events.iter().any(
self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate {
source,
payment_preimage: Some(payment_preimage),
- payment_hash
+ payment_hash,
+ onchain_value_satoshis: Some(amount_msat / 1000),
}));
}
} else if offered_preimage_claim {
self.pending_monitor_events.push(MonitorEvent::HTLCEvent(HTLCUpdate {
source,
payment_preimage: Some(payment_preimage),
- payment_hash
+ payment_hash,
+ onchain_value_satoshis: Some(amount_msat / 1000),
}));
}
} else {
let entry = OnchainEventEntry {
txid: tx.txid(),
height,
- event: OnchainEvent::HTLCUpdate { source: source, payment_hash: payment_hash },
+ event: OnchainEvent::HTLCUpdate {
+ source, payment_hash,
+ onchain_value_satoshis: Some(amount_msat / 1000),
+ },
};
log_info!(logger, "Failing HTLC with payment_hash {} timeout by a spend tx, waiting for confirmation (at height {})", log_bytes!(payment_hash.0), entry.confirmation_threshold());
self.onchain_events_awaiting_threshold_conf.push(entry);
output: outp.clone(),
});
break;
- } else if let Some(ref broadcasted_holder_revokable_script) = self.broadcasted_holder_revokable_script {
+ }
+ if let Some(ref broadcasted_holder_revokable_script) = self.broadcasted_holder_revokable_script {
if broadcasted_holder_revokable_script.0 == outp.script_pubkey {
spendable_output = Some(SpendableOutputDescriptor::DelayedPaymentOutput(DelayedPaymentOutputDescriptor {
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
}));
break;
}
- } else if self.counterparty_payment_script == outp.script_pubkey {
+ }
+ if self.counterparty_payment_script == outp.script_pubkey {
spendable_output = Some(SpendableOutputDescriptor::StaticPaymentOutput(StaticPaymentOutputDescriptor {
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
output: outp.clone(),
channel_value_satoshis: self.channel_value_satoshis,
}));
break;
- } else if outp.script_pubkey == self.shutdown_script {
+ }
+ if outp.script_pubkey == self.shutdown_script {
spendable_output = Some(SpendableOutputDescriptor::StaticOutput {
outpoint: OutPoint { txid: tx.txid(), index: i as u16 },
output: outp.clone(),
});
+ break;
}
}
if let Some(spendable_output) = spendable_output {
impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
for (BlockHash, ChannelMonitor<Signer>) {
- fn read<R: ::std::io::Read>(reader: &mut R, keys_manager: &'a K) -> Result<Self, DecodeError> {
+ fn read<R: io::Read>(reader: &mut R, keys_manager: &'a K) -> Result<Self, DecodeError> {
macro_rules! unwrap_obj {
($key: expr) => {
match $key {