use bitcoin::consensus::encode;
use bitcoin::util::hash::BitcoinHash;
-use bitcoin_hashes::Hash;
-use bitcoin_hashes::sha256::Hash as Sha256;
-use bitcoin_hashes::hash160::Hash as Hash160;
-use bitcoin_hashes::sha256d::Hash as Sha256dHash;
+use bitcoin::hashes::Hash;
+use bitcoin::hashes::sha256::Hash as Sha256;
+use bitcoin::hash_types::{Txid, BlockHash, WPubkeyHash};
-use secp256k1::{Secp256k1,Signature};
-use secp256k1::key::{SecretKey,PublicKey};
-use secp256k1;
+use bitcoin::secp256k1::{Secp256k1,Signature};
+use bitcoin::secp256k1::key::{SecretKey,PublicKey};
+use bitcoin::secp256k1;
use ln::msgs::DecodeError;
use ln::chan_utils;
use chain::transaction::OutPoint;
use chain::keysinterface::{SpendableOutputDescriptor, ChannelKeys};
use util::logger::Logger;
-use util::ser::{ReadableArgs, Readable, MaybeReadable, Writer, Writeable, U48};
+use util::ser::{Readable, MaybeReadable, Writer, Writeable, U48};
use util::{byte_utils, events};
use std::collections::{HashMap, hash_map};
-use std::sync::{Arc,Mutex};
+use std::sync::Mutex;
use std::{hash,cmp, mem};
use std::ops::Deref;
///
/// If you're using this for local monitoring of your own channels, you probably want to use
/// `OutPoint` as the key, which will give you a ManyChannelMonitor implementation.
-pub struct SimpleManyChannelMonitor<Key, ChanSigner: ChannelKeys, T: Deref, F: Deref>
+pub struct SimpleManyChannelMonitor<Key, ChanSigner: ChannelKeys, T: Deref, F: Deref, L: Deref, C: Deref>
where T::Target: BroadcasterInterface,
- F::Target: FeeEstimator
+ F::Target: FeeEstimator,
+ L::Target: Logger,
+ C::Target: ChainWatchInterface,
{
#[cfg(test)] // Used in ChannelManager tests to manipulate channels directly
pub monitors: Mutex<HashMap<Key, ChannelMonitor<ChanSigner>>>,
#[cfg(not(test))]
monitors: Mutex<HashMap<Key, ChannelMonitor<ChanSigner>>>,
- chain_monitor: Arc<ChainWatchInterface>,
+ chain_monitor: C,
broadcaster: T,
- logger: Arc<Logger>,
+ logger: L,
fee_estimator: F
}
-impl<'a, Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref + Sync + Send, F: Deref + Sync + Send>
- ChainListener for SimpleManyChannelMonitor<Key, ChanSigner, T, F>
+impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send, C: Deref + Sync + Send>
+ ChainListener for SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C>
where T::Target: BroadcasterInterface,
- F::Target: FeeEstimator
+ F::Target: FeeEstimator,
+ L::Target: Logger,
+ C::Target: ChainWatchInterface,
{
fn block_connected(&self, header: &BlockHeader, height: u32, txn_matched: &[&Transaction], _indexes_of_txn_matched: &[u32]) {
let block_hash = header.bitcoin_hash();
{
let mut monitors = self.monitors.lock().unwrap();
for monitor in monitors.values_mut() {
- let txn_outputs = monitor.block_connected(txn_matched, height, &block_hash, &*self.broadcaster, &*self.fee_estimator);
+ let txn_outputs = monitor.block_connected(txn_matched, height, &block_hash, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
for (ref txid, ref outputs) in txn_outputs {
for (idx, output) in outputs.iter().enumerate() {
let block_hash = header.bitcoin_hash();
let mut monitors = self.monitors.lock().unwrap();
for monitor in monitors.values_mut() {
- monitor.block_disconnected(disconnected_height, &block_hash, &*self.broadcaster, &*self.fee_estimator);
+ monitor.block_disconnected(disconnected_height, &block_hash, &*self.broadcaster, &*self.fee_estimator, &*self.logger);
}
}
}
-impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: Deref, F: Deref> SimpleManyChannelMonitor<Key, ChanSigner, T, F>
+impl<Key : Send + cmp::Eq + hash::Hash + 'static, ChanSigner: ChannelKeys, T: Deref, F: Deref, L: Deref, C: Deref> SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C>
where T::Target: BroadcasterInterface,
- F::Target: FeeEstimator
+ F::Target: FeeEstimator,
+ L::Target: Logger,
+ C::Target: ChainWatchInterface,
{
/// Creates a new object which can be used to monitor several channels given the chain
/// interface with which to register to receive notifications.
- pub fn new(chain_monitor: Arc<ChainWatchInterface>, broadcaster: T, logger: Arc<Logger>, feeest: F) -> SimpleManyChannelMonitor<Key, ChanSigner, T, F> {
+ pub fn new(chain_monitor: C, broadcaster: T, logger: L, feeest: F) -> SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C> {
let res = SimpleManyChannelMonitor {
monitors: Mutex::new(HashMap::new()),
chain_monitor,
hash_map::Entry::Occupied(_) => return Err(MonitorUpdateError("Channel monitor for given key is already present")),
hash_map::Entry::Vacant(e) => e,
};
- log_trace!(self, "Got new Channel Monitor for channel {}", log_bytes!(monitor.funding_info.0.to_channel_id()[..]));
+ log_trace!(self.logger, "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() {
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));
- orig_monitor.update_monitor(update, &self.broadcaster)
+ log_trace!(self.logger, "Updating Channel Monitor for channel {}", log_funding_info!(orig_monitor));
+ orig_monitor.update_monitor(update, &self.broadcaster, &self.logger)
},
None => Err(MonitorUpdateError("No such monitor registered"))
}
}
}
-impl<ChanSigner: ChannelKeys, T: Deref + Sync + Send, F: Deref + Sync + Send> ManyChannelMonitor<ChanSigner> for SimpleManyChannelMonitor<OutPoint, ChanSigner, T, F>
+impl<ChanSigner: ChannelKeys, T: Deref + Sync + Send, F: Deref + Sync + Send, L: Deref + Sync + Send, C: Deref + Sync + Send> ManyChannelMonitor<ChanSigner> for SimpleManyChannelMonitor<OutPoint, ChanSigner, T, F, L, C>
where T::Target: BroadcasterInterface,
- F::Target: FeeEstimator
+ F::Target: FeeEstimator,
+ L::Target: Logger,
+ C::Target: ChainWatchInterface,
{
fn add_monitor(&self, funding_txo: OutPoint, monitor: ChannelMonitor<ChanSigner>) -> Result<(), ChannelMonitorUpdateErr> {
match self.add_monitor_by_key(funding_txo, monitor) {
}
}
-impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref, F: Deref> events::EventsProvider for SimpleManyChannelMonitor<Key, ChanSigner, T, F>
+impl<Key : Send + cmp::Eq + hash::Hash, ChanSigner: ChannelKeys, T: Deref, F: Deref, L: Deref, C: Deref> events::EventsProvider for SimpleManyChannelMonitor<Key, ChanSigner, T, F, L, C>
where T::Target: BroadcasterInterface,
- F::Target: FeeEstimator
+ F::Target: FeeEstimator,
+ L::Target: Logger,
+ C::Target: ChainWatchInterface,
{
fn get_and_clear_pending_events(&self) -> Vec<events::Event> {
let mut pending_events = Vec::new();
#[derive(Clone, PartialEq)]
struct LocalSignedTx {
/// txid of the transaction in tx, just used to make comparison faster
- txid: Sha256dHash,
+ txid: Txid,
revocation_key: PublicKey,
a_htlc_key: PublicKey,
b_htlc_key: PublicKey,
preimage: Option<PaymentPreimage>,
amount: u64,
},
- Funding {}
+ Funding {
+ funding_redeemscript: Script,
+ }
}
impl Writeable for InputMaterial {
preimage.write(writer)?;
writer.write_all(&byte_utils::be64_to_array(*amount))?;
},
- &InputMaterial::Funding {} => {
+ &InputMaterial::Funding { ref funding_redeemscript } => {
writer.write_all(&[3; 1])?;
+ funding_redeemscript.write(writer)?;
}
}
Ok(())
}
},
3 => {
- InputMaterial::Funding {}
+ InputMaterial::Funding {
+ funding_redeemscript: Readable::read(reader)?,
+ }
}
_ => return Err(DecodeError::InvalidValue),
};
idx: u64,
secret: [u8; 32],
},
- /// Indicates our channel is likely a stale version, we're closing, but this update should
- /// allow us to spend what is ours if our counterparty broadcasts their latest state.
- RescueRemoteCommitmentTXInfo {
- their_current_per_commitment_point: PublicKey,
- },
/// Used to indicate that the no future updates will occur, and likely that the latest local
/// commitment transaction(s) should be broadcast, as the channel has been force-closed.
ChannelForceClosed {
idx.write(w)?;
secret.write(w)?;
},
- &ChannelMonitorUpdateStep::RescueRemoteCommitmentTXInfo { ref their_current_per_commitment_point } => {
- 4u8.write(w)?;
- their_current_per_commitment_point.write(w)?;
- },
&ChannelMonitorUpdateStep::ChannelForceClosed { ref should_broadcast } => {
- 5u8.write(w)?;
+ 4u8.write(w)?;
should_broadcast.write(w)?;
},
}
})
},
4u8 => {
- Ok(ChannelMonitorUpdateStep::RescueRemoteCommitmentTXInfo {
- their_current_per_commitment_point: Readable::read(r)?,
- })
- },
- 5u8 => {
Ok(ChannelMonitorUpdateStep::ChannelForceClosed {
should_broadcast: Readable::read(r)?
})
destination_script: Script,
broadcasted_local_revokable_script: Option<(Script, SecretKey, Script)>,
- broadcasted_remote_payment_script: Option<(Script, SecretKey)>,
+ remote_payment_script: Script,
shutdown_script: Script,
keys: ChanSigner,
funding_info: (OutPoint, Script),
- current_remote_commitment_txid: Option<Sha256dHash>,
- prev_remote_commitment_txid: Option<Sha256dHash>,
+ current_remote_commitment_txid: Option<Txid>,
+ prev_remote_commitment_txid: Option<Txid>,
their_htlc_base_key: PublicKey,
their_delayed_payment_base_key: PublicKey,
their_to_self_delay: u16,
commitment_secrets: CounterpartyCommitmentSecrets,
- remote_claimable_outpoints: HashMap<Sha256dHash, Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>>,
+ remote_claimable_outpoints: HashMap<Txid, Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>>,
/// We cannot identify HTLC-Success or HTLC-Timeout transactions by themselves on the chain.
/// Nor can we figure out their commitment numbers without the commitment transaction they are
/// spending. Thus, in order to claim them via revocation key, we track all the remote
/// commitment transactions which we find on-chain, mapping them to the commitment number which
/// can be used to derive the revocation key and claim the transactions.
- remote_commitment_txn_on_chain: HashMap<Sha256dHash, (u64, Vec<Script>)>,
+ remote_commitment_txn_on_chain: HashMap<Txid, (u64, Vec<Script>)>,
/// Cache used to make pruning of payment_preimages faster.
/// Maps payment_hash values to commitment numbers for remote transactions for non-revoked
/// remote transactions (ie should remain pretty small).
// interface knows about the TXOs that we want to be notified of spends of. We could probably
// be smart and derive them from the above storage fields, but its much simpler and more
// Obviously Correct (tm) if we just keep track of them explicitly.
- outputs_to_watch: HashMap<Sha256dHash, Vec<Script>>,
+ outputs_to_watch: HashMap<Txid, Vec<Script>>,
#[cfg(test)]
pub onchain_tx_handler: OnchainTxHandler<ChanSigner>,
// (we do *not*, however, update them in update_monitor to ensure any local user copies keep
// their last_block_hash from its state and not based on updated copies that didn't run through
// the full block_connected).
- pub(crate) last_block_hash: Sha256dHash,
+ pub(crate) last_block_hash: BlockHash,
secp_ctx: Secp256k1<secp256k1::All>, //TODO: dedup this a bit...
- logger: Arc<Logger>,
}
#[cfg(any(test, feature = "fuzztarget"))]
self.commitment_transaction_number_obscure_factor != other.commitment_transaction_number_obscure_factor ||
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.remote_payment_script != other.remote_payment_script ||
self.keys.pubkeys() != other.keys.pubkeys() ||
self.funding_info != other.funding_info ||
self.current_remote_commitment_txid != other.current_remote_commitment_txid ||
writer.write_all(&[1; 1])?;
}
- if let Some(ref broadcasted_remote_payment_script) = self.broadcasted_remote_payment_script {
- writer.write_all(&[0; 1])?;
- broadcasted_remote_payment_script.0.write(writer)?;
- broadcasted_remote_payment_script.1.write(writer)?;
- } else {
- writer.write_all(&[1; 1])?;
- }
+ self.remote_payment_script.write(writer)?;
self.shutdown_script.write(writer)?;
self.keys.write(writer)?;
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> {
+ initial_local_commitment_tx: LocalCommitmentTransaction) -> ChannelMonitor<ChanSigner> {
assert!(commitment_transaction_number_obscure_factor <= (1 << 48));
- let our_channel_close_key_hash = Hash160::hash(&shutdown_pubkey.serialize());
+ let our_channel_close_key_hash = WPubkeyHash::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 payment_key_hash = WPubkeyHash::hash(&keys.pubkeys().payment_point.serialize());
+ let remote_payment_script = Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&payment_key_hash[..]).into_script();
- let mut onchain_tx_handler = OnchainTxHandler::new(destination_script.clone(), keys.clone(), their_to_self_delay, logger.clone());
+ let mut onchain_tx_handler = OnchainTxHandler::new(destination_script.clone(), keys.clone(), their_to_self_delay);
- 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_tx_sequence = initial_local_commitment_tx.unsigned_tx.input[0].sequence as u64;
+ let local_tx_locktime = initial_local_commitment_tx.unsigned_tx.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,
destination_script: destination_script.clone(),
broadcasted_local_revokable_script: None,
- broadcasted_remote_payment_script: None,
+ remote_payment_script,
shutdown_script,
keys,
last_block_hash: Default::default(),
secp_ctx: Secp256k1::new(),
- logger,
}
}
/// The monitor watches for it to be broadcasted and then uses the HTLC information (and
/// possibly future revocation/preimage information) to claim outputs where possible.
/// We cache also the mapping hash:commitment number to lighten pruning of old preimages by watchtowers.
- pub(super) fn provide_latest_remote_commitment_tx_info(&mut self, unsigned_commitment_tx: &Transaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>, commitment_number: u64, their_revocation_point: PublicKey) {
+ pub(super) fn provide_latest_remote_commitment_tx_info<L: Deref>(&mut self, unsigned_commitment_tx: &Transaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Box<HTLCSource>>)>, commitment_number: u64, their_revocation_point: PublicKey, logger: &L) where L::Target: Logger {
// TODO: Encrypt the htlc_outputs data with the single-hash of the commitment transaction
// so that a remote monitor doesn't learn anything unless there is a malicious close.
// (only maybe, sadly we cant do the same for local info, as we need to be aware of
}
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));
+ log_trace!(logger, "Tracking new remote commitment transaction with txid {} at commitment number {} with {} HTLC outputs", new_txid, commitment_number, htlc_outputs.len());
+ log_trace!(logger, "New potential remote commitment transaction: {}", encode::serialize_hex(unsigned_commitment_tx));
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);
}
}
- 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.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.keys.payment_base_key()) {
- self.broadcasted_remote_payment_script = Some((to_remote_script, to_remote_key));
- }
- }
- }
-
/// Informs this monitor of the latest local (ie broadcastable) commitment transaction. The
/// monitor watches for timeouts and may broadcast it if we approach such a timeout. Thus, it
/// is important that any clones of this channel monitor (including remote clones) by kept
return Err(MonitorUpdateError("A local commitment tx has already been signed, no new local commitment txn can be sent to our counterparty"));
}
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 sequence = commitment_tx.unsigned_tx.input[0].sequence as u64;
+ let locktime = commitment_tx.unsigned_tx.lock_time as u64;
let mut new_local_commitment_tx = LocalSignedTx {
txid,
revocation_key: commitment_tx.local_keys.revocation_key,
self.payment_preimages.insert(payment_hash.clone(), payment_preimage.clone());
}
- pub(super) fn broadcast_latest_local_commitment_txn<B: Deref>(&mut self, broadcaster: &B)
+ pub(super) fn broadcast_latest_local_commitment_txn<B: Deref, L: Deref>(&mut self, broadcaster: &B, logger: &L)
where B::Target: BroadcasterInterface,
+ L::Target: Logger,
{
- for tx in self.get_latest_local_commitment_txn().iter() {
+ for tx in self.get_latest_local_commitment_txn(logger).iter() {
broadcaster.broadcast_transaction(tx);
}
}
/// 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> {
+ pub(super) fn update_monitor_ooo<L: Deref>(&mut self, mut updates: ChannelMonitorUpdate, logger: &L) -> Result<(), MonitorUpdateError> where L::Target: Logger {
for update in updates.updates.drain(..) {
match update {
ChannelMonitorUpdateStep::LatestLocalCommitmentTXInfo { commitment_tx, 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),
+ self.provide_latest_remote_commitment_tx_info(&unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point, logger),
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)?,
- ChannelMonitorUpdateStep::RescueRemoteCommitmentTXInfo { their_current_per_commitment_point } =>
- self.provide_rescue_remote_commitment_tx_info(their_current_per_commitment_point),
ChannelMonitorUpdateStep::ChannelForceClosed { .. } => {},
}
}
/// itself.
///
/// panics if the given update is not the next update by update_id.
- pub fn update_monitor<B: Deref>(&mut self, mut updates: ChannelMonitorUpdate, broadcaster: &B) -> Result<(), MonitorUpdateError>
+ pub fn update_monitor<B: Deref, L: Deref>(&mut self, mut updates: ChannelMonitorUpdate, broadcaster: &B, logger: &L) -> Result<(), MonitorUpdateError>
where B::Target: BroadcasterInterface,
+ L::Target: Logger,
{
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!");
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),
+ self.provide_latest_remote_commitment_tx_info(&unsigned_commitment_tx, htlc_outputs, commitment_number, their_revocation_point, logger),
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)?,
- ChannelMonitorUpdateStep::RescueRemoteCommitmentTXInfo { their_current_per_commitment_point } =>
- self.provide_rescue_remote_commitment_tx_info(their_current_per_commitment_point),
ChannelMonitorUpdateStep::ChannelForceClosed { should_broadcast } => {
self.lockdown_from_offchain = true;
if should_broadcast {
- self.broadcast_latest_local_commitment_txn(broadcaster);
+ self.broadcast_latest_local_commitment_txn(broadcaster, logger);
} else {
- log_error!(self, "You have a toxic local commitment transaction avaible in channel monitor, read comment in ChannelMonitor::get_latest_local_commitment_txn to be informed of manual action to take");
+ log_error!(logger, "You have a toxic local commitment transaction avaible in channel monitor, read comment in ChannelMonitor::get_latest_local_commitment_txn to be informed of manual action to take");
}
}
}
/// Gets a list of txids, with their output scripts (in the order they appear in the
/// transaction), which we must learn about spends of via block_connected().
- pub fn get_outputs_to_watch(&self) -> &HashMap<Sha256dHash, Vec<Script>> {
+ pub fn get_outputs_to_watch(&self) -> &HashMap<Txid, Vec<Script>> {
&self.outputs_to_watch
}
/// Generally useful when deserializing as during normal operation the return values of
/// block_connected are sufficient to ensure all relevant outpoints are being monitored (note
/// that the get_funding_txo outpoint and transaction must also be monitored for!).
- pub fn get_monitored_outpoints(&self) -> Vec<(Sha256dHash, u32, &Script)> {
+ pub fn get_monitored_outpoints(&self) -> Vec<(Txid, u32, &Script)> {
let mut res = Vec::with_capacity(self.remote_commitment_txn_on_chain.len() * 2);
for (ref txid, &(_, ref outputs)) in self.remote_commitment_txn_on_chain.iter() {
for (idx, output) in outputs.iter().enumerate() {
/// HTLC-Success/HTLC-Timeout transactions.
/// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
/// revoked remote commitment tx
- fn check_spend_remote_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec<ClaimRequest>, (Sha256dHash, Vec<TxOut>)) {
+ fn check_spend_remote_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec<ClaimRequest>, (Txid, Vec<TxOut>)) where L::Target: Logger {
// Most secp and related errors trying to create keys means we have no hope of constructing
// a spend transaction...so we return no transactions to broadcast
let mut claimable_outpoints = Vec::new();
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();
- self.broadcasted_remote_payment_script = {
- // Note that the Network here is ignored as we immediately drop the address for the
- // script_pubkey version
- let payment_hash160 = Hash160::hash(&PublicKey::from_secret_key(&self.secp_ctx, &local_payment_key).serialize());
- Some((Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&payment_hash160[..]).into_script(), local_payment_key))
- };
-
// First, process non-htlc outputs (to_local & to_remote)
for (idx, outp) in tx.output.iter().enumerate() {
if outp.script_pubkey == revokeable_p2wsh {
// Last, track onchain revoked commitment transaction and fail backward outgoing HTLCs as payment path is broken
if !claimable_outpoints.is_empty() || per_commitment_option.is_some() { // ie we're confident this is actually ours
// We're definitely a remote commitment transaction!
- log_trace!(self, "Got broadcast of revoked remote commitment transaction, going to generate general spend tx with {} inputs", claimable_outpoints.len());
+ log_trace!(logger, "Got broadcast of revoked remote commitment transaction, going to generate general spend tx with {} inputs", claimable_outpoints.len());
watch_outputs.append(&mut tx.output.clone());
self.remote_commitment_txn_on_chain.insert(commitment_txid, (commitment_number, tx.output.iter().map(|output| { output.script_pubkey.clone() }).collect()));
if let Some(ref outpoints) = self.remote_claimable_outpoints.get($txid) {
for &(ref htlc, ref source_option) in outpoints.iter() {
if let &Some(ref source) = source_option {
- log_info!(self, "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of revoked remote commitment transaction, waiting for confirmation (at height {})", log_bytes!(htlc.payment_hash.0), $commitment_tx, height + ANTI_REORG_DELAY - 1);
+ log_info!(logger, "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of revoked remote commitment transaction, waiting for confirmation (at height {})", log_bytes!(htlc.payment_hash.0), $commitment_tx, height + ANTI_REORG_DELAY - 1);
match self.onchain_events_waiting_threshold_conf.entry(height + ANTI_REORG_DELAY - 1) {
hash_map::Entry::Occupied(mut entry) => {
let e = entry.get_mut();
watch_outputs.append(&mut tx.output.clone());
self.remote_commitment_txn_on_chain.insert(commitment_txid, (commitment_number, tx.output.iter().map(|output| { output.script_pubkey.clone() }).collect()));
- log_trace!(self, "Got broadcast of non-revoked remote commitment transaction {}", commitment_txid);
+ log_trace!(logger, "Got broadcast of non-revoked remote commitment transaction {}", commitment_txid);
macro_rules! check_htlc_fails {
($txid: expr, $commitment_tx: expr, $id: tt) => {
continue $id;
}
}
- log_trace!(self, "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of remote commitment transaction", log_bytes!(htlc.payment_hash.0), $commitment_tx);
+ log_trace!(logger, "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of remote commitment transaction", log_bytes!(htlc.payment_hash.0), $commitment_tx);
match self.onchain_events_waiting_threshold_conf.entry(height + ANTI_REORG_DELAY - 1) {
hash_map::Entry::Occupied(mut entry) => {
let e = entry.get_mut();
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
- // script_pubkey version
- let payment_hash160 = Hash160::hash(&PublicKey::from_secret_key(&self.secp_ctx, &local_payment_key).serialize());
- Some((Builder::new().push_opcode(opcodes::all::OP_PUSHBYTES_0).push_slice(&payment_hash160[..]).into_script(), local_payment_key))
- };
// Then, try to find htlc outputs
for (_, &(ref htlc, _)) in per_commitment_data.iter().enumerate() {
}
/// Attempts to claim a remote HTLC-Success/HTLC-Timeout's outputs using the revocation key
- fn check_spend_remote_htlc(&mut self, tx: &Transaction, commitment_number: u64, height: u32) -> (Vec<ClaimRequest>, Option<(Sha256dHash, Vec<TxOut>)>) {
+ fn check_spend_remote_htlc<L: Deref>(&mut self, tx: &Transaction, commitment_number: u64, height: u32, logger: &L) -> (Vec<ClaimRequest>, Option<(Txid, Vec<TxOut>)>) where L::Target: Logger {
let htlc_txid = tx.txid();
if tx.input.len() != 1 || tx.output.len() != 1 || tx.input[0].witness.len() != 5 {
return (Vec::new(), None)
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);
+ log_trace!(logger, "Remote HTLC broadcast {}:{}", htlc_txid, 0);
let witness_data = InputMaterial::Revoked { witness_script: redeemscript, pubkey: Some(revocation_pubkey), key: revocation_key, is_htlc: false, amount: tx.output[0].value };
let claimable_outpoints = vec!(ClaimRequest { absolute_timelock: height + self.our_to_self_delay as u32, aggregable: true, outpoint: BitcoinOutPoint { txid: htlc_txid, vout: 0}, witness_data });
(claimable_outpoints, Some((htlc_txid, tx.output.clone())))
for &(ref htlc, _, _) in local_tx.htlc_outputs.iter() {
if let Some(transaction_output_index) = htlc.transaction_output_index {
- let preimage = if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) { Some(*preimage) } else { None };
- claim_requests.push(ClaimRequest { absolute_timelock: ::std::u32::MAX, aggregable: false, outpoint: BitcoinOutPoint { txid: local_tx.txid, vout: transaction_output_index as u32 }, witness_data: InputMaterial::LocalHTLC { preimage, amount: htlc.amount_msat / 1000 }});
+ claim_requests.push(ClaimRequest { absolute_timelock: ::std::u32::MAX, aggregable: false, outpoint: BitcoinOutPoint { txid: local_tx.txid, vout: transaction_output_index as u32 },
+ witness_data: InputMaterial::LocalHTLC {
+ preimage: if !htlc.offered {
+ if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) {
+ Some(preimage.clone())
+ } else {
+ // We can't build an HTLC-Success transaction without the preimage
+ continue;
+ }
+ } else { None },
+ amount: htlc.amount_msat,
+ }});
watch_outputs.push(commitment_tx.output[transaction_output_index as usize].clone());
}
}
/// Attempts to claim any claimable HTLCs in a commitment transaction which was not (yet)
/// revoked using data in local_claimable_outpoints.
/// Should not be used if check_spend_revoked_transaction succeeds.
- fn check_spend_local_transaction(&mut self, tx: &Transaction, height: u32) -> (Vec<ClaimRequest>, (Sha256dHash, Vec<TxOut>)) {
+ fn check_spend_local_transaction<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) -> (Vec<ClaimRequest>, (Txid, Vec<TxOut>)) where L::Target: Logger {
let commitment_txid = tx.txid();
let mut claim_requests = Vec::new();
let mut watch_outputs = Vec::new();
macro_rules! wait_threshold_conf {
($height: expr, $source: expr, $commitment_tx: expr, $payment_hash: expr) => {
- log_trace!(self, "Failing HTLC with payment_hash {} from {} local commitment tx due to broadcast of transaction, waiting confirmation (at height{})", log_bytes!($payment_hash.0), $commitment_tx, height + ANTI_REORG_DELAY - 1);
+ log_trace!(logger, "Failing HTLC with payment_hash {} from {} local commitment tx due to broadcast of transaction, waiting confirmation (at height{})", log_bytes!($payment_hash.0), $commitment_tx, height + ANTI_REORG_DELAY - 1);
match self.onchain_events_waiting_threshold_conf.entry($height + ANTI_REORG_DELAY - 1) {
hash_map::Entry::Occupied(mut entry) => {
let e = entry.get_mut();
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");
+ log_trace!(logger, "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");
+ log_trace!(logger, "Got previous 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);
}
/// substantial amount of time (a month or even a year) to get back funds. Best may be to contact
/// out-of-band the other node operator to coordinate with him if option is available to you.
/// 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!");
+ pub fn get_latest_local_commitment_txn<L: Deref>(&mut self, logger: &L) -> Vec<Transaction> where L::Target: Logger {
+ log_trace!(logger, "Getting signed latest local commitment transaction!");
self.local_tx_signed = true;
- if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx() {
+ if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx(&self.funding_redeemscript) {
let txid = commitment_tx.txid();
let mut res = vec![commitment_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) {
+ if let Some(vout) = htlc.0.transaction_output_index {
+ let preimage = if !htlc.0.offered {
+ if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(preimage.clone()) } else {
+ // We can't build an HTLC-Success transaction without the preimage
+ continue;
+ }
+ } else { None };
+ if let Some(htlc_tx) = self.onchain_tx_handler.get_fully_signed_htlc_tx(
+ &::bitcoin::OutPoint { txid, vout }, &preimage) {
res.push(htlc_tx);
}
}
/// to bypass LocalCommitmentTransaction state update lockdown after signature and generate
/// revoked commitment transaction.
#[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() {
+ pub fn unsafe_get_latest_local_commitment_txn<L: Deref>(&mut self, logger: &L) -> Vec<Transaction> where L::Target: Logger {
+ log_trace!(logger, "Getting signed copy of latest local commitment transaction!");
+ if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_copy_local_tx(&self.funding_redeemscript) {
let txid = commitment_tx.txid();
let mut res = vec![commitment_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) {
+ if let Some(vout) = htlc.0.transaction_output_index {
+ let preimage = if !htlc.0.offered {
+ if let Some(preimage) = self.payment_preimages.get(&htlc.0.payment_hash) { Some(preimage.clone()) } else {
+ // We can't build an HTLC-Success transaction without the preimage
+ continue;
+ }
+ } else { None };
+ if let Some(htlc_tx) = self.onchain_tx_handler.unsafe_get_fully_signed_htlc_tx(
+ &::bitcoin::OutPoint { txid, vout }, &preimage) {
res.push(htlc_tx);
}
}
Vec::new()
}
- /// Called by SimpleManyChannelMonitor::block_connected, which implements
- /// ChainListener::block_connected.
- /// Eventually this should be pub and, roughly, implement ChainListener, however this requires
- /// &mut self, as well as returns new spendable outputs and outpoints to watch for spending of
- /// on-chain.
- fn block_connected<B: Deref, F: Deref>(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &Sha256dHash, broadcaster: B, fee_estimator: F)-> Vec<(Sha256dHash, Vec<TxOut>)>
+ /// Called when a new block has been connected to the best chain by <SimpleManyChannelMonitor
+ /// as ChainListener>::block_connected, and should thus generally not be called during normal
+ /// operation. It is exposed both for users who wish to use ChannelMonitors directly and to
+ /// simplify rescans that occur at load-time.
+ ///
+ /// This is very similar to ChainListener::block_connected itself, but requires an &mut self,
+ /// and an explicit reference to a transaction broadcaster and fee estimator.
+ ///
+ /// Returns a list of new (txid, outputs) pairs which spends of must be watched for. Note that
+ /// after this call these are also available via get_outputs_to_watch().
+ pub fn block_connected<B: Deref, F: Deref, L: Deref>(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)-> Vec<(Txid, Vec<TxOut>)>
where B::Target: BroadcasterInterface,
- F::Target: FeeEstimator
+ F::Target: FeeEstimator,
+ L::Target: Logger,
{
for tx in txn_matched {
let mut output_val = 0;
}
}
- log_trace!(self, "Block {} at height {} connected with {} txn matched", block_hash, height, txn_matched.len());
+ log_trace!(logger, "Block {} at height {} connected with {} txn matched", block_hash, height, txn_matched.len());
let mut watch_outputs = Vec::new();
let mut claimable_outpoints = Vec::new();
for tx in txn_matched {
let prevout = &tx.input[0].previous_output;
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);
+ let (mut new_outpoints, new_outputs) = self.check_spend_remote_transaction(&tx, height, &logger);
if !new_outputs.1.is_empty() {
watch_outputs.push(new_outputs);
}
if new_outpoints.is_empty() {
- let (mut new_outpoints, new_outputs) = self.check_spend_local_transaction(&tx, height);
+ let (mut new_outpoints, new_outputs) = self.check_spend_local_transaction(&tx, height, &logger);
if !new_outputs.1.is_empty() {
watch_outputs.push(new_outputs);
}
}
} else {
if let Some(&(commitment_number, _)) = self.remote_commitment_txn_on_chain.get(&prevout.txid) {
- let (mut new_outpoints, new_outputs_option) = self.check_spend_remote_htlc(&tx, commitment_number, height);
+ let (mut new_outpoints, new_outputs_option) = self.check_spend_remote_htlc(&tx, commitment_number, height, &logger);
claimable_outpoints.append(&mut new_outpoints);
if let Some(new_outputs) = new_outputs_option {
watch_outputs.push(new_outputs);
// While all commitment/HTLC-Success/HTLC-Timeout transactions have one input, HTLCs
// can also be resolved in a few other ways which can have more than one output. Thus,
// we call is_resolving_htlc_output here outside of the tx.input.len() == 1 check.
- self.is_resolving_htlc_output(&tx, height);
+ self.is_resolving_htlc_output(&tx, height, &logger);
- self.is_paying_spendable_output(&tx, height);
+ self.is_paying_spendable_output(&tx, height, &logger);
}
- let should_broadcast = self.would_broadcast_at_height(height);
+ let should_broadcast = self.would_broadcast_at_height(height, &logger);
if should_broadcast {
- 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 {}});
+ 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 { funding_redeemscript: self.funding_redeemscript.clone() }});
}
if should_broadcast {
- if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx() {
+ if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_local_tx(&self.funding_redeemscript) {
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));
for ev in events {
match ev {
OnchainEvent::HTLCUpdate { htlc_update } => {
- log_trace!(self, "HTLC {} failure update has got enough confirmations to be passed upstream", log_bytes!((htlc_update.1).0));
+ log_trace!(logger, "HTLC {} failure update has got enough confirmations to be passed upstream", log_bytes!((htlc_update.1).0));
self.pending_htlcs_updated.push(HTLCUpdate {
payment_hash: htlc_update.1,
payment_preimage: None,
});
},
OnchainEvent::MaturingOutput { descriptor } => {
- log_trace!(self, "Descriptor {} has got enough confirmations to be passed upstream", log_spendable!(descriptor));
+ log_trace!(logger, "Descriptor {} has got enough confirmations to be passed upstream", log_spendable!(descriptor));
self.pending_events.push(events::Event::SpendableOutputs {
outputs: vec![descriptor]
});
}
}
}
- self.onchain_tx_handler.block_connected(txn_matched, claimable_outpoints, height, &*broadcaster, &*fee_estimator);
+ self.onchain_tx_handler.block_connected(txn_matched, claimable_outpoints, height, &*broadcaster, &*fee_estimator, &*logger);
self.last_block_hash = block_hash.clone();
for &(ref txid, ref output_scripts) in watch_outputs.iter() {
watch_outputs
}
- fn block_disconnected<B: Deref, F: Deref>(&mut self, height: u32, block_hash: &Sha256dHash, broadcaster: B, fee_estimator: F)
+ /// Called when a block has been disconnected from the best chain by <SimpleManyChannelMonitor
+ /// as ChainListener>::block_disconnected, and should thus generally not be called during
+ /// normal operation. It is exposed both for users who wish to use ChannelMonitors directly and
+ /// to simplify rescans that occur at load-time.
+ ///
+ /// This is very similar to ChainListener::block_disconnected itself, but requires an &mut self,
+ /// and an explicit reference to a transaction broadcaster and fee estimator.
+ pub fn block_disconnected<B: Deref, F: Deref, L: Deref>(&mut self, height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F, logger: L)
where B::Target: BroadcasterInterface,
- F::Target: FeeEstimator
+ F::Target: FeeEstimator,
+ L::Target: Logger,
{
- log_trace!(self, "Block {} at height {} disconnected", block_hash, height);
+ log_trace!(logger, "Block {} at height {} disconnected", block_hash, height);
if let Some(_) = self.onchain_events_waiting_threshold_conf.remove(&(height + ANTI_REORG_DELAY - 1)) {
//We may discard:
//- htlc update there as failure-trigger tx (revoked commitment tx, non-revoked commitment tx, HTLC-timeout tx) has been disconnected
//- maturing spendable output has transaction paying us has been disconnected
}
- self.onchain_tx_handler.block_disconnected(height, broadcaster, fee_estimator);
+ self.onchain_tx_handler.block_disconnected(height, broadcaster, fee_estimator, logger);
self.last_block_hash = block_hash.clone();
}
- pub(super) fn would_broadcast_at_height(&self, height: u32) -> bool {
+ pub(super) fn would_broadcast_at_height<L: Deref>(&self, height: u32, logger: &L) -> bool where L::Target: Logger {
// We need to consider all HTLCs which are:
// * in any unrevoked remote commitment transaction, as they could broadcast said
// transactions and we'd end up in a race, or
let htlc_outbound = $local_tx == htlc.offered;
if ( htlc_outbound && htlc.cltv_expiry + LATENCY_GRACE_PERIOD_BLOCKS <= height) ||
(!htlc_outbound && htlc.cltv_expiry <= height + CLTV_CLAIM_BUFFER && self.payment_preimages.contains_key(&htlc.payment_hash)) {
- log_info!(self, "Force-closing channel due to {} HTLC timeout, HTLC expiry is {}", if htlc_outbound { "outbound" } else { "inbound "}, htlc.cltv_expiry);
+ log_info!(logger, "Force-closing channel due to {} HTLC timeout, HTLC expiry is {}", if htlc_outbound { "outbound" } else { "inbound "}, htlc.cltv_expiry);
return true;
}
}
/// Check if any transaction broadcasted is resolving HTLC output by a success or timeout on a local
/// or remote commitment tx, if so send back the source, preimage if found and payment_hash of resolved HTLC
- fn is_resolving_htlc_output(&mut self, tx: &Transaction, height: u32) {
+ fn is_resolving_htlc_output<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) where L::Target: Logger {
'outer_loop: for input in &tx.input {
let mut payment_data = None;
let revocation_sig_claim = (input.witness.len() == 3 && HTLCType::scriptlen_to_htlctype(input.witness[2].len()) == Some(HTLCType::OfferedHTLC) && input.witness[1].len() == 33)
let outbound_htlc = $local_tx == $htlc.offered;
if ($local_tx && revocation_sig_claim) ||
(outbound_htlc && !$source_avail && (accepted_preimage_claim || offered_preimage_claim)) {
- log_error!(self, "Input spending {} ({}:{}) in {} resolves {} HTLC with payment hash {} with {}!",
+ log_error!(logger, "Input spending {} ({}:{}) in {} resolves {} HTLC with payment hash {} with {}!",
$tx_info, input.previous_output.txid, input.previous_output.vout, tx.txid(),
if outbound_htlc { "outbound" } else { "inbound" }, log_bytes!($htlc.payment_hash.0),
if revocation_sig_claim { "revocation sig" } else { "preimage claim after we'd passed the HTLC resolution back" });
} else {
- log_info!(self, "Input spending {} ({}:{}) in {} resolves {} HTLC with payment hash {} with {}",
+ log_info!(logger, "Input spending {} ({}:{}) in {} resolves {} HTLC with payment hash {} with {}",
$tx_info, input.previous_output.txid, input.previous_output.vout, tx.txid(),
if outbound_htlc { "outbound" } else { "inbound" }, log_bytes!($htlc.payment_hash.0),
if revocation_sig_claim { "revocation sig" } else if accepted_preimage_claim || offered_preimage_claim { "preimage" } else { "timeout" });
});
}
} else {
- log_info!(self, "Failing HTLC with payment_hash {} timeout by a spend tx, waiting for confirmation (at height{})", log_bytes!(payment_hash.0), height + ANTI_REORG_DELAY - 1);
+ log_info!(logger, "Failing HTLC with payment_hash {} timeout by a spend tx, waiting for confirmation (at height{})", log_bytes!(payment_hash.0), height + ANTI_REORG_DELAY - 1);
match self.onchain_events_waiting_threshold_conf.entry(height + ANTI_REORG_DELAY - 1) {
hash_map::Entry::Occupied(mut entry) => {
let e = entry.get_mut();
}
/// Check if any transaction broadcasted is paying fund back to some address we can assume to own
- fn is_paying_spendable_output(&mut self, tx: &Transaction, height: u32) {
+ fn is_paying_spendable_output<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) where L::Target: Logger {
let mut spendable_output = None;
for (i, outp) in tx.output.iter().enumerate() { // There is max one spendable output for any channel tx, including ones generated by us
if outp.script_pubkey == self.destination_script {
});
break;
}
- } else if let Some(ref broadcasted_remote_payment_script) = self.broadcasted_remote_payment_script {
- if broadcasted_remote_payment_script.0 == outp.script_pubkey {
- spendable_output = Some(SpendableOutputDescriptor::DynamicOutputP2WPKH {
- outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 },
- key: broadcasted_remote_payment_script.1,
- output: outp.clone(),
- });
- break;
- }
+ } else if self.remote_payment_script == outp.script_pubkey {
+ spendable_output = Some(SpendableOutputDescriptor::DynamicOutputP2WPKH {
+ outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 },
+ key: self.keys.payment_key().clone(),
+ output: outp.clone(),
+ });
+ break;
} else if outp.script_pubkey == self.shutdown_script {
spendable_output = Some(SpendableOutputDescriptor::StaticOutput {
outpoint: BitcoinOutPoint { txid: tx.txid(), vout: i as u32 },
}
}
if let Some(spendable_output) = spendable_output {
- log_trace!(self, "Maturing {} until {}", log_spendable!(spendable_output), height + ANTI_REORG_DELAY - 1);
+ log_trace!(logger, "Maturing {} until {}", log_spendable!(spendable_output), height + ANTI_REORG_DELAY - 1);
match self.onchain_events_waiting_threshold_conf.entry(height + ANTI_REORG_DELAY - 1) {
hash_map::Entry::Occupied(mut entry) => {
let e = entry.get_mut();
const MAX_ALLOC_SIZE: usize = 64*1024;
-impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (Sha256dHash, ChannelMonitor<ChanSigner>) {
- fn read<R: ::std::io::Read>(reader: &mut R, logger: Arc<Logger>) -> Result<Self, DecodeError> {
+impl<ChanSigner: ChannelKeys + Readable> Readable for (BlockHash, ChannelMonitor<ChanSigner>) {
+ fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
macro_rules! unwrap_obj {
($key: expr) => {
match $key {
1 => { None },
_ => return Err(DecodeError::InvalidValue),
};
- let broadcasted_remote_payment_script = match <u8 as Readable>::read(reader)? {
- 0 => {
- let payment_address = Readable::read(reader)?;
- let payment_key = Readable::read(reader)?;
- Some((payment_address, payment_key))
- },
- 1 => { None },
- _ => return Err(DecodeError::InvalidValue),
- };
+ let remote_payment_script = Readable::read(reader)?;
let shutdown_script = Readable::read(reader)?;
let keys = Readable::read(reader)?;
let remote_claimable_outpoints_len: u64 = Readable::read(reader)?;
let mut remote_claimable_outpoints = HashMap::with_capacity(cmp::min(remote_claimable_outpoints_len as usize, MAX_ALLOC_SIZE / 64));
for _ in 0..remote_claimable_outpoints_len {
- let txid: Sha256dHash = Readable::read(reader)?;
+ let txid: Txid = Readable::read(reader)?;
let htlcs_count: u64 = Readable::read(reader)?;
let mut htlcs = Vec::with_capacity(cmp::min(htlcs_count as usize, MAX_ALLOC_SIZE / 32));
for _ in 0..htlcs_count {
let remote_commitment_txn_on_chain_len: u64 = Readable::read(reader)?;
let mut remote_commitment_txn_on_chain = HashMap::with_capacity(cmp::min(remote_commitment_txn_on_chain_len as usize, MAX_ALLOC_SIZE / 32));
for _ in 0..remote_commitment_txn_on_chain_len {
- let txid: Sha256dHash = Readable::read(reader)?;
+ let txid: Txid = Readable::read(reader)?;
let commitment_number = <U48 as Readable>::read(reader)?.0;
let outputs_count = <u64 as Readable>::read(reader)?;
let mut outputs = Vec::with_capacity(cmp::min(outputs_count as usize, MAX_ALLOC_SIZE / 8));
}
}
- let last_block_hash: Sha256dHash = Readable::read(reader)?;
+ let last_block_hash: BlockHash = Readable::read(reader)?;
let waiting_threshold_conf_len: u64 = Readable::read(reader)?;
let mut onchain_events_waiting_threshold_conf = HashMap::with_capacity(cmp::min(waiting_threshold_conf_len as usize, MAX_ALLOC_SIZE / 128));
}
let outputs_to_watch_len: u64 = Readable::read(reader)?;
- let mut outputs_to_watch = HashMap::with_capacity(cmp::min(outputs_to_watch_len as usize, MAX_ALLOC_SIZE / (mem::size_of::<Sha256dHash>() + mem::size_of::<Vec<Script>>())));
+ let mut outputs_to_watch = HashMap::with_capacity(cmp::min(outputs_to_watch_len as usize, MAX_ALLOC_SIZE / (mem::size_of::<Txid>() + mem::size_of::<Vec<Script>>())));
for _ in 0..outputs_to_watch_len {
let txid = Readable::read(reader)?;
let outputs_len: u64 = Readable::read(reader)?;
return Err(DecodeError::InvalidValue);
}
}
- let onchain_tx_handler = ReadableArgs::read(reader, logger.clone())?;
+ let onchain_tx_handler = Readable::read(reader)?;
let lockdown_from_offchain = Readable::read(reader)?;
let local_tx_signed = Readable::read(reader)?;
destination_script,
broadcasted_local_revokable_script,
- broadcasted_remote_payment_script,
+ remote_payment_script,
shutdown_script,
keys,
last_block_hash,
secp_ctx: Secp256k1::new(),
- logger,
}))
}
}
use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut, SigHashType};
use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
use bitcoin::util::bip143;
- use bitcoin_hashes::Hash;
- use bitcoin_hashes::sha256::Hash as Sha256;
- use bitcoin_hashes::sha256d::Hash as Sha256dHash;
- use bitcoin_hashes::hex::FromHex;
+ use bitcoin::hashes::Hash;
+ use bitcoin::hashes::sha256::Hash as Sha256;
+ use bitcoin::hashes::hex::FromHex;
+ use bitcoin::hash_types::Txid;
use hex;
use chain::transaction::OutPoint;
use ln::channelmanager::{PaymentPreimage, PaymentHash};
use ln::chan_utils;
use ln::chan_utils::{HTLCOutputInCommitment, LocalCommitmentTransaction};
use util::test_utils::TestLogger;
- use secp256k1::key::{SecretKey,PublicKey};
- use secp256k1::Secp256k1;
+ use bitcoin::secp256k1::key::{SecretKey,PublicKey};
+ use bitcoin::secp256k1::Secp256k1;
use rand::{thread_rng,Rng};
use std::sync::Arc;
use chain::keysinterface::InMemoryChannelKeys;
// old state.
let mut monitor = ChannelMonitor::new(keys,
&PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap()), 0, &Script::new(),
- (OutPoint { txid: Sha256dHash::from_slice(&[43; 32]).unwrap(), index: 0 }, Script::new()),
+ (OutPoint { txid: Txid::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()),
- 10, Script::new(), 46, 0, LocalCommitmentTransaction::dummy(), logger.clone());
+ 10, Script::new(), 46, 0, LocalCommitmentTransaction::dummy());
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);
- monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key);
+ monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key, &logger);
+ monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[15..20]), 281474976710654, dummy_key, &logger);
+ monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key, &logger);
+ monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[18..20]), 281474976710652, dummy_key, &logger);
for &(ref preimage, ref hash) in preimages.iter() {
monitor.provide_payment_preimage(hash, preimage);
}
}
let script_pubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script();
- let txid = Sha256dHash::from_hex("56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d").unwrap();
+ let txid = Txid::from_hex("56944c5d3f98413ef45cf54545538103cc9f298e0575820ad3591376e2e0f65d").unwrap();
// Justice tx with 1 to_local, 2 revoked offered HTLCs, 1 revoked received HTLCs
let mut claim_tx = Transaction { version: 0, lock_time: 0, input: Vec::new(), output: Vec::new() };