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;
/// 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;
+/// 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 {
/// 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,
amount: u64,
},
Funding {
- channel_value: u64,
+ funding_redeemscript: Script,
}
}
preimage.write(writer)?;
writer.write_all(&byte_utils::be64_to_array(*amount))?;
},
- &InputMaterial::Funding { ref channel_value } => {
+ &InputMaterial::Funding { ref funding_redeemscript } => {
writer.write_all(&[3; 1])?;
- channel_value.write(writer)?;
+ funding_redeemscript.write(writer)?;
}
}
Ok(())
}
},
3 => {
- let channel_value = Readable::read(reader)?;
InputMaterial::Funding {
- channel_value
+ funding_redeemscript: Readable::read(reader)?,
}
}
_ => return Err(DecodeError::InvalidValue),
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).
// 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
// 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>,
#[cfg(not(test))]
onchain_tx_handler: OnchainTxHandler<ChanSigner>,
- // Used to detect programming bug due to unsafe monitor update sequence { ChannelForceClosed, LatestLocalCommitmentTXInfo }
+ // This is set when the Channel[Manager] generated a ChannelMonitorUpdate which indicated the
+ // channel has been force-closed. After this is set, no further local commitment transaction
+ // updates may occur, and we panic!() if one is provided.
lockdown_from_offchain: bool,
+ // Set once we've signed a local commitment transaction and handed it over to our
+ // OnchainTxHandler. After this is set, no future updates to our local commitment transactions
+ // may occur, and we fail any such monitor updates.
+ local_tx_signed: bool,
+
// We simply modify last_block_hash in Channel's block_connected so that serialization is
// consistent but hopefully the users' copy handles block_connected in a consistent way.
// (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>,
}
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
self.onchain_events_waiting_threshold_conf != other.onchain_events_waiting_threshold_conf ||
- self.outputs_to_watch != other.outputs_to_watch
+ self.outputs_to_watch != other.outputs_to_watch ||
+ self.lockdown_from_offchain != other.lockdown_from_offchain ||
+ self.local_tx_signed != other.local_tx_signed
{
false
} else {
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])?;
- }
+ serialize_local_tx!(self.current_local_commitment_tx);
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))?;
self.onchain_tx_handler.write(writer)?;
self.lockdown_from_offchain.write(writer)?;
+ self.local_tx_signed.write(writer)?;
Ok(())
}
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 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 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.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,
+ 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,
commitment_transaction_number_obscure_factor,
broadcasted_remote_payment_script: None,
shutdown_script,
- keys: keys.clone(),
+ 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: funding_redeemscript.clone(),
+ funding_redeemscript,
channel_value_satoshis: channel_value_satoshis,
their_cur_revocation_points: None,
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, their_to_self_delay, logger.clone()),
+ onchain_tx_handler,
lockdown_from_offchain: false,
+ local_tx_signed: false,
last_block_hash: Default::default(),
secp_ctx: Secp256k1::new(),
}
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
}
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())[..])
+ .push_slice(&WPubkeyHash::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));
/// up-to-date as our local commitment transaction is updated.
/// Panics if set_their_to_self_delay has never been called.
pub(super) fn provide_latest_local_commitment_tx_info(&mut self, commitment_tx: LocalCommitmentTransaction, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>) -> Result<(), MonitorUpdateError> {
+ if self.local_tx_signed {
+ 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 new_local_signed_commitment_tx = LocalSignedTx {
+ 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,
a_htlc_key: commitment_tx.local_keys.a_htlc_key,
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(new_local_signed_commitment_tx);
+ 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(())
}
/// 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(&mut self, tx: &Transaction, height: u32) -> (Vec<ClaimRequest>, (Txid, Vec<TxOut>)) {
// 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();
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());
+ let payment_hash160 = WPubkeyHash::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))
};
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());
+ let payment_hash160 = WPubkeyHash::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))
};
}
/// 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(&mut self, tx: &Transaction, commitment_number: u64, height: u32) -> (Vec<ClaimRequest>, Option<(Txid, Vec<TxOut>)>) {
let htlc_txid = tx.txid();
if tx.input.len() != 1 || tx.output.len() != 1 || tx.input[0].witness.len() != 5 {
return (Vec::new(), None)
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(&mut self, tx: &Transaction, height: u32) -> (Vec<ClaimRequest>, (Txid, Vec<TxOut>)) {
let commitment_txid = tx.txid();
let mut claim_requests = Vec::new();
let mut watch_outputs = Vec::new();
// 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.local_tx_signed = true;
+ 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];
- 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(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);
}
}
- // 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() {
+ 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];
- 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(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);
}
}
}
/// 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>)>
+ fn block_connected<B: Deref, F: Deref>(&mut self, txn_matched: &[&Transaction], height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F)-> Vec<(Txid, Vec<TxOut>)>
where B::Target: BroadcasterInterface,
F::Target: FeeEstimator
{
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.funding_info.0.txid.clone(), vout: self.funding_info.0.index as u32 }, witness_data: InputMaterial::Funding { channel_value: self.channel_value_satoshis }});
- }
- 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() {
- 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 { funding_redeemscript: self.funding_redeemscript.clone() }});
+ }
+ if should_broadcast {
+ 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));
}
+ claimable_outpoints.append(&mut new_outpoints);
}
}
if let Some(events) = self.onchain_events_waiting_threshold_conf.remove(&height) {
watch_outputs
}
- fn block_disconnected<B: Deref, F: Deref>(&mut self, height: u32, block_hash: &Sha256dHash, broadcaster: B, fee_estimator: F)
+ fn block_disconnected<B: Deref, F: Deref>(&mut self, height: u32, block_hash: &BlockHash, broadcaster: B, fee_estimator: F)
where B::Target: BroadcasterInterface,
F::Target: FeeEstimator
{
}
}
- 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.current_remote_commitment_txid {
if let Some(ref htlc_outputs) = self.remote_claimable_outpoints.get(txid) {
}
}
- 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 {
const MAX_ALLOC_SIZE: usize = 64*1024;
-impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (Sha256dHash, ChannelMonitor<ChanSigner>) {
+impl<ChanSigner: ChannelKeys + Readable> ReadableArgs<Arc<Logger>> for (BlockHash, ChannelMonitor<ChanSigner>) {
fn read<R: ::std::io::Read>(reader: &mut R, logger: Arc<Logger>) -> Result<Self, DecodeError> {
macro_rules! unwrap_obj {
($key: expr) => {
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));
},
_ => 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;
}
}
- 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)?;
let onchain_tx_handler = ReadableArgs::read(reader, logger.clone())?;
let lockdown_from_offchain = Readable::read(reader)?;
+ let local_tx_signed = Readable::read(reader)?;
Ok((last_block_hash.clone(), ChannelMonitor {
latest_update_id,
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,
onchain_tx_handler,
lockdown_from_offchain,
+ local_tx_signed,
last_block_hash,
secp_ctx: Secp256k1::new(),
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, logger.clone());
+ 10, Script::new(), 46, 0, LocalCommitmentTransaction::dummy(), logger.clone());
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);
}
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() };