hash_map::Entry::Occupied(_) => return Err(MonitorUpdateError("Channel monitor for given key is already present")),
hash_map::Entry::Vacant(e) => e,
};
- match monitor.onchain_detection.funding_info {
- None => {
- return Err(MonitorUpdateError("Try to update a useless monitor without funding_txo !"));
- },
- Some((ref outpoint, ref script)) => {
- log_trace!(self, "Got new Channel Monitor for channel {}", log_bytes!(outpoint.to_channel_id()[..]));
- self.chain_monitor.install_watch_tx(&outpoint.txid, script);
- self.chain_monitor.install_watch_outpoint((outpoint.txid, outpoint.index as u32), script);
- },
- }
+ log_trace!(self, "Got new Channel Monitor for channel {}", log_bytes!(monitor.funding_info.0.to_channel_id()[..]));
+ self.chain_monitor.install_watch_tx(&monitor.funding_info.0.txid, &monitor.funding_info.1);
+ self.chain_monitor.install_watch_outpoint((monitor.funding_info.0.txid, monitor.funding_info.0.index as u32), &monitor.funding_info.1);
for (txid, outputs) in monitor.get_outputs_to_watch().iter() {
for (idx, script) in outputs.iter().enumerate() {
self.chain_monitor.install_watch_outpoint((*txid, idx as u32), script);
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.onchain_detection));
+ log_trace!(self, "Updating Channel Monitor for channel {}", log_funding_info!(orig_monitor));
orig_monitor.update_monitor(update, &self.broadcaster)
},
None => Err(MonitorUpdateError("No such monitor registered"))
/// solved by a previous claim tx. What we want to avoid is reorg evicting our claim tx and us not
/// keeping bumping another claim tx to solve the outpoint.
pub(crate) const ANTI_REORG_DELAY: u32 = 6;
-
-struct OnchainDetection<ChanSigner: ChannelKeys> {
- keys: ChanSigner,
- funding_info: Option<(OutPoint, Script)>,
- current_remote_commitment_txid: Option<Sha256dHash>,
- prev_remote_commitment_txid: Option<Sha256dHash>,
-}
-
-#[cfg(any(test, feature = "fuzztarget"))]
-impl<ChanSigner: ChannelKeys> PartialEq for OnchainDetection<ChanSigner> {
- fn eq(&self, other: &Self) -> bool {
- self.keys.pubkeys() == other.keys.pubkeys()
- }
-}
+/// Number of blocks before confirmation at which we fail back an un-relayed HTLC or at which we
+/// refuse to accept a new HTLC.
+///
+/// This is used for a few separate purposes:
+/// 1) if we've received an MPP HTLC to us and it expires within this many blocks and we are
+/// waiting on additional parts (or waiting on the preimage for any HTLC from the user), we will
+/// fail this HTLC,
+/// 2) if we receive an HTLC within this many blocks of its expiry (plus one to avoid a race
+/// condition with the above), we will fail this HTLC without telling the user we received it,
+/// 3) if we are waiting on a connection or a channel state update to send an HTLC to a peer, and
+/// that HTLC expires within this many blocks, we will simply fail the HTLC instead.
+///
+/// (1) is all about protecting us - we need enough time to update the channel state before we hit
+/// CLTV_CLAIM_BUFFER, at which point we'd go on chain to claim the HTLC with the preimage.
+///
+/// (2) is the same, but with an additional buffer to avoid accepting an HTLC which is immediately
+/// in a race condition between the user connecting a block (which would fail it) and the user
+/// providing us the preimage (which would claim it).
+///
+/// (3) is about our counterparty - we don't want to relay an HTLC to a counterparty when they may
+/// end up force-closing the channel on us to claim it.
+pub(crate) const HTLC_FAIL_BACK_BUFFER: u32 = CLTV_CLAIM_BUFFER + LATENCY_GRACE_PERIOD_BLOCKS;
#[derive(Clone, PartialEq)]
struct LocalSignedTx {
#[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 {
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 } => {
+ &ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { ref commitment_tx, 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)?;
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();
broadcasted_remote_payment_script: Option<(Script, SecretKey)>,
shutdown_script: Script,
- onchain_detection: OnchainDetection<ChanSigner>,
- their_htlc_base_key: Option<PublicKey>,
- their_delayed_payment_base_key: Option<PublicKey>,
- funding_redeemscript: Option<Script>,
- channel_value_satoshis: Option<u64>,
+ keys: ChanSigner,
+ funding_info: (OutPoint, Script),
+ current_remote_commitment_txid: Option<Sha256dHash>,
+ prev_remote_commitment_txid: Option<Sha256dHash>,
+
+ their_htlc_base_key: PublicKey,
+ their_delayed_payment_base_key: PublicKey,
+ funding_redeemscript: Script,
+ channel_value_satoshis: u64,
// first is the idx of the first of the two revocation points
their_cur_revocation_points: Option<(u64, PublicKey, Option<PublicKey>)>,
our_to_self_delay: u16,
- their_to_self_delay: Option<u16>,
+ their_to_self_delay: u16,
commitment_secrets: CounterpartyCommitmentSecrets,
remote_claimable_outpoints: HashMap<Sha256dHash, Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>>,
// various monitors for one channel being out of sync, and us broadcasting a local
// transaction for which we have deleted claim information on some watchtowers.
prev_local_signed_commitment_tx: Option<LocalSignedTx>,
- current_local_signed_commitment_tx: Option<LocalSignedTx>,
+ current_local_commitment_tx: LocalSignedTx,
// Used just for ChannelManager to make sure it has the latest channel data during
// deserialization
self.destination_script != other.destination_script ||
self.broadcasted_local_revokable_script != other.broadcasted_local_revokable_script ||
self.broadcasted_remote_payment_script != other.broadcasted_remote_payment_script ||
- self.onchain_detection != other.onchain_detection ||
+ self.keys.pubkeys() != other.keys.pubkeys() ||
+ self.funding_info != other.funding_info ||
+ self.current_remote_commitment_txid != other.current_remote_commitment_txid ||
+ self.prev_remote_commitment_txid != other.prev_remote_commitment_txid ||
self.their_htlc_base_key != other.their_htlc_base_key ||
self.their_delayed_payment_base_key != other.their_delayed_payment_base_key ||
self.funding_redeemscript != other.funding_redeemscript ||
self.prev_local_signed_commitment_tx != other.prev_local_signed_commitment_tx ||
self.current_remote_commitment_number != other.current_remote_commitment_number ||
self.current_local_commitment_number != other.current_local_commitment_number ||
- self.current_local_signed_commitment_tx != other.current_local_signed_commitment_tx ||
+ self.current_local_commitment_tx != other.current_local_commitment_tx ||
self.payment_preimages != other.payment_preimages ||
self.pending_htlcs_updated != other.pending_htlcs_updated ||
self.pending_events.len() != other.pending_events.len() || // We trust events to round-trip properly
}
impl<ChanSigner: ChannelKeys + Writeable> ChannelMonitor<ChanSigner> {
- /// Serializes into a vec, with various modes for the exposed pub fns
- fn write<W: Writer>(&self, writer: &mut W, for_local_storage: bool) -> Result<(), ::std::io::Error> {
+ /// Writes this monitor into the given writer, suitable for writing to disk.
+ ///
+ /// Note that the deserializer is only implemented for (Sha256dHash, ChannelMonitor), which
+ /// tells you the last block hash which was block_connect()ed. You MUST rescan any blocks along
+ /// the "reorg path" (ie disconnecting blocks until you find a common ancestor from both the
+ /// returned block hash and the the current chain and then reconnecting blocks to get to the
+ /// best chain) upon deserializing the object!
+ pub fn write_for_disk<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
//TODO: We still write out all the serialization here manually instead of using the fancy
//serialization framework we have, we should migrate things over to it.
writer.write_all(&[SERIALIZATION_VERSION; 1])?;
}
self.shutdown_script.write(writer)?;
- self.onchain_detection.keys.write(writer)?;
- match self.onchain_detection.funding_info {
- Some((ref outpoint, ref script)) => {
- writer.write_all(&outpoint.txid[..])?;
- writer.write_all(&byte_utils::be16_to_array(outpoint.index))?;
- script.write(writer)?;
- },
- None => {
- debug_assert!(false, "Try to serialize a useless Local monitor !");
- },
- }
- self.onchain_detection.current_remote_commitment_txid.write(writer)?;
- self.onchain_detection.prev_remote_commitment_txid.write(writer)?;
+ self.keys.write(writer)?;
+ writer.write_all(&self.funding_info.0.txid[..])?;
+ writer.write_all(&byte_utils::be16_to_array(self.funding_info.0.index))?;
+ self.funding_info.1.write(writer)?;
+ self.current_remote_commitment_txid.write(writer)?;
+ self.prev_remote_commitment_txid.write(writer)?;
- writer.write_all(&self.their_htlc_base_key.as_ref().unwrap().serialize())?;
- writer.write_all(&self.their_delayed_payment_base_key.as_ref().unwrap().serialize())?;
- self.funding_redeemscript.as_ref().unwrap().write(writer)?;
- self.channel_value_satoshis.unwrap().write(writer)?;
+ writer.write_all(&self.their_htlc_base_key.serialize())?;
+ writer.write_all(&self.their_delayed_payment_base_key.serialize())?;
+ self.funding_redeemscript.write(writer)?;
+ self.channel_value_satoshis.write(writer)?;
match self.their_cur_revocation_points {
Some((idx, pubkey, second_option)) => {
}
writer.write_all(&byte_utils::be16_to_array(self.our_to_self_delay))?;
- writer.write_all(&byte_utils::be16_to_array(self.their_to_self_delay.unwrap()))?;
+ writer.write_all(&byte_utils::be16_to_array(self.their_to_self_delay))?;
self.commitment_secrets.write(writer)?;
}
}
- if for_local_storage {
- writer.write_all(&byte_utils::be64_to_array(self.remote_hash_commitment_number.len() as u64))?;
- for (ref payment_hash, commitment_number) in self.remote_hash_commitment_number.iter() {
- writer.write_all(&payment_hash.0[..])?;
- writer.write_all(&byte_utils::be48_to_array(*commitment_number))?;
- }
- } else {
- writer.write_all(&byte_utils::be64_to_array(0))?;
+ writer.write_all(&byte_utils::be64_to_array(self.remote_hash_commitment_number.len() as u64))?;
+ for (ref payment_hash, commitment_number) in self.remote_hash_commitment_number.iter() {
+ writer.write_all(&payment_hash.0[..])?;
+ writer.write_all(&byte_utils::be48_to_array(*commitment_number))?;
}
macro_rules! serialize_local_tx {
writer.write_all(&[0; 1])?;
}
- if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx {
- writer.write_all(&[1; 1])?;
- serialize_local_tx!(cur_local_tx);
- } else {
- writer.write_all(&[0; 1])?;
- }
-
- if for_local_storage {
- writer.write_all(&byte_utils::be48_to_array(self.current_remote_commitment_number))?;
- } else {
- writer.write_all(&byte_utils::be48_to_array(0))?;
- }
+ serialize_local_tx!(self.current_local_commitment_tx);
- if for_local_storage {
- writer.write_all(&byte_utils::be48_to_array(self.current_local_commitment_number))?;
- } else {
- writer.write_all(&byte_utils::be48_to_array(0))?;
- }
+ writer.write_all(&byte_utils::be48_to_array(self.current_remote_commitment_number))?;
+ writer.write_all(&byte_utils::be48_to_array(self.current_local_commitment_number))?;
writer.write_all(&byte_utils::be64_to_array(self.payment_preimages.len() as u64))?;
for payment_preimage in self.payment_preimages.values() {
Ok(())
}
-
- /// Writes this monitor into the given writer, suitable for writing to disk.
- ///
- /// Note that the deserializer is only implemented for (Sha256dHash, ChannelMonitor), which
- /// tells you the last block hash which was block_connect()ed. You MUST rescan any blocks along
- /// the "reorg path" (ie not just starting at the same height but starting at the highest
- /// common block that appears on your best chain as well as on the chain which contains the
- /// last block hash returned) upon deserializing the object!
- pub fn write_for_disk<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- self.write(writer, true)
- }
-
- /// Encodes this monitor into the given writer, suitable for sending to a remote watchtower
- ///
- /// Note that the deserializer is only implemented for (Sha256dHash, ChannelMonitor), which
- /// tells you the last block hash which was block_connect()ed. You MUST rescan any blocks along
- /// the "reorg path" (ie not just starting at the same height but starting at the highest
- /// common block that appears on your best chain as well as on the chain which contains the
- /// last block hash returned) upon deserializing the object!
- pub fn write_for_watchtower<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
- self.write(writer, false)
- }
}
impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
their_htlc_base_key: &PublicKey, their_delayed_payment_base_key: &PublicKey,
their_to_self_delay: u16, funding_redeemscript: Script, channel_value_satoshis: u64,
commitment_transaction_number_obscure_factor: u64,
+ initial_local_commitment_tx: LocalCommitmentTransaction,
logger: Arc<Logger>) -> ChannelMonitor<ChanSigner> {
assert!(commitment_transaction_number_obscure_factor <= (1 << 48));
let our_channel_close_key_hash = Hash160::hash(&shutdown_pubkey.serialize());
let shutdown_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&our_channel_close_key_hash[..]).into_script();
- let onchain_detection = OnchainDetection {
- keys: keys.clone(),
- funding_info: Some(funding_info.clone()),
- current_remote_commitment_txid: None,
- prev_remote_commitment_txid: None,
+ let mut onchain_tx_handler = OnchainTxHandler::new(destination_script.clone(), keys.clone(), their_to_self_delay, logger.clone());
+
+ let local_tx_sequence = initial_local_commitment_tx.without_valid_witness().input[0].sequence as u64;
+ let local_tx_locktime = initial_local_commitment_tx.without_valid_witness().lock_time as u64;
+ let local_commitment_tx = LocalSignedTx {
+ txid: initial_local_commitment_tx.txid(),
+ revocation_key: initial_local_commitment_tx.local_keys.revocation_key,
+ a_htlc_key: initial_local_commitment_tx.local_keys.a_htlc_key,
+ b_htlc_key: initial_local_commitment_tx.local_keys.b_htlc_key,
+ delayed_payment_key: initial_local_commitment_tx.local_keys.a_delayed_payment_key,
+ per_commitment_point: initial_local_commitment_tx.local_keys.per_commitment_point,
+ feerate_per_kw: initial_local_commitment_tx.feerate_per_kw,
+ htlc_outputs: Vec::new(), // There are never any HTLCs in the initial commitment transactions
};
+ // Returning a monitor error before updating tracking points means in case of using
+ // a concurrent watchtower implementation for same channel, if this one doesn't
+ // reject update as we do, you MAY have the latest local valid commitment tx onchain
+ // for which you want to spend outputs. We're NOT robust again this scenario right
+ // now but we should consider it later.
+ onchain_tx_handler.provide_latest_local_tx(initial_local_commitment_tx).unwrap();
ChannelMonitor {
latest_update_id: 0,
broadcasted_remote_payment_script: None,
shutdown_script,
- onchain_detection: onchain_detection,
- their_htlc_base_key: Some(their_htlc_base_key.clone()),
- their_delayed_payment_base_key: Some(their_delayed_payment_base_key.clone()),
- funding_redeemscript: Some(funding_redeemscript.clone()),
- channel_value_satoshis: Some(channel_value_satoshis),
+ keys,
+ funding_info,
+ current_remote_commitment_txid: None,
+ prev_remote_commitment_txid: None,
+
+ their_htlc_base_key: their_htlc_base_key.clone(),
+ their_delayed_payment_base_key: their_delayed_payment_base_key.clone(),
+ funding_redeemscript,
+ channel_value_satoshis: channel_value_satoshis,
their_cur_revocation_points: None,
- our_to_self_delay: our_to_self_delay,
- their_to_self_delay: Some(their_to_self_delay),
+ our_to_self_delay,
+ their_to_self_delay,
commitment_secrets: CounterpartyCommitmentSecrets::new(),
remote_claimable_outpoints: HashMap::new(),
remote_hash_commitment_number: HashMap::new(),
prev_local_signed_commitment_tx: None,
- current_local_signed_commitment_tx: None,
+ current_local_commitment_tx: local_commitment_tx,
current_remote_commitment_number: 1 << 48,
- current_local_commitment_number: 0xffff_ffff_ffff,
+ current_local_commitment_number: 0xffff_ffff_ffff - ((((local_tx_sequence & 0xffffff) << 3*8) | (local_tx_locktime as u64 & 0xffffff)) ^ commitment_transaction_number_obscure_factor),
payment_preimages: HashMap::new(),
pending_htlcs_updated: Vec::new(),
onchain_events_waiting_threshold_conf: HashMap::new(),
outputs_to_watch: HashMap::new(),
- onchain_tx_handler: OnchainTxHandler::new(destination_script.clone(), keys, funding_redeemscript, their_to_self_delay, logger.clone()),
+ onchain_tx_handler,
lockdown_from_offchain: false,
// Prune HTLCs from the previous remote commitment tx so we don't generate failure/fulfill
// events for now-revoked/fulfilled HTLCs.
- if let Some(txid) = self.onchain_detection.prev_remote_commitment_txid.take() {
+ if let Some(txid) = self.prev_remote_commitment_txid.take() {
for &mut (_, ref mut source) in self.remote_claimable_outpoints.get_mut(&txid).unwrap() {
*source = None;
}
}
if !self.payment_preimages.is_empty() {
- let local_signed_commitment_tx = self.current_local_signed_commitment_tx.as_ref().expect("Channel needs at least an initial commitment tx !");
+ let cur_local_signed_commitment_tx = &self.current_local_commitment_tx;
let prev_local_signed_commitment_tx = self.prev_local_signed_commitment_tx.as_ref();
let min_idx = self.get_min_seen_secret();
let remote_hash_commitment_number = &mut self.remote_hash_commitment_number;
self.payment_preimages.retain(|&k, _| {
- for &(ref htlc, _, _) in &local_signed_commitment_tx.htlc_outputs {
+ for &(ref htlc, _, _) in cur_local_signed_commitment_tx.htlc_outputs.iter() {
if k == htlc.payment_hash {
return true
}
let new_txid = unsigned_commitment_tx.txid();
log_trace!(self, "Tracking new remote commitment transaction with txid {} at commitment number {} with {} HTLC outputs", new_txid, commitment_number, htlc_outputs.len());
log_trace!(self, "New potential remote commitment transaction: {}", encode::serialize_hex(unsigned_commitment_tx));
- self.onchain_detection.prev_remote_commitment_txid = self.onchain_detection.current_remote_commitment_txid.take();
- self.onchain_detection.current_remote_commitment_txid = Some(new_txid);
+ self.prev_remote_commitment_txid = self.current_remote_commitment_txid.take();
+ self.current_remote_commitment_txid = Some(new_txid);
self.remote_claimable_outpoints.insert(new_txid, htlc_outputs);
self.current_remote_commitment_number = commitment_number;
//TODO: Merge this into the other per-remote-transaction output storage stuff
}
pub(super) fn provide_rescue_remote_commitment_tx_info(&mut self, their_revocation_point: PublicKey) {
- if let Ok(payment_key) = chan_utils::derive_public_key(&self.secp_ctx, &their_revocation_point, &self.onchain_detection.keys.pubkeys().payment_basepoint) {
+ if let Ok(payment_key) = chan_utils::derive_public_key(&self.secp_ctx, &their_revocation_point, &self.keys.pubkeys().payment_basepoint) {
let to_remote_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0)
.push_slice(&Hash160::hash(&payment_key.serialize())[..])
.into_script();
- if let Ok(to_remote_key) = chan_utils::derive_private_key(&self.secp_ctx, &their_revocation_point, &self.onchain_detection.keys.payment_base_key()) {
+ if let Ok(to_remote_key) = chan_utils::derive_private_key(&self.secp_ctx, &their_revocation_point, &self.keys.payment_base_key()) {
self.broadcasted_remote_payment_script = Some((to_remote_script, to_remote_key));
}
}
/// 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, mut 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"));
- }
+ pub(super) fn provide_latest_local_commitment_tx_info(&mut self, commitment_tx: LocalCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), MonitorUpdateError> {
let txid = commitment_tx.txid();
let sequence = commitment_tx.without_valid_witness().input[0].sequence as u64;
let locktime = commitment_tx.without_valid_witness().lock_time as u64;
- let mut htlcs = Vec::with_capacity(htlc_outputs.len());
- for htlc in htlc_outputs.clone() {
- if let Some(_) = htlc.0.transaction_output_index {
- htlcs.push((htlc.0, htlc.1, None));
- }
- }
- commitment_tx.set_htlc_cache(local_keys.clone(), feerate_per_kw, htlcs);
+ let mut new_local_commitment_tx = LocalSignedTx {
+ txid,
+ revocation_key: commitment_tx.local_keys.revocation_key,
+ a_htlc_key: commitment_tx.local_keys.a_htlc_key,
+ b_htlc_key: commitment_tx.local_keys.b_htlc_key,
+ delayed_payment_key: commitment_tx.local_keys.a_delayed_payment_key,
+ per_commitment_point: commitment_tx.local_keys.per_commitment_point,
+ feerate_per_kw: commitment_tx.feerate_per_kw,
+ htlc_outputs: htlc_outputs,
+ };
// Returning a monitor error before updating tracking points means in case of using
// a concurrent watchtower implementation for same channel, if this one doesn't
// reject update as we do, you MAY have the latest local valid commitment tx onchain
return Err(MonitorUpdateError("Local commitment signed has already been signed, no further update of LOCAL commitment transaction is allowed"));
}
self.current_local_commitment_number = 0xffff_ffff_ffff - ((((sequence & 0xffffff) << 3*8) | (locktime as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor);
- self.prev_local_signed_commitment_tx = self.current_local_signed_commitment_tx.take();
- self.current_local_signed_commitment_tx = Some(LocalSignedTx {
- txid,
- revocation_key: local_keys.revocation_key,
- a_htlc_key: local_keys.a_htlc_key,
- b_htlc_key: local_keys.b_htlc_key,
- delayed_payment_key: local_keys.a_delayed_payment_key,
- per_commitment_point: local_keys.per_commitment_point,
- feerate_per_kw,
- htlc_outputs: htlc_outputs,
- });
+ mem::swap(&mut new_local_commitment_tx, &mut self.current_local_commitment_tx);
+ self.prev_local_signed_commitment_tx = Some(new_local_commitment_tx);
Ok(())
}
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 } => {
+ ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx, htlc_outputs } => {
if self.lockdown_from_offchain { panic!(); }
- self.provide_latest_local_commitment_tx_info(commitment_tx, local_keys, feerate_per_kw, htlc_outputs)?
+ self.provide_latest_local_commitment_tx_info(commitment_tx, 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),
}
for update in updates.updates.drain(..) {
match update {
- ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx, local_keys, feerate_per_kw, htlc_outputs } => {
+ ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx, htlc_outputs } => {
if self.lockdown_from_offchain { panic!(); }
- self.provide_latest_local_commitment_tx_info(commitment_tx, local_keys, feerate_per_kw, htlc_outputs)?
+ self.provide_latest_local_commitment_tx_info(commitment_tx, 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),
}
/// Gets the funding transaction outpoint of the channel this ChannelMonitor is monitoring for.
- pub fn get_funding_txo(&self) -> Option<OutPoint> {
- if let Some((outp, _)) = self.onchain_detection.funding_info {
- return Some(outp)
- }
- None
+ pub fn get_funding_txo(&self) -> OutPoint {
+ self.funding_info.0
}
/// Gets a list of txids, with their output scripts (in the order they appear in the
let secret = self.get_secret(commitment_number).unwrap();
let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret));
let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
- let revocation_pubkey = ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &self.onchain_detection.keys.pubkeys().revocation_basepoint));
- let revocation_key = ignore_error!(chan_utils::derive_private_revocation_key(&self.secp_ctx, &per_commitment_key, &self.onchain_detection.keys.revocation_base_key()));
- let b_htlc_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &per_commitment_point, &self.onchain_detection.keys.pubkeys().htlc_basepoint));
- let local_payment_key = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, &per_commitment_point, &self.onchain_detection.keys.payment_base_key()));
- let delayed_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.their_delayed_payment_base_key.unwrap()));
- let a_htlc_key = match self.their_htlc_base_key {
- None => return (claimable_outpoints, (commitment_txid, watch_outputs)),
- Some(their_htlc_base_key) => ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &their_htlc_base_key)),
- };
+ let revocation_pubkey = ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &self.keys.pubkeys().revocation_basepoint));
+ let revocation_key = ignore_error!(chan_utils::derive_private_revocation_key(&self.secp_ctx, &per_commitment_key, &self.keys.revocation_base_key()));
+ let b_htlc_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &per_commitment_point, &self.keys.pubkeys().htlc_basepoint));
+ let local_payment_key = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, &per_commitment_point, &self.keys.payment_base_key()));
+ let delayed_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.their_delayed_payment_base_key));
+ let a_htlc_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key), &self.their_htlc_base_key));
let revokeable_redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.our_to_self_delay, &delayed_key);
let revokeable_p2wsh = revokeable_redeemscript.to_v0_p2wsh();
}
}
}
- if let Some(ref txid) = self.onchain_detection.current_remote_commitment_txid {
+ if let Some(ref txid) = self.current_remote_commitment_txid {
check_htlc_fails!(txid, "current");
}
- if let Some(ref txid) = self.onchain_detection.prev_remote_commitment_txid {
+ if let Some(ref txid) = self.prev_remote_commitment_txid {
check_htlc_fails!(txid, "remote");
}
// No need to check local commitment txn, symmetric HTLCSource must be present as per-htlc data on remote commitment tx
}
}
}
- if let Some(ref txid) = self.onchain_detection.current_remote_commitment_txid {
+ if let Some(ref txid) = self.current_remote_commitment_txid {
check_htlc_fails!(txid, "current", 'current_loop);
}
- if let Some(ref txid) = self.onchain_detection.prev_remote_commitment_txid {
+ if let Some(ref txid) = self.prev_remote_commitment_txid {
check_htlc_fails!(txid, "previous", 'prev_loop);
}
if revocation_points.0 == commitment_number + 1 { Some(point) } else { None }
} else { None };
if let Some(revocation_point) = revocation_point_option {
- let revocation_pubkey = ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, revocation_point, &self.onchain_detection.keys.pubkeys().revocation_basepoint));
- let b_htlc_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, revocation_point, &self.onchain_detection.keys.pubkeys().htlc_basepoint));
- let htlc_privkey = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, revocation_point, &self.onchain_detection.keys.htlc_base_key()));
- let a_htlc_key = match self.their_htlc_base_key {
- None => return (claimable_outpoints, (commitment_txid, watch_outputs)),
- Some(their_htlc_base_key) => ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, revocation_point, &their_htlc_base_key)),
- };
- let local_payment_key = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, revocation_point, &self.onchain_detection.keys.payment_base_key()));
+ let revocation_pubkey = ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, revocation_point, &self.keys.pubkeys().revocation_basepoint));
+ let b_htlc_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, revocation_point, &self.keys.pubkeys().htlc_basepoint));
+ let htlc_privkey = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, revocation_point, &self.keys.htlc_base_key()));
+ let a_htlc_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, revocation_point, &self.their_htlc_base_key));
+ let local_payment_key = ignore_error!(chan_utils::derive_private_key(&self.secp_ctx, revocation_point, &self.keys.payment_base_key()));
self.broadcasted_remote_payment_script = {
// Note that the Network here is ignored as we immediately drop the address for the
let secret = if let Some(secret) = self.get_secret(commitment_number) { secret } else { return (Vec::new(), None); };
let per_commitment_key = ignore_error!(SecretKey::from_slice(&secret));
let per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &per_commitment_key);
- let revocation_pubkey = ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &self.onchain_detection.keys.pubkeys().revocation_basepoint));
- let revocation_key = ignore_error!(chan_utils::derive_private_revocation_key(&self.secp_ctx, &per_commitment_key, &self.onchain_detection.keys.revocation_base_key()));
- let delayed_key = match self.their_delayed_payment_base_key {
- None => return (Vec::new(), None),
- Some(their_delayed_payment_base_key) => ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &per_commitment_point, &their_delayed_payment_base_key)),
- };
+ let revocation_pubkey = ignore_error!(chan_utils::derive_public_revocation_key(&self.secp_ctx, &per_commitment_point, &self.keys.pubkeys().revocation_basepoint));
+ let revocation_key = ignore_error!(chan_utils::derive_private_revocation_key(&self.secp_ctx, &per_commitment_key, &self.keys.revocation_base_key()));
+ let delayed_key = ignore_error!(chan_utils::derive_public_key(&self.secp_ctx, &per_commitment_point, &self.their_delayed_payment_base_key));
let redeemscript = chan_utils::get_revokeable_redeemscript(&revocation_pubkey, self.our_to_self_delay, &delayed_key);
log_trace!(self, "Remote HTLC broadcast {}:{}", htlc_txid, 0);
let mut claim_requests = Vec::with_capacity(local_tx.htlc_outputs.len());
let mut watch_outputs = Vec::with_capacity(local_tx.htlc_outputs.len());
- let redeemscript = chan_utils::get_revokeable_redeemscript(&local_tx.revocation_key, self.their_to_self_delay.unwrap(), &local_tx.delayed_payment_key);
- let broadcasted_local_revokable_script = if let Ok(local_delayedkey) = chan_utils::derive_private_key(&self.secp_ctx, &local_tx.per_commitment_point, self.onchain_detection.keys.delayed_payment_base_key()) {
+ let redeemscript = chan_utils::get_revokeable_redeemscript(&local_tx.revocation_key, self.their_to_self_delay, &local_tx.delayed_payment_key);
+ let broadcasted_local_revokable_script = if let Ok(local_delayedkey) = chan_utils::derive_private_key(&self.secp_ctx, &local_tx.per_commitment_point, self.keys.delayed_payment_base_key()) {
Some((redeemscript.to_v0_p2wsh(), local_delayedkey, redeemscript))
} else { None };
// HTLCs set may differ between last and previous local commitment txn, in case of one them hitting chain, ensure we cancel all HTLCs backward
let mut is_local_tx = false;
- if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
- if local_tx.txid == commitment_txid {
- is_local_tx = true;
- log_trace!(self, "Got latest local commitment tx broadcast, searching for available HTLCs to claim");
- let mut res = self.broadcast_by_local_state(tx, local_tx);
- append_onchain_update!(res);
- }
- }
- if let &Some(ref local_tx) = &self.prev_local_signed_commitment_tx {
+ if self.current_local_commitment_tx.txid == commitment_txid {
+ is_local_tx = true;
+ log_trace!(self, "Got latest local commitment tx broadcast, searching for available HTLCs to claim");
+ let mut res = self.broadcast_by_local_state(tx, &self.current_local_commitment_tx);
+ append_onchain_update!(res);
+ } else if let &Some(ref local_tx) = &self.prev_local_signed_commitment_tx {
if local_tx.txid == commitment_txid {
is_local_tx = true;
log_trace!(self, "Got previous local commitment tx broadcast, searching for available HTLCs to claim");
}
if is_local_tx {
- if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
- fail_dust_htlcs_after_threshold_conf!(local_tx);
- }
+ fail_dust_htlcs_after_threshold_conf!(self.current_local_commitment_tx);
if let &Some(ref local_tx) = &self.prev_local_signed_commitment_tx {
fail_dust_htlcs_after_threshold_conf!(local_tx);
}
/// In any-case, choice is up to the user.
pub fn get_latest_local_commitment_txn(&mut self) -> Vec<Transaction> {
log_trace!(self, "Getting signed latest local commitment transaction!");
- if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx(self.channel_value_satoshis.unwrap()) {
+ if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx() {
let txid = commitment_tx.txid();
let mut res = vec![commitment_tx];
- if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
- for htlc in local_tx.htlc_outputs.iter() {
- if let Some(htlc_index) = htlc.0.transaction_output_index {
- let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(*preimage) } else { None };
- if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(txid, htlc_index, preimage) {
- res.push(htlc_tx);
- }
+ for htlc in self.current_local_commitment_tx.htlc_outputs.iter() {
+ if let Some(htlc_index) = htlc.0.transaction_output_index {
+ let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(*preimage) } else { None };
+ if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(txid, htlc_index, preimage) {
+ res.push(htlc_tx);
}
}
- // We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do.
- // The data will be re-generated and tracked in check_spend_local_transaction if we get a confirmation.
}
+ // We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do.
+ // The data will be re-generated and tracked in check_spend_local_transaction if we get a confirmation.
return res
}
Vec::new()
#[cfg(test)]
pub fn unsafe_get_latest_local_commitment_txn(&mut self) -> Vec<Transaction> {
log_trace!(self, "Getting signed copy of latest local commitment transaction!");
- if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_copy_local_tx(self.channel_value_satoshis.unwrap()) {
+ if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_copy_local_tx() {
let txid = commitment_tx.txid();
let mut res = vec![commitment_tx];
- if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
- for htlc in local_tx.htlc_outputs.iter() {
- if let Some(htlc_index) = htlc.0.transaction_output_index {
- let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(*preimage) } else { None };
- if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(txid, htlc_index, preimage) {
- res.push(htlc_tx);
- }
+ for htlc in self.current_local_commitment_tx.htlc_outputs.iter() {
+ if let Some(htlc_index) = htlc.0.transaction_output_index {
+ let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(*preimage) } else { None };
+ if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(txid, htlc_index, preimage) {
+ res.push(htlc_tx);
}
}
}
// which is an easy way to filter out any potential non-matching txn for lazy
// filters.
let prevout = &tx.input[0].previous_output;
- let funding_txo = self.onchain_detection.funding_info.clone();
- if funding_txo.is_none() || (prevout.txid == funding_txo.as_ref().unwrap().0.txid && prevout.vout == funding_txo.as_ref().unwrap().0.index as u32) {
+ if prevout.txid == self.funding_info.0.txid && prevout.vout == self.funding_info.0.index as u32 {
if (tx.input[0].sequence >> 8*3) as u8 == 0x80 && (tx.lock_time >> 8*3) as u8 == 0x20 {
let (mut new_outpoints, new_outputs) = self.check_spend_remote_transaction(&tx, height);
if !new_outputs.1.is_empty() {
self.is_paying_spendable_output(&tx, height);
}
- let should_broadcast = if let Some(_) = self.current_local_signed_commitment_tx {
- self.would_broadcast_at_height(height)
- } else { false };
+ let should_broadcast = self.would_broadcast_at_height(height);
if should_broadcast {
- claimable_outpoints.push(ClaimRequest { absolute_timelock: height, aggregable: false, outpoint: BitcoinOutPoint { txid: self.onchain_detection.funding_info.as_ref().unwrap().0.txid.clone(), vout: self.onchain_detection.funding_info.as_ref().unwrap().0.index as u32 }, witness_data: InputMaterial::Funding { channel_value: self.channel_value_satoshis.unwrap() }});
- }
- if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx {
- if should_broadcast {
- if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx(self.channel_value_satoshis.unwrap()) {
- let (mut new_outpoints, new_outputs, _) = self.broadcast_by_local_state(&commitment_tx, cur_local_tx);
- if !new_outputs.is_empty() {
- watch_outputs.push((cur_local_tx.txid.clone(), new_outputs));
- }
- claimable_outpoints.append(&mut new_outpoints);
+ claimable_outpoints.push(ClaimRequest { absolute_timelock: height, aggregable: false, outpoint: BitcoinOutPoint { txid: self.funding_info.0.txid.clone(), vout: self.funding_info.0.index as u32 }, witness_data: InputMaterial::Funding { channel_value: self.channel_value_satoshis }});
+ }
+ if should_broadcast {
+ if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx() {
+ let (mut new_outpoints, new_outputs, _) = self.broadcast_by_local_state(&commitment_tx, &self.current_local_commitment_tx);
+ if !new_outputs.is_empty() {
+ watch_outputs.push((self.current_local_commitment_tx.txid.clone(), new_outputs));
}
+ claimable_outpoints.append(&mut new_outpoints);
}
}
if let Some(events) = self.onchain_events_waiting_threshold_conf.remove(&height) {
}
}
- if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx {
- scan_commitment!(cur_local_tx.htlc_outputs.iter().map(|&(ref a, _, _)| a), true);
- }
+ scan_commitment!(self.current_local_commitment_tx.htlc_outputs.iter().map(|&(ref a, _, _)| a), true);
- if let Some(ref txid) = self.onchain_detection.current_remote_commitment_txid {
+ if let Some(ref txid) = self.current_remote_commitment_txid {
if let Some(ref htlc_outputs) = self.remote_claimable_outpoints.get(txid) {
scan_commitment!(htlc_outputs.iter().map(|&(ref a, _)| a), false);
}
}
- if let Some(ref txid) = self.onchain_detection.prev_remote_commitment_txid {
+ if let Some(ref txid) = self.prev_remote_commitment_txid {
if let Some(ref htlc_outputs) = self.remote_claimable_outpoints.get(txid) {
scan_commitment!(htlc_outputs.iter().map(|&(ref a, _)| a), false);
}
// resolve the source HTLC with the original sender.
payment_data = Some(((*source).clone(), htlc_output.payment_hash));
} else if !$local_tx {
- check_htlc_valid_remote!(self.onchain_detection.current_remote_commitment_txid, htlc_output);
+ check_htlc_valid_remote!(self.current_remote_commitment_txid, htlc_output);
if payment_data.is_none() {
- check_htlc_valid_remote!(self.onchain_detection.prev_remote_commitment_txid, htlc_output);
+ check_htlc_valid_remote!(self.prev_remote_commitment_txid, htlc_output);
}
}
if payment_data.is_none() {
}
}
- if let Some(ref current_local_signed_commitment_tx) = self.current_local_signed_commitment_tx {
- if input.previous_output.txid == current_local_signed_commitment_tx.txid {
- scan_commitment!(current_local_signed_commitment_tx.htlc_outputs.iter().map(|&(ref a, _, ref b)| (a, b.as_ref())),
- "our latest local commitment tx", true);
- }
+ if input.previous_output.txid == self.current_local_commitment_tx.txid {
+ scan_commitment!(self.current_local_commitment_tx.htlc_outputs.iter().map(|&(ref a, _, ref b)| (a, b.as_ref())),
+ "our latest local commitment tx", true);
}
if let Some(ref prev_local_signed_commitment_tx) = self.prev_local_signed_commitment_tx {
if input.previous_output.txid == prev_local_signed_commitment_tx.txid {
outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 },
key: broadcasted_local_revokable_script.1,
witness_script: broadcasted_local_revokable_script.2.clone(),
- to_self_delay: self.their_to_self_delay.unwrap(),
+ to_self_delay: self.their_to_self_delay,
output: outp.clone(),
});
break;
};
let shutdown_script = Readable::read(reader)?;
- let onchain_detection = {
- let keys = Readable::read(reader)?;
- // Technically this can fail and serialize fail a round-trip, but only for serialization of
- // barely-init'd ChannelMonitors that we can't do anything with.
- let outpoint = OutPoint {
- txid: Readable::read(reader)?,
- index: Readable::read(reader)?,
- };
- let funding_info = Some((outpoint, Readable::read(reader)?));
- let current_remote_commitment_txid = Readable::read(reader)?;
- let prev_remote_commitment_txid = Readable::read(reader)?;
- OnchainDetection {
- keys,
- funding_info,
- current_remote_commitment_txid,
- prev_remote_commitment_txid,
- }
+ let keys = Readable::read(reader)?;
+ // Technically this can fail and serialize fail a round-trip, but only for serialization of
+ // barely-init'd ChannelMonitors that we can't do anything with.
+ let outpoint = OutPoint {
+ txid: Readable::read(reader)?,
+ index: Readable::read(reader)?,
};
+ let funding_info = (outpoint, Readable::read(reader)?);
+ let current_remote_commitment_txid = Readable::read(reader)?;
+ let prev_remote_commitment_txid = Readable::read(reader)?;
- let their_htlc_base_key = Some(Readable::read(reader)?);
- let their_delayed_payment_base_key = Some(Readable::read(reader)?);
- let funding_redeemscript = Some(Readable::read(reader)?);
- let channel_value_satoshis = Some(Readable::read(reader)?);
+ let their_htlc_base_key = Readable::read(reader)?;
+ let their_delayed_payment_base_key = Readable::read(reader)?;
+ let funding_redeemscript = Readable::read(reader)?;
+ let channel_value_satoshis = Readable::read(reader)?;
let their_cur_revocation_points = {
let first_idx = <U48 as Readable>::read(reader)?.0;
};
let our_to_self_delay: u16 = Readable::read(reader)?;
- let their_to_self_delay: Option<u16> = Some(Readable::read(reader)?);
+ let their_to_self_delay: u16 = Readable::read(reader)?;
let commitment_secrets = Readable::read(reader)?;
},
_ => return Err(DecodeError::InvalidValue),
};
-
- let current_local_signed_commitment_tx = match <u8 as Readable>::read(reader)? {
- 0 => None,
- 1 => {
- Some(read_local_tx!())
- },
- _ => return Err(DecodeError::InvalidValue),
- };
+ let current_local_commitment_tx = read_local_tx!();
let current_remote_commitment_number = <U48 as Readable>::read(reader)?.0;
let current_local_commitment_number = <U48 as Readable>::read(reader)?.0;
broadcasted_remote_payment_script,
shutdown_script,
- onchain_detection,
+ keys,
+ funding_info,
+ current_remote_commitment_txid,
+ prev_remote_commitment_txid,
+
their_htlc_base_key,
their_delayed_payment_base_key,
funding_redeemscript,
remote_hash_commitment_number,
prev_local_signed_commitment_tx,
- current_local_signed_commitment_tx,
+ current_local_commitment_tx,
current_remote_commitment_number,
current_local_commitment_number,
use ln::channelmonitor::ChannelMonitor;
use ln::onchaintx::{OnchainTxHandler, InputDescriptors};
use ln::chan_utils;
- use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys, LocalCommitmentTransaction};
+ use ln::chan_utils::{HTLCOutputInCommitment, LocalCommitmentTransaction};
use util::test_utils::TestLogger;
use secp256k1::key::{SecretKey,PublicKey};
use secp256k1::Secp256k1;
let logger = Arc::new(TestLogger::new());
let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
- macro_rules! dummy_keys {
- () => {
- {
- TxCreationKeys {
- per_commitment_point: dummy_key.clone(),
- revocation_key: dummy_key.clone(),
- a_htlc_key: dummy_key.clone(),
- b_htlc_key: dummy_key.clone(),
- a_delayed_payment_key: dummy_key.clone(),
- b_payment_key: dummy_key.clone(),
- }
- }
- }
- }
let dummy_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };
let mut preimages = Vec::new();
(OutPoint { txid: Sha256dHash::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()),
&PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[44; 32]).unwrap()),
&PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()),
- 0, Script::new(), 46, 0, logger.clone());
-
- monitor.their_to_self_delay = Some(10);
+ 10, Script::new(), 46, 0, LocalCommitmentTransaction::dummy(), logger.clone());
- monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..10])).unwrap();
+ monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), 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])).unwrap();
+ monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), 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])).unwrap();
+ monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), 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);