monitor.latest_good_update.lock().unwrap().insert(outpoint, monitor_ser);
}
let mut monitor_refs = HashMap::new();
- for (outpoint, monitor) in monitors.iter() {
+ for (outpoint, monitor) in monitors.iter_mut() {
monitor_refs.insert(*outpoint, monitor);
}
tx_broadcaster: broadcast.clone(),
logger,
default_config: config,
- channel_monitors: &monitor_refs,
+ channel_monitors: &mut monitor_refs,
};
let res = (<(Sha256d, ChannelManager<EnforcingChannelKeys>)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor);
use bitcoin::blockdata::script::{Script,Builder};
use bitcoin::blockdata::opcodes;
-use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction};
+use bitcoin::blockdata::transaction::{TxIn,TxOut,OutPoint,Transaction, SigHashType};
+use bitcoin::consensus::encode::{self, Decodable, Encodable};
+use bitcoin::util::bip143;
use bitcoin_hashes::{Hash, HashEngine};
use bitcoin_hashes::sha256::Hash as Sha256;
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
use ln::channelmanager::PaymentHash;
+use ln::msgs::DecodeError;
+use util::ser::{Readable, Writeable, Writer, WriterWriteAdaptor};
-use secp256k1::key::{PublicKey,SecretKey};
-use secp256k1::Secp256k1;
+use secp256k1::key::{SecretKey,PublicKey};
+use secp256k1::{Secp256k1, Signature};
use secp256k1;
pub(super) const HTLC_SUCCESS_TX_WEIGHT: u64 = 703;
output: txouts,
}
}
+
+#[derive(Clone)]
+/// We use this to track local commitment transactions and put off signing them until we are ready
+/// to broadcast. Eventually this will require a signer which is possibly external, but for now we
+/// just pass in the SecretKeys required.
+pub(crate) struct LocalCommitmentTransaction {
+ tx: Transaction
+}
+impl LocalCommitmentTransaction {
+ #[cfg(test)]
+ pub fn dummy() -> Self {
+ Self { tx: Transaction {
+ version: 2,
+ input: Vec::new(),
+ output: Vec::new(),
+ lock_time: 0,
+ } }
+ }
+
+ pub fn new_missing_local_sig(mut tx: Transaction, their_sig: &Signature, our_funding_key: &PublicKey, their_funding_key: &PublicKey) -> LocalCommitmentTransaction {
+ if tx.input.len() != 1 { panic!("Tried to store a commitment transaction that had input count != 1!"); }
+ if tx.input[0].witness.len() != 0 { panic!("Tried to store a signed commitment transaction?"); }
+
+ tx.input[0].witness.push(Vec::new()); // First is the multisig dummy
+
+ if our_funding_key.serialize()[..] < their_funding_key.serialize()[..] {
+ tx.input[0].witness.push(Vec::new());
+ tx.input[0].witness.push(their_sig.serialize_der().to_vec());
+ tx.input[0].witness[2].push(SigHashType::All as u8);
+ } else {
+ tx.input[0].witness.push(their_sig.serialize_der().to_vec());
+ tx.input[0].witness[1].push(SigHashType::All as u8);
+ tx.input[0].witness.push(Vec::new());
+ }
+
+ Self { tx }
+ }
+
+ pub fn txid(&self) -> Sha256dHash {
+ self.tx.txid()
+ }
+
+ pub fn has_local_sig(&self) -> bool {
+ if self.tx.input.len() != 1 { panic!("Commitment transactions must have input count == 1!"); }
+ if self.tx.input[0].witness.len() == 4 {
+ assert!(!self.tx.input[0].witness[1].is_empty());
+ assert!(!self.tx.input[0].witness[2].is_empty());
+ true
+ } else {
+ assert_eq!(self.tx.input[0].witness.len(), 3);
+ assert!(self.tx.input[0].witness[0].is_empty());
+ assert!(self.tx.input[0].witness[1].is_empty() || self.tx.input[0].witness[2].is_empty());
+ false
+ }
+ }
+
+ pub fn add_local_sig<T: secp256k1::Signing>(&mut self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) {
+ if self.has_local_sig() { return; }
+ let sighash = hash_to_message!(&bip143::SighashComponents::new(&self.tx)
+ .sighash_all(&self.tx.input[0], funding_redeemscript, channel_value_satoshis)[..]);
+ let our_sig = secp_ctx.sign(&sighash, funding_key);
+
+ if self.tx.input[0].witness[1].is_empty() {
+ self.tx.input[0].witness[1] = our_sig.serialize_der().to_vec();
+ self.tx.input[0].witness[1].push(SigHashType::All as u8);
+ } else {
+ self.tx.input[0].witness[2] = our_sig.serialize_der().to_vec();
+ self.tx.input[0].witness[2].push(SigHashType::All as u8);
+ }
+
+ self.tx.input[0].witness.push(funding_redeemscript.as_bytes().to_vec());
+ }
+
+ pub fn without_valid_witness(&self) -> &Transaction { &self.tx }
+ pub fn with_valid_witness(&self) -> &Transaction {
+ assert!(self.has_local_sig());
+ &self.tx
+ }
+}
+impl PartialEq for LocalCommitmentTransaction {
+ // We dont care whether we are signed in equality comparison
+ fn eq(&self, o: &Self) -> bool {
+ self.txid() == o.txid()
+ }
+}
+impl Writeable for LocalCommitmentTransaction {
+ fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
+ if let Err(e) = self.tx.consensus_encode(&mut WriterWriteAdaptor(writer)) {
+ match e {
+ encode::Error::Io(e) => return Err(e),
+ _ => panic!("local tx must have been well-formed!"),
+ }
+ }
+ Ok(())
+ }
+}
+impl<R: ::std::io::Read> Readable<R> for LocalCommitmentTransaction {
+ fn read(reader: &mut R) -> Result<Self, DecodeError> {
+ let tx = match Transaction::consensus_decode(reader.by_ref()) {
+ Ok(tx) => tx,
+ Err(e) => match e {
+ encode::Error::Io(ioe) => return Err(DecodeError::Io(ioe)),
+ _ => return Err(DecodeError::InvalidValue),
+ },
+ };
+
+ if tx.input.len() != 1 {
+ // Ensure tx didn't hit the 0-input ambiguity case.
+ return Err(DecodeError::InvalidValue);
+ }
+ Ok(Self { tx })
+ }
+}
use ln::msgs::{DecodeError, OptionalField, LocalFeatures, DataLossProtect};
use ln::channelmonitor::ChannelMonitor;
use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingForwardHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT};
-use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT};
+use ln::chan_utils::{LocalCommitmentTransaction,TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGHT,HTLC_TIMEOUT_TX_WEIGHT};
use ln::chan_utils;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
use chain::transaction::OutPoint;
let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
let secp_ctx = Secp256k1::new();
- let channel_monitor = ChannelMonitor::new(chan_keys.revocation_base_key(), chan_keys.delayed_payment_base_key(),
+ let channel_monitor = ChannelMonitor::new(chan_keys.funding_key(), chan_keys.revocation_base_key(), chan_keys.delayed_payment_base_key(),
chan_keys.htlc_base_key(), chan_keys.payment_base_key(), &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay,
keys_provider.get_destination_script(), logger.clone());
}
let secp_ctx = Secp256k1::new();
- let channel_monitor = ChannelMonitor::new(chan_keys.revocation_base_key(), chan_keys.delayed_payment_base_key(),
+ let channel_monitor = ChannelMonitor::new(chan_keys.funding_key(), chan_keys.revocation_base_key(), chan_keys.delayed_payment_base_key(),
chan_keys.htlc_base_key(), chan_keys.payment_base_key(), &keys_provider.get_shutdown_pubkey(), config.own_channel_config.our_to_self_delay,
keys_provider.get_destination_script(), logger.clone());
}.push_opcode(opcodes::all::OP_PUSHNUM_2).push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script()
}
- fn sign_commitment_transaction(&self, tx: &mut Transaction, their_sig: &Signature) -> Signature {
- if tx.input.len() != 1 {
- panic!("Tried to sign commitment transaction that had input count != 1!");
- }
- if tx.input[0].witness.len() != 0 {
- panic!("Tried to re-sign commitment transaction");
- }
-
- let funding_redeemscript = self.get_funding_redeemscript();
-
- let sighash = hash_to_message!(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]);
- let our_sig = self.secp_ctx.sign(&sighash, self.local_keys.funding_key());
-
- tx.input[0].witness.push(Vec::new()); // First is the multisig dummy
-
- let our_funding_key = PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()).serialize();
- let their_funding_key = self.their_funding_pubkey.unwrap().serialize();
- if our_funding_key[..] < their_funding_key[..] {
- tx.input[0].witness.push(our_sig.serialize_der().to_vec());
- tx.input[0].witness.push(their_sig.serialize_der().to_vec());
- } else {
- tx.input[0].witness.push(their_sig.serialize_der().to_vec());
- tx.input[0].witness.push(our_sig.serialize_der().to_vec());
- }
- tx.input[0].witness[1].push(SigHashType::All as u8);
- tx.input[0].witness[2].push(SigHashType::All as u8);
-
- tx.input[0].witness.push(funding_redeemscript.into_bytes());
-
- our_sig
- }
-
/// Builds the htlc-success or htlc-timeout transaction which spends a given HTLC output
/// @local is used only to convert relevant internal structures which refer to remote vs local
/// to decide value of outputs and direction of HTLCs.
Ok(())
}
- fn funding_created_signature(&mut self, sig: &Signature) -> Result<(Transaction, Transaction, Signature, TxCreationKeys), ChannelError> {
+ fn funding_created_signature(&mut self, sig: &Signature) -> Result<(Transaction, LocalCommitmentTransaction, Signature, TxCreationKeys), ChannelError> {
let funding_script = self.get_funding_redeemscript();
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
- let mut local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0;
+ let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0;
let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]);
// They sign the "local" commitment transaction...
secp_check!(self.secp_ctx.verify(&local_sighash, &sig, &self.their_funding_pubkey.unwrap()), "Invalid funding_created signature from peer");
- // ...and we sign it, allowing us to broadcast the tx if we wish
- self.sign_commitment_transaction(&mut local_initial_commitment_tx, sig);
+ let localtx = LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, sig, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey.as_ref().unwrap());
let remote_keys = self.build_remote_transaction_keys()?;
let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0;
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?.0;
// We sign the "remote" commitment transaction, allowing them to broadcast the tx if they wish.
- Ok((remote_initial_commitment_tx, local_initial_commitment_tx, remote_signature, local_keys))
+ Ok((remote_initial_commitment_tx, localtx, remote_signature, local_keys))
}
pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> {
let funding_script = self.get_funding_redeemscript();
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
- let mut local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0;
+ let local_initial_commitment_tx = self.build_commitment_transaction(self.cur_local_commitment_transaction_number, &local_keys, true, false, self.feerate_per_kw).0;
let local_sighash = hash_to_message!(&bip143::SighashComponents::new(&local_initial_commitment_tx).sighash_all(&local_initial_commitment_tx.input[0], &funding_script, self.channel_value_satoshis)[..]);
// They sign the "local" commitment transaction, allowing us to broadcast the tx if we wish.
secp_check!(self.secp_ctx.verify(&local_sighash, &msg.signature, &self.their_funding_pubkey.unwrap()), "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, local_keys, self.feerate_per_kw, Vec::new());
+ self.channel_monitor.provide_latest_local_commitment_tx_info(
+ LocalCommitmentTransaction::new_missing_local_sig(local_initial_commitment_tx, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey.as_ref().unwrap()),
+ local_keys, self.feerate_per_kw, Vec::new());
self.channel_state = ChannelState::FundingSent as u32 | (self.channel_state & (ChannelState::MonitorUpdateFailed as u32));
self.cur_local_commitment_transaction_number -= 1;
return Err(ChannelError::Close("Got wrong number of HTLC signatures from remote"));
}
- self.sign_commitment_transaction(&mut local_commitment_tx.0, &msg.signature);
-
let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.2.len());
for (idx, (htlc, source)) in local_commitment_tx.2.drain(..).enumerate() {
if let Some(_) = htlc.transaction_output_index {
}
}
- self.channel_monitor.provide_latest_local_commitment_tx_info(local_commitment_tx.0, local_keys, self.feerate_per_kw, htlcs_and_sigs);
+
+ self.channel_monitor.provide_latest_local_commitment_tx_info(
+ LocalCommitmentTransaction::new_missing_local_sig(local_commitment_tx.0, &msg.signature, &PublicKey::from_secret_key(&self.secp_ctx, self.local_keys.funding_key()), self.their_funding_pubkey.as_ref().unwrap()),
+ local_keys, self.feerate_per_kw, htlcs_and_sigs);
for htlc in self.pending_inbound_htlcs.iter_mut() {
let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state {
}
/// May only be called after funding has been initiated (ie is_funding_initiated() is true)
- pub fn channel_monitor(&self) -> &ChannelMonitor {
+ pub fn channel_monitor(&mut self) -> &mut ChannelMonitor {
if self.channel_state < ChannelState::FundingCreated as u32 {
panic!("Can't get a channel monitor until funding has been created");
}
- &self.channel_monitor
+ &mut self.channel_monitor
}
/// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus,
use ln::channel::{Channel,ChannelKeys,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,TxCreationKeys};
use ln::channel::MAX_FUNDING_SATOSHIS;
use ln::chan_utils;
+ use ln::chan_utils::LocalCommitmentTransaction;
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
use chain::keysinterface::{InMemoryChannelKeys, KeysInterface};
use chain::transaction::OutPoint;
.collect();
(res.0, htlcs)
};
+ let redeemscript = chan.get_funding_redeemscript();
let their_signature = Signature::from_der(&hex::decode($their_sig_hex).unwrap()[..]).unwrap();
- let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &chan.get_funding_redeemscript(), chan.channel_value_satoshis)[..]).unwrap();
+ let sighash = Message::from_slice(&bip143::SighashComponents::new(&unsigned_tx.0).sighash_all(&unsigned_tx.0.input[0], &redeemscript, chan.channel_value_satoshis)[..]).unwrap();
secp_ctx.verify(&sighash, &their_signature, &chan.their_funding_pubkey.unwrap()).unwrap();
- chan.sign_commitment_transaction(&mut unsigned_tx.0, &their_signature);
+ let mut localtx = LocalCommitmentTransaction::new_missing_local_sig(unsigned_tx.0.clone(), &their_signature, &PublicKey::from_secret_key(&secp_ctx, chan.local_keys.funding_key()), chan.their_funding_pubkey.as_ref().unwrap());
+ localtx.add_local_sig(chan.local_keys.funding_key(), &redeemscript, chan.channel_value_satoshis, &chan.secp_ctx);
- assert_eq!(serialize(&unsigned_tx.0)[..],
+ assert_eq!(serialize(localtx.with_valid_witness())[..],
hex::decode($tx_hex).unwrap()[..]);
};
}
///
/// In such cases the latest local transactions will be sent to the tx_broadcaster included in
/// this struct.
- pub channel_monitors: &'a HashMap<OutPoint, &'a ChannelMonitor>,
+ pub channel_monitors: &'a mut HashMap<OutPoint, &'a mut ChannelMonitor>,
}
impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArgs<R, ChannelManagerReadArgs<'a, ChanSigner>> for (Sha256dHash, ChannelManager<ChanSigner>) {
let funding_txo = channel.channel_monitor().get_funding_txo().ok_or(DecodeError::InvalidValue)?;
funding_txo_set.insert(funding_txo.clone());
- if let Some(monitor) = args.channel_monitors.get(&funding_txo) {
+ if let Some(ref mut monitor) = args.channel_monitors.get_mut(&funding_txo) {
if channel.get_cur_local_commitment_transaction_number() != monitor.get_cur_local_commitment_number() ||
channel.get_revoked_remote_commitment_transaction_number() != monitor.get_min_seen_secret() ||
channel.get_cur_remote_commitment_transaction_number() != monitor.get_cur_remote_commitment_number() {
}
}
- for (ref funding_txo, ref monitor) in args.channel_monitors.iter() {
+ for (ref funding_txo, ref mut monitor) in args.channel_monitors.iter_mut() {
if !funding_txo_set.contains(funding_txo) {
closed_channels.push((monitor.get_latest_local_commitment_txn(), Vec::new()));
}
use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
use bitcoin::blockdata::script::{Script, Builder};
use bitcoin::blockdata::opcodes;
-use bitcoin::consensus::encode::{self, Decodable, Encodable};
+use bitcoin::consensus::encode;
use bitcoin::util::hash::BitcoinHash;
use bitcoin::util::bip143;
use ln::msgs::DecodeError;
use ln::chan_utils;
-use ln::chan_utils::HTLCOutputInCommitment;
+use ln::chan_utils::{HTLCOutputInCommitment, LocalCommitmentTransaction};
use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
use ln::channel::{ACCEPTED_HTLC_SCRIPT_WEIGHT, OFFERED_HTLC_SCRIPT_WEIGHT};
use chain::chaininterface::{ChainListener, ChainWatchInterface, BroadcasterInterface, FeeEstimator, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT};
use chain::transaction::OutPoint;
use chain::keysinterface::SpendableOutputDescriptor;
use util::logger::Logger;
-use util::ser::{ReadableArgs, Readable, Writer, Writeable, WriterWriteAdaptor, U48};
+use util::ser::{ReadableArgs, Readable, Writer, Writeable, U48};
use util::{byte_utils, events};
use std::collections::{HashMap, hash_map, HashSet};
#[derive(Clone, PartialEq)]
enum Storage {
Local {
+ funding_key: SecretKey,
revocation_base_key: SecretKey,
htlc_base_key: SecretKey,
delayed_payment_base_key: SecretKey,
struct LocalSignedTx {
/// txid of the transaction in tx, just used to make comparison faster
txid: Sha256dHash,
- tx: Transaction,
+ tx: LocalCommitmentTransaction,
revocation_key: PublicKey,
a_htlc_key: PublicKey,
b_htlc_key: PublicKey,
}
impl ChannelMonitor {
- pub(super) fn new(revocation_base_key: &SecretKey, delayed_payment_base_key: &SecretKey, htlc_base_key: &SecretKey, payment_base_key: &SecretKey, shutdown_pubkey: &PublicKey, our_to_self_delay: u16, destination_script: Script, logger: Arc<Logger>) -> ChannelMonitor {
+ pub(super) fn new(funding_key: &SecretKey, revocation_base_key: &SecretKey, delayed_payment_base_key: &SecretKey, htlc_base_key: &SecretKey, payment_base_key: &SecretKey, shutdown_pubkey: &PublicKey, our_to_self_delay: u16, destination_script: Script, logger: Arc<Logger>) -> ChannelMonitor {
ChannelMonitor {
commitment_transaction_number_obscure_factor: 0,
key_storage: Storage::Local {
+ funding_key: funding_key.clone(),
revocation_base_key: revocation_base_key.clone(),
htlc_base_key: htlc_base_key.clone(),
delayed_payment_base_key: delayed_payment_base_key.clone(),
/// Panics if set_their_to_self_delay has never been called.
/// Also update Storage with latest local per_commitment_point to derive local_delayedkey in
/// case of onchain HTLC tx
- pub(super) fn provide_latest_local_commitment_tx_info(&mut self, signed_commitment_tx: Transaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<(Signature, Signature)>, Option<HTLCSource>)>) {
+ pub(super) fn provide_latest_local_commitment_tx_info(&mut self, commitment_tx: LocalCommitmentTransaction, local_keys: chan_utils::TxCreationKeys, feerate_per_kw: u64, htlc_outputs: Vec<(HTLCOutputInCommitment, Option<(Signature, Signature)>, Option<HTLCSource>)>) {
assert!(self.their_to_self_delay.is_some());
self.prev_local_signed_commitment_tx = self.current_local_signed_commitment_tx.take();
self.current_local_signed_commitment_tx = Some(LocalSignedTx {
- txid: signed_commitment_tx.txid(),
- tx: signed_commitment_tx,
+ txid: commitment_tx.txid(),
+ tx: commitment_tx,
revocation_key: local_keys.revocation_key,
a_htlc_key: local_keys.a_htlc_key,
b_htlc_key: local_keys.b_htlc_key,
}
if let Some(ref local_tx) = self.current_local_signed_commitment_tx {
if let Some(ref other_local_tx) = other.current_local_signed_commitment_tx {
- let our_commitment_number = 0xffffffffffff - ((((local_tx.tx.input[0].sequence as u64 & 0xffffff) << 3*8) | (local_tx.tx.lock_time as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor);
- let other_commitment_number = 0xffffffffffff - ((((other_local_tx.tx.input[0].sequence as u64 & 0xffffff) << 3*8) | (other_local_tx.tx.lock_time as u64 & 0xffffff)) ^ other.commitment_transaction_number_obscure_factor);
+ let our_commitment_number = 0xffffffffffff - ((((local_tx.tx.without_valid_witness().input[0].sequence as u64 & 0xffffff) << 3*8) | (local_tx.tx.without_valid_witness().lock_time as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor);
+ let other_commitment_number = 0xffffffffffff - ((((other_local_tx.tx.without_valid_witness().input[0].sequence as u64 & 0xffffff) << 3*8) | (other_local_tx.tx.without_valid_witness().lock_time as u64 & 0xffffff)) ^ other.commitment_transaction_number_obscure_factor);
if our_commitment_number >= other_commitment_number {
self.key_storage = other.key_storage;
}
}
match self.key_storage {
- Storage::Local { ref revocation_base_key, ref htlc_base_key, ref delayed_payment_base_key, ref payment_base_key, ref shutdown_pubkey, ref prev_latest_per_commitment_point, ref latest_per_commitment_point, ref funding_info, ref current_remote_commitment_txid, ref prev_remote_commitment_txid } => {
+ Storage::Local { ref funding_key, ref revocation_base_key, ref htlc_base_key, ref delayed_payment_base_key, ref payment_base_key, ref shutdown_pubkey, ref prev_latest_per_commitment_point, ref latest_per_commitment_point, ref funding_info, ref current_remote_commitment_txid, ref prev_remote_commitment_txid } => {
writer.write_all(&[0; 1])?;
+ writer.write_all(&funding_key[..])?;
writer.write_all(&revocation_base_key[..])?;
writer.write_all(&htlc_base_key[..])?;
writer.write_all(&delayed_payment_base_key[..])?;
macro_rules! serialize_local_tx {
($local_tx: expr) => {
- if let Err(e) = $local_tx.tx.consensus_encode(&mut WriterWriteAdaptor(writer)) {
- match e {
- encode::Error::Io(e) => return Err(e),
- _ => panic!("local tx must have been well-formed!"),
- }
- }
-
+ $local_tx.tx.write(writer)?;
writer.write_all(&$local_tx.revocation_key.serialize())?;
writer.write_all(&$local_tx.a_htlc_key.serialize())?;
writer.write_all(&$local_tx.b_htlc_key.serialize())?;
pub(super) fn get_cur_local_commitment_number(&self) -> u64 {
if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
- 0xffff_ffff_ffff - ((((local_tx.tx.input[0].sequence as u64 & 0xffffff) << 3*8) | (local_tx.tx.lock_time as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor)
+ 0xffff_ffff_ffff - ((((local_tx.tx.without_valid_witness().input[0].sequence as u64 & 0xffffff) << 3*8) | (local_tx.tx.without_valid_witness().lock_time as u64 & 0xffffff)) ^ self.commitment_transaction_number_obscure_factor)
} else { 0xffff_ffff_ffff }
}
let redeemscript = chan_utils::get_revokeable_redeemscript(&local_tx.revocation_key, self.their_to_self_delay.unwrap(), &local_tx.delayed_payment_key);
let revokeable_p2wsh = redeemscript.to_v0_p2wsh();
- for (idx, output) in local_tx.tx.output.iter().enumerate() {
+ for (idx, output) in local_tx.tx.without_valid_witness().output.iter().enumerate() {
if output.script_pubkey == revokeable_p2wsh {
- add_dynamic_output!(local_tx.tx, idx as u32);
+ add_dynamic_output!(local_tx.tx.without_valid_witness(), idx as u32);
break;
}
}
res.push(htlc_success_tx);
}
}
- watch_outputs.push(local_tx.tx.output[transaction_output_index as usize].clone());
+ watch_outputs.push(local_tx.tx.without_valid_witness().output[transaction_output_index as usize].clone());
} else { panic!("Should have sigs for non-dust local tx outputs!") }
}
}
// 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 &mut Some(ref mut local_tx) = &mut self.current_local_signed_commitment_tx {
+ if local_tx.txid == commitment_txid {
+ match self.key_storage {
+ Storage::Local { ref funding_key, .. } => {
+ local_tx.tx.add_local_sig(funding_key, self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
+ },
+ _ => {},
+ }
+ }
+ }
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");
+ assert!(local_tx.tx.has_local_sig());
match self.key_storage {
Storage::Local { ref delayed_payment_base_key, ref latest_per_commitment_point, .. } => {
append_onchain_update!(self.broadcast_by_local_state(local_tx, latest_per_commitment_point, &Some(*delayed_payment_base_key), height));
}
}
}
+ if let &mut Some(ref mut local_tx) = &mut self.prev_local_signed_commitment_tx {
+ if local_tx.txid == commitment_txid {
+ match self.key_storage {
+ Storage::Local { ref funding_key, .. } => {
+ local_tx.tx.add_local_sig(funding_key, self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
+ },
+ _ => {},
+ }
+ }
+ }
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");
+ assert!(local_tx.tx.has_local_sig());
match self.key_storage {
Storage::Local { ref delayed_payment_base_key, ref prev_latest_per_commitment_point, .. } => {
append_onchain_update!(self.broadcast_by_local_state(local_tx, prev_latest_per_commitment_point, &Some(*delayed_payment_base_key), height));
/// substantial amount of time (a month or even a year) to get back funds. Best may be to contact
/// out-of-band the other node operator to coordinate with him if option is available to you.
/// In any-case, choice is up to the user.
- pub fn get_latest_local_commitment_txn(&self) -> Vec<Transaction> {
+ pub fn get_latest_local_commitment_txn(&mut self) -> Vec<Transaction> {
log_trace!(self, "Getting signed latest local commitment transaction!");
+ if let &mut Some(ref mut local_tx) = &mut self.current_local_signed_commitment_tx {
+ match self.key_storage {
+ Storage::Local { ref funding_key, .. } => {
+ local_tx.tx.add_local_sig(funding_key, self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
+ },
+ _ => {},
+ }
+ }
if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
- let mut res = vec![local_tx.tx.clone()];
+ let mut res = vec![local_tx.tx.with_valid_witness().clone()];
match self.key_storage {
Storage::Local { ref delayed_payment_base_key, ref prev_latest_per_commitment_point, .. } => {
res.append(&mut self.broadcast_by_local_state(local_tx, prev_latest_per_commitment_point, &Some(*delayed_payment_base_key), 0).0);
}
}
}
+ let should_broadcast = if let Some(_) = self.current_local_signed_commitment_tx {
+ self.would_broadcast_at_height(height)
+ } else { false };
+ if let Some(ref mut cur_local_tx) = self.current_local_signed_commitment_tx {
+ if should_broadcast {
+ match self.key_storage {
+ Storage::Local { ref funding_key, .. } => {
+ cur_local_tx.tx.add_local_sig(funding_key, self.funding_redeemscript.as_ref().unwrap(), self.channel_value_satoshis.unwrap(), &self.secp_ctx);
+ },
+ _ => {}
+ }
+ }
+ }
if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx {
- if self.would_broadcast_at_height(height) {
- log_trace!(self, "Broadcast onchain {}", log_tx!(cur_local_tx.tx));
- broadcaster.broadcast_transaction(&cur_local_tx.tx);
+ if should_broadcast {
+ log_trace!(self, "Broadcast onchain {}", log_tx!(cur_local_tx.tx.with_valid_witness()));
+ broadcaster.broadcast_transaction(&cur_local_tx.tx.with_valid_witness());
match self.key_storage {
Storage::Local { ref delayed_payment_base_key, ref latest_per_commitment_point, .. } => {
let (txs, mut spendable_output, new_outputs, _) = self.broadcast_by_local_state(&cur_local_tx, latest_per_commitment_point, &Some(*delayed_payment_base_key), height);
let key_storage = match <u8 as Readable<R>>::read(reader)? {
0 => {
+ let funding_key = Readable::read(reader)?;
let revocation_base_key = Readable::read(reader)?;
let htlc_base_key = Readable::read(reader)?;
let delayed_payment_base_key = Readable::read(reader)?;
let current_remote_commitment_txid = Readable::read(reader)?;
let prev_remote_commitment_txid = Readable::read(reader)?;
Storage::Local {
+ funding_key,
revocation_base_key,
htlc_base_key,
delayed_payment_base_key,
macro_rules! read_local_tx {
() => {
{
- let tx = match Transaction::consensus_decode(reader.by_ref()) {
- Ok(tx) => tx,
- Err(e) => match e {
- encode::Error::Io(ioe) => return Err(DecodeError::Io(ioe)),
- _ => return Err(DecodeError::InvalidValue),
- },
- };
-
- if tx.input.is_empty() {
- // Ensure tx didn't hit the 0-input ambiguity case.
- return Err(DecodeError::InvalidValue);
- }
-
+ let tx = <LocalCommitmentTransaction as Readable<R>>::read(reader)?;
let revocation_key = Readable::read(reader)?;
let a_htlc_key = Readable::read(reader)?;
let b_htlc_key = Readable::read(reader)?;
use ln::channelmanager::{PaymentPreimage, PaymentHash};
use ln::channelmonitor::{ChannelMonitor, InputDescriptors};
use ln::chan_utils;
- use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys};
+ use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys, LocalCommitmentTransaction};
use util::test_utils::TestLogger;
use secp256k1::key::{SecretKey,PublicKey};
use secp256k1::Secp256k1;
{
// insert_secret correct sequence
- monitor = ChannelMonitor::new(&SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&[41; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
secrets.clear();
secrets.push([0; 32]);
{
// insert_secret #1 incorrect
- monitor = ChannelMonitor::new(&SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&[41; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
secrets.clear();
secrets.push([0; 32]);
{
// insert_secret #2 incorrect (#1 derived from incorrect)
- monitor = ChannelMonitor::new(&SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&[41; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
secrets.clear();
secrets.push([0; 32]);
{
// insert_secret #3 incorrect
- monitor = ChannelMonitor::new(&SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&[41; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
secrets.clear();
secrets.push([0; 32]);
{
// insert_secret #4 incorrect (1,2,3 derived from incorrect)
- monitor = ChannelMonitor::new(&SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&[41; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
secrets.clear();
secrets.push([0; 32]);
{
// insert_secret #5 incorrect
- monitor = ChannelMonitor::new(&SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&[41; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
secrets.clear();
secrets.push([0; 32]);
{
// insert_secret #6 incorrect (5 derived from incorrect)
- monitor = ChannelMonitor::new(&SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&[41; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
secrets.clear();
secrets.push([0; 32]);
{
// insert_secret #7 incorrect
- monitor = ChannelMonitor::new(&SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&[41; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
secrets.clear();
secrets.push([0; 32]);
{
// insert_secret #8 incorrect
- monitor = ChannelMonitor::new(&SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
+ monitor = ChannelMonitor::new(&SecretKey::from_slice(&[41; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
secrets.clear();
secrets.push([0; 32]);
// Prune with one old state and a local commitment tx holding a few overlaps with the
// old state.
- let mut monitor = ChannelMonitor::new(&SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
+ let mut monitor = ChannelMonitor::new(&SecretKey::from_slice(&[41; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[43; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &SecretKey::from_slice(&[44; 32]).unwrap(), &PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[45; 32]).unwrap()), 0, Script::new(), logger.clone());
monitor.their_to_self_delay = Some(10);
- monitor.provide_latest_local_commitment_tx_info(dummy_tx.clone(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..10]));
+ monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..10]));
monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[5..15]), 281474976710655, dummy_key);
monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[15..20]), 281474976710654, dummy_key);
monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key);
// Now update local commitment tx info, pruning only element 18 as we still care about the
// previous commitment tx's preimages too
- monitor.provide_latest_local_commitment_tx_info(dummy_tx.clone(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..5]));
+ monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..5]));
secret[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
monitor.provide_secret(281474976710653, secret.clone()).unwrap();
assert_eq!(monitor.payment_preimages.len(), 12);
test_preimages_exist!(&preimages[18..20], monitor);
// But if we do it again, we'll prune 5-10
- monitor.provide_latest_local_commitment_tx_info(dummy_tx.clone(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..3]));
+ monitor.provide_latest_local_commitment_tx_info(LocalCommitmentTransaction::dummy(), dummy_keys!(), 0, preimages_to_local_htlcs!(preimages[0..3]));
secret[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
monitor.provide_secret(281474976710652, secret.clone()).unwrap();
assert_eq!(monitor.payment_preimages.len(), 5);
//Confirm that the new fee based on the last local commitment txn is what we expected based on the feerate of 260 set above.
//This value results in a fee that is exactly what the funder can afford (277 sat + 1000 sat channel reserve)
{
- let chan_lock = nodes[1].node.channel_state.lock().unwrap();
- let chan = chan_lock.by_id.get(&channel_id).unwrap();
+ let mut chan_lock = nodes[1].node.channel_state.lock().unwrap();
+ let chan = chan_lock.by_id.get_mut(&channel_id).unwrap();
//We made sure neither party's funds are below the dust limit so -2 non-HTLC txns from number of outputs
let num_htlcs = chan.channel_monitor().get_latest_local_commitment_txn()[0].output.len() - 2;
check_added_monitors!(nodes[0], 1);
// Broadcast node 1 commitment txn
- let remote_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let remote_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(remote_txn[0].output.len(), 4); // 1 local, 1 remote, 1 htlc inbound, 1 htlc outbound
let mut has_both_htlcs = 0; // check htlcs match ones committed
// 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.channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.iter_mut().next().unwrap().1.channel_monitor().get_latest_local_commitment_txn();
assert_eq!(revoked_local_txn.len(), 2); // First commitment tx, then HTLC tx
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_5.3.txid());
// A pending HTLC which will be revoked:
let payment_preimage_4 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
// Get the will-be-revoked local txn from B
- let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.iter().next().unwrap().1.channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.iter_mut().next().unwrap().1.channel_monitor().get_latest_local_commitment_txn();
assert_eq!(revoked_local_txn.len(), 1); // Only commitment tx
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_6.3.txid());
let nodes = create_network(2, &[None, None]);
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
// node[0] is gonna to revoke an old state thus node[1] should be able to claim the revoked output
- let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(revoked_local_txn.len(), 1);
// Only output is the full channel value back to nodes[0]:
assert_eq!(revoked_local_txn[0].output.len(), 1);
let (_payment_preimage_2, payment_hash_2) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000);
// Get the will-be-revoked local txn from node[0]
- let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(revoked_local_txn.len(), 2); // commitment tx + 1 HTLC-Timeout tx
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
let (_payment_preimage_2, payment_hash_2) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000);
// Get the will-be-revoked local txn from node[0]
- let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
//Revoke the old state
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1, 3_000_000);
// Broadcast legit commitment tx from C on B's chain
// Broadcast HTLC Success transaction by C on received output from C's commitment tx on B's chain
- let commitment_tx = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let commitment_tx = nodes[2].node.channel_state.lock().unwrap().by_id.get_mut(&chan_2.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(commitment_tx.len(), 1);
check_spends!(commitment_tx[0], chan_2.3.clone());
nodes[2].node.claim_funds(our_payment_preimage, 3_000_000);
// Broadcast legit commitment tx from A on B's chain
// Broadcast preimage tx by B on offered output from A commitment tx on A's chain
- let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
check_spends!(commitment_tx[0], chan_1.3.clone());
nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
check_closed_broadcast!(nodes[1]);
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
// Broadcast legit commitment tx from C on B's chain
- let commitment_tx = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let commitment_tx = nodes[2].node.channel_state.lock().unwrap().by_id.get_mut(&chan_2.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
check_spends!(commitment_tx[0], chan_2.3.clone());
nodes[2].node.fail_htlc_backwards(&payment_hash);
check_added_monitors!(nodes[2], 0);
assert_eq!(node_txn.len(), 0);
// Broadcast legit commitment tx from B on A's chain
- let commitment_tx = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let commitment_tx = nodes[1].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
check_spends!(commitment_tx[0], chan_1.3.clone());
nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 200);
let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3000000);
// Get the will-be-revoked local txn from nodes[2]
- let revoked_local_txn = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[2].node.channel_state.lock().unwrap().by_id.get_mut(&chan_2.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
// Revoke the old state
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage, 3_000_000);
let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], if no_to_remote { 10_000 } else { 3_000_000 });
// Get the will-be-revoked local txn from nodes[2]
- let revoked_local_txn = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[2].node.channel_state.lock().unwrap().by_id.get_mut(&chan_2.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(revoked_local_txn[0].output.len(), if no_to_remote { 1 } else { 2 });
// Revoke the old state
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage, if no_to_remote { 10_000 } else { 3_000_000});
nodes[0].chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(nodes[0].chain_monitor.clone(), nodes[0].tx_broadcaster.clone(), Arc::new(test_utils::TestLogger::new()), Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 })));
let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..];
- let (_, chan_0_monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut chan_0_monitor_read, Arc::new(test_utils::TestLogger::new())).unwrap();
+ let (_, mut chan_0_monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut chan_0_monitor_read, Arc::new(test_utils::TestLogger::new())).unwrap();
assert!(chan_0_monitor_read.is_empty());
let mut nodes_0_read = &nodes_0_serialized[..];
let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new())));
let (_, nodes_0_deserialized) = {
let mut channel_monitors = HashMap::new();
- channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &chan_0_monitor);
+ channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &mut chan_0_monitor);
<(Sha256dHash, ChannelManager<EnforcingChannelKeys>)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
default_config: config,
keys_manager,
monitor: nodes[0].chan_monitor.clone(),
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
logger: Arc::new(test_utils::TestLogger::new()),
- channel_monitors: &channel_monitors,
+ channel_monitors: &mut channel_monitors,
}).unwrap()
};
assert!(nodes_0_read.is_empty());
nodes[0].chan_monitor = Arc::new(test_utils::TestChannelMonitor::new(nodes[0].chain_monitor.clone(), nodes[0].tx_broadcaster.clone(), Arc::new(test_utils::TestLogger::new()), Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 })));
let mut chan_0_monitor_read = &chan_0_monitor_serialized.0[..];
- let (_, chan_0_monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut chan_0_monitor_read, Arc::new(test_utils::TestLogger::new())).unwrap();
+ let (_, mut chan_0_monitor) = <(Sha256dHash, ChannelMonitor)>::read(&mut chan_0_monitor_read, Arc::new(test_utils::TestLogger::new())).unwrap();
assert!(chan_0_monitor_read.is_empty());
let mut nodes_0_read = &nodes_0_serialized[..];
let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new())));
let (_, nodes_0_deserialized) = {
let mut channel_monitors = HashMap::new();
- channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &chan_0_monitor);
+ channel_monitors.insert(chan_0_monitor.get_funding_txo().unwrap(), &mut chan_0_monitor);
<(Sha256dHash, ChannelManager<EnforcingChannelKeys>)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
default_config: UserConfig::default(),
keys_manager,
monitor: nodes[0].chan_monitor.clone(),
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
logger: Arc::new(test_utils::TestLogger::new()),
- channel_monitors: &channel_monitors,
+ channel_monitors: &mut channel_monitors,
}).unwrap()
};
assert!(nodes_0_read.is_empty());
monitor: nodes[0].chan_monitor.clone(),
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
logger: Arc::new(test_utils::TestLogger::new()),
- channel_monitors: &node_0_monitors.iter().map(|monitor| { (monitor.get_funding_txo().unwrap(), monitor) }).collect(),
+ channel_monitors: &mut node_0_monitors.iter_mut().map(|monitor| { (monitor.get_funding_txo().unwrap(), monitor) }).collect(),
}).unwrap();
assert!(nodes_0_read.is_empty());
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 59000000, LocalFeatures::new(), LocalFeatures::new());
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
- let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
- let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(commitment_tx[0].input.len(), 1);
assert_eq!(commitment_tx[0].input[0].previous_output.txid, chan_1.3.txid());
check_spends!(node_txn[0], commitment_tx[0].clone());
assert_eq!(node_txn[0], node_txn[3]);
assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
+eprintln!("{:?}", node_txn[1]);
check_spends!(node_txn[1], chan_1.3.clone());
check_spends!(node_txn[2], node_txn[1]);
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
- let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.iter().next().unwrap().1.channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.iter_mut().next().unwrap().1.channel_monitor().get_latest_local_commitment_txn();
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
- let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
- let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
- let commitment_tx = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let commitment_tx = nodes[2].node.channel_state.lock().unwrap().by_id.get_mut(&chan_2.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
check_spends!(commitment_tx[0], chan_2.3.clone());
nodes[2].node.claim_funds(payment_preimage, 3_000_000);
check_added_monitors!(nodes[2], 1);
_ => panic!("Unexpected event"),
};
// Broadcast A's commitment tx on B's chain to see if we are able to claim inbound HTLC with our HTLC-Success tx
- let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
let b_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
assert_eq!(b_txn.len(), 4);
*nodes[0].network_payment_count.borrow_mut() -= 1;
assert_eq!(route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 900000).1, duplicate_payment_hash);
- let commitment_txn = nodes[2].node.channel_state.lock().unwrap().by_id.get(&chan_2.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let commitment_txn = nodes[2].node.channel_state.lock().unwrap().by_id.get_mut(&chan_2.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(commitment_txn[0].input.len(), 1);
check_spends!(commitment_txn[0], chan_2.3.clone());
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000).0;
- let local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(local_txn[0].input.len(), 1);
check_spends!(local_txn[0], chan_1.3.clone());
// Rebalance and check output sanity...
send_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 500000, 500_000);
send_payment(&nodes[1], &[&nodes[2], &nodes[3], &nodes[5]], 500000, 500_000);
- assert_eq!(nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn()[0].output.len(), 2);
+ assert_eq!(nodes[3].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn()[0].output.len(), 2);
let ds_dust_limit = nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().our_dust_limit_satoshis;
// 0th HTLC:
// Double-check that six of the new HTLC were added
// We now have six HTLCs pending over the dust limit and six HTLCs under the dust limit (ie,
// with to_local and to_remote outputs, 8 outputs and 6 HTLCs not included).
- assert_eq!(nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn().len(), 1);
- assert_eq!(nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn()[0].output.len(), 8);
+ assert_eq!(nodes[3].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn().len(), 1);
+ assert_eq!(nodes[3].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn()[0].output.len(), 8);
// Now fail back three of the over-dust-limit and three of the under-dust-limit payments in one go.
// Fail 0th below-dust, 4th above-dust, 8th above-dust, 10th below-dust HTLCs
nodes[3].node.handle_update_fail_htlc(&nodes[5].node.get_our_node_id(), &two_removes.update_fail_htlcs[1]).unwrap();
commitment_signed_dance!(nodes[3], nodes[5], two_removes.commitment_signed, false);
- let ds_prev_commitment_tx = nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let ds_prev_commitment_tx = nodes[3].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
expect_pending_htlcs_forwardable!(nodes[3]);
check_added_monitors!(nodes[3], 1);
//
// Alternatively, we may broadcast the previous commitment transaction, which should only
// result in failures for the below-dust HTLCs, ie the 0th, 1st, 2nd, 3rd, 9th, and 10th HTLCs.
- let ds_last_commitment_tx = nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let ds_last_commitment_tx = nodes[3].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
if announce_latest {
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000).0;
- let local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let local_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan_1.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(local_txn[0].input.len(), 1);
check_spends!(local_txn[0], chan_1.3.clone());
route_payment(&nodes[0], &[&nodes[1]], 1000000);
// Cache one local commitment tx as previous
- let as_prev_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let as_prev_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
// Fail one HTLC to prune it in the will-be-latest-local commitment tx
assert!(nodes[1].node.fail_htlc_backwards(&payment_hash_2));
check_added_monitors!(nodes[0], 1);
// Cache one local commitment tx as lastest
- let as_last_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let as_last_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
let events = nodes[0].node.get_and_clear_pending_msg_events();
match events[0] {
let (_payment_preimage_1, dust_hash) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
let (_payment_preimage_2, non_dust_hash) = route_payment(&nodes[0], &[&nodes[1]], 1000000);
- let as_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
- let bs_commitment_tx = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let as_commitment_tx = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let bs_commitment_tx = nodes[1].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
// We revoked bs_commitment_tx
if revoked {
// Restore node A from previous state
let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::with_id(format!("node {}", 0)));
- let chan_monitor = <(Sha256dHash, ChannelMonitor)>::read(&mut ::std::io::Cursor::new(previous_chan_monitor_state.0), Arc::clone(&logger)).unwrap().1;
+ let mut chan_monitor = <(Sha256dHash, ChannelMonitor)>::read(&mut ::std::io::Cursor::new(previous_chan_monitor_state.0), Arc::clone(&logger)).unwrap().1;
let chain_monitor = Arc::new(ChainWatchInterfaceUtil::new(Network::Testnet, Arc::clone(&logger)));
let tx_broadcaster = Arc::new(test_utils::TestBroadcaster{txn_broadcasted: Mutex::new(Vec::new())});
let feeest = Arc::new(test_utils::TestFeeEstimator { sat_per_kw: 253 });
let monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone(), logger.clone(), feeest.clone()));
- let mut channel_monitors = HashMap::new();
- channel_monitors.insert(OutPoint { txid: chan.3.txid(), index: 0 }, &chan_monitor);
- let node_state_0 = <(Sha256dHash, ChannelManager<EnforcingChannelKeys>)>::read(&mut ::std::io::Cursor::new(previous_node_state), ChannelManagerReadArgs {
- keys_manager: Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::clone(&logger))),
- fee_estimator: feeest.clone(),
- monitor: monitor.clone(),
- logger: Arc::clone(&logger),
- tx_broadcaster,
- default_config: UserConfig::default(),
- channel_monitors: &channel_monitors
- }).unwrap().1;
+ let node_state_0 = {
+ let mut channel_monitors = HashMap::new();
+ channel_monitors.insert(OutPoint { txid: chan.3.txid(), index: 0 }, &mut chan_monitor);
+ <(Sha256dHash, ChannelManager<EnforcingChannelKeys>)>::read(&mut ::std::io::Cursor::new(previous_node_state), ChannelManagerReadArgs {
+ keys_manager: Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::clone(&logger))),
+ fee_estimator: feeest.clone(),
+ monitor: monitor.clone(),
+ logger: Arc::clone(&logger),
+ tx_broadcaster,
+ default_config: UserConfig::default(),
+ channel_monitors: &mut channel_monitors
+ }).unwrap().1
+ };
nodes[0].node = Arc::new(node_state_0);
assert!(monitor.add_update_monitor(OutPoint { txid: chan.3.txid(), index: 0 }, chan_monitor.clone()).is_ok());
nodes[0].chan_monitor = monitor;
let route = nodes[1].router.get_route(&nodes[0].node.get_our_node_id(), None, &Vec::new(), 3000000, 30).unwrap();
send_along_route(&nodes[1], route, &vec!(&nodes[0])[..], 3000000);
- let revoked_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let revoked_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
// Revoked commitment txn with 4 outputs : to_local, to_remote, 1 outgoing HTLC, 1 incoming HTLC
assert_eq!(revoked_txn[0].output.len(), 4);
assert_eq!(revoked_txn[0].input.len(), 1);
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3_000_000).0;
route_payment(&nodes[1], &vec!(&nodes[0])[..], 3_000_000).0;
- let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000).0;
// Remote commitment txn with 4 outputs : to_local, to_remote, 1 outgoing HTLC, 1 incoming HTLC
- let remote_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let remote_txn = nodes[0].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(remote_txn[0].output.len(), 4);
assert_eq!(remote_txn[0].input.len(), 1);
assert_eq!(remote_txn[0].input[0].previous_output.txid, chan.3.txid());
let payment_preimage_2 = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3_000_000).0;
// Remote commitment txn with 4 outputs: to_local, to_remote, 2 outgoing HTLC
- let remote_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let remote_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(remote_txn.len(), 3);
assert_eq!(remote_txn[0].output.len(), 4);
assert_eq!(remote_txn[0].input.len(), 1);
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000).0;
route_payment(&nodes[1], &vec!(&nodes[0])[..], 9_000_000).0;
- let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
+ let revoked_local_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get_mut(&chan.2).unwrap().channel_monitor().get_latest_local_commitment_txn();
assert_eq!(revoked_local_txn[0].input.len(), 1);
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());