Rewrite channelmonitor framework and implement a bunch of it

This commit is contained in:
Matt Corallo 2018-04-24 00:19:52 -04:00
parent 7400b3bb7c
commit 2d8afeccdb
6 changed files with 1169 additions and 459 deletions

View file

@ -15,7 +15,7 @@ use crypto::sha2::Sha256;
use crypto::digest::Digest;
use lightning::chain::chaininterface::{BroadcasterInterface,ConfirmationTarget,ChainListener,FeeEstimator,ChainWatchInterfaceUtil};
use lightning::ln::{channelmonitor,msgs};
use lightning::ln::channelmonitor;
use lightning::ln::channelmanager::ChannelManager;
use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor};
use lightning::ln::router::Router;
@ -93,7 +93,7 @@ impl FeeEstimator for FuzzEstimator {
struct TestChannelMonitor {}
impl channelmonitor::ManyChannelMonitor for TestChannelMonitor {
fn add_update_monitor(&self, _funding_txo: (Sha256dHash, u16), _monitor: channelmonitor::ChannelMonitor) -> Result<(), msgs::HandleError> {
fn add_update_monitor(&self, _funding_txo: (Sha256dHash, u16), _monitor: channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
//TODO!
Ok(())
}

View file

@ -1,6 +1,7 @@
use bitcoin::blockdata::script::{Script,Builder};
use bitcoin::blockdata::opcodes;
use bitcoin::util::hash::Hash160;
use bitcoin::blockdata::transaction::{TxIn,TxOut,Transaction};
use bitcoin::util::hash::{Hash160,Sha256dHash};
use secp256k1::key::{PublicKey,SecretKey};
use secp256k1::Secp256k1;
@ -11,6 +12,9 @@ use crypto::ripemd160::Ripemd160;
use util::sha2::Sha256;
pub const HTLC_SUCCESS_TX_WEIGHT: u64 = 703;
pub const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663;
// Various functions for key derivation and transaction creation for use within channels. Primarily
// used in Channel and ChannelMonitor.
@ -233,3 +237,33 @@ pub fn get_htlc_redeemscript_with_explicit_keys(htlc: &HTLCOutputInCommitment, a
pub fn get_htlc_redeemscript(htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Script {
get_htlc_redeemscript_with_explicit_keys(htlc, &keys.a_htlc_key, &keys.b_htlc_key, &keys.revocation_key)
}
pub fn build_htlc_transaction(prev_hash: &Sha256dHash, feerate_per_kw: u64, to_self_delay: u16, htlc: &HTLCOutputInCommitment, a_delayed_payment_key: &PublicKey, revocation_key: &PublicKey) -> Transaction {
let mut txins: Vec<TxIn> = Vec::new();
txins.push(TxIn {
prev_hash: prev_hash.clone(),
prev_index: htlc.transaction_output_index,
script_sig: Script::new(),
sequence: 0,
witness: Vec::new(),
});
let total_fee = if htlc.offered {
feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000
} else {
feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000
};
let mut txouts: Vec<TxOut> = Vec::new();
txouts.push(TxOut {
script_pubkey: get_revokeable_redeemscript(revocation_key, to_self_delay, a_delayed_payment_key).to_v0_p2wsh(),
value: htlc.amount_msat / 1000 - total_fee //TODO: BOLT 3 does not specify if we should add amount_msat before dividing or if we should divide by 1000 before subtracting (as we do here)
});
Transaction {
version: 2,
lock_time: if htlc.offered { htlc.cltv_expiry } else { 0 },
input: txins,
output: txouts,
}
}

View file

@ -18,7 +18,7 @@ use ln::msgs;
use ln::msgs::{HandleError, MsgEncodable};
use ln::channelmonitor::ChannelMonitor;
use ln::channelmanager::{PendingForwardHTLCInfo, HTLCFailReason};
use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment};
use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT};
use ln::chan_utils;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
use util::{transaction_utils,rng};
@ -254,6 +254,12 @@ pub struct Channel {
channel_update_count: u32,
feerate_per_kw: u64,
#[cfg(test)]
// Used in ChannelManager's tests to send a revoked transaction
pub last_local_commitment_txn: Vec<Transaction>,
#[cfg(not(test))]
last_local_commitment_txn: Vec<Transaction>,
last_sent_closing_fee: Option<(u64, u64)>, // (feerate, fee)
/// The hash of the block in which the funding transaction reached our CONF_TARGET. We use this
@ -307,8 +313,6 @@ const BREAKDOWN_TIMEOUT: u16 = 6 * 24 * 7; //TODO?
const MAX_LOCAL_BREAKDOWN_TIMEOUT: u16 = 6 * 24 * 14;
const COMMITMENT_TX_BASE_WEIGHT: u64 = 724;
const COMMITMENT_TX_WEIGHT_PER_HTLC: u64 = 172;
const HTLC_SUCCESS_TX_WEIGHT: u64 = 703;
const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663;
const SPENDING_INPUT_FOR_A_OUTPUT_WEIGHT: u64 = 79; // prevout: 36, nSequence: 4, script len: 1, witness lengths: (3+1)/4, sig: 73/4, if-selector: 1, redeemScript: (6 ops + 2*33 pubkeys + 1*2 delay)/4
const B_OUTPUT_PLUS_SPENDING_INPUT_WEIGHT: u64 = 104; // prevout: 40, nSequence: 4, script len: 1, witness lengths: 3/4, sig: 73/4, pubkey: 33/4, output: 31 (TODO: Wrong? Useless?)
@ -362,7 +366,7 @@ impl Channel {
let our_channel_monitor_claim_script = Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script();
let channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key,
&PublicKey::from_secret_key(&secp_ctx, &chan_keys.delayed_payment_base_key).unwrap(),
&PublicKey::from_secret_key(&secp_ctx, &chan_keys.htlc_base_key).unwrap(),
&chan_keys.htlc_base_key,
BREAKDOWN_TIMEOUT, our_channel_monitor_claim_script);
Channel {
@ -385,6 +389,8 @@ impl Channel {
next_remote_htlc_id: 0,
channel_update_count: 0,
last_local_commitment_txn: Vec::new(),
last_sent_closing_fee: None,
funding_tx_confirmed_in: Default::default(),
@ -477,9 +483,10 @@ impl Channel {
let our_channel_monitor_claim_script = Builder::new().push_opcode(opcodes::All::OP_PUSHBYTES_0).push_slice(&our_channel_monitor_claim_key_hash[..]).into_script();
let mut channel_monitor = ChannelMonitor::new(&chan_keys.revocation_base_key,
&PublicKey::from_secret_key(&secp_ctx, &chan_keys.delayed_payment_base_key).unwrap(),
&PublicKey::from_secret_key(&secp_ctx, &chan_keys.htlc_base_key).unwrap(),
&chan_keys.htlc_base_key,
BREAKDOWN_TIMEOUT, our_channel_monitor_claim_script);
channel_monitor.set_their_htlc_base_key(&msg.htlc_basepoint);
channel_monitor.set_their_to_self_delay(msg.to_self_delay);
let mut chan = Channel {
user_id: user_id,
@ -500,6 +507,8 @@ impl Channel {
next_remote_htlc_id: 0,
channel_update_count: 0,
last_local_commitment_txn: Vec::new(),
last_sent_closing_fee: None,
funding_tx_confirmed_in: Default::default(),
@ -855,40 +864,25 @@ impl Channel {
/// @local is used only to convert relevant internal structures which refer to remote vs local
/// to decide value of outputs and direction of HTLCs.
fn build_htlc_transaction(&self, prev_hash: &Sha256dHash, htlc: &HTLCOutputInCommitment, local: bool, keys: &TxCreationKeys) -> Transaction {
let mut txins: Vec<TxIn> = Vec::new();
txins.push(TxIn {
prev_hash: prev_hash.clone(),
prev_index: htlc.transaction_output_index,
script_sig: Script::new(),
sequence: 0,
witness: Vec::new(),
});
let total_fee = if htlc.offered {
self.feerate_per_kw * HTLC_TIMEOUT_TX_WEIGHT / 1000
} else {
self.feerate_per_kw * HTLC_SUCCESS_TX_WEIGHT / 1000
};
let mut txouts: Vec<TxOut> = Vec::new();
txouts.push(TxOut {
script_pubkey: chan_utils::get_revokeable_redeemscript(&keys.revocation_key,
if local { self.their_to_self_delay } else { BREAKDOWN_TIMEOUT },
&keys.a_delayed_payment_key).to_v0_p2wsh(),
value: htlc.amount_msat / 1000 - total_fee //TODO: BOLT 3 does not specify if we should add amount_msat before dividing or if we should divide by 1000 before subtracting (as we do here)
});
Transaction {
version: 2,
lock_time: if htlc.offered { htlc.cltv_expiry } else { 0 },
input: txins,
output: txouts,
chan_utils::build_htlc_transaction(prev_hash, self.feerate_per_kw, if local { self.their_to_self_delay } else { BREAKDOWN_TIMEOUT }, htlc, &keys.a_delayed_payment_key, &keys.revocation_key)
}
fn create_htlc_tx_signature(&self, tx: &Transaction, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result<(Script, Signature, bool), HandleError> {
if tx.input.len() != 1 {
panic!("Tried to sign HTLC transaction that had input count != 1!");
}
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
let our_htlc_key = secp_derived_key!(chan_utils::derive_private_key(&self.secp_ctx, &keys.per_commitment_point, &self.local_keys.htlc_base_key));
let sighash = Message::from_slice(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
let is_local_tx = PublicKey::from_secret_key(&self.secp_ctx, &our_htlc_key).unwrap() == keys.a_htlc_key;
Ok((htlc_redeemscript, self.secp_ctx.sign(&sighash, &our_htlc_key).unwrap(), is_local_tx))
}
/// Signs a transaction created by build_htlc_transaction. If the transaction is an
/// HTLC-Success transaction (ie htlc.offered is false), preimate must be set!
fn sign_htlc_transaction(&self, tx: &mut Transaction, their_sig: &Signature, preimage: &Option<[u8; 32]>, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result<(), HandleError> {
fn sign_htlc_transaction(&self, tx: &mut Transaction, their_sig: &Signature, preimage: &Option<[u8; 32]>, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result<Signature, HandleError> {
if tx.input.len() != 1 {
panic!("Tried to sign HTLC transaction that had input count != 1!");
}
@ -896,13 +890,7 @@ impl Channel {
panic!("Tried to re-sign HTLC transaction");
}
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &keys);
let our_htlc_key = secp_derived_key!(chan_utils::derive_private_key(&self.secp_ctx, &keys.per_commitment_point, &self.local_keys.htlc_base_key));
let sighash = Message::from_slice(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
let our_sig = self.secp_ctx.sign(&sighash, &our_htlc_key).unwrap();
let local_tx = PublicKey::from_secret_key(&self.secp_ctx, &our_htlc_key).unwrap() == keys.a_htlc_key;
let (htlc_redeemscript, our_sig, local_tx) = self.create_htlc_tx_signature(tx, htlc, keys)?;
tx.input[0].witness.push(Vec::new()); // First is the multisig dummy
@ -924,10 +912,10 @@ impl Channel {
tx.input[0].witness.push(htlc_redeemscript.into_vec());
Ok(())
Ok(our_sig)
}
pub fn get_update_fulfill_htlc(&mut self, payment_preimage_arg: [u8; 32]) -> Result<Option<msgs::UpdateFulfillHTLC>, HandleError> {
pub fn get_update_fulfill_htlc(&mut self, payment_preimage_arg: [u8; 32]) -> Result<Option<(msgs::UpdateFulfillHTLC, ChannelMonitor)>, HandleError> {
// Either ChannelFunded got set (which means it wont bet unset) or there is no way any
// caller thought we could have something claimed (cause we wouldn't have accepted in an
// incoming HTLC anyway). If we got to ShutdownComplete, callers aren't allowed to call us,
@ -989,19 +977,21 @@ impl Channel {
if htlc_amount_msat == 0 {
return Err(HandleError{err: "Unable to find a pending HTLC which matched the given payment preimage", msg: None});
}
self.channel_monitor.provide_payment_preimage(&payment_preimage_arg);
self.channel_monitor.provide_payment_preimage(&payment_hash_calc, &payment_preimage_arg);
Ok(Some(msgs::UpdateFulfillHTLC {
Ok(Some((msgs::UpdateFulfillHTLC {
channel_id: self.channel_id(),
htlc_id: htlc_id,
payment_preimage: payment_preimage_arg,
}))
}, self.channel_monitor.clone())))
}
pub fn get_update_fulfill_htlc_and_commit(&mut self, payment_preimage: [u8; 32]) -> Result<Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned)>, HandleError> {
pub fn get_update_fulfill_htlc_and_commit(&mut self, payment_preimage: [u8; 32]) -> Result<Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned, ChannelMonitor)>, HandleError> {
match self.get_update_fulfill_htlc(payment_preimage)? {
Some(update_fulfill_htlc) =>
Ok(Some((update_fulfill_htlc, self.send_commitment_no_status_check()?))),
Some(update_fulfill_htlc) => {
let (commitment, monitor_update) = self.send_commitment_no_status_check()?;
Ok(Some((update_fulfill_htlc.0, commitment, monitor_update)))
},
None => Ok(None)
}
}
@ -1067,10 +1057,12 @@ impl Channel {
}))
}
pub fn get_update_fail_htlc_and_commit(&mut self, payment_hash: &[u8; 32], err_packet: msgs::OnionErrorPacket) -> Result<Option<(msgs::UpdateFailHTLC, msgs::CommitmentSigned)>, HandleError> {
pub fn get_update_fail_htlc_and_commit(&mut self, payment_hash: &[u8; 32], err_packet: msgs::OnionErrorPacket) -> Result<Option<(msgs::UpdateFailHTLC, msgs::CommitmentSigned, ChannelMonitor)>, HandleError> {
match self.get_update_fail_htlc(payment_hash, err_packet)? {
Some(update_fail_htlc) =>
Ok(Some((update_fail_htlc, self.send_commitment_no_status_check()?))),
Some(update_fail_htlc) => {
let (commitment, monitor_update) = self.send_commitment_no_status_check()?;
Ok(Some((update_fail_htlc, commitment, monitor_update)))
},
None => Ok(None)
}
}
@ -1122,6 +1114,7 @@ impl Channel {
let obscure_factor = self.get_commitment_transaction_number_obscure_factor();
self.channel_monitor.set_commitment_obscure_factor(obscure_factor);
self.channel_monitor.set_their_to_self_delay(msg.to_self_delay);
self.channel_state = ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32;
@ -1146,7 +1139,7 @@ impl Channel {
Ok((remote_initial_commitment_tx, self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key).unwrap()))
}
pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<msgs::FundingSigned, HandleError> {
pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<(msgs::FundingSigned, ChannelMonitor), HandleError> {
if self.channel_outbound {
return Err(HandleError{err: "Received funding_created for an outbound channel?", msg: None});
}
@ -1160,7 +1153,7 @@ impl Channel {
self.channel_monitor.set_funding_info(msg.funding_txid, msg.funding_output_index);
let (remote_initial_commitment_tx, our_signature) = match self.funding_created_signature(&msg.signature) {
Ok((remote_initial_commitment_tx, sig)) => (remote_initial_commitment_tx, sig),
Ok(res) => res,
Err(e) => {
self.channel_monitor.unset_funding_info();
return Err(e);
@ -1169,24 +1162,22 @@ impl Channel {
// Now that we're past error-generating stuff, update our local state:
//TODO: Determine which tx index in remote_initial_commitment_transaction's outputs
//represent a revokeable script!
self.channel_monitor.provide_tx_info(&remote_initial_commitment_tx, 0, Vec::new());
self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new());
self.channel_state = ChannelState::FundingSent as u32;
let funding_txo = self.channel_monitor.get_funding_txo().unwrap();
self.channel_id = funding_txo.0.into_be() ^ Uint256::from_u64(funding_txo.1 as u64).unwrap(); //TODO: or le?
self.cur_remote_commitment_transaction_number -= 1;
self.cur_local_commitment_transaction_number -= 1;
Ok(msgs::FundingSigned {
Ok((msgs::FundingSigned {
channel_id: self.channel_id,
signature: our_signature
})
}, self.channel_monitor.clone()))
}
/// Handles a funding_signed message from the remote end.
/// If this call is successful, broadcast the funding transaction (and not before!)
pub fn funding_signed(&mut self, msg: &msgs::FundingSigned) -> Result<(), HandleError> {
pub fn funding_signed(&mut self, msg: &msgs::FundingSigned) -> Result<ChannelMonitor, HandleError> {
if !self.channel_outbound {
return Err(HandleError{err: "Received funding_signed for an inbound channel?", msg: None});
}
@ -1200,16 +1191,19 @@ impl Channel {
let funding_script = self.get_funding_redeemscript();
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false).0;
let mut local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false).0;
let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
// They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish.
secp_call!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey), "Invalid funding_signed signature from peer");
self.sign_commitment_transaction(&mut local_initial_commitment_tx, &msg.signature);
self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx.clone(), local_keys, self.feerate_per_kw, Vec::new());
self.last_local_commitment_txn = vec![local_initial_commitment_tx];
self.channel_state = ChannelState::FundingSent as u32;
self.cur_local_commitment_transaction_number -= 1;
Ok(())
Ok(self.channel_monitor.clone())
}
pub fn funding_locked(&mut self, msg: &msgs::FundingLocked) -> Result<(), HandleError> {
@ -1342,7 +1336,7 @@ impl Channel {
Err(HandleError{err: "Remote tried to fulfill/fail an HTLC we couldn't find", msg: None})
}
pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<(), HandleError> {
pub fn update_fulfill_htlc(&mut self, msg: &msgs::UpdateFulfillHTLC) -> Result<ChannelMonitor, HandleError> {
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
return Err(HandleError{err: "Got add HTLC message when channel was not in an operational state", msg: None});
}
@ -1352,9 +1346,9 @@ impl Channel {
let mut payment_hash = [0; 32];
sha.result(&mut payment_hash);
self.channel_monitor.provide_payment_preimage(&msg.payment_preimage);
self.channel_monitor.provide_payment_preimage(&payment_hash, &msg.payment_preimage);
self.mark_outbound_htlc_removed(msg.htlc_id, Some(payment_hash), None)?;
Ok(())
Ok(self.channel_monitor.clone())
}
pub fn update_fail_htlc(&mut self, msg: &msgs::UpdateFailHTLC, fail_reason: HTLCFailReason) -> Result<[u8; 32], HandleError> {
@ -1374,7 +1368,7 @@ impl Channel {
Ok(())
}
pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned) -> Result<(msgs::RevokeAndACK, Option<msgs::CommitmentSigned>), HandleError> {
pub fn commitment_signed(&mut self, msg: &msgs::CommitmentSigned) -> Result<(msgs::RevokeAndACK, Option<msgs::CommitmentSigned>, ChannelMonitor), HandleError> {
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
return Err(HandleError{err: "Got commitment signed message when channel was not in an operational state", msg: None});
}
@ -1382,7 +1376,7 @@ impl Channel {
let funding_script = self.get_funding_redeemscript();
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
let local_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false);
let mut local_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false);
let local_commitment_txid = local_commitment_tx.0.txid();
let local_sighash = Message::from_slice(&bip143::SighashComponents::new(&local_commitment_tx.0).sighash_all(&local_commitment_tx.0.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
secp_call!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey), "Invalid commitment tx signature from peer");
@ -1391,17 +1385,31 @@ impl Channel {
return Err(HandleError{err: "Got wrong number of HTLC signatures from remote", msg: None});
}
let mut new_local_commitment_txn = Vec::with_capacity(local_commitment_tx.1.len() + 1);
self.sign_commitment_transaction(&mut local_commitment_tx.0, &msg.signature);
new_local_commitment_txn.push(local_commitment_tx.0.clone());
let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.1.len());
for (idx, ref htlc) in local_commitment_tx.1.iter().enumerate() {
let htlc_tx = self.build_htlc_transaction(&local_commitment_txid, htlc, true, &local_keys);
let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, htlc, true, &local_keys);
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys);
let htlc_sighash = Message::from_slice(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]).unwrap();
secp_call!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx siganture from peer");
let htlc_sig = if htlc.offered {
let htlc_sig = self.sign_htlc_transaction(&mut htlc_tx, &msg.htlc_signatures[idx], &None, htlc, &local_keys)?;
new_local_commitment_txn.push(htlc_tx);
htlc_sig
} else {
self.create_htlc_tx_signature(&htlc_tx, htlc, &local_keys)?.1
};
htlcs_and_sigs.push(((*htlc).clone(), msg.htlc_signatures[idx], htlc_sig));
}
let next_per_commitment_point = PublicKey::from_secret_key(&self.secp_ctx, &self.build_local_commitment_secret(self.cur_local_commitment_transaction_number - 1)).unwrap();
let per_commitment_secret = chan_utils::build_commitment_secret(self.local_keys.commitment_seed, self.cur_local_commitment_transaction_number + 1);
// Update state now that we've passed all the can-fail calls...
self.channel_monitor.provide_latest_local_commitment_tx_info(local_commitment_tx.0, local_keys, self.feerate_per_kw, htlcs_and_sigs);
let mut need_our_commitment = false;
for htlc in self.pending_htlcs.iter_mut() {
@ -1425,24 +1433,26 @@ impl Channel {
self.value_to_self_msat += claimed_value_msat;
self.cur_local_commitment_transaction_number -= 1;
self.last_local_commitment_txn = new_local_commitment_txn;
let our_commitment_signed = if need_our_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
let (our_commitment_signed, monitor_update) = if need_our_commitment && (self.channel_state & (ChannelState::AwaitingRemoteRevoke as u32)) == 0 {
// If we're AwaitingRemoteRevoke we can't send a new commitment here, but that's ok -
// we'll send one right away when we get the revoke_and_ack when we
// free_holding_cell_htlcs().
Some(self.send_commitment_no_status_check()?)
} else { None };
let (msg, monitor) = self.send_commitment_no_status_check()?;
(Some(msg), monitor)
} else { (None, self.channel_monitor.clone()) };
Ok((msgs::RevokeAndACK {
channel_id: self.channel_id,
per_commitment_secret: per_commitment_secret,
next_per_commitment_point: next_per_commitment_point,
}, our_commitment_signed))
}, our_commitment_signed, monitor_update))
}
/// Used to fulfill holding_cell_htlcs when we get a remote ack (or implicitly get it by them
/// fulfilling or failing the last pending HTLC)
fn free_holding_cell_htlcs(&mut self) -> Result<Option<msgs::CommitmentUpdate>, HandleError> {
fn free_holding_cell_htlcs(&mut self) -> Result<Option<(msgs::CommitmentUpdate, ChannelMonitor)>, HandleError> {
if self.holding_cell_htlc_updates.len() != 0 {
let mut htlc_updates = Vec::new();
mem::swap(&mut htlc_updates, &mut self.holding_cell_htlc_updates);
@ -1470,7 +1480,7 @@ impl Channel {
},
&HTLCUpdateAwaitingACK::ClaimHTLC { payment_preimage, .. } => {
match self.get_update_fulfill_htlc(payment_preimage) {
Ok(update_fulfill_msg_option) => update_fulfill_htlcs.push(update_fulfill_msg_option.unwrap()),
Ok(update_fulfill_msg_option) => update_fulfill_htlcs.push(update_fulfill_msg_option.unwrap().0),
Err(e) => {
err = Some(e);
}
@ -1494,12 +1504,13 @@ impl Channel {
//fail it back the route, if its a temporary issue we can ignore it...
match err {
None => {
Ok(Some(msgs::CommitmentUpdate {
let (commitment_signed, monitor_update) = self.send_commitment_no_status_check()?;
Ok(Some((msgs::CommitmentUpdate {
update_add_htlcs,
update_fulfill_htlcs,
update_fail_htlcs,
commitment_signed: self.send_commitment_no_status_check()?
}))
commitment_signed,
}, monitor_update)))
},
Some(e) => Err(e)
}
@ -1513,7 +1524,7 @@ impl Channel {
/// waiting on this revoke_and_ack. The generation of this new commitment_signed may also fail,
/// generating an appropriate error *after* the channel state has been updated based on the
/// revoke_and_ack message.
pub fn revoke_and_ack(&mut self, msg: &msgs::RevokeAndACK) -> Result<(Option<msgs::CommitmentUpdate>, Vec<PendingForwardHTLCInfo>, Vec<([u8; 32], HTLCFailReason)>), HandleError> {
pub fn revoke_and_ack(&mut self, msg: &msgs::RevokeAndACK) -> Result<(Option<msgs::CommitmentUpdate>, Vec<PendingForwardHTLCInfo>, Vec<([u8; 32], HTLCFailReason)>, ChannelMonitor), HandleError> {
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
return Err(HandleError{err: "Got revoke/ACK message when channel was not in an operational state", msg: None});
}
@ -1522,7 +1533,7 @@ impl Channel {
return Err(HandleError{err: "Got a revoke commitment secret which didn't correspond to their current pubkey", msg: None});
}
}
self.channel_monitor.provide_secret(self.cur_remote_commitment_transaction_number + 1, msg.per_commitment_secret)?;
self.channel_monitor.provide_secret(self.cur_remote_commitment_transaction_number + 1, msg.per_commitment_secret, Some((self.cur_remote_commitment_transaction_number - 1, msg.next_per_commitment_point)))?;
// Update state now that we've passed all the can-fail calls...
// (note that we may still fail to generate the new commitment_signed message, but that's
@ -1572,18 +1583,19 @@ impl Channel {
match self.free_holding_cell_htlcs()? {
Some(commitment_update) => {
Ok((Some(commitment_update), to_forward_infos, revoked_htlcs))
Ok((Some(commitment_update.0), to_forward_infos, revoked_htlcs, commitment_update.1))
},
None => {
if require_commitment {
let (commitment_signed, monitor_update) = self.send_commitment_no_status_check()?;
Ok((Some(msgs::CommitmentUpdate {
update_add_htlcs: Vec::new(),
update_fulfill_htlcs: Vec::new(),
update_fail_htlcs: Vec::new(),
commitment_signed: self.send_commitment_no_status_check()?
}), to_forward_infos, revoked_htlcs))
commitment_signed
}), to_forward_infos, revoked_htlcs, monitor_update))
} else {
Ok((None, to_forward_infos, revoked_htlcs))
Ok((None, to_forward_infos, revoked_htlcs, self.channel_monitor.clone()))
}
}
}
@ -1789,6 +1801,13 @@ impl Channel {
self.user_id
}
pub fn channel_monitor(&self) -> ChannelMonitor {
if self.channel_state < ChannelState::FundingCreated as u32 {
panic!("Can't get a channel monitor until funding has been created");
}
self.channel_monitor.clone()
}
/// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus,
/// is_usable() returns true).
pub fn get_short_channel_id(&self) -> Option<u64> {
@ -1837,13 +1856,6 @@ impl Channel {
res as u32
}
pub fn channel_monitor(&self) -> ChannelMonitor {
if self.channel_state < ChannelState::FundingCreated as u32 {
panic!("Can't get a channel monitor until funding has been created");
}
self.channel_monitor.clone()
}
/// Returns true if this channel is fully established and not known to be closing.
pub fn is_usable(&self) -> bool {
let mask = ChannelState::ChannelFunded as u32 | BOTH_SIDES_SHUTDOWN_MASK;
@ -2006,7 +2018,7 @@ impl Channel {
})
}
fn get_outbound_funding_created_signature(&mut self) -> Result<Signature, HandleError> {
fn get_outbound_funding_created_signature(&mut self) -> Result<(Signature, Transaction), HandleError> {
let funding_script = self.get_funding_redeemscript();
let remote_keys = self.build_remote_transaction_keys()?;
@ -2014,7 +2026,7 @@ impl Channel {
let remote_sighash = Message::from_slice(&bip143::SighashComponents::new(&remote_initial_commitment_tx).sighash_all(&remote_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]).unwrap();
// We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
Ok(self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key).unwrap())
Ok((self.secp_ctx.sign(&remote_sighash, &self.local_keys.funding_key).unwrap(), remote_initial_commitment_tx))
}
/// Updates channel state with knowledge of the funding transaction's txid/index, and generates
@ -2023,7 +2035,7 @@ impl Channel {
/// or if called on an inbound channel.
/// Note that channel_id changes during this call!
/// Do NOT broadcast the funding transaction until after a successful funding_signed call!
pub fn get_outbound_funding_created(&mut self, funding_txid: Sha256dHash, funding_output_index: u16) -> Result<msgs::FundingCreated, HandleError> {
pub fn get_outbound_funding_created(&mut self, funding_txid: Sha256dHash, funding_output_index: u16) -> Result<(msgs::FundingCreated, ChannelMonitor), HandleError> {
if !self.channel_outbound {
panic!("Tried to create outbound funding_created message on an inbound channel!");
}
@ -2036,8 +2048,8 @@ impl Channel {
self.channel_monitor.set_funding_info(funding_txid, funding_output_index);
let our_signature = match self.get_outbound_funding_created_signature() {
Ok(sig) => sig,
let (our_signature, commitment_tx) = match self.get_outbound_funding_created_signature() {
Ok(res) => res,
Err(e) => {
self.channel_monitor.unset_funding_info();
return Err(e);
@ -2047,18 +2059,18 @@ impl Channel {
let temporary_channel_id = self.channel_id;
// Now that we're past error-generating stuff, update our local state:
self.channel_monitor.provide_latest_remote_commitment_tx_info(&commitment_tx, Vec::new());
self.channel_state = ChannelState::FundingCreated as u32;
let funding_txo = self.channel_monitor.get_funding_txo().unwrap();
self.channel_id = funding_txo.0.into_be() ^ Uint256::from_u64(funding_txo.1 as u64).unwrap(); //TODO: or le?
self.cur_remote_commitment_transaction_number -= 1;
Ok(msgs::FundingCreated {
Ok((msgs::FundingCreated {
temporary_channel_id: temporary_channel_id,
funding_txid: funding_txid,
funding_output_index: funding_output_index,
signature: our_signature
})
}, self.channel_monitor.clone()))
}
/// Gets an UnsignedChannelAnnouncement, as well as a signature covering it using our
@ -2170,7 +2182,7 @@ impl Channel {
}
/// Creates a signed commitment transaction to send to the remote peer.
pub fn send_commitment(&mut self) -> Result<msgs::CommitmentSigned, HandleError> {
pub fn send_commitment(&mut self) -> Result<(msgs::CommitmentSigned, ChannelMonitor), HandleError> {
if (self.channel_state & (ChannelState::ChannelFunded as u32)) != (ChannelState::ChannelFunded as u32) {
return Err(HandleError{err: "Cannot create commitment tx until channel is fully established", msg: None});
}
@ -2190,7 +2202,7 @@ impl Channel {
self.send_commitment_no_status_check()
}
/// Only fails in case of bad keys
fn send_commitment_no_status_check(&mut self) -> Result<msgs::CommitmentSigned, HandleError> {
fn send_commitment_no_status_check(&mut self) -> Result<(msgs::CommitmentSigned, ChannelMonitor), HandleError> {
let funding_script = self.get_funding_redeemscript();
// We can upgrade the status of some HTLCs that are waiting on a commitment, even if we
@ -2221,23 +2233,26 @@ impl Channel {
}
// Update state now that we've passed all the can-fail calls...
self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_commitment_tx.0, remote_commitment_tx.1);
self.channel_state |= ChannelState::AwaitingRemoteRevoke as u32;
Ok(msgs::CommitmentSigned {
Ok((msgs::CommitmentSigned {
channel_id: self.channel_id,
signature: our_sig,
htlc_signatures: htlc_sigs,
})
}, self.channel_monitor.clone()))
}
/// Adds a pending outbound HTLC to this channel, and creates a signed commitment transaction
/// to send to the remote peer in one go.
/// Shorthand for calling send_htlc() followed by send_commitment(), see docs on those for
/// more info.
pub fn send_htlc_and_commit(&mut self, amount_msat: u64, payment_hash: [u8; 32], cltv_expiry: u32, onion_routing_packet: msgs::OnionPacket) -> Result<Option<(msgs::UpdateAddHTLC, msgs::CommitmentSigned)>, HandleError> {
pub fn send_htlc_and_commit(&mut self, amount_msat: u64, payment_hash: [u8; 32], cltv_expiry: u32, onion_routing_packet: msgs::OnionPacket) -> Result<Option<(msgs::UpdateAddHTLC, msgs::CommitmentSigned, ChannelMonitor)>, HandleError> {
match self.send_htlc(amount_msat, payment_hash, cltv_expiry, onion_routing_packet)? {
Some(update_add_htlc) =>
Ok(Some((update_add_htlc, self.send_commitment_no_status_check()?))),
Some(update_add_htlc) => {
let (commitment_signed, monitor_update) = self.send_commitment_no_status_check()?;
Ok(Some((update_add_htlc, commitment_signed, monitor_update)))
},
None => Ok(None)
}
}
@ -2283,6 +2298,16 @@ impl Channel {
scriptpubkey: our_closing_script,
}, dropped_outbound_htlcs))
}
/// Gets the latest commitment transaction and any dependant transactions for relay (forcing
/// shutdown of this channel - no more calls into this Channel may be made afterwards.
pub fn force_shutdown(&mut self) -> Vec<Transaction> {
assert!(self.channel_state != ChannelState::ShutdownComplete as u32);
self.channel_state = ChannelState::ShutdownComplete as u32;
let mut res = Vec::new();
mem::swap(&mut res, &mut self.last_local_commitment_txn);
res
}
}
#[cfg(test)]

View file

@ -608,6 +608,7 @@ impl ChannelManager {
let (onion_payloads, htlc_msat, htlc_cltv) = ChannelManager::build_onion_payloads(&route)?;
let onion_packet = ChannelManager::construct_onion_packet(onion_payloads, onion_keys, associated_data)?;
let (update_add, commitment_signed, chan_monitor) = {
let mut channel_state = self.channel_state.lock().unwrap();
let id = match channel_state.short_to_id.get(&route.hops.first().unwrap().short_channel_id) {
None => return Err(HandleError{err: "No channel available with first hop!", msg: None}),
@ -630,19 +631,28 @@ impl ChannelManager {
panic!("payment_hash was repeated! Don't let this happen");
}
Ok(res)
match res {
Some(msgs) => msgs,
None => return Ok(None),
}
};
if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
unimplemented!(); // maybe remove from claimable_htlcs?
}
Ok(Some((update_add, commitment_signed)))
}
/// Call this upon creation of a funding transaction for the given channel.
/// Panics if a funding transaction has already been provided for this channel.
pub fn funding_transaction_generated(&self, temporary_channel_id: &Uint256, funding_txo: (Sha256dHash, u16)) {
let (chan, msg) = {
let (chan, msg, chan_monitor) = {
let mut channel_state = self.channel_state.lock().unwrap();
match channel_state.by_id.remove(&temporary_channel_id) {
Some(mut chan) => {
match chan.get_outbound_funding_created(funding_txo.0, funding_txo.1) {
Ok(funding_msg) => {
(chan, funding_msg)
(chan, funding_msg.0, funding_msg.1)
},
Err(_e) => {
//TODO: Push e to pendingevents
@ -653,15 +663,9 @@ impl ChannelManager {
None => return
}
}; // Release channel lock for install_watch_outpoint call,
let chan_monitor = chan.channel_monitor();
match self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
Ok(()) => {},
Err(_e) => {
//TODO: Push e to pendingevents?
return;
if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
unimplemented!(); // maybe remove from claimable_htlcs?
}
};
{
let mut pending_events = self.pending_events.lock().unwrap();
pending_events.push(events::Event::SendFundingCreated {
@ -741,25 +745,25 @@ impl ChannelManager {
}
if !add_htlc_msgs.is_empty() {
let commitment_msg = match forward_chan.send_commitment() {
Ok(msg) => msg,
let (commitment_msg, monitor) = match forward_chan.send_commitment() {
Ok(res) => res,
Err(_) => {
//TODO: Handle...this is bad!
continue;
},
};
new_events.push(events::Event::SendHTLCs {
new_events.push((Some(monitor), events::Event::SendHTLCs {
node_id: forward_chan.get_their_node_id(),
msgs: add_htlc_msgs,
commitment_msg: commitment_msg,
});
}));
}
} else {
for forward_info in pending_forwards {
new_events.push(events::Event::PaymentReceived {
new_events.push((None, events::Event::PaymentReceived {
payment_hash: forward_info.payment_hash,
amt: forward_info.amt_to_forward,
});
}));
}
}
}
@ -774,10 +778,19 @@ impl ChannelManager {
if new_events.is_empty() { return }
new_events.retain(|event| {
if let &Some(ref monitor) = &event.0 {
if let Err(_e) = self.monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor.clone()) {
unimplemented!();// but def dont push the event...
}
}
true
});
let mut events = self.pending_events.lock().unwrap();
events.reserve(new_events.len());
for event in new_events.drain(..) {
events.push(event);
events.push(event.1);
}
}
@ -844,13 +857,18 @@ impl ChannelManager {
};
match fail_msgs {
Some(msgs) => {
Some((msg, commitment_msg, chan_monitor)) => {
mem::drop(channel_state);
if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
unimplemented!();// but def dont push the event...
}
let mut pending_events = self.pending_events.lock().unwrap();
pending_events.push(events::Event::SendFailHTLC {
node_id,
msg: msgs.0,
commitment_msg: msgs.1,
msg: msg,
commitment_msg: commitment_msg,
});
},
None => {},
@ -910,7 +928,7 @@ impl ChannelManager {
false
},
PendingOutboundHTLC::IntermediaryHopData { source_short_channel_id, .. } => {
let (node_id, fulfill_msgs, monitor) = {
let (node_id, fulfill_msgs) = {
let chan_id = match channel_state.short_to_id.get(&source_short_channel_id) {
Some(chan_id) => chan_id.clone(),
None => return false
@ -918,7 +936,7 @@ impl ChannelManager {
let chan = channel_state.by_id.get_mut(&chan_id).unwrap();
match chan.get_update_fulfill_htlc_and_commit(payment_preimage) {
Ok(msg) => (chan.get_their_node_id(), msg, if from_user { Some(chan.channel_monitor()) } else { None }),
Ok(msg) => (chan.get_their_node_id(), msg),
Err(_e) => {
//TODO: Do something with e?
return false;
@ -928,25 +946,21 @@ impl ChannelManager {
mem::drop(channel_state);
match fulfill_msgs {
Some(msgs) => {
Some((msg, commitment_msg, chan_monitor)) => {
if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
unimplemented!();// but def dont push the event...
}
let mut pending_events = self.pending_events.lock().unwrap();
pending_events.push(events::Event::SendFulfillHTLC {
node_id: node_id,
msg: msgs.0,
commitment_msg: msgs.1,
msg,
commitment_msg,
});
},
None => {},
}
//TODO: It may not be possible to handle add_update_monitor fails gracefully, maybe
//it should return no Err? Sadly, panic!()s instead doesn't help much :(
if from_user {
match self.monitor.add_update_monitor(monitor.as_ref().unwrap().get_funding_txo().unwrap(), monitor.unwrap()) {
Ok(()) => true,
Err(_) => true,
}
} else { true }
true
},
}
}
@ -955,6 +969,13 @@ impl ChannelManager {
pub fn get_our_node_id(&self) -> PublicKey {
PublicKey::from_secret_key(&self.secp_ctx, &self.our_network_key).unwrap()
}
/// Used to restore channels to normal operation after a
/// ChannelMonitorUpdateErr::TemporaryFailure was returned from a channel monitor update
/// operation.
pub fn test_restore_channel_monitor(&self) {
unimplemented!();
}
}
impl events::EventsProvider for ChannelManager {
@ -972,14 +993,14 @@ impl ChainListener for ChannelManager {
{
let mut channel_state = self.channel_state.lock().unwrap();
let mut short_to_ids_to_insert = Vec::new();
for channel in channel_state.by_id.values_mut() {
match channel.block_connected(header, height, txn_matched, indexes_of_txn_matched) {
Some(funding_locked) => {
let mut short_to_ids_to_remove = Vec::new();
channel_state.by_id.retain(|_, channel| {
if let Some(funding_locked) = channel.block_connected(header, height, txn_matched, indexes_of_txn_matched) {
let announcement_sigs = match self.get_announcement_sigs(channel) {
Ok(res) => res,
Err(_e) => {
//TODO: push e on events and blow up the channel (it has bad keys)
continue;
return true;
}
};
new_funding_locked_messages.push(events::Event::SendFundingLocked {
@ -988,10 +1009,31 @@ impl ChainListener for ChannelManager {
announcement_sigs: announcement_sigs
});
short_to_ids_to_insert.push((channel.get_short_channel_id().unwrap(), channel.channel_id()));
},
None => {}
}
//TODO: Check if channel was closed (or disabled) here
if let Some(funding_txo) = channel.get_funding_txo() {
for tx in txn_matched {
for inp in tx.input.iter() {
if inp.prev_hash == funding_txo.0 && inp.prev_index == funding_txo.1 as u32 {
if let Some(short_id) = channel.get_short_channel_id() {
short_to_ids_to_remove.push(short_id);
}
channel.force_shutdown();
return false;
}
}
}
}
if channel.channel_monitor().would_broadcast_at_height(height) {
if let Some(short_id) = channel.get_short_channel_id() {
short_to_ids_to_remove.push(short_id);
}
channel.force_shutdown();
return false;
}
true
});
for to_remove in short_to_ids_to_remove {
channel_state.short_to_id.remove(&to_remove);
}
for to_insert in short_to_ids_to_insert {
channel_state.short_to_id.insert(to_insert.0, to_insert.1);
@ -1078,7 +1120,7 @@ impl ChannelMessageHandler for ChannelManager {
//TODO: broke this - a node shouldn't be able to get their channel removed by sending a
//funding_created a second time, or long after the first, or whatever (note this also
//leaves the short_to_id map in a busted state.
let chan = {
let (chan, funding_msg, monitor_update) = {
let mut channel_state = self.channel_state.lock().unwrap();
match channel_state.by_id.remove(&msg.temporary_channel_id) {
Some(mut chan) => {
@ -1086,8 +1128,8 @@ impl ChannelMessageHandler for ChannelManager {
return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
}
match chan.funding_created(msg) {
Ok(funding_msg) => {
(chan, funding_msg)
Ok((funding_msg, monitor_update)) => {
(chan, funding_msg, monitor_update)
},
Err(e) => {
return Err(e);
@ -1100,27 +1142,31 @@ impl ChannelMessageHandler for ChannelManager {
// note that this means if the remote end is misbehaving and sends a message for the same
// channel back-to-back with funding_created, we'll end up thinking they sent a message
// for a bogus channel.
let chan_monitor = chan.0.channel_monitor();
self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor)?;
if let Err(_e) = self.monitor.add_update_monitor(monitor_update.get_funding_txo().unwrap(), monitor_update) {
unimplemented!();
}
let mut channel_state = self.channel_state.lock().unwrap();
channel_state.by_id.insert(chan.1.channel_id, chan.0);
Ok(chan.1)
channel_state.by_id.insert(funding_msg.channel_id, chan);
Ok(funding_msg)
}
fn handle_funding_signed(&self, their_node_id: &PublicKey, msg: &msgs::FundingSigned) -> Result<(), HandleError> {
let (funding_txo, user_id) = {
let (funding_txo, user_id, monitor) = {
let mut channel_state = self.channel_state.lock().unwrap();
match channel_state.by_id.get_mut(&msg.channel_id) {
Some(chan) => {
if chan.get_their_node_id() != *their_node_id {
return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
}
chan.funding_signed(&msg)?;
(chan.get_funding_txo().unwrap(), chan.get_user_id())
let chan_monitor = chan.funding_signed(&msg)?;
(chan.get_funding_txo().unwrap(), chan.get_user_id(), chan_monitor)
},
None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
}
};
if let Err(_e) = self.monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor) {
unimplemented!();
}
let mut pending_events = self.pending_events.lock().unwrap();
pending_events.push(events::Event::FundingBroadcastSafe {
funding_txo: funding_txo,
@ -1446,13 +1492,14 @@ impl ChannelMessageHandler for ChannelManager {
if chan.get_their_node_id() != *their_node_id {
return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
}
chan.update_fulfill_htlc(&msg)?;
chan.channel_monitor()
chan.update_fulfill_htlc(&msg)?
},
None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
}
};
self.monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor)?;
if let Err(_e) = self.monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor) {
unimplemented!();
}
Ok(())
}
@ -1545,38 +1592,41 @@ impl ChannelMessageHandler for ChannelManager {
}
fn handle_commitment_signed(&self, their_node_id: &PublicKey, msg: &msgs::CommitmentSigned) -> Result<(msgs::RevokeAndACK, Option<msgs::CommitmentSigned>), HandleError> {
let (res, monitor) = {
let (revoke_and_ack, commitment_signed, chan_monitor) = {
let mut channel_state = self.channel_state.lock().unwrap();
match channel_state.by_id.get_mut(&msg.channel_id) {
Some(chan) => {
if chan.get_their_node_id() != *their_node_id {
return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
}
(chan.commitment_signed(&msg)?, chan.channel_monitor())
chan.commitment_signed(&msg)?
},
None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
}
};
//TODO: Only if we store HTLC sigs
self.monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor)?;
if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
unimplemented!();
}
Ok(res)
Ok((revoke_and_ack, commitment_signed))
}
fn handle_revoke_and_ack(&self, their_node_id: &PublicKey, msg: &msgs::RevokeAndACK) -> Result<Option<msgs::CommitmentUpdate>, HandleError> {
let ((res, mut pending_forwards, mut pending_failures), monitor) = {
let (res, mut pending_forwards, mut pending_failures, chan_monitor) = {
let mut channel_state = self.channel_state.lock().unwrap();
match channel_state.by_id.get_mut(&msg.channel_id) {
Some(chan) => {
if chan.get_their_node_id() != *their_node_id {
return Err(HandleError{err: "Got a message for a channel from the wrong node!", msg: None})
}
(chan.revoke_and_ack(&msg)?, chan.channel_monitor())
chan.revoke_and_ack(&msg)?
},
None => return Err(HandleError{err: "Failed to find corresponding channel", msg: None})
}
};
self.monitor.add_update_monitor(monitor.get_funding_txo().unwrap(), monitor)?;
if let Err(_e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
unimplemented!();
}
for failure in pending_failures.drain(..) {
self.fail_htlc_backwards_internal(self.channel_state.lock().unwrap(), &failure.0, failure.1);
}
@ -1673,8 +1723,10 @@ impl ChannelMessageHandler for ChannelManager {
if let Some(short_id) = chan.get_short_channel_id() {
short_to_id.remove(&short_id);
}
//TODO: get the latest commitment tx, any HTLC txn built on top of it, etc out
//of the channel and throw those into the announcement blackhole.
let txn_to_broadcast = chan.force_shutdown();
for tx in txn_to_broadcast {
self.tx_broadcaster.broadcast_transaction(&tx);
}
false
} else {
true
@ -1723,6 +1775,7 @@ mod tests {
use std::default::Default;
use std::sync::{Arc, Mutex};
use std::time::Instant;
use std::mem;
fn build_test_onion_keys() -> Vec<OnionKeys> {
// Keys from BOLT 4, used in both test vector tests
@ -1940,6 +1993,12 @@ mod tests {
};
node_a.node.handle_funding_signed(&node_b.node.get_our_node_id(), &funding_signed).unwrap();
{
let mut added_monitors = node_a.chan_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 1);
assert_eq!(added_monitors[0].0, funding_output);
added_monitors.clear();
}
let events_3 = node_a.node.get_and_clear_pending_events();
assert_eq!(events_3.len(), 1);
@ -2084,6 +2143,11 @@ mod tests {
let mut payment_event = {
let msgs = origin_node.node.send_payment(route, our_payment_hash).unwrap().unwrap();
{
let mut added_monitors = origin_node.chan_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 1);
added_monitors.clear();
}
SendEvent {
node_id: expected_route[0].node.get_our_node_id(),
msgs: vec!(msgs.0),
@ -2143,6 +2207,11 @@ mod tests {
_ => panic!("Unexpected event"),
}
} else {
{
let mut added_monitors = node.chan_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 1);
added_monitors.clear();
}
for event in events_2.drain(..) {
payment_event = SendEvent::from_event(event);
}
@ -2165,13 +2234,23 @@ mod tests {
let mut next_msgs: Option<(msgs::UpdateFulfillHTLC, msgs::CommitmentSigned)> = None;
macro_rules! update_fulfill_dance {
($node: expr, $prev_node: expr) => {
($node: expr, $prev_node: expr, $last_node: expr) => {
{
$node.node.handle_update_fulfill_htlc(&$prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0).unwrap();
{
let mut added_monitors = $node.chan_monitor.added_monitors.lock().unwrap();
if $last_node {
assert_eq!(added_monitors.len(), 1);
} else {
assert_eq!(added_monitors.len(), 2);
assert!(added_monitors[0].0 != added_monitors[1].0);
}
added_monitors.clear();
}
let revoke_and_commit = $node.node.handle_commitment_signed(&$prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().1).unwrap();
{
let mut added_monitors = $node.chan_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 2);
assert_eq!(added_monitors.len(), 1);
added_monitors.clear();
}
assert!($prev_node.node.handle_revoke_and_ack(&$node.node.get_our_node_id(), &revoke_and_commit.0).unwrap().is_none());
@ -2197,7 +2276,7 @@ mod tests {
for node in expected_route.iter().rev() {
assert_eq!(expected_next_node, node.node.get_our_node_id());
if next_msgs.is_some() {
update_fulfill_dance!(node, prev_node);
update_fulfill_dance!(node, prev_node, false);
}
let events = node.node.get_and_clear_pending_events();
@ -2214,7 +2293,7 @@ mod tests {
}
assert_eq!(expected_next_node, origin_node.node.get_our_node_id());
update_fulfill_dance!(origin_node, expected_route.first().unwrap());
update_fulfill_dance!(origin_node, expected_route.first().unwrap(), true);
let events = origin_node.node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
@ -2226,8 +2305,10 @@ mod tests {
}
}
const TEST_FINAL_CLTV: u32 = 32;
fn route_payment(origin_node: &Node, expected_route: &[&Node], recv_value: u64) -> ([u8; 32], [u8; 32]) {
let route = origin_node.router.get_route(&expected_route.last().unwrap().node.get_our_node_id(), &Vec::new(), recv_value, 142).unwrap();
let route = origin_node.router.get_route(&expected_route.last().unwrap().node.get_our_node_id(), &Vec::new(), recv_value, TEST_FINAL_CLTV).unwrap();
assert_eq!(route.hops.len(), expected_route.len());
for (node, hop) in expected_route.iter().zip(route.hops.iter()) {
assert_eq!(hop.pubkey, node.node.get_our_node_id());
@ -2237,7 +2318,7 @@ mod tests {
}
fn route_over_limit(origin_node: &Node, expected_route: &[&Node], recv_value: u64) {
let route = origin_node.router.get_route(&expected_route.last().unwrap().node.get_our_node_id(), &Vec::new(), recv_value, 142).unwrap();
let route = origin_node.router.get_route(&expected_route.last().unwrap().node.get_our_node_id(), &Vec::new(), recv_value, TEST_FINAL_CLTV).unwrap();
assert_eq!(route.hops.len(), expected_route.len());
for (node, hop) in expected_route.iter().zip(route.hops.iter()) {
assert_eq!(hop.pubkey, node.node.get_our_node_id());
@ -2264,30 +2345,47 @@ mod tests {
fn fail_payment(origin_node: &Node, expected_route: &[&Node], our_payment_hash: [u8; 32]) {
assert!(expected_route.last().unwrap().node.fail_htlc_backwards(&our_payment_hash));
{
let mut added_monitors = expected_route.last().unwrap().chan_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 1);
added_monitors.clear();
}
let mut next_msgs: Option<(msgs::UpdateFailHTLC, msgs::CommitmentSigned)> = None;
macro_rules! update_fail_dance {
($node: expr, $prev_node: expr) => {
($node: expr, $prev_node: expr, $last_node: expr) => {
{
$node.node.handle_update_fail_htlc(&$prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().0).unwrap();
let revoke_and_commit = $node.node.handle_commitment_signed(&$prev_node.node.get_our_node_id(), &next_msgs.as_ref().unwrap().1).unwrap();
{
let mut added_monitors = $node.chan_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 1);
added_monitors.clear();
}
assert!($prev_node.node.handle_revoke_and_ack(&$node.node.get_our_node_id(), &revoke_and_commit.0).unwrap().is_none());
let revoke_and_ack = $prev_node.node.handle_commitment_signed(&$node.node.get_our_node_id(), &revoke_and_commit.1.unwrap()).unwrap();
assert!(revoke_and_ack.1.is_none());
{
let mut added_monitors = $prev_node.chan_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 2);
assert_eq!(added_monitors.len(), 1);
added_monitors.clear();
}
let revoke_and_ack = $prev_node.node.handle_commitment_signed(&$node.node.get_our_node_id(), &revoke_and_commit.1.unwrap()).unwrap();
{
let mut added_monitors = $prev_node.chan_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 1);
added_monitors.clear();
}
assert!(revoke_and_ack.1.is_none());
assert!($node.node.get_and_clear_pending_events().is_empty());
assert!($node.node.handle_revoke_and_ack(&$prev_node.node.get_our_node_id(), &revoke_and_ack.0).unwrap().is_none());
{
let mut added_monitors = $node.chan_monitor.added_monitors.lock().unwrap();
if $last_node {
assert_eq!(added_monitors.len(), 1);
} else {
assert_eq!(added_monitors.len(), 2);
assert!(added_monitors[0].0 != added_monitors[1].0);
}
added_monitors.clear();
}
}
@ -2299,7 +2397,7 @@ mod tests {
for node in expected_route.iter().rev() {
assert_eq!(expected_next_node, node.node.get_our_node_id());
if next_msgs.is_some() {
update_fail_dance!(node, prev_node);
update_fail_dance!(node, prev_node, false);
}
let events = node.node.get_and_clear_pending_events();
@ -2316,7 +2414,7 @@ mod tests {
}
assert_eq!(expected_next_node, origin_node.node.get_our_node_id());
update_fail_dance!(origin_node, expected_route.first().unwrap());
update_fail_dance!(origin_node, expected_route.first().unwrap(), true);
let events = origin_node.node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
@ -2406,7 +2504,7 @@ mod tests {
pubkey: nodes[1].node.get_our_node_id(),
short_channel_id: chan_4.0.contents.short_channel_id,
fee_msat: 1000000,
cltv_expiry_delta: 142,
cltv_expiry_delta: TEST_FINAL_CLTV,
});
hops[1].fee_msat = chan_4.1.contents.fee_base_msat as u64 + chan_4.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000;
hops[0].fee_msat = chan_3.0.contents.fee_base_msat as u64 + chan_3.0.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000;
@ -2429,7 +2527,7 @@ mod tests {
pubkey: nodes[1].node.get_our_node_id(),
short_channel_id: chan_2.0.contents.short_channel_id,
fee_msat: 1000000,
cltv_expiry_delta: 142,
cltv_expiry_delta: TEST_FINAL_CLTV,
});
hops[1].fee_msat = chan_2.1.contents.fee_base_msat as u64 + chan_2.1.contents.fee_proportional_millionths as u64 * hops[2].fee_msat as u64 / 1000000;
hops[0].fee_msat = chan_3.1.contents.fee_base_msat as u64 + chan_3.1.contents.fee_proportional_millionths as u64 * hops[1].fee_msat as u64 / 1000000;
@ -2468,4 +2566,233 @@ mod tests {
assert_eq!(node.chan_monitor.added_monitors.lock().unwrap().len(), 0);
}
}
#[derive(PartialEq)]
enum HTLCType { NONE, TIMEOUT, SUCCESS }
fn test_txn_broadcast(node: &Node, chan: &(msgs::ChannelUpdate, msgs::ChannelUpdate, Uint256, Transaction), commitment_tx: Option<Transaction>, has_htlc_tx: HTLCType) -> Vec<Transaction> {
let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap();
assert!(node_txn.len() >= if commitment_tx.is_some() { 0 } else { 1 } + if has_htlc_tx == HTLCType::NONE { 0 } else { 1 });
let mut res = Vec::with_capacity(2);
if let Some(explicit_tx) = commitment_tx {
res.push(explicit_tx.clone());
} else {
for tx in node_txn.iter() {
if tx.input.len() == 1 && tx.input[0].prev_hash == chan.3.txid() {
let mut funding_tx_map = HashMap::new();
funding_tx_map.insert(chan.3.txid(), chan.3.clone());
tx.verify(&funding_tx_map).unwrap();
res.push(tx.clone());
}
}
}
assert_eq!(res.len(), 1);
if has_htlc_tx != HTLCType::NONE {
for tx in node_txn.iter() {
if tx.input.len() == 1 && tx.input[0].prev_hash == res[0].txid() {
let mut funding_tx_map = HashMap::new();
funding_tx_map.insert(res[0].txid(), res[0].clone());
tx.verify(&funding_tx_map).unwrap();
if has_htlc_tx == HTLCType::TIMEOUT {
assert!(tx.lock_time != 0);
} else {
assert!(tx.lock_time == 0);
}
res.push(tx.clone());
break;
}
}
assert_eq!(res.len(), 2);
}
node_txn.clear();
res
}
fn check_preimage_claim(node: &Node, prev_txn: &Vec<Transaction>) -> Vec<Transaction> {
let mut node_txn = node.tx_broadcaster.txn_broadcasted.lock().unwrap();
assert!(node_txn.len() >= 1);
assert_eq!(node_txn[0].input.len(), 1);
let mut found_prev = false;
for tx in prev_txn {
if node_txn[0].input[0].prev_hash == tx.txid() {
let mut funding_tx_map = HashMap::new();
funding_tx_map.insert(tx.txid(), tx.clone());
node_txn[0].verify(&funding_tx_map).unwrap();
assert!(node_txn[0].input[0].witness[2].len() > 106); // must spend an htlc output
assert_eq!(tx.input.len(), 1); // must spend a commitment tx
found_prev = true;
break;
}
}
assert!(found_prev);
let mut res = Vec::new();
mem::swap(&mut *node_txn, &mut res);
res
}
#[test]
fn channel_monitor_network_test() {
// Simple test which builds a network of ChannelManagers, connects them to each other, and
// tests that ChannelMonitor is able to recover from various states.
let nodes = create_network(5);
// Create some initial channels
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1);
let chan_2 = create_announced_chan_between_nodes(&nodes, 1, 2);
let chan_3 = create_announced_chan_between_nodes(&nodes, 2, 3);
let chan_4 = create_announced_chan_between_nodes(&nodes, 3, 4);
// Rebalance the network a bit by relaying one payment through all the channels...
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
send_payment(&nodes[0], &vec!(&nodes[1], &nodes[2], &nodes[3], &nodes[4])[..], 8000000);
// Simple case with no pending HTLCs:
nodes[1].node.peer_disconnected(&nodes[0].node.get_our_node_id(), true);
{
let node_txn = test_txn_broadcast(&nodes[1], &chan_1, None, HTLCType::NONE);
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[0].chain_monitor.block_connected_checked(&header, 1, &[&node_txn[0]; 1], &[4; 1]);
assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 0);
}
assert_eq!(nodes[0].node.list_channels().len(), 0);
assert_eq!(nodes[1].node.list_channels().len(), 1);
// One pending HTLC is discarded by the force-close:
let payment_preimage_1 = route_payment(&nodes[1], &vec!(&nodes[2], &nodes[3])[..], 3000000).0;
// Simple case of one pending HTLC to HTLC-Timeout
nodes[1].node.peer_disconnected(&nodes[2].node.get_our_node_id(), true);
{
let node_txn = test_txn_broadcast(&nodes[1], &chan_2, None, HTLCType::TIMEOUT);
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[2].chain_monitor.block_connected_checked(&header, 1, &[&node_txn[0]; 1], &[4; 1]);
assert_eq!(nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 0);
}
assert_eq!(nodes[1].node.list_channels().len(), 0);
assert_eq!(nodes[2].node.list_channels().len(), 1);
macro_rules! claim_funds {
($node: expr, $prev_node: expr, $preimage: expr) => {
{
assert!($node.node.claim_funds($preimage));
{
let mut added_monitors = $node.chan_monitor.added_monitors.lock().unwrap();
assert_eq!(added_monitors.len(), 1);
added_monitors.clear();
}
let events = $node.node.get_and_clear_pending_events();
assert_eq!(events.len(), 1);
match events[0] {
Event::SendFulfillHTLC { ref node_id, .. } => {
assert_eq!(*node_id, $prev_node.node.get_our_node_id());
},
_ => panic!("Unexpected event"),
};
}
}
}
// nodes[3] gets the preimage, but nodes[2] already disconnected, resulting in a nodes[2]
// HTLC-Timeout and a nodes[3] claim against it (+ its own announces)
nodes[2].node.peer_disconnected(&nodes[3].node.get_our_node_id(), true);
{
let node_txn = test_txn_broadcast(&nodes[2], &chan_3, None, HTLCType::TIMEOUT);
// Claim the payment on nodes[3], giving it knowledge of the preimage
claim_funds!(nodes[3], nodes[2], payment_preimage_1);
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[3].chain_monitor.block_connected_checked(&header, 1, &[&node_txn[0]; 1], &[4; 1]);
check_preimage_claim(&nodes[3], &node_txn);
}
assert_eq!(nodes[2].node.list_channels().len(), 0);
assert_eq!(nodes[3].node.list_channels().len(), 1);
// One pending HTLC to time out:
let payment_preimage_2 = route_payment(&nodes[3], &vec!(&nodes[4])[..], 3000000).0;
{
let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[3].chain_monitor.block_connected_checked(&header, 1, &Vec::new()[..], &[0; 0]);
for i in 2..TEST_FINAL_CLTV - 5 {
header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[3].chain_monitor.block_connected_checked(&header, i, &Vec::new()[..], &[0; 0]);
}
let node_txn = test_txn_broadcast(&nodes[3], &chan_4, None, HTLCType::TIMEOUT);
// Claim the payment on nodes[3], giving it knowledge of the preimage
claim_funds!(nodes[4], nodes[3], payment_preimage_2);
header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[4].chain_monitor.block_connected_checked(&header, 1, &Vec::new()[..], &[0; 0]);
for i in 2..TEST_FINAL_CLTV - 5 {
header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[4].chain_monitor.block_connected_checked(&header, i, &Vec::new()[..], &[0; 0]);
}
test_txn_broadcast(&nodes[4], &chan_4, None, HTLCType::SUCCESS);
header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[4].chain_monitor.block_connected_checked(&header, TEST_FINAL_CLTV - 5, &[&node_txn[0]; 1], &[4; 1]);
check_preimage_claim(&nodes[4], &node_txn);
}
assert_eq!(nodes[3].node.list_channels().len(), 0);
assert_eq!(nodes[4].node.list_channels().len(), 0);
// TODO: Need to reenable this when we fix local route tracking
// Create some new channels:
/*let chan_5 = create_announced_chan_between_nodes(&nodes, 0, 1);
// A pending HTLC which will be revoked:
let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
// Get the will-be-revoked local txn from nodes[0]
let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.iter().next().unwrap().1.last_local_commitment_txn.clone();
// Revoke the old state
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_3);
{
let mut header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[1].chain_monitor.block_connected_checked(&header, 1, &vec![&revoked_local_txn[0]; 1], &[4; 1]);
{
let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
assert_eq!(node_txn.len(), 1);
assert_eq!(node_txn[0].input.len(), 1);
let mut funding_tx_map = HashMap::new();
funding_tx_map.insert(revoked_local_txn[0].txid(), revoked_local_txn[0].clone());
node_txn[0].verify(&funding_tx_map).unwrap();
node_txn.clear();
}
nodes[0].chain_monitor.block_connected_checked(&header, 1, &vec![&revoked_local_txn[0]; 1], &[4; 0]);
let node_txn = test_txn_broadcast(&nodes[0], &chan_5, Some(revoked_local_txn[0].clone()), HTLCType::TIMEOUT);
header = BlockHeader { version: 0x20000000, prev_blockhash: header.bitcoin_hash(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
nodes[1].chain_monitor.block_connected_checked(&header, 1, &[&node_txn[1]; 1], &[4; 1]);
//TODO: At this point nodes[1] should claim the revoked HTLC-Timeout output, but that's
//not yet implemented in ChannelMonitor
}
get_announce_close_broadcast_events(&nodes, 0, 1);
assert_eq!(nodes[0].node.list_channels().len(), 0);
assert_eq!(nodes[1].node.list_channels().len(), 0);*/
// Check that we processed all pending events
for node in nodes {
assert_eq!(node.node.get_and_clear_pending_events().len(), 0);
assert_eq!(node.chan_monitor.added_monitors.lock().unwrap().len(), 0);
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,6 @@
use chain::chaininterface;
use chain::chaininterface::ConfirmationTarget;
use ln::channelmonitor;
use ln::msgs::HandleError;
use bitcoin::blockdata::transaction::Transaction;
use bitcoin::util::hash::Sha256dHash;
@ -30,7 +29,7 @@ impl TestChannelMonitor {
}
}
impl channelmonitor::ManyChannelMonitor for TestChannelMonitor {
fn add_update_monitor(&self, funding_txo: (Sha256dHash, u16), monitor: channelmonitor::ChannelMonitor) -> Result<(), HandleError> {
fn add_update_monitor(&self, funding_txo: (Sha256dHash, u16), monitor: channelmonitor::ChannelMonitor) -> Result<(), channelmonitor::ChannelMonitorUpdateErr> {
self.added_monitors.lock().unwrap().push((funding_txo, monitor.clone()));
self.simple_monitor.add_update_monitor(funding_txo, monitor)
}