mirror of
https://github.com/lightningdevkit/rust-lightning.git
synced 2025-02-25 15:20:24 +01:00
Merge pull request #420 from TheBlueMatt/2019-12-chan-ext-signer
Remove signing from Channel
This commit is contained in:
commit
9310813e98
7 changed files with 479 additions and 424 deletions
|
@ -212,7 +212,7 @@ pub fn do_test(data: &[u8]) {
|
||||||
monitor.latest_good_update.lock().unwrap().insert(outpoint, monitor_ser);
|
monitor.latest_good_update.lock().unwrap().insert(outpoint, monitor_ser);
|
||||||
}
|
}
|
||||||
let mut monitor_refs = HashMap::new();
|
let mut monitor_refs = HashMap::new();
|
||||||
for (outpoint, monitor) in monitors.iter() {
|
for (outpoint, monitor) in monitors.iter_mut() {
|
||||||
monitor_refs.insert(*outpoint, monitor);
|
monitor_refs.insert(*outpoint, monitor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ pub fn do_test(data: &[u8]) {
|
||||||
tx_broadcaster: broadcast.clone(),
|
tx_broadcaster: broadcast.clone(),
|
||||||
logger,
|
logger,
|
||||||
default_config: config,
|
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);
|
let res = (<(Sha256d, ChannelManager<EnforcingChannelKeys>)>::read(&mut Cursor::new(&$ser.0), read_args).expect("Failed to read manager").1, monitor);
|
||||||
|
|
|
@ -142,7 +142,7 @@ pub trait ChannelKeys : Send {
|
||||||
/// TODO: Document the things someone using this interface should enforce before signing.
|
/// TODO: Document the things someone using this interface should enforce before signing.
|
||||||
/// TODO: Add more input vars to enable better checking (preferably removing commitment_tx and
|
/// TODO: Add more input vars to enable better checking (preferably removing commitment_tx and
|
||||||
/// making the callee generate it via some util function we expose)!
|
/// making the callee generate it via some util function we expose)!
|
||||||
fn sign_remote_commitment<T: secp256k1::Signing>(&self, channel_value_satoshis: u64, channel_funding_redeemscript: &Script, absolute_fee: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
|
fn sign_remote_commitment<T: secp256k1::Signing>(&self, channel_value_satoshis: u64, channel_funding_redeemscript: &Script, feerate_per_kw: u64, commitment_tx: &Transaction, keys: &TxCreationKeys, htlcs: &[&HTLCOutputInCommitment], to_self_delay: u16, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Vec<Signature>), ()>;
|
||||||
|
|
||||||
/// Create a signature for a (proposed) closing transaction.
|
/// Create a signature for a (proposed) closing transaction.
|
||||||
///
|
///
|
||||||
|
|
|
@ -4,7 +4,9 @@
|
||||||
|
|
||||||
use bitcoin::blockdata::script::{Script,Builder};
|
use bitcoin::blockdata::script::{Script,Builder};
|
||||||
use bitcoin::blockdata::opcodes;
|
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::{Hash, HashEngine};
|
||||||
use bitcoin_hashes::sha256::Hash as Sha256;
|
use bitcoin_hashes::sha256::Hash as Sha256;
|
||||||
|
@ -12,10 +14,12 @@ use bitcoin_hashes::ripemd160::Hash as Ripemd160;
|
||||||
use bitcoin_hashes::hash160::Hash as Hash160;
|
use bitcoin_hashes::hash160::Hash as Hash160;
|
||||||
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
use bitcoin_hashes::sha256d::Hash as Sha256dHash;
|
||||||
|
|
||||||
use ln::channelmanager::PaymentHash;
|
use ln::channelmanager::{PaymentHash, PaymentPreimage};
|
||||||
|
use ln::msgs::DecodeError;
|
||||||
|
use util::ser::{Readable, Writeable, Writer, WriterWriteAdaptor};
|
||||||
|
|
||||||
use secp256k1::key::{PublicKey,SecretKey};
|
use secp256k1::key::{SecretKey,PublicKey};
|
||||||
use secp256k1::Secp256k1;
|
use secp256k1::{Secp256k1, Signature};
|
||||||
use secp256k1;
|
use secp256k1;
|
||||||
|
|
||||||
pub(super) const HTLC_SUCCESS_TX_WEIGHT: u64 = 703;
|
pub(super) const HTLC_SUCCESS_TX_WEIGHT: u64 = 703;
|
||||||
|
@ -59,7 +63,9 @@ pub(super) fn derive_public_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>,
|
||||||
base_point.combine(&hashkey)
|
base_point.combine(&hashkey)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Derives a revocation key from its constituent parts
|
/// Derives a revocation key from its constituent parts.
|
||||||
|
/// Note that this is infallible iff we trust that at least one of the two input keys are randomly
|
||||||
|
/// generated (ie our own).
|
||||||
pub(super) fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_secret: &SecretKey, revocation_base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
|
pub(super) fn derive_private_revocation_key<T: secp256k1::Signing>(secp_ctx: &Secp256k1<T>, per_commitment_secret: &SecretKey, revocation_base_secret: &SecretKey) -> Result<SecretKey, secp256k1::Error> {
|
||||||
let revocation_base_point = PublicKey::from_secret_key(&secp_ctx, &revocation_base_secret);
|
let revocation_base_point = PublicKey::from_secret_key(&secp_ctx, &revocation_base_secret);
|
||||||
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
|
let per_commitment_point = PublicKey::from_secret_key(&secp_ctx, &per_commitment_secret);
|
||||||
|
@ -281,3 +287,153 @@ pub fn build_htlc_transaction(prev_hash: &Sha256dHash, feerate_per_kw: u64, to_s
|
||||||
output: txouts,
|
output: txouts,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Signs a transaction created by build_htlc_transaction. If the transaction is an
|
||||||
|
/// HTLC-Success transaction (ie htlc.offered is false), preimage must be set!
|
||||||
|
pub(crate) fn sign_htlc_transaction<T: secp256k1::Signing>(tx: &mut Transaction, their_sig: &Signature, preimage: &Option<PaymentPreimage>, htlc: &HTLCOutputInCommitment, a_htlc_key: &PublicKey, b_htlc_key: &PublicKey, revocation_key: &PublicKey, per_commitment_point: &PublicKey, htlc_base_key: &SecretKey, secp_ctx: &Secp256k1<T>) -> Result<(Signature, Script), ()> {
|
||||||
|
if tx.input.len() != 1 { return Err(()); }
|
||||||
|
if tx.input[0].witness.len() != 0 { return Err(()); }
|
||||||
|
|
||||||
|
let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&htlc, a_htlc_key, b_htlc_key, revocation_key);
|
||||||
|
|
||||||
|
let our_htlc_key = derive_private_key(secp_ctx, per_commitment_point, htlc_base_key).map_err(|_| ())?;
|
||||||
|
let sighash = hash_to_message!(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
|
||||||
|
let local_tx = PublicKey::from_secret_key(&secp_ctx, &our_htlc_key) == *a_htlc_key;
|
||||||
|
let our_sig = secp_ctx.sign(&sighash, &our_htlc_key);
|
||||||
|
|
||||||
|
tx.input[0].witness.push(Vec::new()); // First is the multisig dummy
|
||||||
|
|
||||||
|
if local_tx { // b, then a
|
||||||
|
tx.input[0].witness.push(their_sig.serialize_der().to_vec());
|
||||||
|
tx.input[0].witness.push(our_sig.serialize_der().to_vec());
|
||||||
|
} else {
|
||||||
|
tx.input[0].witness.push(our_sig.serialize_der().to_vec());
|
||||||
|
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[2].push(SigHashType::All as u8);
|
||||||
|
|
||||||
|
if htlc.offered {
|
||||||
|
tx.input[0].witness.push(Vec::new());
|
||||||
|
assert!(preimage.is_none());
|
||||||
|
} else {
|
||||||
|
tx.input[0].witness.push(preimage.unwrap().0.to_vec());
|
||||||
|
}
|
||||||
|
|
||||||
|
tx.input[0].witness.push(htlc_redeemscript.as_bytes().to_vec());
|
||||||
|
|
||||||
|
Ok((our_sig, htlc_redeemscript))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[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 })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType};
|
||||||
use bitcoin::blockdata::opcodes;
|
use bitcoin::blockdata::opcodes;
|
||||||
use bitcoin::util::hash::BitcoinHash;
|
use bitcoin::util::hash::BitcoinHash;
|
||||||
use bitcoin::util::bip143;
|
use bitcoin::util::bip143;
|
||||||
use bitcoin::consensus::encode::{self, Encodable, Decodable};
|
use bitcoin::consensus::encode;
|
||||||
|
|
||||||
use bitcoin_hashes::{Hash, HashEngine};
|
use bitcoin_hashes::{Hash, HashEngine};
|
||||||
use bitcoin_hashes::sha256::Hash as Sha256;
|
use bitcoin_hashes::sha256::Hash as Sha256;
|
||||||
|
@ -19,13 +19,13 @@ use ln::msgs;
|
||||||
use ln::msgs::{DecodeError, OptionalField, LocalFeatures, DataLossProtect};
|
use ln::msgs::{DecodeError, OptionalField, LocalFeatures, DataLossProtect};
|
||||||
use ln::channelmonitor::ChannelMonitor;
|
use ln::channelmonitor::ChannelMonitor;
|
||||||
use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingForwardHTLCInfo, RAACommitmentOrder, PaymentPreimage, PaymentHash, BREAKDOWN_TIMEOUT, MAX_LOCAL_BREAKDOWN_TIMEOUT};
|
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 ln::chan_utils;
|
||||||
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
|
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
|
||||||
use chain::transaction::OutPoint;
|
use chain::transaction::OutPoint;
|
||||||
use chain::keysinterface::{ChannelKeys, KeysInterface};
|
use chain::keysinterface::{ChannelKeys, KeysInterface};
|
||||||
use util::transaction_utils;
|
use util::transaction_utils;
|
||||||
use util::ser::{Readable, ReadableArgs, Writeable, Writer, WriterWriteAdaptor};
|
use util::ser::{Readable, ReadableArgs, Writeable, Writer};
|
||||||
use util::logger::{Logger, LogHolder};
|
use util::logger::{Logger, LogHolder};
|
||||||
use util::errors::APIError;
|
use util::errors::APIError;
|
||||||
use util::config::{UserConfig,ChannelConfig};
|
use util::config::{UserConfig,ChannelConfig};
|
||||||
|
@ -297,12 +297,6 @@ pub(super) struct Channel<ChanSigner: ChannelKeys> {
|
||||||
/// Max to_local and to_remote outputs in a remote-generated commitment transaction
|
/// Max to_local and to_remote outputs in a remote-generated commitment transaction
|
||||||
max_commitment_tx_output_remote: ::std::sync::Mutex<(u64, u64)>,
|
max_commitment_tx_output_remote: ::std::sync::Mutex<(u64, 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, Signature)>, // (feerate, fee, our_sig)
|
last_sent_closing_fee: Option<(u64, u64, Signature)>, // (feerate, fee, our_sig)
|
||||||
|
|
||||||
/// The hash of the block in which the funding transaction reached our CONF_TARGET. We use this
|
/// The hash of the block in which the funding transaction reached our CONF_TARGET. We use this
|
||||||
|
@ -456,7 +450,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
|
let feerate = fee_estimator.get_est_sat_per_1000_weight(ConfirmationTarget::Normal);
|
||||||
|
|
||||||
let secp_ctx = Secp256k1::new();
|
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,
|
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());
|
keys_provider.get_destination_script(), logger.clone());
|
||||||
|
|
||||||
|
@ -498,8 +492,6 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
max_commitment_tx_output_remote: ::std::sync::Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
|
max_commitment_tx_output_remote: ::std::sync::Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
|
||||||
|
|
||||||
last_local_commitment_txn: Vec::new(),
|
|
||||||
|
|
||||||
last_sent_closing_fee: None,
|
last_sent_closing_fee: None,
|
||||||
|
|
||||||
funding_tx_confirmed_in: None,
|
funding_tx_confirmed_in: None,
|
||||||
|
@ -652,11 +644,9 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let secp_ctx = Secp256k1::new();
|
let secp_ctx = Secp256k1::new();
|
||||||
let mut 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,
|
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());
|
keys_provider.get_destination_script(), logger.clone());
|
||||||
channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint);
|
|
||||||
channel_monitor.set_their_to_self_delay(msg.to_self_delay);
|
|
||||||
|
|
||||||
let their_shutdown_scriptpubkey = if their_local_features.supports_upfront_shutdown_script() {
|
let their_shutdown_scriptpubkey = if their_local_features.supports_upfront_shutdown_script() {
|
||||||
match &msg.shutdown_scriptpubkey {
|
match &msg.shutdown_scriptpubkey {
|
||||||
|
@ -716,8 +706,6 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
max_commitment_tx_output_remote: ::std::sync::Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
|
max_commitment_tx_output_remote: ::std::sync::Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
|
||||||
|
|
||||||
last_local_commitment_txn: Vec::new(),
|
|
||||||
|
|
||||||
last_sent_closing_fee: None,
|
last_sent_closing_fee: None,
|
||||||
|
|
||||||
funding_tx_confirmed_in: None,
|
funding_tx_confirmed_in: None,
|
||||||
|
@ -758,7 +746,8 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
};
|
};
|
||||||
|
|
||||||
let obscure_factor = chan.get_commitment_transaction_number_obscure_factor();
|
let obscure_factor = chan.get_commitment_transaction_number_obscure_factor();
|
||||||
chan.channel_monitor.set_commitment_obscure_factor(obscure_factor);
|
let funding_redeemscript = chan.get_funding_redeemscript();
|
||||||
|
chan.channel_monitor.set_basic_channel_info(&msg.htlc_basepoint, &msg.delayed_payment_basepoint, msg.to_self_delay, funding_redeemscript, msg.funding_satoshis, obscure_factor);
|
||||||
|
|
||||||
Ok(chan)
|
Ok(chan)
|
||||||
}
|
}
|
||||||
|
@ -1133,38 +1122,6 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
}.push_opcode(opcodes::all::OP_PUSHNUM_2).push_opcode(opcodes::all::OP_CHECKMULTISIG).into_script()
|
}.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
|
/// 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
|
/// @local is used only to convert relevant internal structures which refer to remote vs local
|
||||||
/// to decide value of outputs and direction of HTLCs.
|
/// to decide value of outputs and direction of HTLCs.
|
||||||
|
@ -1172,54 +1129,6 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
chan_utils::build_htlc_transaction(prev_hash, feerate_per_kw, if local { self.their_to_self_delay } else { self.our_to_self_delay }, htlc, &keys.a_delayed_payment_key, &keys.revocation_key)
|
chan_utils::build_htlc_transaction(prev_hash, feerate_per_kw, if local { self.their_to_self_delay } else { self.our_to_self_delay }, 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), ChannelError> {
|
|
||||||
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_check!(chan_utils::derive_private_key(&self.secp_ctx, &keys.per_commitment_point, self.local_keys.htlc_base_key()), "Derived invalid key, peer is maliciously selecting parameters");
|
|
||||||
let sighash = hash_to_message!(&bip143::SighashComponents::new(&tx).sighash_all(&tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
|
|
||||||
let is_local_tx = PublicKey::from_secret_key(&self.secp_ctx, &our_htlc_key) == keys.a_htlc_key;
|
|
||||||
Ok((htlc_redeemscript, self.secp_ctx.sign(&sighash, &our_htlc_key), is_local_tx))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Signs a transaction created by build_htlc_transaction. If the transaction is an
|
|
||||||
/// HTLC-Success transaction (ie htlc.offered is false), preimage must be set!
|
|
||||||
fn sign_htlc_transaction(&self, tx: &mut Transaction, their_sig: &Signature, preimage: &Option<PaymentPreimage>, htlc: &HTLCOutputInCommitment, keys: &TxCreationKeys) -> Result<Signature, ChannelError> {
|
|
||||||
if tx.input.len() != 1 {
|
|
||||||
panic!("Tried to sign HTLC transaction that had input count != 1!");
|
|
||||||
}
|
|
||||||
if tx.input[0].witness.len() != 0 {
|
|
||||||
panic!("Tried to re-sign HTLC transaction");
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
if local_tx { // b, then a
|
|
||||||
tx.input[0].witness.push(their_sig.serialize_der().to_vec());
|
|
||||||
tx.input[0].witness.push(our_sig.serialize_der().to_vec());
|
|
||||||
} else {
|
|
||||||
tx.input[0].witness.push(our_sig.serialize_der().to_vec());
|
|
||||||
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[2].push(SigHashType::All as u8);
|
|
||||||
|
|
||||||
if htlc.offered {
|
|
||||||
tx.input[0].witness.push(Vec::new());
|
|
||||||
} else {
|
|
||||||
tx.input[0].witness.push(preimage.unwrap().0.to_vec());
|
|
||||||
}
|
|
||||||
|
|
||||||
tx.input[0].witness.push(htlc_redeemscript.into_bytes());
|
|
||||||
|
|
||||||
Ok(our_sig)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made.
|
/// Per HTLC, only one get_update_fail_htlc or get_update_fulfill_htlc call may be made.
|
||||||
/// In such cases we debug_assert!(false) and return an IgnoreError. Thus, will always return
|
/// In such cases we debug_assert!(false) and return an IgnoreError. Thus, will always return
|
||||||
/// Ok(_) if debug assertions are turned on and preconditions are met.
|
/// Ok(_) if debug assertions are turned on and preconditions are met.
|
||||||
|
@ -1477,8 +1386,6 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
}
|
}
|
||||||
} else { None };
|
} else { None };
|
||||||
|
|
||||||
self.channel_monitor.set_their_base_keys(&msg.htlc_basepoint, &msg.delayed_payment_basepoint);
|
|
||||||
|
|
||||||
self.their_dust_limit_satoshis = msg.dust_limit_satoshis;
|
self.their_dust_limit_satoshis = msg.dust_limit_satoshis;
|
||||||
self.their_max_htlc_value_in_flight_msat = cmp::min(msg.max_htlc_value_in_flight_msat, self.channel_value_satoshis * 1000);
|
self.their_max_htlc_value_in_flight_msat = cmp::min(msg.max_htlc_value_in_flight_msat, self.channel_value_satoshis * 1000);
|
||||||
self.their_channel_reserve_satoshis = msg.channel_reserve_satoshis;
|
self.their_channel_reserve_satoshis = msg.channel_reserve_satoshis;
|
||||||
|
@ -1495,26 +1402,25 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
self.their_shutdown_scriptpubkey = their_shutdown_scriptpubkey;
|
self.their_shutdown_scriptpubkey = their_shutdown_scriptpubkey;
|
||||||
|
|
||||||
let obscure_factor = self.get_commitment_transaction_number_obscure_factor();
|
let obscure_factor = self.get_commitment_transaction_number_obscure_factor();
|
||||||
self.channel_monitor.set_commitment_obscure_factor(obscure_factor);
|
let funding_redeemscript = self.get_funding_redeemscript();
|
||||||
self.channel_monitor.set_their_to_self_delay(msg.to_self_delay);
|
self.channel_monitor.set_basic_channel_info(&msg.htlc_basepoint, &msg.delayed_payment_basepoint, msg.to_self_delay, funding_redeemscript, self.channel_value_satoshis, obscure_factor);
|
||||||
|
|
||||||
self.channel_state = ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32;
|
self.channel_state = ChannelState::OurInitSent as u32 | ChannelState::TheirInitSent as u32;
|
||||||
|
|
||||||
Ok(())
|
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 funding_script = self.get_funding_redeemscript();
|
||||||
|
|
||||||
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
|
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)[..]);
|
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...
|
// 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");
|
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
|
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());
|
||||||
self.sign_commitment_transaction(&mut local_initial_commitment_tx, sig);
|
|
||||||
|
|
||||||
let remote_keys = self.build_remote_transaction_keys()?;
|
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;
|
let remote_initial_commitment_tx = self.build_commitment_transaction(self.cur_remote_commitment_transaction_number, &remote_keys, false, false, self.feerate_per_kw).0;
|
||||||
|
@ -1522,7 +1428,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
.map_err(|_| ChannelError::Close("Failed to get signatures for new commitment_signed"))?.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.
|
// 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> {
|
pub fn funding_created(&mut self, msg: &msgs::FundingCreated) -> Result<(msgs::FundingSigned, ChannelMonitor), ChannelError> {
|
||||||
|
@ -1556,7 +1462,6 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
// Now that we're past error-generating stuff, update our local state:
|
// Now that we're past error-generating stuff, update our local state:
|
||||||
|
|
||||||
self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap());
|
self.channel_monitor.provide_latest_remote_commitment_tx_info(&remote_initial_commitment_tx, Vec::new(), self.cur_remote_commitment_transaction_number, self.their_cur_commitment_point.unwrap());
|
||||||
self.last_local_commitment_txn = vec![local_initial_commitment_tx.clone()];
|
|
||||||
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(local_initial_commitment_tx, local_keys, self.feerate_per_kw, Vec::new());
|
||||||
self.channel_state = ChannelState::FundingSent as u32;
|
self.channel_state = ChannelState::FundingSent as u32;
|
||||||
self.channel_id = funding_txo.to_channel_id();
|
self.channel_id = funding_txo.to_channel_id();
|
||||||
|
@ -1587,15 +1492,15 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
let funding_script = self.get_funding_redeemscript();
|
let funding_script = self.get_funding_redeemscript();
|
||||||
|
|
||||||
let local_keys = self.build_local_transaction_keys(self.cur_local_commitment_transaction_number)?;
|
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)[..]);
|
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.
|
// 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");
|
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(
|
||||||
self.channel_monitor.provide_latest_local_commitment_tx_info(local_initial_commitment_tx.clone(), local_keys, self.feerate_per_kw, Vec::new());
|
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()),
|
||||||
self.last_local_commitment_txn = vec![local_initial_commitment_tx];
|
local_keys, self.feerate_per_kw, Vec::new());
|
||||||
self.channel_state = ChannelState::FundingSent as u32 | (self.channel_state & (ChannelState::MonitorUpdateFailed as u32));
|
self.channel_state = ChannelState::FundingSent as u32 | (self.channel_state & (ChannelState::MonitorUpdateFailed as u32));
|
||||||
self.cur_local_commitment_transaction_number -= 1;
|
self.cur_local_commitment_transaction_number -= 1;
|
||||||
|
|
||||||
|
@ -1859,26 +1764,15 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
return Err(ChannelError::Close("Got wrong number of HTLC signatures from remote"));
|
return Err(ChannelError::Close("Got wrong number of HTLC signatures from remote"));
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut new_local_commitment_txn = Vec::with_capacity(local_commitment_tx.1 + 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.2.len());
|
let mut htlcs_and_sigs = Vec::with_capacity(local_commitment_tx.2.len());
|
||||||
for (idx, (htlc, source)) in local_commitment_tx.2.drain(..).enumerate() {
|
for (idx, (htlc, source)) in local_commitment_tx.2.drain(..).enumerate() {
|
||||||
if let Some(_) = htlc.transaction_output_index {
|
if let Some(_) = htlc.transaction_output_index {
|
||||||
let mut htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw);
|
let htlc_tx = self.build_htlc_transaction(&local_commitment_txid, &htlc, true, &local_keys, feerate_per_kw);
|
||||||
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys);
|
let htlc_redeemscript = chan_utils::get_htlc_redeemscript(&htlc, &local_keys);
|
||||||
log_trace!(self, "Checking HTLC tx signature {} by key {} against tx {} with redeemscript {}", log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(local_keys.b_htlc_key.serialize()), encode::serialize_hex(&htlc_tx), encode::serialize_hex(&htlc_redeemscript));
|
log_trace!(self, "Checking HTLC tx signature {} by key {} against tx {} with redeemscript {}", log_bytes!(msg.htlc_signatures[idx].serialize_compact()[..]), log_bytes!(local_keys.b_htlc_key.serialize()), encode::serialize_hex(&htlc_tx), encode::serialize_hex(&htlc_redeemscript));
|
||||||
let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
|
let htlc_sighash = hash_to_message!(&bip143::SighashComponents::new(&htlc_tx).sighash_all(&htlc_tx.input[0], &htlc_redeemscript, htlc.amount_msat / 1000)[..]);
|
||||||
secp_check!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx signature from peer");
|
secp_check!(self.secp_ctx.verify(&htlc_sighash, &msg.htlc_signatures[idx], &local_keys.b_htlc_key), "Invalid HTLC tx signature from peer");
|
||||||
let htlc_sig = if htlc.offered {
|
htlcs_and_sigs.push((htlc, Some(msg.htlc_signatures[idx]), source));
|
||||||
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, Some((msg.htlc_signatures[idx], htlc_sig)), source));
|
|
||||||
} else {
|
} else {
|
||||||
htlcs_and_sigs.push((htlc, None, source));
|
htlcs_and_sigs.push((htlc, None, source));
|
||||||
}
|
}
|
||||||
|
@ -1902,7 +1796,10 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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() {
|
for htlc in self.pending_inbound_htlcs.iter_mut() {
|
||||||
let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state {
|
let new_forward = if let &InboundHTLCState::RemoteAnnounced(ref forward_info) = &htlc.state {
|
||||||
|
@ -1923,7 +1820,6 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.cur_local_commitment_transaction_number -= 1;
|
self.cur_local_commitment_transaction_number -= 1;
|
||||||
self.last_local_commitment_txn = new_local_commitment_txn;
|
|
||||||
// Note that if we need_our_commitment & !AwaitingRemoteRevoke we'll call
|
// Note that if we need_our_commitment & !AwaitingRemoteRevoke we'll call
|
||||||
// send_commitment_no_status_check() next which will reset this to RAAFirst.
|
// send_commitment_no_status_check() next which will reset this to RAAFirst.
|
||||||
self.resend_order = RAACommitmentOrder::CommitmentFirst;
|
self.resend_order = RAACommitmentOrder::CommitmentFirst;
|
||||||
|
@ -2881,11 +2777,11 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// May only be called after funding has been initiated (ie is_funding_initiated() is true)
|
/// 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 {
|
if self.channel_state < ChannelState::FundingCreated as u32 {
|
||||||
panic!("Can't get a channel monitor until funding has been created");
|
panic!("Can't get a channel monitor until funding has been created");
|
||||||
}
|
}
|
||||||
self.channel_monitor.clone()
|
&mut self.channel_monitor
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus,
|
/// Guaranteed to be Some after both FundingLocked messages have been exchanged (and, thus,
|
||||||
|
@ -3681,9 +3577,7 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
|
||||||
|
|
||||||
self.channel_state = ChannelState::ShutdownComplete as u32;
|
self.channel_state = ChannelState::ShutdownComplete as u32;
|
||||||
self.channel_update_count += 1;
|
self.channel_update_count += 1;
|
||||||
let mut res = Vec::new();
|
(self.channel_monitor.get_latest_local_commitment_txn(), dropped_outbound_htlcs)
|
||||||
mem::swap(&mut res, &mut self.last_local_commitment_txn);
|
|
||||||
(res, dropped_outbound_htlcs)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3873,16 +3767,6 @@ impl<ChanSigner: ChannelKeys + Writeable> Writeable for Channel<ChanSigner> {
|
||||||
self.channel_update_count.write(writer)?;
|
self.channel_update_count.write(writer)?;
|
||||||
self.feerate_per_kw.write(writer)?;
|
self.feerate_per_kw.write(writer)?;
|
||||||
|
|
||||||
(self.last_local_commitment_txn.len() as u64).write(writer)?;
|
|
||||||
for tx in self.last_local_commitment_txn.iter() {
|
|
||||||
if let Err(e) = tx.consensus_encode(&mut WriterWriteAdaptor(writer)) {
|
|
||||||
match e {
|
|
||||||
encode::Error::Io(e) => return Err(e),
|
|
||||||
_ => panic!("last_local_commitment_txn must have been well-formed!"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.last_sent_closing_fee {
|
match self.last_sent_closing_fee {
|
||||||
Some((feerate, fee, sig)) => {
|
Some((feerate, fee, sig)) => {
|
||||||
1u8.write(writer)?;
|
1u8.write(writer)?;
|
||||||
|
@ -4041,15 +3925,6 @@ impl<R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArgs<R,
|
||||||
let channel_update_count = Readable::read(reader)?;
|
let channel_update_count = Readable::read(reader)?;
|
||||||
let feerate_per_kw = Readable::read(reader)?;
|
let feerate_per_kw = Readable::read(reader)?;
|
||||||
|
|
||||||
let last_local_commitment_txn_count: u64 = Readable::read(reader)?;
|
|
||||||
let mut last_local_commitment_txn = Vec::with_capacity(cmp::min(last_local_commitment_txn_count as usize, OUR_MAX_HTLCS as usize*2 + 1));
|
|
||||||
for _ in 0..last_local_commitment_txn_count {
|
|
||||||
last_local_commitment_txn.push(match Transaction::consensus_decode(reader.by_ref()) {
|
|
||||||
Ok(tx) => tx,
|
|
||||||
Err(_) => return Err(DecodeError::InvalidValue),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let last_sent_closing_fee = match <u8 as Readable<R>>::read(reader)? {
|
let last_sent_closing_fee = match <u8 as Readable<R>>::read(reader)? {
|
||||||
0 => None,
|
0 => None,
|
||||||
1 => Some((Readable::read(reader)?, Readable::read(reader)?, Readable::read(reader)?)),
|
1 => Some((Readable::read(reader)?, Readable::read(reader)?, Readable::read(reader)?)),
|
||||||
|
@ -4132,8 +4007,6 @@ impl<R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArgs<R,
|
||||||
#[cfg(debug_assertions)]
|
#[cfg(debug_assertions)]
|
||||||
max_commitment_tx_output_remote: ::std::sync::Mutex::new((0, 0)),
|
max_commitment_tx_output_remote: ::std::sync::Mutex::new((0, 0)),
|
||||||
|
|
||||||
last_local_commitment_txn,
|
|
||||||
|
|
||||||
last_sent_closing_fee,
|
last_sent_closing_fee,
|
||||||
|
|
||||||
funding_tx_confirmed_in,
|
funding_tx_confirmed_in,
|
||||||
|
@ -4186,6 +4059,7 @@ mod tests {
|
||||||
use ln::channel::{Channel,ChannelKeys,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,TxCreationKeys};
|
use ln::channel::{Channel,ChannelKeys,InboundHTLCOutput,OutboundHTLCOutput,InboundHTLCState,OutboundHTLCState,HTLCOutputInCommitment,TxCreationKeys};
|
||||||
use ln::channel::MAX_FUNDING_SATOSHIS;
|
use ln::channel::MAX_FUNDING_SATOSHIS;
|
||||||
use ln::chan_utils;
|
use ln::chan_utils;
|
||||||
|
use ln::chan_utils::LocalCommitmentTransaction;
|
||||||
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
|
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
|
||||||
use chain::keysinterface::{InMemoryChannelKeys, KeysInterface};
|
use chain::keysinterface::{InMemoryChannelKeys, KeysInterface};
|
||||||
use chain::transaction::OutPoint;
|
use chain::transaction::OutPoint;
|
||||||
|
@ -4305,13 +4179,15 @@ mod tests {
|
||||||
.collect();
|
.collect();
|
||||||
(res.0, htlcs)
|
(res.0, htlcs)
|
||||||
};
|
};
|
||||||
|
let redeemscript = chan.get_funding_redeemscript();
|
||||||
let their_signature = Signature::from_der(&hex::decode($their_sig_hex).unwrap()[..]).unwrap();
|
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();
|
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()[..]);
|
hex::decode($tx_hex).unwrap()[..]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -4338,7 +4214,7 @@ mod tests {
|
||||||
assert!(preimage.is_some());
|
assert!(preimage.is_some());
|
||||||
}
|
}
|
||||||
|
|
||||||
chan.sign_htlc_transaction(&mut htlc_tx, &remote_signature, &preimage, &htlc, &keys).unwrap();
|
chan_utils::sign_htlc_transaction(&mut htlc_tx, &remote_signature, &preimage, &htlc, &keys.a_htlc_key, &keys.b_htlc_key, &keys.revocation_key, &keys.per_commitment_point, chan.local_keys.htlc_base_key(), &chan.secp_ctx).unwrap();
|
||||||
assert_eq!(serialize(&htlc_tx)[..],
|
assert_eq!(serialize(&htlc_tx)[..],
|
||||||
hex::decode($tx_hex).unwrap()[..]);
|
hex::decode($tx_hex).unwrap()[..]);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1791,7 +1791,7 @@ impl<ChanSigner: ChannelKeys> ChannelManager<ChanSigner> {
|
||||||
let pending_msg_events = channel_state.pending_msg_events;
|
let pending_msg_events = channel_state.pending_msg_events;
|
||||||
channel_state.by_id.retain(|_, channel| {
|
channel_state.by_id.retain(|_, channel| {
|
||||||
if channel.is_awaiting_monitor_update() {
|
if channel.is_awaiting_monitor_update() {
|
||||||
let chan_monitor = channel.channel_monitor();
|
let chan_monitor = channel.channel_monitor().clone();
|
||||||
if let Err(e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
|
if let Err(e) = self.monitor.add_update_monitor(chan_monitor.get_funding_txo().unwrap(), chan_monitor) {
|
||||||
match e {
|
match e {
|
||||||
ChannelMonitorUpdateErr::PermanentFailure => {
|
ChannelMonitorUpdateErr::PermanentFailure => {
|
||||||
|
@ -3216,7 +3216,7 @@ pub struct ChannelManagerReadArgs<'a, ChanSigner: ChannelKeys> {
|
||||||
///
|
///
|
||||||
/// In such cases the latest local transactions will be sent to the tx_broadcaster included in
|
/// In such cases the latest local transactions will be sent to the tx_broadcaster included in
|
||||||
/// this struct.
|
/// 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>) {
|
impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArgs<R, ChannelManagerReadArgs<'a, ChanSigner>> for (Sha256dHash, ChannelManager<ChanSigner>) {
|
||||||
|
@ -3245,7 +3245,7 @@ impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArg
|
||||||
|
|
||||||
let funding_txo = channel.channel_monitor().get_funding_txo().ok_or(DecodeError::InvalidValue)?;
|
let funding_txo = channel.channel_monitor().get_funding_txo().ok_or(DecodeError::InvalidValue)?;
|
||||||
funding_txo_set.insert(funding_txo.clone());
|
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() ||
|
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_revoked_remote_commitment_transaction_number() != monitor.get_min_seen_secret() ||
|
||||||
channel.get_cur_remote_commitment_transaction_number() != monitor.get_cur_remote_commitment_number() {
|
channel.get_cur_remote_commitment_transaction_number() != monitor.get_cur_remote_commitment_number() {
|
||||||
|
@ -3263,7 +3263,7 @@ impl<'a, R : ::std::io::Read, ChanSigner: ChannelKeys + Readable<R>> ReadableArg
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
if !funding_txo_set.contains(funding_txo) {
|
||||||
closed_channels.push((monitor.get_latest_local_commitment_txn(), Vec::new()));
|
closed_channels.push((monitor.get_latest_local_commitment_txn(), Vec::new()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ use bitcoin::blockdata::transaction::{TxIn,TxOut,SigHashType,Transaction};
|
||||||
use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
|
use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
|
||||||
use bitcoin::blockdata::script::{Script, Builder};
|
use bitcoin::blockdata::script::{Script, Builder};
|
||||||
use bitcoin::blockdata::opcodes;
|
use bitcoin::blockdata::opcodes;
|
||||||
use bitcoin::consensus::encode::{self, Decodable, Encodable};
|
use bitcoin::consensus::encode;
|
||||||
use bitcoin::util::hash::BitcoinHash;
|
use bitcoin::util::hash::BitcoinHash;
|
||||||
use bitcoin::util::bip143;
|
use bitcoin::util::bip143;
|
||||||
|
|
||||||
|
@ -31,14 +31,14 @@ use secp256k1;
|
||||||
|
|
||||||
use ln::msgs::DecodeError;
|
use ln::msgs::DecodeError;
|
||||||
use ln::chan_utils;
|
use ln::chan_utils;
|
||||||
use ln::chan_utils::HTLCOutputInCommitment;
|
use ln::chan_utils::{HTLCOutputInCommitment, LocalCommitmentTransaction};
|
||||||
use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
|
use ln::channelmanager::{HTLCSource, PaymentPreimage, PaymentHash};
|
||||||
use ln::channel::{ACCEPTED_HTLC_SCRIPT_WEIGHT, OFFERED_HTLC_SCRIPT_WEIGHT};
|
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::chaininterface::{ChainListener, ChainWatchInterface, BroadcasterInterface, FeeEstimator, ConfirmationTarget, MIN_RELAY_FEE_SAT_PER_1000_WEIGHT};
|
||||||
use chain::transaction::OutPoint;
|
use chain::transaction::OutPoint;
|
||||||
use chain::keysinterface::SpendableOutputDescriptor;
|
use chain::keysinterface::SpendableOutputDescriptor;
|
||||||
use util::logger::Logger;
|
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 util::{byte_utils, events};
|
||||||
|
|
||||||
use std::collections::{HashMap, hash_map, HashSet};
|
use std::collections::{HashMap, hash_map, HashSet};
|
||||||
|
@ -331,13 +331,12 @@ pub(crate) const ANTI_REORG_DELAY: u32 = 6;
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
enum Storage {
|
enum Storage {
|
||||||
Local {
|
Local {
|
||||||
|
funding_key: SecretKey,
|
||||||
revocation_base_key: SecretKey,
|
revocation_base_key: SecretKey,
|
||||||
htlc_base_key: SecretKey,
|
htlc_base_key: SecretKey,
|
||||||
delayed_payment_base_key: SecretKey,
|
delayed_payment_base_key: SecretKey,
|
||||||
payment_base_key: SecretKey,
|
payment_base_key: SecretKey,
|
||||||
shutdown_pubkey: PublicKey,
|
shutdown_pubkey: PublicKey,
|
||||||
prev_latest_per_commitment_point: Option<PublicKey>,
|
|
||||||
latest_per_commitment_point: Option<PublicKey>,
|
|
||||||
funding_info: Option<(OutPoint, Script)>,
|
funding_info: Option<(OutPoint, Script)>,
|
||||||
current_remote_commitment_txid: Option<Sha256dHash>,
|
current_remote_commitment_txid: Option<Sha256dHash>,
|
||||||
prev_remote_commitment_txid: Option<Sha256dHash>,
|
prev_remote_commitment_txid: Option<Sha256dHash>,
|
||||||
|
@ -352,13 +351,14 @@ enum Storage {
|
||||||
struct LocalSignedTx {
|
struct LocalSignedTx {
|
||||||
/// txid of the transaction in tx, just used to make comparison faster
|
/// txid of the transaction in tx, just used to make comparison faster
|
||||||
txid: Sha256dHash,
|
txid: Sha256dHash,
|
||||||
tx: Transaction,
|
tx: LocalCommitmentTransaction,
|
||||||
revocation_key: PublicKey,
|
revocation_key: PublicKey,
|
||||||
a_htlc_key: PublicKey,
|
a_htlc_key: PublicKey,
|
||||||
b_htlc_key: PublicKey,
|
b_htlc_key: PublicKey,
|
||||||
delayed_payment_key: PublicKey,
|
delayed_payment_key: PublicKey,
|
||||||
|
per_commitment_point: PublicKey,
|
||||||
feerate_per_kw: u64,
|
feerate_per_kw: u64,
|
||||||
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<(Signature, Signature)>, Option<HTLCSource>)>,
|
htlc_outputs: Vec<(HTLCOutputInCommitment, Option<Signature>, Option<HTLCSource>)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq)]
|
#[derive(PartialEq)]
|
||||||
|
@ -571,6 +571,8 @@ pub struct ChannelMonitor {
|
||||||
key_storage: Storage,
|
key_storage: Storage,
|
||||||
their_htlc_base_key: Option<PublicKey>,
|
their_htlc_base_key: Option<PublicKey>,
|
||||||
their_delayed_payment_base_key: Option<PublicKey>,
|
their_delayed_payment_base_key: Option<PublicKey>,
|
||||||
|
funding_redeemscript: Option<Script>,
|
||||||
|
channel_value_satoshis: Option<u64>,
|
||||||
// first is the idx of the first of the two revocation points
|
// first is the idx of the first of the two revocation points
|
||||||
their_cur_revocation_points: Option<(u64, PublicKey, Option<PublicKey>)>,
|
their_cur_revocation_points: Option<(u64, PublicKey, Option<PublicKey>)>,
|
||||||
|
|
||||||
|
@ -696,6 +698,8 @@ impl PartialEq for ChannelMonitor {
|
||||||
self.key_storage != other.key_storage ||
|
self.key_storage != other.key_storage ||
|
||||||
self.their_htlc_base_key != other.their_htlc_base_key ||
|
self.their_htlc_base_key != other.their_htlc_base_key ||
|
||||||
self.their_delayed_payment_base_key != other.their_delayed_payment_base_key ||
|
self.their_delayed_payment_base_key != other.their_delayed_payment_base_key ||
|
||||||
|
self.funding_redeemscript != other.funding_redeemscript ||
|
||||||
|
self.channel_value_satoshis != other.channel_value_satoshis ||
|
||||||
self.their_cur_revocation_points != other.their_cur_revocation_points ||
|
self.their_cur_revocation_points != other.their_cur_revocation_points ||
|
||||||
self.our_to_self_delay != other.our_to_self_delay ||
|
self.our_to_self_delay != other.our_to_self_delay ||
|
||||||
self.their_to_self_delay != other.their_to_self_delay ||
|
self.their_to_self_delay != other.their_to_self_delay ||
|
||||||
|
@ -725,24 +729,25 @@ impl PartialEq for ChannelMonitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChannelMonitor {
|
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 {
|
ChannelMonitor {
|
||||||
commitment_transaction_number_obscure_factor: 0,
|
commitment_transaction_number_obscure_factor: 0,
|
||||||
|
|
||||||
key_storage: Storage::Local {
|
key_storage: Storage::Local {
|
||||||
|
funding_key: funding_key.clone(),
|
||||||
revocation_base_key: revocation_base_key.clone(),
|
revocation_base_key: revocation_base_key.clone(),
|
||||||
htlc_base_key: htlc_base_key.clone(),
|
htlc_base_key: htlc_base_key.clone(),
|
||||||
delayed_payment_base_key: delayed_payment_base_key.clone(),
|
delayed_payment_base_key: delayed_payment_base_key.clone(),
|
||||||
payment_base_key: payment_base_key.clone(),
|
payment_base_key: payment_base_key.clone(),
|
||||||
shutdown_pubkey: shutdown_pubkey.clone(),
|
shutdown_pubkey: shutdown_pubkey.clone(),
|
||||||
prev_latest_per_commitment_point: None,
|
|
||||||
latest_per_commitment_point: None,
|
|
||||||
funding_info: None,
|
funding_info: None,
|
||||||
current_remote_commitment_txid: None,
|
current_remote_commitment_txid: None,
|
||||||
prev_remote_commitment_txid: None,
|
prev_remote_commitment_txid: None,
|
||||||
},
|
},
|
||||||
their_htlc_base_key: None,
|
their_htlc_base_key: None,
|
||||||
their_delayed_payment_base_key: None,
|
their_delayed_payment_base_key: None,
|
||||||
|
funding_redeemscript: None,
|
||||||
|
channel_value_satoshis: None,
|
||||||
their_cur_revocation_points: None,
|
their_cur_revocation_points: None,
|
||||||
|
|
||||||
our_to_self_delay: our_to_self_delay,
|
our_to_self_delay: our_to_self_delay,
|
||||||
|
@ -961,27 +966,20 @@ impl ChannelMonitor {
|
||||||
/// is important that any clones of this channel monitor (including remote clones) by kept
|
/// is important that any clones of this channel monitor (including remote clones) by kept
|
||||||
/// up-to-date as our local commitment transaction is updated.
|
/// up-to-date as our local commitment transaction is updated.
|
||||||
/// Panics if set_their_to_self_delay has never been called.
|
/// 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
|
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>, Option<HTLCSource>)>) {
|
||||||
/// 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>)>) {
|
|
||||||
assert!(self.their_to_self_delay.is_some());
|
assert!(self.their_to_self_delay.is_some());
|
||||||
self.prev_local_signed_commitment_tx = self.current_local_signed_commitment_tx.take();
|
self.prev_local_signed_commitment_tx = self.current_local_signed_commitment_tx.take();
|
||||||
self.current_local_signed_commitment_tx = Some(LocalSignedTx {
|
self.current_local_signed_commitment_tx = Some(LocalSignedTx {
|
||||||
txid: signed_commitment_tx.txid(),
|
txid: commitment_tx.txid(),
|
||||||
tx: signed_commitment_tx,
|
tx: commitment_tx,
|
||||||
revocation_key: local_keys.revocation_key,
|
revocation_key: local_keys.revocation_key,
|
||||||
a_htlc_key: local_keys.a_htlc_key,
|
a_htlc_key: local_keys.a_htlc_key,
|
||||||
b_htlc_key: local_keys.b_htlc_key,
|
b_htlc_key: local_keys.b_htlc_key,
|
||||||
delayed_payment_key: local_keys.a_delayed_payment_key,
|
delayed_payment_key: local_keys.a_delayed_payment_key,
|
||||||
|
per_commitment_point: local_keys.per_commitment_point,
|
||||||
feerate_per_kw,
|
feerate_per_kw,
|
||||||
htlc_outputs,
|
htlc_outputs,
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Storage::Local { ref mut latest_per_commitment_point, .. } = self.key_storage {
|
|
||||||
*latest_per_commitment_point = Some(local_keys.per_commitment_point);
|
|
||||||
} else {
|
|
||||||
panic!("Channel somehow ended up with its internal ChannelMonitor being in Watchtower mode?");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all
|
/// Provides a payment_hash->payment_preimage mapping. Will be automatically pruned when all
|
||||||
|
@ -1024,8 +1022,8 @@ impl ChannelMonitor {
|
||||||
}
|
}
|
||||||
if let Some(ref local_tx) = self.current_local_signed_commitment_tx {
|
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 {
|
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 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.input[0].sequence as u64 & 0xffffff) << 3*8) | (other_local_tx.tx.lock_time as u64 & 0xffffff)) ^ other.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 {
|
if our_commitment_number >= other_commitment_number {
|
||||||
self.key_storage = other.key_storage;
|
self.key_storage = other.key_storage;
|
||||||
}
|
}
|
||||||
|
@ -1052,12 +1050,6 @@ impl ChannelMonitor {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Panics if commitment_transaction_number_obscure_factor doesn't fit in 48 bits
|
|
||||||
pub(super) fn set_commitment_obscure_factor(&mut self, commitment_transaction_number_obscure_factor: u64) {
|
|
||||||
assert!(commitment_transaction_number_obscure_factor < (1 << 48));
|
|
||||||
self.commitment_transaction_number_obscure_factor = commitment_transaction_number_obscure_factor;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Allows this monitor to scan only for transactions which are applicable. Note that this is
|
/// Allows this monitor to scan only for transactions which are applicable. Note that this is
|
||||||
/// optional, without it this monitor cannot be used in an SPV client, but you may wish to
|
/// optional, without it this monitor cannot be used in an SPV client, but you may wish to
|
||||||
/// avoid this (or call unset_funding_info) on a monitor you wish to send to a watchtower as it
|
/// avoid this (or call unset_funding_info) on a monitor you wish to send to a watchtower as it
|
||||||
|
@ -1076,13 +1068,15 @@ impl ChannelMonitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// We log these base keys at channel opening to being able to rebuild redeemscript in case of leaked revoked commit tx
|
/// We log these base keys at channel opening to being able to rebuild redeemscript in case of leaked revoked commit tx
|
||||||
pub(super) fn set_their_base_keys(&mut self, their_htlc_base_key: &PublicKey, their_delayed_payment_base_key: &PublicKey) {
|
/// Panics if commitment_transaction_number_obscure_factor doesn't fit in 48 bits
|
||||||
|
pub(super) fn set_basic_channel_info(&mut self, their_htlc_base_key: &PublicKey, their_delayed_payment_base_key: &PublicKey, their_to_self_delay: u16, funding_redeemscript: Script, channel_value_satoshis: u64, commitment_transaction_number_obscure_factor: u64) {
|
||||||
self.their_htlc_base_key = Some(their_htlc_base_key.clone());
|
self.their_htlc_base_key = Some(their_htlc_base_key.clone());
|
||||||
self.their_delayed_payment_base_key = Some(their_delayed_payment_base_key.clone());
|
self.their_delayed_payment_base_key = Some(their_delayed_payment_base_key.clone());
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn set_their_to_self_delay(&mut self, their_to_self_delay: u16) {
|
|
||||||
self.their_to_self_delay = Some(their_to_self_delay);
|
self.their_to_self_delay = Some(their_to_self_delay);
|
||||||
|
self.funding_redeemscript = Some(funding_redeemscript);
|
||||||
|
self.channel_value_satoshis = Some(channel_value_satoshis);
|
||||||
|
assert!(commitment_transaction_number_obscure_factor < (1 << 48));
|
||||||
|
self.commitment_transaction_number_obscure_factor = commitment_transaction_number_obscure_factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(super) fn unset_funding_info(&mut self) {
|
pub(super) fn unset_funding_info(&mut self) {
|
||||||
|
@ -1148,15 +1142,14 @@ impl ChannelMonitor {
|
||||||
}
|
}
|
||||||
|
|
||||||
match self.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 funding_info, ref current_remote_commitment_txid, ref prev_remote_commitment_txid } => {
|
||||||
writer.write_all(&[0; 1])?;
|
writer.write_all(&[0; 1])?;
|
||||||
|
writer.write_all(&funding_key[..])?;
|
||||||
writer.write_all(&revocation_base_key[..])?;
|
writer.write_all(&revocation_base_key[..])?;
|
||||||
writer.write_all(&htlc_base_key[..])?;
|
writer.write_all(&htlc_base_key[..])?;
|
||||||
writer.write_all(&delayed_payment_base_key[..])?;
|
writer.write_all(&delayed_payment_base_key[..])?;
|
||||||
writer.write_all(&payment_base_key[..])?;
|
writer.write_all(&payment_base_key[..])?;
|
||||||
writer.write_all(&shutdown_pubkey.serialize())?;
|
writer.write_all(&shutdown_pubkey.serialize())?;
|
||||||
prev_latest_per_commitment_point.write(writer)?;
|
|
||||||
latest_per_commitment_point.write(writer)?;
|
|
||||||
match funding_info {
|
match funding_info {
|
||||||
&Some((ref outpoint, ref script)) => {
|
&Some((ref outpoint, ref script)) => {
|
||||||
writer.write_all(&outpoint.txid[..])?;
|
writer.write_all(&outpoint.txid[..])?;
|
||||||
|
@ -1175,6 +1168,8 @@ impl ChannelMonitor {
|
||||||
|
|
||||||
writer.write_all(&self.their_htlc_base_key.as_ref().unwrap().serialize())?;
|
writer.write_all(&self.their_htlc_base_key.as_ref().unwrap().serialize())?;
|
||||||
writer.write_all(&self.their_delayed_payment_base_key.as_ref().unwrap().serialize())?;
|
writer.write_all(&self.their_delayed_payment_base_key.as_ref().unwrap().serialize())?;
|
||||||
|
self.funding_redeemscript.as_ref().unwrap().write(writer)?;
|
||||||
|
self.channel_value_satoshis.unwrap().write(writer)?;
|
||||||
|
|
||||||
match self.their_cur_revocation_points {
|
match self.their_cur_revocation_points {
|
||||||
Some((idx, pubkey, second_option)) => {
|
Some((idx, pubkey, second_option)) => {
|
||||||
|
@ -1244,26 +1239,20 @@ impl ChannelMonitor {
|
||||||
|
|
||||||
macro_rules! serialize_local_tx {
|
macro_rules! serialize_local_tx {
|
||||||
($local_tx: expr) => {
|
($local_tx: expr) => {
|
||||||
if let Err(e) = $local_tx.tx.consensus_encode(&mut WriterWriteAdaptor(writer)) {
|
$local_tx.tx.write(writer)?;
|
||||||
match e {
|
|
||||||
encode::Error::Io(e) => return Err(e),
|
|
||||||
_ => panic!("local tx must have been well-formed!"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
writer.write_all(&$local_tx.revocation_key.serialize())?;
|
writer.write_all(&$local_tx.revocation_key.serialize())?;
|
||||||
writer.write_all(&$local_tx.a_htlc_key.serialize())?;
|
writer.write_all(&$local_tx.a_htlc_key.serialize())?;
|
||||||
writer.write_all(&$local_tx.b_htlc_key.serialize())?;
|
writer.write_all(&$local_tx.b_htlc_key.serialize())?;
|
||||||
writer.write_all(&$local_tx.delayed_payment_key.serialize())?;
|
writer.write_all(&$local_tx.delayed_payment_key.serialize())?;
|
||||||
|
writer.write_all(&$local_tx.per_commitment_point.serialize())?;
|
||||||
|
|
||||||
writer.write_all(&byte_utils::be64_to_array($local_tx.feerate_per_kw))?;
|
writer.write_all(&byte_utils::be64_to_array($local_tx.feerate_per_kw))?;
|
||||||
writer.write_all(&byte_utils::be64_to_array($local_tx.htlc_outputs.len() as u64))?;
|
writer.write_all(&byte_utils::be64_to_array($local_tx.htlc_outputs.len() as u64))?;
|
||||||
for &(ref htlc_output, ref sigs, ref htlc_source) in $local_tx.htlc_outputs.iter() {
|
for &(ref htlc_output, ref sig, ref htlc_source) in $local_tx.htlc_outputs.iter() {
|
||||||
serialize_htlc_in_commitment!(htlc_output);
|
serialize_htlc_in_commitment!(htlc_output);
|
||||||
if let &Some((ref their_sig, ref our_sig)) = sigs {
|
if let &Some(ref their_sig) = sig {
|
||||||
1u8.write(writer)?;
|
1u8.write(writer)?;
|
||||||
writer.write_all(&their_sig.serialize_compact())?;
|
writer.write_all(&their_sig.serialize_compact())?;
|
||||||
writer.write_all(&our_sig.serialize_compact())?;
|
|
||||||
} else {
|
} else {
|
||||||
0u8.write(writer)?;
|
0u8.write(writer)?;
|
||||||
}
|
}
|
||||||
|
@ -1397,7 +1386,7 @@ impl ChannelMonitor {
|
||||||
|
|
||||||
pub(super) fn get_cur_local_commitment_number(&self) -> u64 {
|
pub(super) fn get_cur_local_commitment_number(&self) -> u64 {
|
||||||
if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
|
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 }
|
} else { 0xffff_ffff_ffff }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2086,7 +2075,7 @@ impl ChannelMonitor {
|
||||||
} else { (None, None) }
|
} else { (None, None) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn broadcast_by_local_state(&self, local_tx: &LocalSignedTx, per_commitment_point: &Option<PublicKey>, delayed_payment_base_key: &Option<SecretKey>, height: u32) -> (Vec<Transaction>, Vec<SpendableOutputDescriptor>, Vec<TxOut>, Vec<(Sha256dHash, ClaimTxBumpMaterial)>) {
|
fn broadcast_by_local_state(&self, local_tx: &LocalSignedTx, delayed_payment_base_key: &SecretKey, height: u32) -> (Vec<Transaction>, Vec<SpendableOutputDescriptor>, Vec<TxOut>, Vec<(Sha256dHash, ClaimTxBumpMaterial)>) {
|
||||||
let mut res = Vec::with_capacity(local_tx.htlc_outputs.len());
|
let mut res = Vec::with_capacity(local_tx.htlc_outputs.len());
|
||||||
let mut spendable_outputs = Vec::with_capacity(local_tx.htlc_outputs.len());
|
let mut spendable_outputs = Vec::with_capacity(local_tx.htlc_outputs.len());
|
||||||
let mut watch_outputs = Vec::with_capacity(local_tx.htlc_outputs.len());
|
let mut watch_outputs = Vec::with_capacity(local_tx.htlc_outputs.len());
|
||||||
|
@ -2094,85 +2083,71 @@ impl ChannelMonitor {
|
||||||
|
|
||||||
macro_rules! add_dynamic_output {
|
macro_rules! add_dynamic_output {
|
||||||
($father_tx: expr, $vout: expr) => {
|
($father_tx: expr, $vout: expr) => {
|
||||||
if let Some(ref per_commitment_point) = *per_commitment_point {
|
if let Ok(local_delayedkey) = chan_utils::derive_private_key(&self.secp_ctx, &local_tx.per_commitment_point, delayed_payment_base_key) {
|
||||||
if let Some(ref delayed_payment_base_key) = *delayed_payment_base_key {
|
spendable_outputs.push(SpendableOutputDescriptor::DynamicOutputP2WSH {
|
||||||
if let Ok(local_delayedkey) = chan_utils::derive_private_key(&self.secp_ctx, per_commitment_point, delayed_payment_base_key) {
|
outpoint: BitcoinOutPoint { txid: $father_tx.txid(), vout: $vout },
|
||||||
spendable_outputs.push(SpendableOutputDescriptor::DynamicOutputP2WSH {
|
key: local_delayedkey,
|
||||||
outpoint: BitcoinOutPoint { txid: $father_tx.txid(), vout: $vout },
|
witness_script: chan_utils::get_revokeable_redeemscript(&local_tx.revocation_key, self.our_to_self_delay, &local_tx.delayed_payment_key),
|
||||||
key: local_delayedkey,
|
to_self_delay: self.our_to_self_delay,
|
||||||
witness_script: chan_utils::get_revokeable_redeemscript(&local_tx.revocation_key, self.our_to_self_delay, &local_tx.delayed_payment_key),
|
output: $father_tx.output[$vout as usize].clone(),
|
||||||
to_self_delay: self.our_to_self_delay,
|
});
|
||||||
output: $father_tx.output[$vout as usize].clone(),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let redeemscript = chan_utils::get_revokeable_redeemscript(&local_tx.revocation_key, self.their_to_self_delay.unwrap(), &local_tx.delayed_payment_key);
|
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();
|
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 {
|
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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for &(ref htlc, ref sigs, _) in local_tx.htlc_outputs.iter() {
|
if let &Storage::Local { ref htlc_base_key, .. } = &self.key_storage {
|
||||||
if let Some(transaction_output_index) = htlc.transaction_output_index {
|
for &(ref htlc, ref sigs, _) in local_tx.htlc_outputs.iter() {
|
||||||
if let &Some((ref their_sig, ref our_sig)) = sigs {
|
if let Some(transaction_output_index) = htlc.transaction_output_index {
|
||||||
if htlc.offered {
|
if let &Some(ref their_sig) = sigs {
|
||||||
log_trace!(self, "Broadcasting HTLC-Timeout transaction against local commitment transactions");
|
if htlc.offered {
|
||||||
let mut htlc_timeout_tx = chan_utils::build_htlc_transaction(&local_tx.txid, local_tx.feerate_per_kw, self.their_to_self_delay.unwrap(), htlc, &local_tx.delayed_payment_key, &local_tx.revocation_key);
|
log_trace!(self, "Broadcasting HTLC-Timeout transaction against local commitment transactions");
|
||||||
|
let mut htlc_timeout_tx = chan_utils::build_htlc_transaction(&local_tx.txid, local_tx.feerate_per_kw, self.their_to_self_delay.unwrap(), htlc, &local_tx.delayed_payment_key, &local_tx.revocation_key);
|
||||||
|
let (our_sig, htlc_script) = match
|
||||||
|
chan_utils::sign_htlc_transaction(&mut htlc_timeout_tx, their_sig, &None, htlc, &local_tx.a_htlc_key, &local_tx.b_htlc_key, &local_tx.revocation_key, &local_tx.per_commitment_point, htlc_base_key, &self.secp_ctx) {
|
||||||
|
Ok(res) => res,
|
||||||
|
Err(_) => continue,
|
||||||
|
};
|
||||||
|
|
||||||
htlc_timeout_tx.input[0].witness.push(Vec::new()); // First is the multisig dummy
|
add_dynamic_output!(htlc_timeout_tx, 0);
|
||||||
|
|
||||||
htlc_timeout_tx.input[0].witness.push(their_sig.serialize_der().to_vec());
|
|
||||||
htlc_timeout_tx.input[0].witness[1].push(SigHashType::All as u8);
|
|
||||||
htlc_timeout_tx.input[0].witness.push(our_sig.serialize_der().to_vec());
|
|
||||||
htlc_timeout_tx.input[0].witness[2].push(SigHashType::All as u8);
|
|
||||||
|
|
||||||
htlc_timeout_tx.input[0].witness.push(Vec::new());
|
|
||||||
let htlc_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(htlc, &local_tx.a_htlc_key, &local_tx.b_htlc_key, &local_tx.revocation_key);
|
|
||||||
htlc_timeout_tx.input[0].witness.push(htlc_script.clone().into_bytes());
|
|
||||||
|
|
||||||
add_dynamic_output!(htlc_timeout_tx, 0);
|
|
||||||
let height_timer = Self::get_height_timer(height, htlc.cltv_expiry);
|
|
||||||
let mut per_input_material = HashMap::with_capacity(1);
|
|
||||||
per_input_material.insert(htlc_timeout_tx.input[0].previous_output, InputMaterial::LocalHTLC { script: htlc_script, sigs: (*their_sig, *our_sig), preimage: None, amount: htlc.amount_msat / 1000});
|
|
||||||
//TODO: with option_simplified_commitment track outpoint too
|
|
||||||
log_trace!(self, "Outpoint {}:{} is being being claimed, if it doesn't succeed, a bumped claiming txn is going to be broadcast at height {}", htlc_timeout_tx.input[0].previous_output.vout, htlc_timeout_tx.input[0].previous_output.txid, height_timer);
|
|
||||||
pending_claims.push((htlc_timeout_tx.txid(), ClaimTxBumpMaterial { height_timer, feerate_previous: 0, soonest_timelock: htlc.cltv_expiry, per_input_material }));
|
|
||||||
res.push(htlc_timeout_tx);
|
|
||||||
} else {
|
|
||||||
if let Some(payment_preimage) = self.payment_preimages.get(&htlc.payment_hash) {
|
|
||||||
log_trace!(self, "Broadcasting HTLC-Success transaction against local commitment transactions");
|
|
||||||
let mut htlc_success_tx = chan_utils::build_htlc_transaction(&local_tx.txid, local_tx.feerate_per_kw, self.their_to_self_delay.unwrap(), htlc, &local_tx.delayed_payment_key, &local_tx.revocation_key);
|
|
||||||
|
|
||||||
htlc_success_tx.input[0].witness.push(Vec::new()); // First is the multisig dummy
|
|
||||||
|
|
||||||
htlc_success_tx.input[0].witness.push(their_sig.serialize_der().to_vec());
|
|
||||||
htlc_success_tx.input[0].witness[1].push(SigHashType::All as u8);
|
|
||||||
htlc_success_tx.input[0].witness.push(our_sig.serialize_der().to_vec());
|
|
||||||
htlc_success_tx.input[0].witness[2].push(SigHashType::All as u8);
|
|
||||||
|
|
||||||
htlc_success_tx.input[0].witness.push(payment_preimage.0.to_vec());
|
|
||||||
let htlc_script = chan_utils::get_htlc_redeemscript_with_explicit_keys(htlc, &local_tx.a_htlc_key, &local_tx.b_htlc_key, &local_tx.revocation_key);
|
|
||||||
htlc_success_tx.input[0].witness.push(htlc_script.clone().into_bytes());
|
|
||||||
|
|
||||||
add_dynamic_output!(htlc_success_tx, 0);
|
|
||||||
let height_timer = Self::get_height_timer(height, htlc.cltv_expiry);
|
let height_timer = Self::get_height_timer(height, htlc.cltv_expiry);
|
||||||
let mut per_input_material = HashMap::with_capacity(1);
|
let mut per_input_material = HashMap::with_capacity(1);
|
||||||
per_input_material.insert(htlc_success_tx.input[0].previous_output, InputMaterial::LocalHTLC { script: htlc_script, sigs: (*their_sig, *our_sig), preimage: Some(*payment_preimage), amount: htlc.amount_msat / 1000});
|
per_input_material.insert(htlc_timeout_tx.input[0].previous_output, InputMaterial::LocalHTLC { script: htlc_script, sigs: (*their_sig, our_sig), preimage: None, amount: htlc.amount_msat / 1000});
|
||||||
//TODO: with option_simplified_commitment track outpoint too
|
//TODO: with option_simplified_commitment track outpoint too
|
||||||
log_trace!(self, "Outpoint {}:{} is being being claimed, if it doesn't succeed, a bumped claiming txn is going to be broadcast at height {}", htlc_success_tx.input[0].previous_output.vout, htlc_success_tx.input[0].previous_output.txid, height_timer);
|
log_trace!(self, "Outpoint {}:{} is being being claimed, if it doesn't succeed, a bumped claiming txn is going to be broadcast at height {}", htlc_timeout_tx.input[0].previous_output.vout, htlc_timeout_tx.input[0].previous_output.txid, height_timer);
|
||||||
pending_claims.push((htlc_success_tx.txid(), ClaimTxBumpMaterial { height_timer, feerate_previous: 0, soonest_timelock: htlc.cltv_expiry, per_input_material }));
|
pending_claims.push((htlc_timeout_tx.txid(), ClaimTxBumpMaterial { height_timer, feerate_previous: 0, soonest_timelock: htlc.cltv_expiry, per_input_material }));
|
||||||
res.push(htlc_success_tx);
|
res.push(htlc_timeout_tx);
|
||||||
|
} else {
|
||||||
|
if let Some(payment_preimage) = self.payment_preimages.get(&htlc.payment_hash) {
|
||||||
|
log_trace!(self, "Broadcasting HTLC-Success transaction against local commitment transactions");
|
||||||
|
let mut htlc_success_tx = chan_utils::build_htlc_transaction(&local_tx.txid, local_tx.feerate_per_kw, self.their_to_self_delay.unwrap(), htlc, &local_tx.delayed_payment_key, &local_tx.revocation_key);
|
||||||
|
let (our_sig, htlc_script) = match
|
||||||
|
chan_utils::sign_htlc_transaction(&mut htlc_success_tx, their_sig, &Some(*payment_preimage), htlc, &local_tx.a_htlc_key, &local_tx.b_htlc_key, &local_tx.revocation_key, &local_tx.per_commitment_point, htlc_base_key, &self.secp_ctx) {
|
||||||
|
Ok(res) => res,
|
||||||
|
Err(_) => continue,
|
||||||
|
};
|
||||||
|
|
||||||
|
add_dynamic_output!(htlc_success_tx, 0);
|
||||||
|
let height_timer = Self::get_height_timer(height, htlc.cltv_expiry);
|
||||||
|
let mut per_input_material = HashMap::with_capacity(1);
|
||||||
|
per_input_material.insert(htlc_success_tx.input[0].previous_output, InputMaterial::LocalHTLC { script: htlc_script, sigs: (*their_sig, our_sig), preimage: Some(*payment_preimage), amount: htlc.amount_msat / 1000});
|
||||||
|
//TODO: with option_simplified_commitment track outpoint too
|
||||||
|
log_trace!(self, "Outpoint {}:{} is being being claimed, if it doesn't succeed, a bumped claiming txn is going to be broadcast at height {}", htlc_success_tx.input[0].previous_output.vout, htlc_success_tx.input[0].previous_output.txid, height_timer);
|
||||||
|
pending_claims.push((htlc_success_tx.txid(), ClaimTxBumpMaterial { height_timer, feerate_previous: 0, soonest_timelock: htlc.cltv_expiry, per_input_material }));
|
||||||
|
res.push(htlc_success_tx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
watch_outputs.push(local_tx.tx.without_valid_witness().output[transaction_output_index as usize].clone());
|
||||||
watch_outputs.push(local_tx.tx.output[transaction_output_index as usize].clone());
|
} else { panic!("Should have sigs for non-dust local tx outputs!") }
|
||||||
} else { panic!("Should have sigs for non-dust local tx outputs!") }
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2228,17 +2203,36 @@ impl ChannelMonitor {
|
||||||
// HTLCs set may differ between last and previous local commitment txn, in case of one them hitting chain, ensure we cancel all HTLCs backward
|
// 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;
|
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 let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
|
||||||
if local_tx.txid == commitment_txid {
|
if local_tx.txid == commitment_txid {
|
||||||
is_local_tx = true;
|
is_local_tx = true;
|
||||||
log_trace!(self, "Got latest local commitment tx broadcast, searching for available HTLCs to claim");
|
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 {
|
match self.key_storage {
|
||||||
Storage::Local { ref delayed_payment_base_key, ref latest_per_commitment_point, .. } => {
|
Storage::Local { ref delayed_payment_base_key, .. } => {
|
||||||
append_onchain_update!(self.broadcast_by_local_state(local_tx, latest_per_commitment_point, &Some(*delayed_payment_base_key), height));
|
append_onchain_update!(self.broadcast_by_local_state(local_tx, delayed_payment_base_key, height));
|
||||||
},
|
},
|
||||||
Storage::Watchtower { .. } => {
|
Storage::Watchtower { .. } => { }
|
||||||
append_onchain_update!(self.broadcast_by_local_state(local_tx, &None, &None, 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);
|
||||||
|
},
|
||||||
|
_ => {},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2246,13 +2240,12 @@ impl ChannelMonitor {
|
||||||
if local_tx.txid == commitment_txid {
|
if local_tx.txid == commitment_txid {
|
||||||
is_local_tx = true;
|
is_local_tx = true;
|
||||||
log_trace!(self, "Got previous local commitment tx broadcast, searching for available HTLCs to claim");
|
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 {
|
match self.key_storage {
|
||||||
Storage::Local { ref delayed_payment_base_key, ref prev_latest_per_commitment_point, .. } => {
|
Storage::Local { ref delayed_payment_base_key, .. } => {
|
||||||
append_onchain_update!(self.broadcast_by_local_state(local_tx, prev_latest_per_commitment_point, &Some(*delayed_payment_base_key), height));
|
append_onchain_update!(self.broadcast_by_local_state(local_tx, delayed_payment_base_key, height));
|
||||||
},
|
},
|
||||||
Storage::Watchtower { .. } => {
|
Storage::Watchtower { .. } => { }
|
||||||
append_onchain_update!(self.broadcast_by_local_state(local_tx, &None, &None, height));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2315,12 +2308,21 @@ impl ChannelMonitor {
|
||||||
/// substantial amount of time (a month or even a year) to get back funds. Best may be to contact
|
/// 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.
|
/// 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.
|
/// 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> {
|
||||||
if let &Some(ref local_tx) = &self.current_local_signed_commitment_tx {
|
log_trace!(self, "Getting signed latest local commitment transaction!");
|
||||||
let mut res = vec![local_tx.tx.clone()];
|
if let &mut Some(ref mut local_tx) = &mut self.current_local_signed_commitment_tx {
|
||||||
match self.key_storage {
|
match self.key_storage {
|
||||||
Storage::Local { ref delayed_payment_base_key, ref prev_latest_per_commitment_point, .. } => {
|
Storage::Local { ref funding_key, .. } => {
|
||||||
res.append(&mut self.broadcast_by_local_state(local_tx, prev_latest_per_commitment_point, &Some(*delayed_payment_base_key), 0).0);
|
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.with_valid_witness().clone()];
|
||||||
|
match self.key_storage {
|
||||||
|
Storage::Local { ref delayed_payment_base_key, .. } => {
|
||||||
|
res.append(&mut self.broadcast_by_local_state(local_tx, delayed_payment_base_key, 0).0);
|
||||||
// We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do.
|
// We throw away the generated waiting_first_conf data as we aren't (yet) confirmed and we don't actually know what the caller wants to do.
|
||||||
// The data will be re-generated and tracked in check_spend_local_transaction if we get a confirmation.
|
// The data will be re-generated and tracked in check_spend_local_transaction if we get a confirmation.
|
||||||
},
|
},
|
||||||
|
@ -2474,13 +2476,26 @@ impl ChannelMonitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(ref cur_local_tx) = self.current_local_signed_commitment_tx {
|
let should_broadcast = if let Some(_) = self.current_local_signed_commitment_tx {
|
||||||
if self.would_broadcast_at_height(height) {
|
self.would_broadcast_at_height(height)
|
||||||
log_trace!(self, "Broadcast onchain {}", log_tx!(cur_local_tx.tx));
|
} else { false };
|
||||||
broadcaster.broadcast_transaction(&cur_local_tx.tx);
|
if let Some(ref mut cur_local_tx) = self.current_local_signed_commitment_tx {
|
||||||
|
if should_broadcast {
|
||||||
match self.key_storage {
|
match self.key_storage {
|
||||||
Storage::Local { ref delayed_payment_base_key, ref latest_per_commitment_point, .. } => {
|
Storage::Local { ref funding_key, .. } => {
|
||||||
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);
|
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 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, .. } => {
|
||||||
|
let (txs, mut spendable_output, new_outputs, _) = self.broadcast_by_local_state(&cur_local_tx, delayed_payment_base_key, height);
|
||||||
spendable_outputs.append(&mut spendable_output);
|
spendable_outputs.append(&mut spendable_output);
|
||||||
if !new_outputs.is_empty() {
|
if !new_outputs.is_empty() {
|
||||||
watch_outputs.push((cur_local_tx.txid.clone(), new_outputs));
|
watch_outputs.push((cur_local_tx.txid.clone(), new_outputs));
|
||||||
|
@ -2490,17 +2505,7 @@ impl ChannelMonitor {
|
||||||
broadcaster.broadcast_transaction(&tx);
|
broadcaster.broadcast_transaction(&tx);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Storage::Watchtower { .. } => {
|
Storage::Watchtower { .. } => { },
|
||||||
let (txs, mut spendable_output, new_outputs, _) = self.broadcast_by_local_state(&cur_local_tx, &None, &None, height);
|
|
||||||
spendable_outputs.append(&mut spendable_output);
|
|
||||||
if !new_outputs.is_empty() {
|
|
||||||
watch_outputs.push((cur_local_tx.txid.clone(), new_outputs));
|
|
||||||
}
|
|
||||||
for tx in txs {
|
|
||||||
log_trace!(self, "Broadcast onchain {}", log_tx!(tx));
|
|
||||||
broadcaster.broadcast_transaction(&tx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2959,13 +2964,12 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
|
||||||
|
|
||||||
let key_storage = match <u8 as Readable<R>>::read(reader)? {
|
let key_storage = match <u8 as Readable<R>>::read(reader)? {
|
||||||
0 => {
|
0 => {
|
||||||
|
let funding_key = Readable::read(reader)?;
|
||||||
let revocation_base_key = Readable::read(reader)?;
|
let revocation_base_key = Readable::read(reader)?;
|
||||||
let htlc_base_key = Readable::read(reader)?;
|
let htlc_base_key = Readable::read(reader)?;
|
||||||
let delayed_payment_base_key = Readable::read(reader)?;
|
let delayed_payment_base_key = Readable::read(reader)?;
|
||||||
let payment_base_key = Readable::read(reader)?;
|
let payment_base_key = Readable::read(reader)?;
|
||||||
let shutdown_pubkey = Readable::read(reader)?;
|
let shutdown_pubkey = Readable::read(reader)?;
|
||||||
let prev_latest_per_commitment_point = Readable::read(reader)?;
|
|
||||||
let latest_per_commitment_point = Readable::read(reader)?;
|
|
||||||
// Technically this can fail and serialize fail a round-trip, but only for serialization of
|
// Technically this can fail and serialize fail a round-trip, but only for serialization of
|
||||||
// barely-init'd ChannelMonitors that we can't do anything with.
|
// barely-init'd ChannelMonitors that we can't do anything with.
|
||||||
let outpoint = OutPoint {
|
let outpoint = OutPoint {
|
||||||
|
@ -2976,13 +2980,12 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
|
||||||
let current_remote_commitment_txid = Readable::read(reader)?;
|
let current_remote_commitment_txid = Readable::read(reader)?;
|
||||||
let prev_remote_commitment_txid = Readable::read(reader)?;
|
let prev_remote_commitment_txid = Readable::read(reader)?;
|
||||||
Storage::Local {
|
Storage::Local {
|
||||||
|
funding_key,
|
||||||
revocation_base_key,
|
revocation_base_key,
|
||||||
htlc_base_key,
|
htlc_base_key,
|
||||||
delayed_payment_base_key,
|
delayed_payment_base_key,
|
||||||
payment_base_key,
|
payment_base_key,
|
||||||
shutdown_pubkey,
|
shutdown_pubkey,
|
||||||
prev_latest_per_commitment_point,
|
|
||||||
latest_per_commitment_point,
|
|
||||||
funding_info,
|
funding_info,
|
||||||
current_remote_commitment_txid,
|
current_remote_commitment_txid,
|
||||||
prev_remote_commitment_txid,
|
prev_remote_commitment_txid,
|
||||||
|
@ -2993,6 +2996,8 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
|
||||||
|
|
||||||
let their_htlc_base_key = Some(Readable::read(reader)?);
|
let their_htlc_base_key = Some(Readable::read(reader)?);
|
||||||
let their_delayed_payment_base_key = Some(Readable::read(reader)?);
|
let their_delayed_payment_base_key = Some(Readable::read(reader)?);
|
||||||
|
let funding_redeemscript = Some(Readable::read(reader)?);
|
||||||
|
let channel_value_satoshis = Some(Readable::read(reader)?);
|
||||||
|
|
||||||
let their_cur_revocation_points = {
|
let their_cur_revocation_points = {
|
||||||
let first_idx = <U48 as Readable<R>>::read(reader)?.0;
|
let first_idx = <U48 as Readable<R>>::read(reader)?.0;
|
||||||
|
@ -3076,23 +3081,12 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
|
||||||
macro_rules! read_local_tx {
|
macro_rules! read_local_tx {
|
||||||
() => {
|
() => {
|
||||||
{
|
{
|
||||||
let tx = match Transaction::consensus_decode(reader.by_ref()) {
|
let tx = <LocalCommitmentTransaction as Readable<R>>::read(reader)?;
|
||||||
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 revocation_key = Readable::read(reader)?;
|
let revocation_key = Readable::read(reader)?;
|
||||||
let a_htlc_key = Readable::read(reader)?;
|
let a_htlc_key = Readable::read(reader)?;
|
||||||
let b_htlc_key = Readable::read(reader)?;
|
let b_htlc_key = Readable::read(reader)?;
|
||||||
let delayed_payment_key = Readable::read(reader)?;
|
let delayed_payment_key = Readable::read(reader)?;
|
||||||
|
let per_commitment_point = Readable::read(reader)?;
|
||||||
let feerate_per_kw: u64 = Readable::read(reader)?;
|
let feerate_per_kw: u64 = Readable::read(reader)?;
|
||||||
|
|
||||||
let htlcs_len: u64 = Readable::read(reader)?;
|
let htlcs_len: u64 = Readable::read(reader)?;
|
||||||
|
@ -3101,7 +3095,7 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
|
||||||
let htlc = read_htlc_in_commitment!();
|
let htlc = read_htlc_in_commitment!();
|
||||||
let sigs = match <u8 as Readable<R>>::read(reader)? {
|
let sigs = match <u8 as Readable<R>>::read(reader)? {
|
||||||
0 => None,
|
0 => None,
|
||||||
1 => Some((Readable::read(reader)?, Readable::read(reader)?)),
|
1 => Some(Readable::read(reader)?),
|
||||||
_ => return Err(DecodeError::InvalidValue),
|
_ => return Err(DecodeError::InvalidValue),
|
||||||
};
|
};
|
||||||
htlcs.push((htlc, sigs, Readable::read(reader)?));
|
htlcs.push((htlc, sigs, Readable::read(reader)?));
|
||||||
|
@ -3109,7 +3103,7 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
|
||||||
|
|
||||||
LocalSignedTx {
|
LocalSignedTx {
|
||||||
txid: tx.txid(),
|
txid: tx.txid(),
|
||||||
tx, revocation_key, a_htlc_key, b_htlc_key, delayed_payment_key, feerate_per_kw,
|
tx, revocation_key, a_htlc_key, b_htlc_key, delayed_payment_key, per_commitment_point, feerate_per_kw,
|
||||||
htlc_outputs: htlcs
|
htlc_outputs: htlcs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3213,6 +3207,8 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
|
||||||
key_storage,
|
key_storage,
|
||||||
their_htlc_base_key,
|
their_htlc_base_key,
|
||||||
their_delayed_payment_base_key,
|
their_delayed_payment_base_key,
|
||||||
|
funding_redeemscript,
|
||||||
|
channel_value_satoshis,
|
||||||
their_cur_revocation_points,
|
their_cur_revocation_points,
|
||||||
|
|
||||||
our_to_self_delay,
|
our_to_self_delay,
|
||||||
|
@ -3261,7 +3257,7 @@ mod tests {
|
||||||
use ln::channelmanager::{PaymentPreimage, PaymentHash};
|
use ln::channelmanager::{PaymentPreimage, PaymentHash};
|
||||||
use ln::channelmonitor::{ChannelMonitor, InputDescriptors};
|
use ln::channelmonitor::{ChannelMonitor, InputDescriptors};
|
||||||
use ln::chan_utils;
|
use ln::chan_utils;
|
||||||
use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys};
|
use ln::chan_utils::{HTLCOutputInCommitment, TxCreationKeys, LocalCommitmentTransaction};
|
||||||
use util::test_utils::TestLogger;
|
use util::test_utils::TestLogger;
|
||||||
use secp256k1::key::{SecretKey,PublicKey};
|
use secp256k1::key::{SecretKey,PublicKey};
|
||||||
use secp256k1::Secp256k1;
|
use secp256k1::Secp256k1;
|
||||||
|
@ -3290,7 +3286,7 @@ mod tests {
|
||||||
|
|
||||||
{
|
{
|
||||||
// insert_secret correct sequence
|
// 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.clear();
|
||||||
|
|
||||||
secrets.push([0; 32]);
|
secrets.push([0; 32]);
|
||||||
|
@ -3336,7 +3332,7 @@ mod tests {
|
||||||
|
|
||||||
{
|
{
|
||||||
// insert_secret #1 incorrect
|
// 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.clear();
|
||||||
|
|
||||||
secrets.push([0; 32]);
|
secrets.push([0; 32]);
|
||||||
|
@ -3352,7 +3348,7 @@ mod tests {
|
||||||
|
|
||||||
{
|
{
|
||||||
// insert_secret #2 incorrect (#1 derived from incorrect)
|
// 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.clear();
|
||||||
|
|
||||||
secrets.push([0; 32]);
|
secrets.push([0; 32]);
|
||||||
|
@ -3378,7 +3374,7 @@ mod tests {
|
||||||
|
|
||||||
{
|
{
|
||||||
// insert_secret #3 incorrect
|
// 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.clear();
|
||||||
|
|
||||||
secrets.push([0; 32]);
|
secrets.push([0; 32]);
|
||||||
|
@ -3404,7 +3400,7 @@ mod tests {
|
||||||
|
|
||||||
{
|
{
|
||||||
// insert_secret #4 incorrect (1,2,3 derived from incorrect)
|
// 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.clear();
|
||||||
|
|
||||||
secrets.push([0; 32]);
|
secrets.push([0; 32]);
|
||||||
|
@ -3450,7 +3446,7 @@ mod tests {
|
||||||
|
|
||||||
{
|
{
|
||||||
// insert_secret #5 incorrect
|
// 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.clear();
|
||||||
|
|
||||||
secrets.push([0; 32]);
|
secrets.push([0; 32]);
|
||||||
|
@ -3486,7 +3482,7 @@ mod tests {
|
||||||
|
|
||||||
{
|
{
|
||||||
// insert_secret #6 incorrect (5 derived from incorrect)
|
// 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.clear();
|
||||||
|
|
||||||
secrets.push([0; 32]);
|
secrets.push([0; 32]);
|
||||||
|
@ -3532,7 +3528,7 @@ mod tests {
|
||||||
|
|
||||||
{
|
{
|
||||||
// insert_secret #7 incorrect
|
// 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.clear();
|
||||||
|
|
||||||
secrets.push([0; 32]);
|
secrets.push([0; 32]);
|
||||||
|
@ -3578,7 +3574,7 @@ mod tests {
|
||||||
|
|
||||||
{
|
{
|
||||||
// insert_secret #8 incorrect
|
// 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.clear();
|
||||||
|
|
||||||
secrets.push([0; 32]);
|
secrets.push([0; 32]);
|
||||||
|
@ -3693,10 +3689,10 @@ mod tests {
|
||||||
|
|
||||||
// Prune with one old state and a local commitment tx holding a few overlaps with the
|
// Prune with one old state and a local commitment tx holding a few overlaps with the
|
||||||
// old state.
|
// 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.set_their_to_self_delay(10);
|
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[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[15..20]), 281474976710654, dummy_key);
|
||||||
monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key);
|
monitor.provide_latest_remote_commitment_tx_info(&dummy_tx, preimages_slice_to_htlc_outputs!(preimages[17..20]), 281474976710653, dummy_key);
|
||||||
|
@ -3722,7 +3718,7 @@ mod tests {
|
||||||
|
|
||||||
// Now update local commitment tx info, pruning only element 18 as we still care about the
|
// Now update local commitment tx info, pruning only element 18 as we still care about the
|
||||||
// previous commitment tx's preimages too
|
// 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());
|
secret[0..32].clone_from_slice(&hex::decode("2273e227a5b7449b6e70f1fb4652864038b1cbf9cd7c043a7d6456b7fc275ad8").unwrap());
|
||||||
monitor.provide_secret(281474976710653, secret.clone()).unwrap();
|
monitor.provide_secret(281474976710653, secret.clone()).unwrap();
|
||||||
assert_eq!(monitor.payment_preimages.len(), 12);
|
assert_eq!(monitor.payment_preimages.len(), 12);
|
||||||
|
@ -3730,7 +3726,7 @@ mod tests {
|
||||||
test_preimages_exist!(&preimages[18..20], monitor);
|
test_preimages_exist!(&preimages[18..20], monitor);
|
||||||
|
|
||||||
// But if we do it again, we'll prune 5-10
|
// 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());
|
secret[0..32].clone_from_slice(&hex::decode("27cddaa5624534cb6cb9d7da077cf2b22ab21e9b506fd4998a51d54502e99116").unwrap());
|
||||||
monitor.provide_secret(281474976710652, secret.clone()).unwrap();
|
monitor.provide_secret(281474976710652, secret.clone()).unwrap();
|
||||||
assert_eq!(monitor.payment_preimages.len(), 5);
|
assert_eq!(monitor.payment_preimages.len(), 5);
|
||||||
|
|
|
@ -422,13 +422,13 @@ fn test_update_fee_that_funder_cannot_afford() {
|
||||||
//Confirm that the new fee based on the last local commitment txn is what we expected based on the feerate of 260 set above.
|
//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)
|
//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 mut chan_lock = nodes[1].node.channel_state.lock().unwrap();
|
||||||
let chan = chan_lock.by_id.get(&channel_id).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
|
//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.last_local_commitment_txn[0].output.len() - 2;
|
let num_htlcs = chan.channel_monitor().get_latest_local_commitment_txn()[0].output.len() - 2;
|
||||||
let total_fee: u64 = feerate * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
|
let total_fee: u64 = feerate * (COMMITMENT_TX_BASE_WEIGHT + (num_htlcs as u64) * COMMITMENT_TX_WEIGHT_PER_HTLC) / 1000;
|
||||||
let mut actual_fee = chan.last_local_commitment_txn[0].output.iter().fold(0, |acc, output| acc + output.value);
|
let mut actual_fee = chan.channel_monitor().get_latest_local_commitment_txn()[0].output.iter().fold(0, |acc, output| acc + output.value);
|
||||||
actual_fee = channel_value - actual_fee;
|
actual_fee = channel_value - actual_fee;
|
||||||
assert_eq!(total_fee, actual_fee);
|
assert_eq!(total_fee, actual_fee);
|
||||||
} //drop the mutex
|
} //drop the mutex
|
||||||
|
@ -1267,7 +1267,7 @@ fn test_duplicate_htlc_different_direction_onchain() {
|
||||||
check_added_monitors!(nodes[0], 1);
|
check_added_monitors!(nodes[0], 1);
|
||||||
|
|
||||||
// Broadcast node 1 commitment txn
|
// Broadcast node 1 commitment txn
|
||||||
let remote_txn = nodes[1].node.channel_state.lock().unwrap().by_id.get(&chan_1.2).unwrap().last_local_commitment_txn.clone();
|
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
|
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
|
let mut has_both_htlcs = 0; // check htlcs match ones committed
|
||||||
|
@ -1286,7 +1286,11 @@ fn test_duplicate_htlc_different_direction_onchain() {
|
||||||
// Check we only broadcast 1 timeout tx
|
// Check we only broadcast 1 timeout tx
|
||||||
let claim_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
|
let claim_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
|
||||||
let htlc_pair = if claim_txn[0].output[0].value == 800_000 / 1000 { (claim_txn[0].clone(), claim_txn[1].clone()) } else { (claim_txn[1].clone(), claim_txn[0].clone()) };
|
let htlc_pair = if claim_txn[0].output[0].value == 800_000 / 1000 { (claim_txn[0].clone(), claim_txn[1].clone()) } else { (claim_txn[1].clone(), claim_txn[0].clone()) };
|
||||||
assert_eq!(claim_txn.len(), 6);
|
assert_eq!(claim_txn.len(), 7);
|
||||||
|
check_spends!(claim_txn[2], chan_1.3);
|
||||||
|
check_spends!(claim_txn[3], claim_txn[2]);
|
||||||
|
assert_eq!(claim_txn[0], claim_txn[5]);
|
||||||
|
assert_eq!(claim_txn[1], claim_txn[6]);
|
||||||
assert_eq!(htlc_pair.0.input.len(), 1);
|
assert_eq!(htlc_pair.0.input.len(), 1);
|
||||||
assert_eq!(htlc_pair.0.input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); // HTLC 1 <--> 0, preimage tx
|
assert_eq!(htlc_pair.0.input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT); // HTLC 1 <--> 0, preimage tx
|
||||||
check_spends!(htlc_pair.0, remote_txn[0].clone());
|
check_spends!(htlc_pair.0, remote_txn[0].clone());
|
||||||
|
@ -1874,7 +1878,7 @@ fn test_justice_tx() {
|
||||||
// A pending HTLC which will be revoked:
|
// A pending HTLC which will be revoked:
|
||||||
let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
|
let payment_preimage_3 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
|
||||||
// Get the will-be-revoked local txn from nodes[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();
|
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.len(), 2); // First commitment tx, then HTLC tx
|
||||||
assert_eq!(revoked_local_txn[0].input.len(), 1);
|
assert_eq!(revoked_local_txn[0].input.len(), 1);
|
||||||
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_5.3.txid());
|
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_5.3.txid());
|
||||||
|
@ -1922,7 +1926,7 @@ fn test_justice_tx() {
|
||||||
// A pending HTLC which will be revoked:
|
// A pending HTLC which will be revoked:
|
||||||
let payment_preimage_4 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
|
let payment_preimage_4 = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
|
||||||
// Get the will-be-revoked local txn from B
|
// 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.last_local_commitment_txn.clone();
|
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.len(), 1); // Only commitment tx
|
||||||
assert_eq!(revoked_local_txn[0].input.len(), 1);
|
assert_eq!(revoked_local_txn[0].input.len(), 1);
|
||||||
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_6.3.txid());
|
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_6.3.txid());
|
||||||
|
@ -1961,7 +1965,7 @@ fn revoked_output_claim() {
|
||||||
let nodes = create_network(2, &[None, None]);
|
let nodes = create_network(2, &[None, None]);
|
||||||
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
|
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
|
// 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().last_local_commitment_txn.clone();
|
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);
|
assert_eq!(revoked_local_txn.len(), 1);
|
||||||
// Only output is the full channel value back to nodes[0]:
|
// Only output is the full channel value back to nodes[0]:
|
||||||
assert_eq!(revoked_local_txn[0].output.len(), 1);
|
assert_eq!(revoked_local_txn[0].output.len(), 1);
|
||||||
|
@ -1999,7 +2003,7 @@ fn claim_htlc_outputs_shared_tx() {
|
||||||
let (_payment_preimage_2, payment_hash_2) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000);
|
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]
|
// 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().last_local_commitment_txn.clone();
|
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.len(), 2); // commitment tx + 1 HTLC-Timeout tx
|
||||||
assert_eq!(revoked_local_txn[0].input.len(), 1);
|
assert_eq!(revoked_local_txn[0].input.len(), 1);
|
||||||
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
|
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
|
||||||
|
@ -2074,7 +2078,7 @@ fn claim_htlc_outputs_single_tx() {
|
||||||
let (_payment_preimage_2, payment_hash_2) = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000);
|
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]
|
// 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().last_local_commitment_txn.clone();
|
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
|
//Revoke the old state
|
||||||
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1, 3_000_000);
|
claim_payment(&nodes[0], &vec!(&nodes[1])[..], payment_preimage_1, 3_000_000);
|
||||||
|
@ -2176,7 +2180,7 @@ fn test_htlc_on_chain_success() {
|
||||||
|
|
||||||
// Broadcast legit commitment tx from C on B's chain
|
// 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
|
// 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().last_local_commitment_txn.clone();
|
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);
|
assert_eq!(commitment_tx.len(), 1);
|
||||||
check_spends!(commitment_tx[0], chan_2.3.clone());
|
check_spends!(commitment_tx[0], chan_2.3.clone());
|
||||||
nodes[2].node.claim_funds(our_payment_preimage, 3_000_000);
|
nodes[2].node.claim_funds(our_payment_preimage, 3_000_000);
|
||||||
|
@ -2190,10 +2194,12 @@ fn test_htlc_on_chain_success() {
|
||||||
|
|
||||||
nodes[2].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
|
nodes[2].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
|
||||||
check_closed_broadcast!(nodes[2]);
|
check_closed_broadcast!(nodes[2]);
|
||||||
let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 1 (commitment tx), ChannelMonitor : 4 (2*2 * HTLC-Success tx)
|
let node_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 3 (commitment tx, 2*htlc-success tx), ChannelMonitor : 4 (2*2 * HTLC-Success tx)
|
||||||
assert_eq!(node_txn.len(), 5);
|
assert_eq!(node_txn.len(), 7);
|
||||||
assert_eq!(node_txn[0], node_txn[3]);
|
assert_eq!(node_txn[0], node_txn[3]);
|
||||||
assert_eq!(node_txn[1], node_txn[4]);
|
assert_eq!(node_txn[1], node_txn[4]);
|
||||||
|
assert_eq!(node_txn[0], node_txn[5]);
|
||||||
|
assert_eq!(node_txn[1], node_txn[6]);
|
||||||
assert_eq!(node_txn[2], commitment_tx[0]);
|
assert_eq!(node_txn[2], commitment_tx[0]);
|
||||||
check_spends!(node_txn[0], commitment_tx[0].clone());
|
check_spends!(node_txn[0], commitment_tx[0].clone());
|
||||||
check_spends!(node_txn[1], commitment_tx[0].clone());
|
check_spends!(node_txn[1], commitment_tx[0].clone());
|
||||||
|
@ -2271,13 +2277,13 @@ fn test_htlc_on_chain_success() {
|
||||||
|
|
||||||
// Broadcast legit commitment tx from A on B's chain
|
// 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
|
// 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().last_local_commitment_txn.clone();
|
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());
|
check_spends!(commitment_tx[0], chan_1.3.clone());
|
||||||
nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
|
nodes[1].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 1);
|
||||||
check_closed_broadcast!(nodes[1]);
|
check_closed_broadcast!(nodes[1]);
|
||||||
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 1 (commitment tx), ChannelMonitor : 1 (HTLC-Success) * 2 (block-rescan)
|
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 3 (commitment tx + 2*HTLC-Success), ChannelMonitor : 1 (HTLC-Success) * 2 (block-rescan)
|
||||||
assert_eq!(node_txn.len(), 3);
|
assert_eq!(node_txn.len(), 5);
|
||||||
assert_eq!(node_txn[0], node_txn[2]);
|
assert_eq!(node_txn[0], node_txn[4]);
|
||||||
check_spends!(node_txn[0], commitment_tx[0].clone());
|
check_spends!(node_txn[0], commitment_tx[0].clone());
|
||||||
assert_eq!(node_txn[0].input.len(), 2);
|
assert_eq!(node_txn[0].input.len(), 2);
|
||||||
assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
|
assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
|
||||||
|
@ -2286,6 +2292,8 @@ fn test_htlc_on_chain_success() {
|
||||||
assert!(node_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment
|
assert!(node_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment
|
||||||
check_spends!(node_txn[1], chan_1.3.clone());
|
check_spends!(node_txn[1], chan_1.3.clone());
|
||||||
assert_eq!(node_txn[1].input[0].witness.clone().last().unwrap().len(), 71);
|
assert_eq!(node_txn[1].input[0].witness.clone().last().unwrap().len(), 71);
|
||||||
|
check_spends!(node_txn[2], node_txn[1]);
|
||||||
|
check_spends!(node_txn[3], node_txn[1]);
|
||||||
// We don't bother to check that B can claim the HTLC output on its commitment tx here as
|
// We don't bother to check that B can claim the HTLC output on its commitment tx here as
|
||||||
// we already checked the same situation with A.
|
// we already checked the same situation with A.
|
||||||
|
|
||||||
|
@ -2335,7 +2343,7 @@ fn test_htlc_on_chain_timeout() {
|
||||||
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42};
|
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
|
// 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().last_local_commitment_txn.clone();
|
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());
|
check_spends!(commitment_tx[0], chan_2.3.clone());
|
||||||
nodes[2].node.fail_htlc_backwards(&payment_hash);
|
nodes[2].node.fail_htlc_backwards(&payment_hash);
|
||||||
check_added_monitors!(nodes[2], 0);
|
check_added_monitors!(nodes[2], 0);
|
||||||
|
@ -2408,7 +2416,7 @@ fn test_htlc_on_chain_timeout() {
|
||||||
assert_eq!(node_txn.len(), 0);
|
assert_eq!(node_txn.len(), 0);
|
||||||
|
|
||||||
// Broadcast legit commitment tx from B on A's chain
|
// 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().last_local_commitment_txn.clone();
|
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());
|
check_spends!(commitment_tx[0], chan_1.3.clone());
|
||||||
|
|
||||||
nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 200);
|
nodes[0].block_notifier.block_connected(&Block { header, txdata: vec![commitment_tx[0].clone()]}, 200);
|
||||||
|
@ -2437,7 +2445,7 @@ fn test_simple_commitment_revoked_fail_backward() {
|
||||||
|
|
||||||
let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3000000);
|
let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], 3000000);
|
||||||
// Get the will-be-revoked local txn from nodes[2]
|
// 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().last_local_commitment_txn.clone();
|
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
|
// Revoke the old state
|
||||||
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage, 3_000_000);
|
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage, 3_000_000);
|
||||||
|
|
||||||
|
@ -2505,7 +2513,7 @@ fn do_test_commitment_revoked_fail_backward_exhaustive(deliver_bs_raa: bool, use
|
||||||
|
|
||||||
let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &[&nodes[1], &nodes[2]], if no_to_remote { 10_000 } else { 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]
|
// 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().last_local_commitment_txn.clone();
|
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 });
|
assert_eq!(revoked_local_txn[0].output.len(), if no_to_remote { 1 } else { 2 });
|
||||||
// Revoke the old state
|
// Revoke the old state
|
||||||
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage, if no_to_remote { 10_000 } else { 3_000_000});
|
claim_payment(&nodes[0], &[&nodes[1], &nodes[2]], payment_preimage, if no_to_remote { 10_000 } else { 3_000_000});
|
||||||
|
@ -3397,7 +3405,7 @@ fn test_no_txn_manager_serialize_deserialize() {
|
||||||
|
|
||||||
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 })));
|
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 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());
|
assert!(chan_0_monitor_read.is_empty());
|
||||||
|
|
||||||
let mut nodes_0_read = &nodes_0_serialized[..];
|
let mut nodes_0_read = &nodes_0_serialized[..];
|
||||||
|
@ -3405,7 +3413,7 @@ fn test_no_txn_manager_serialize_deserialize() {
|
||||||
let keys_manager = Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::new(test_utils::TestLogger::new())));
|
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 (_, nodes_0_deserialized) = {
|
||||||
let mut channel_monitors = HashMap::new();
|
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 {
|
<(Sha256dHash, ChannelManager<EnforcingChannelKeys>)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
|
||||||
default_config: config,
|
default_config: config,
|
||||||
keys_manager,
|
keys_manager,
|
||||||
|
@ -3413,7 +3421,7 @@ fn test_no_txn_manager_serialize_deserialize() {
|
||||||
monitor: nodes[0].chan_monitor.clone(),
|
monitor: nodes[0].chan_monitor.clone(),
|
||||||
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
|
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
|
||||||
logger: Arc::new(test_utils::TestLogger::new()),
|
logger: Arc::new(test_utils::TestLogger::new()),
|
||||||
channel_monitors: &channel_monitors,
|
channel_monitors: &mut channel_monitors,
|
||||||
}).unwrap()
|
}).unwrap()
|
||||||
};
|
};
|
||||||
assert!(nodes_0_read.is_empty());
|
assert!(nodes_0_read.is_empty());
|
||||||
|
@ -3462,14 +3470,14 @@ fn test_simple_manager_serialize_deserialize() {
|
||||||
|
|
||||||
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 })));
|
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 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());
|
assert!(chan_0_monitor_read.is_empty());
|
||||||
|
|
||||||
let mut nodes_0_read = &nodes_0_serialized[..];
|
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 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 (_, nodes_0_deserialized) = {
|
||||||
let mut channel_monitors = HashMap::new();
|
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 {
|
<(Sha256dHash, ChannelManager<EnforcingChannelKeys>)>::read(&mut nodes_0_read, ChannelManagerReadArgs {
|
||||||
default_config: UserConfig::default(),
|
default_config: UserConfig::default(),
|
||||||
keys_manager,
|
keys_manager,
|
||||||
|
@ -3477,7 +3485,7 @@ fn test_simple_manager_serialize_deserialize() {
|
||||||
monitor: nodes[0].chan_monitor.clone(),
|
monitor: nodes[0].chan_monitor.clone(),
|
||||||
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
|
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
|
||||||
logger: Arc::new(test_utils::TestLogger::new()),
|
logger: Arc::new(test_utils::TestLogger::new()),
|
||||||
channel_monitors: &channel_monitors,
|
channel_monitors: &mut channel_monitors,
|
||||||
}).unwrap()
|
}).unwrap()
|
||||||
};
|
};
|
||||||
assert!(nodes_0_read.is_empty());
|
assert!(nodes_0_read.is_empty());
|
||||||
|
@ -3537,7 +3545,7 @@ fn test_manager_serialize_deserialize_inconsistent_monitor() {
|
||||||
monitor: nodes[0].chan_monitor.clone(),
|
monitor: nodes[0].chan_monitor.clone(),
|
||||||
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
|
tx_broadcaster: nodes[0].tx_broadcaster.clone(),
|
||||||
logger: Arc::new(test_utils::TestLogger::new()),
|
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();
|
}).unwrap();
|
||||||
assert!(nodes_0_read.is_empty());
|
assert!(nodes_0_read.is_empty());
|
||||||
|
|
||||||
|
@ -3733,7 +3741,7 @@ fn test_claim_on_remote_revoked_sizeable_push_msat() {
|
||||||
|
|
||||||
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 1, 100000, 59000000, LocalFeatures::new(), LocalFeatures::new());
|
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 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().last_local_commitment_txn.clone();
|
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.len(), 1);
|
||||||
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
|
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
|
||||||
|
|
||||||
|
@ -3760,7 +3768,7 @@ fn test_static_spendable_outputs_preimage_tx() {
|
||||||
|
|
||||||
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3000000).0;
|
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().last_local_commitment_txn.clone();
|
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.len(), 1);
|
||||||
assert_eq!(commitment_tx[0].input[0].previous_output.txid, chan_1.3.txid());
|
assert_eq!(commitment_tx[0].input[0].previous_output.txid, chan_1.3.txid());
|
||||||
|
|
||||||
|
@ -3780,11 +3788,14 @@ fn test_static_spendable_outputs_preimage_tx() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check B's monitor was able to send back output descriptor event for preimage tx on A's commitment tx
|
// Check B's monitor was able to send back output descriptor event for preimage tx on A's commitment tx
|
||||||
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); // ChannelManager : 1 (local commitment tx), ChannelMonitor: 2 (1 preimage tx) * 2 (block-rescan)
|
let node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap(); // ChannelManager : 2 (local commitment tx + HTLC-Success), ChannelMonitor: 2 (1 preimage tx)
|
||||||
|
assert_eq!(node_txn.len(), 4);
|
||||||
check_spends!(node_txn[0], commitment_tx[0].clone());
|
check_spends!(node_txn[0], commitment_tx[0].clone());
|
||||||
assert_eq!(node_txn[0], node_txn[2]);
|
assert_eq!(node_txn[0], node_txn[3]);
|
||||||
assert_eq!(node_txn[0].input[0].witness.last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
|
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[1], chan_1.3.clone());
|
||||||
|
check_spends!(node_txn[2], node_txn[1]);
|
||||||
|
|
||||||
let spend_txn = check_spendable_outputs!(nodes[1], 1); // , 0, 0, 1, 1);
|
let spend_txn = check_spendable_outputs!(nodes[1], 1); // , 0, 0, 1, 1);
|
||||||
assert_eq!(spend_txn.len(), 2);
|
assert_eq!(spend_txn.len(), 2);
|
||||||
|
@ -3800,7 +3811,7 @@ fn test_static_spendable_outputs_justice_tx_revoked_commitment_tx() {
|
||||||
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
|
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 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.last_local_commitment_txn.clone();
|
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.len(), 1);
|
||||||
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
|
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
|
||||||
|
|
||||||
|
@ -3830,7 +3841,7 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_timeout_tx() {
|
||||||
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
|
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 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().last_local_commitment_txn.clone();
|
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.len(), 1);
|
||||||
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
|
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
|
||||||
|
|
||||||
|
@ -3874,7 +3885,7 @@ fn test_static_spendable_outputs_justice_tx_revoked_htlc_success_tx() {
|
||||||
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
|
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 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().last_local_commitment_txn.clone();
|
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.len(), 1);
|
||||||
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
|
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan_1.3.txid());
|
||||||
|
|
||||||
|
@ -3933,7 +3944,7 @@ fn test_onchain_to_onchain_claim() {
|
||||||
|
|
||||||
let (payment_preimage, _payment_hash) = route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2]), 3000000);
|
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 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().last_local_commitment_txn.clone();
|
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());
|
check_spends!(commitment_tx[0], chan_2.3.clone());
|
||||||
nodes[2].node.claim_funds(payment_preimage, 3_000_000);
|
nodes[2].node.claim_funds(payment_preimage, 3_000_000);
|
||||||
check_added_monitors!(nodes[2], 1);
|
check_added_monitors!(nodes[2], 1);
|
||||||
|
@ -3947,8 +3958,9 @@ fn test_onchain_to_onchain_claim() {
|
||||||
check_closed_broadcast!(nodes[2]);
|
check_closed_broadcast!(nodes[2]);
|
||||||
|
|
||||||
let c_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 2 (commitment tx, HTLC-Success tx), ChannelMonitor : 1 (HTLC-Success tx)
|
let c_txn = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone(); // ChannelManager : 2 (commitment tx, HTLC-Success tx), ChannelMonitor : 1 (HTLC-Success tx)
|
||||||
assert_eq!(c_txn.len(), 3);
|
assert_eq!(c_txn.len(), 4);
|
||||||
assert_eq!(c_txn[0], c_txn[2]);
|
assert_eq!(c_txn[0], c_txn[2]);
|
||||||
|
assert_eq!(c_txn[0], c_txn[3]);
|
||||||
assert_eq!(commitment_tx[0], c_txn[1]);
|
assert_eq!(commitment_tx[0], c_txn[1]);
|
||||||
check_spends!(c_txn[1], chan_2.3.clone());
|
check_spends!(c_txn[1], chan_2.3.clone());
|
||||||
check_spends!(c_txn[2], c_txn[1].clone());
|
check_spends!(c_txn[2], c_txn[1].clone());
|
||||||
|
@ -3991,12 +4003,13 @@ fn test_onchain_to_onchain_claim() {
|
||||||
_ => panic!("Unexpected event"),
|
_ => 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
|
// 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().last_local_commitment_txn.clone();
|
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);
|
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();
|
let b_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
|
||||||
assert_eq!(b_txn.len(), 3);
|
assert_eq!(b_txn.len(), 4);
|
||||||
check_spends!(b_txn[1], chan_1.3); // Local commitment tx, issued by ChannelManager
|
check_spends!(b_txn[1], chan_1.3); // Local commitment tx, issued by ChannelManager
|
||||||
assert_eq!(b_txn[0], b_txn[2]); // HTLC-Success tx, issued by ChannelMonitor, * 2 due to block rescan
|
check_spends!(b_txn[2], b_txn[1]); // HTLC-Success tx, as a part of the local txn rebroadcast by ChannelManager in the force close
|
||||||
|
assert_eq!(b_txn[0], b_txn[3]); // HTLC-Success tx, issued by ChannelMonitor, * 2 due to block rescan
|
||||||
check_spends!(b_txn[0], commitment_tx[0].clone());
|
check_spends!(b_txn[0], commitment_tx[0].clone());
|
||||||
assert_eq!(b_txn[0].input[0].witness.clone().last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
|
assert_eq!(b_txn[0].input[0].witness.clone().last().unwrap().len(), OFFERED_HTLC_SCRIPT_WEIGHT);
|
||||||
assert!(b_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment
|
assert!(b_txn[0].output[0].script_pubkey.is_v0_p2wpkh()); // direct payment
|
||||||
|
@ -4018,7 +4031,7 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
|
||||||
*nodes[0].network_payment_count.borrow_mut() -= 1;
|
*nodes[0].network_payment_count.borrow_mut() -= 1;
|
||||||
assert_eq!(route_payment(&nodes[0], &vec!(&nodes[1], &nodes[2])[..], 900000).1, duplicate_payment_hash);
|
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().last_local_commitment_txn.clone();
|
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);
|
assert_eq!(commitment_txn[0].input.len(), 1);
|
||||||
check_spends!(commitment_txn[0], chan_2.3.clone());
|
check_spends!(commitment_txn[0], chan_2.3.clone());
|
||||||
|
|
||||||
|
@ -4056,9 +4069,11 @@ fn test_duplicate_payment_hash_one_failure_one_success() {
|
||||||
_ => panic!("Unexepected event"),
|
_ => panic!("Unexepected event"),
|
||||||
}
|
}
|
||||||
let htlc_success_txn: Vec<_> = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
|
let htlc_success_txn: Vec<_> = nodes[2].tx_broadcaster.txn_broadcasted.lock().unwrap().clone();
|
||||||
assert_eq!(htlc_success_txn.len(), 5);
|
assert_eq!(htlc_success_txn.len(), 7);
|
||||||
check_spends!(htlc_success_txn[2], chan_2.3.clone());
|
check_spends!(htlc_success_txn[2], chan_2.3.clone());
|
||||||
assert_eq!(htlc_success_txn[0], htlc_success_txn[3]);
|
check_spends!(htlc_success_txn[3], htlc_success_txn[2]);
|
||||||
|
check_spends!(htlc_success_txn[4], htlc_success_txn[2]);
|
||||||
|
assert_eq!(htlc_success_txn[0], htlc_success_txn[5]);
|
||||||
assert_eq!(htlc_success_txn[0].input.len(), 1);
|
assert_eq!(htlc_success_txn[0].input.len(), 1);
|
||||||
assert_eq!(htlc_success_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
|
assert_eq!(htlc_success_txn[0].input[0].witness.last().unwrap().len(), ACCEPTED_HTLC_SCRIPT_WEIGHT);
|
||||||
assert_eq!(htlc_success_txn[1], htlc_success_txn[4]);
|
assert_eq!(htlc_success_txn[1], htlc_success_txn[4]);
|
||||||
|
@ -4129,7 +4144,7 @@ fn test_dynamic_spendable_outputs_local_htlc_success_tx() {
|
||||||
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
|
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 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().last_local_commitment_txn.clone();
|
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);
|
assert_eq!(local_txn[0].input.len(), 1);
|
||||||
check_spends!(local_txn[0], chan_1.3.clone());
|
check_spends!(local_txn[0], chan_1.3.clone());
|
||||||
|
|
||||||
|
@ -4183,7 +4198,7 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
|
||||||
// Rebalance and check output sanity...
|
// Rebalance and check output sanity...
|
||||||
send_payment(&nodes[0], &[&nodes[2], &nodes[3], &nodes[4]], 500000, 500_000);
|
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);
|
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().last_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;
|
let ds_dust_limit = nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().our_dust_limit_satoshis;
|
||||||
// 0th HTLC:
|
// 0th HTLC:
|
||||||
|
@ -4220,8 +4235,8 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
|
||||||
// Double-check that six of the new HTLC were added
|
// 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,
|
// 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).
|
// 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().last_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().len(), 1);
|
||||||
assert_eq!(nodes[3].node.channel_state.lock().unwrap().by_id.get(&chan.2).unwrap().last_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()[0].output.len(), 8);
|
||||||
|
|
||||||
// Now fail back three of the over-dust-limit and three of the under-dust-limit payments in one go.
|
// 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
|
// Fail 0th below-dust, 4th above-dust, 8th above-dust, 10th below-dust HTLCs
|
||||||
|
@ -4252,7 +4267,7 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
|
||||||
nodes[3].node.handle_update_fail_htlc(&nodes[5].node.get_our_node_id(), &two_removes.update_fail_htlcs[1]).unwrap();
|
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);
|
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().last_local_commitment_txn.clone();
|
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]);
|
expect_pending_htlcs_forwardable!(nodes[3]);
|
||||||
check_added_monitors!(nodes[3], 1);
|
check_added_monitors!(nodes[3], 1);
|
||||||
|
@ -4280,7 +4295,7 @@ fn do_test_fail_backwards_unrevoked_remote_announce(deliver_last_raa: bool, anno
|
||||||
//
|
//
|
||||||
// Alternatively, we may broadcast the previous commitment transaction, which should only
|
// 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.
|
// 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().last_local_commitment_txn.clone();
|
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 };
|
let header = BlockHeader { version: 0x20000000, prev_blockhash: Default::default(), merkle_root: Default::default(), time: 42, bits: 42, nonce: 42 };
|
||||||
if announce_latest {
|
if announce_latest {
|
||||||
|
@ -4417,7 +4432,7 @@ fn test_dynamic_spendable_outputs_local_htlc_timeout_tx() {
|
||||||
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
|
let chan_1 = create_announced_chan_between_nodes(&nodes, 0, 1, LocalFeatures::new(), LocalFeatures::new());
|
||||||
|
|
||||||
route_payment(&nodes[0], &vec!(&nodes[1])[..], 9000000).0;
|
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().last_local_commitment_txn.clone();
|
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);
|
assert_eq!(local_txn[0].input.len(), 1);
|
||||||
check_spends!(local_txn[0], chan_1.3.clone());
|
check_spends!(local_txn[0], chan_1.3.clone());
|
||||||
|
|
||||||
|
@ -5702,7 +5717,7 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) {
|
||||||
route_payment(&nodes[0], &[&nodes[1]], 1000000);
|
route_payment(&nodes[0], &[&nodes[1]], 1000000);
|
||||||
|
|
||||||
// Cache one local commitment tx as previous
|
// 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().last_local_commitment_txn.clone();
|
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
|
// Fail one HTLC to prune it in the will-be-latest-local commitment tx
|
||||||
assert!(nodes[1].node.fail_htlc_backwards(&payment_hash_2));
|
assert!(nodes[1].node.fail_htlc_backwards(&payment_hash_2));
|
||||||
|
@ -5716,7 +5731,7 @@ fn do_test_failure_delay_dust_htlc_local_commitment(announce_latest: bool) {
|
||||||
check_added_monitors!(nodes[0], 1);
|
check_added_monitors!(nodes[0], 1);
|
||||||
|
|
||||||
// Cache one local commitment tx as lastest
|
// 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().last_local_commitment_txn.clone();
|
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();
|
let events = nodes[0].node.get_and_clear_pending_msg_events();
|
||||||
match events[0] {
|
match events[0] {
|
||||||
|
@ -5843,8 +5858,8 @@ fn do_test_sweep_outbound_htlc_failure_update(revoked: bool, local: bool) {
|
||||||
let (_payment_preimage_1, dust_hash) = route_payment(&nodes[0], &[&nodes[1]], bs_dust_limit*1000);
|
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 (_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().last_local_commitment_txn.clone();
|
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(&chan.2).unwrap().last_local_commitment_txn.clone();
|
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
|
// We revoked bs_commitment_tx
|
||||||
if revoked {
|
if revoked {
|
||||||
|
@ -6135,22 +6150,24 @@ fn test_data_loss_protect() {
|
||||||
|
|
||||||
// Restore node A from previous state
|
// Restore node A from previous state
|
||||||
let logger: Arc<Logger> = Arc::new(test_utils::TestLogger::with_id(format!("node {}", 0)));
|
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 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 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 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 monitor = Arc::new(test_utils::TestChannelMonitor::new(chain_monitor.clone(), tx_broadcaster.clone(), logger.clone(), feeest.clone()));
|
||||||
let mut channel_monitors = HashMap::new();
|
let node_state_0 = {
|
||||||
channel_monitors.insert(OutPoint { txid: chan.3.txid(), index: 0 }, &chan_monitor);
|
let mut channel_monitors = HashMap::new();
|
||||||
let node_state_0 = <(Sha256dHash, ChannelManager<EnforcingChannelKeys>)>::read(&mut ::std::io::Cursor::new(previous_node_state), ChannelManagerReadArgs {
|
channel_monitors.insert(OutPoint { txid: chan.3.txid(), index: 0 }, &mut chan_monitor);
|
||||||
keys_manager: Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::clone(&logger))),
|
<(Sha256dHash, ChannelManager<EnforcingChannelKeys>)>::read(&mut ::std::io::Cursor::new(previous_node_state), ChannelManagerReadArgs {
|
||||||
fee_estimator: feeest.clone(),
|
keys_manager: Arc::new(test_utils::TestKeysInterface::new(&nodes[0].node_seed, Network::Testnet, Arc::clone(&logger))),
|
||||||
monitor: monitor.clone(),
|
fee_estimator: feeest.clone(),
|
||||||
logger: Arc::clone(&logger),
|
monitor: monitor.clone(),
|
||||||
tx_broadcaster,
|
logger: Arc::clone(&logger),
|
||||||
default_config: UserConfig::default(),
|
tx_broadcaster,
|
||||||
channel_monitors: &channel_monitors
|
default_config: UserConfig::default(),
|
||||||
}).unwrap().1;
|
channel_monitors: &mut channel_monitors
|
||||||
|
}).unwrap().1
|
||||||
|
};
|
||||||
nodes[0].node = Arc::new(node_state_0);
|
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());
|
assert!(monitor.add_update_monitor(OutPoint { txid: chan.3.txid(), index: 0 }, chan_monitor.clone()).is_ok());
|
||||||
nodes[0].chan_monitor = monitor;
|
nodes[0].chan_monitor = monitor;
|
||||||
|
@ -6342,7 +6359,7 @@ fn test_bump_penalty_txn_on_revoked_commitment() {
|
||||||
let route = nodes[1].router.get_route(&nodes[0].node.get_our_node_id(), None, &Vec::new(), 3000000, 30).unwrap();
|
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);
|
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().last_local_commitment_txn.clone();
|
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
|
// 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].output.len(), 4);
|
||||||
assert_eq!(revoked_txn[0].input.len(), 1);
|
assert_eq!(revoked_txn[0].input.len(), 1);
|
||||||
|
@ -6442,7 +6459,7 @@ fn test_bump_penalty_txn_on_revoked_htlcs() {
|
||||||
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 3_000_000).0;
|
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;
|
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().last_local_commitment_txn.clone();
|
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.len(), 1);
|
||||||
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
|
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
|
||||||
|
|
||||||
|
@ -6586,7 +6603,7 @@ fn test_bump_penalty_txn_on_remote_commitment() {
|
||||||
route_payment(&nodes[1], &vec!(&nodes[0])[..], 3000000).0;
|
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
|
// 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().last_local_commitment_txn.clone();
|
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].output.len(), 4);
|
||||||
assert_eq!(remote_txn[0].input.len(), 1);
|
assert_eq!(remote_txn[0].input.len(), 1);
|
||||||
assert_eq!(remote_txn[0].input[0].previous_output.txid, chan.3.txid());
|
assert_eq!(remote_txn[0].input[0].previous_output.txid, chan.3.txid());
|
||||||
|
@ -6604,13 +6621,16 @@ fn test_bump_penalty_txn_on_remote_commitment() {
|
||||||
let feerate_preimage;
|
let feerate_preimage;
|
||||||
{
|
{
|
||||||
let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
|
let mut node_txn = nodes[1].tx_broadcaster.txn_broadcasted.lock().unwrap();
|
||||||
assert_eq!(node_txn.len(), 6); // 2 * claim tx (broadcasted from ChannelMonitor) * 2 (block-reparsing) + local commitment tx + local HTLC-timeout (broadcasted from ChannelManager)
|
assert_eq!(node_txn.len(), 7); // 2 * claim tx (broadcasted from ChannelMonitor) * 2 (block-reparsing) + local commitment tx + local HTLC-timeout + HTLC-success (broadcasted from ChannelManager)
|
||||||
assert_eq!(node_txn[0], node_txn[4]);
|
assert_eq!(node_txn[0], node_txn[5]);
|
||||||
assert_eq!(node_txn[1], node_txn[5]);
|
assert_eq!(node_txn[1], node_txn[6]);
|
||||||
assert_eq!(node_txn[0].input.len(), 1);
|
assert_eq!(node_txn[0].input.len(), 1);
|
||||||
assert_eq!(node_txn[1].input.len(), 1);
|
assert_eq!(node_txn[1].input.len(), 1);
|
||||||
check_spends!(node_txn[0], remote_txn[0].clone());
|
check_spends!(node_txn[0], remote_txn[0].clone());
|
||||||
check_spends!(node_txn[1], remote_txn[0].clone());
|
check_spends!(node_txn[1], remote_txn[0].clone());
|
||||||
|
check_spends!(node_txn[2], chan.3);
|
||||||
|
check_spends!(node_txn[3], node_txn[2]);
|
||||||
|
check_spends!(node_txn[4], node_txn[2]);
|
||||||
if node_txn[0].input[0].witness.last().unwrap().len() == ACCEPTED_HTLC_SCRIPT_WEIGHT {
|
if node_txn[0].input[0].witness.last().unwrap().len() == ACCEPTED_HTLC_SCRIPT_WEIGHT {
|
||||||
timeout = node_txn[0].txid();
|
timeout = node_txn[0].txid();
|
||||||
let index = node_txn[0].input[0].previous_output.vout;
|
let index = node_txn[0].input[0].previous_output.vout;
|
||||||
|
@ -6690,10 +6710,13 @@ fn test_set_outpoints_partial_claiming() {
|
||||||
let payment_preimage_2 = route_payment(&nodes[1], &vec!(&nodes[0])[..], 3_000_000).0;
|
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
|
// 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().last_local_commitment_txn.clone();
|
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].output.len(), 4);
|
||||||
assert_eq!(remote_txn[0].input.len(), 1);
|
assert_eq!(remote_txn[0].input.len(), 1);
|
||||||
assert_eq!(remote_txn[0].input[0].previous_output.txid, chan.3.txid());
|
assert_eq!(remote_txn[0].input[0].previous_output.txid, chan.3.txid());
|
||||||
|
check_spends!(remote_txn[1], remote_txn[0].clone());
|
||||||
|
check_spends!(remote_txn[2], remote_txn[0].clone());
|
||||||
|
|
||||||
// Connect blocks on node A to advance height towards TEST_FINAL_CLTV
|
// Connect blocks on node A to advance height towards TEST_FINAL_CLTV
|
||||||
let prev_header_100 = connect_blocks(&nodes[1].block_notifier, 100, 0, false, Default::default());
|
let prev_header_100 = connect_blocks(&nodes[1].block_notifier, 100, 0, false, Default::default());
|
||||||
|
@ -6710,8 +6733,12 @@ fn test_set_outpoints_partial_claiming() {
|
||||||
// Verify node A broadcast tx claiming both HTLCs
|
// Verify node A broadcast tx claiming both HTLCs
|
||||||
{
|
{
|
||||||
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
|
let mut node_txn = nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap();
|
||||||
assert_eq!(node_txn.len(), 3);
|
assert_eq!(node_txn.len(), 5);
|
||||||
|
assert_eq!(node_txn[0], node_txn[4]);
|
||||||
check_spends!(node_txn[0], remote_txn[0].clone());
|
check_spends!(node_txn[0], remote_txn[0].clone());
|
||||||
|
check_spends!(node_txn[1], chan.3.clone());
|
||||||
|
check_spends!(node_txn[2], node_txn[1]);
|
||||||
|
check_spends!(node_txn[3], node_txn[1]);
|
||||||
assert_eq!(node_txn[0].input.len(), 2);
|
assert_eq!(node_txn[0].input.len(), 2);
|
||||||
node_txn.clear();
|
node_txn.clear();
|
||||||
}
|
}
|
||||||
|
@ -6775,7 +6802,7 @@ fn test_bump_txn_sanitize_tracking_maps() {
|
||||||
let payment_preimage = route_payment(&nodes[0], &vec!(&nodes[1])[..], 9_000_000).0;
|
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;
|
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().last_local_commitment_txn.clone();
|
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.len(), 1);
|
||||||
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
|
assert_eq!(revoked_local_txn[0].input[0].previous_output.txid, chan.3.txid());
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue