X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fchan_utils.rs;h=cbafbed67bdf20a7e093f97b5531ace7c8452f26;hb=e88c7210f81d5c09d9f60f7f9d6946de4f18146f;hp=80dd872a9de9cec9e6e3277cf0ccab8c4b2d9705;hpb=3efcbab5d42d5c2cd7d37ce18a8bcca211569bb8;p=rust-lightning diff --git a/lightning/src/ln/chan_utils.rs b/lightning/src/ln/chan_utils.rs index 80dd872a..cbafbed6 100644 --- a/lightning/src/ln/chan_utils.rs +++ b/lightning/src/ln/chan_utils.rs @@ -45,6 +45,20 @@ pub(crate) const MAX_HTLCS: u16 = 483; pub(super) const HTLC_SUCCESS_TX_WEIGHT: u64 = 703; pub(super) const HTLC_TIMEOUT_TX_WEIGHT: u64 = 663; +/// Gets the weight for an HTLC-Success transaction. +#[inline] +pub fn htlc_success_tx_weight(opt_anchors: bool) -> u64 { + const HTLC_SUCCESS_ANCHOR_TX_WEIGHT: u64 = 706; + if opt_anchors { HTLC_SUCCESS_ANCHOR_TX_WEIGHT } else { HTLC_SUCCESS_TX_WEIGHT } +} + +/// Gets the weight for an HTLC-Timeout transaction. +#[inline] +pub fn htlc_timeout_tx_weight(opt_anchors: bool) -> u64 { + const HTLC_TIMEOUT_ANCHOR_TX_WEIGHT: u64 = 666; + if opt_anchors { HTLC_TIMEOUT_ANCHOR_TX_WEIGHT } else { HTLC_TIMEOUT_TX_WEIGHT } +} + #[derive(PartialEq)] pub(crate) enum HTLCType { AcceptedHTLC, @@ -586,7 +600,7 @@ pub fn make_funding_redeemscript(broadcaster: &PublicKey, countersignatory: &Pub /// /// Panics if htlc.transaction_output_index.is_none() (as such HTLCs do not appear in the /// commitment transaction). -pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, broadcaster_delayed_payment_key: &PublicKey, revocation_key: &PublicKey) -> Transaction { +pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, contest_delay: u16, htlc: &HTLCOutputInCommitment, opt_anchors: bool, broadcaster_delayed_payment_key: &PublicKey, revocation_key: &PublicKey) -> Transaction { let mut txins: Vec = Vec::new(); txins.push(TxIn { previous_output: OutPoint { @@ -594,15 +608,16 @@ pub fn build_htlc_transaction(commitment_txid: &Txid, feerate_per_kw: u32, conte vout: htlc.transaction_output_index.expect("Can't build an HTLC transaction for a dust output"), }, script_sig: Script::new(), - sequence: 0, + sequence: if opt_anchors { 1 } else { 0 }, witness: Vec::new(), }); - let total_fee = if htlc.offered { - feerate_per_kw as u64 * HTLC_TIMEOUT_TX_WEIGHT / 1000 - } else { - feerate_per_kw as u64 * HTLC_SUCCESS_TX_WEIGHT / 1000 - }; + let weight = if htlc.offered { + htlc_timeout_tx_weight(opt_anchors) + } else { + htlc_success_tx_weight(opt_anchors) + }; + let total_fee = feerate_per_kw as u64 * weight / 1000; let mut txouts: Vec = Vec::new(); txouts.push(TxOut { @@ -636,7 +651,7 @@ pub(crate) fn get_to_countersignatory_with_anchors_redeemscript(payment_point: & /// <> /// (empty vector required to satisfy compliance with MINIMALIF-standard rule) #[inline] -pub(crate) fn get_anchor_redeemscript(funding_pubkey: &PublicKey) -> Script { +pub fn get_anchor_redeemscript(funding_pubkey: &PublicKey) -> Script { Builder::new().push_slice(&funding_pubkey.serialize()[..]) .push_opcode(opcodes::all::OP_CHECKSIG) .push_opcode(opcodes::all::OP_IFDUP) @@ -774,6 +789,11 @@ impl<'a> DirectedChannelTransactionParameters<'a> { pub fn funding_outpoint(&self) -> OutPoint { self.inner.funding_outpoint.unwrap().into_bitcoin_outpoint() } + + /// Whether to use anchors for this channel + pub fn opt_anchors(&self) -> bool { + self.inner.opt_anchors.is_some() + } } /// Information needed to build and sign a holder's commitment transaction. @@ -920,6 +940,7 @@ impl BuiltCommitmentTransaction { /// /// This class can be used inside a signer implementation to generate a signature given the relevant /// secret key. +#[derive(Clone, Hash, PartialEq)] pub struct ClosingTransaction { to_holder_value_sat: u64, to_counterparty_value_sat: u64, @@ -1382,7 +1403,7 @@ impl<'a> TrustedCommitmentTransaction<'a> { for this_htlc in inner.htlcs.iter() { assert!(this_htlc.transaction_output_index.is_some()); - let htlc_tx = build_htlc_transaction(&txid, inner.feerate_per_kw, channel_parameters.contest_delay(), &this_htlc, &keys.broadcaster_delayed_payment_key, &keys.revocation_key); + let htlc_tx = build_htlc_transaction(&txid, inner.feerate_per_kw, channel_parameters.contest_delay(), &this_htlc, self.opt_anchors(), &keys.broadcaster_delayed_payment_key, &keys.revocation_key); let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc, self.opt_anchors(), &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key); @@ -1404,7 +1425,7 @@ impl<'a> TrustedCommitmentTransaction<'a> { // Further, we should never be provided the preimage for an HTLC-Timeout transaction. if this_htlc.offered && preimage.is_some() { unreachable!(); } - let mut htlc_tx = build_htlc_transaction(&txid, inner.feerate_per_kw, channel_parameters.contest_delay(), &this_htlc, &keys.broadcaster_delayed_payment_key, &keys.revocation_key); + let mut htlc_tx = build_htlc_transaction(&txid, inner.feerate_per_kw, channel_parameters.contest_delay(), &this_htlc, self.opt_anchors(), &keys.broadcaster_delayed_payment_key, &keys.revocation_key); let htlc_redeemscript = get_htlc_redeemscript_with_explicit_keys(&this_htlc, self.opt_anchors(), &keys.broadcaster_htlc_key, &keys.countersignatory_htlc_key, &keys.revocation_key); @@ -1475,6 +1496,7 @@ mod tests { use chain::keysinterface::{KeysInterface, BaseSign}; use bitcoin::Network; use ln::PaymentHash; + use bitcoin::hashes::hex::ToHex; #[test] fn test_anchors() { @@ -1578,6 +1600,10 @@ mod tests { assert_eq!(tx.built.transaction.output.len(), 3); assert_eq!(tx.built.transaction.output[0].script_pubkey, get_htlc_redeemscript(&received_htlc, false, &keys).to_v0_p2wsh()); assert_eq!(tx.built.transaction.output[1].script_pubkey, get_htlc_redeemscript(&offered_htlc, false, &keys).to_v0_p2wsh()); + assert_eq!(get_htlc_redeemscript(&received_htlc, false, &keys).to_v0_p2wsh().to_hex(), + "002085cf52e41ba7c099a39df504e7b61f6de122971ceb53b06731876eaeb85e8dc5"); + assert_eq!(get_htlc_redeemscript(&offered_htlc, false, &keys).to_v0_p2wsh().to_hex(), + "002049f0736bb335c61a04d2623a24df878a7592a3c51fa7258d41b2c85318265e73"); // Generate broadcaster output and received and offered HTLC outputs, with anchors channel_parameters.opt_anchors = Some(()); @@ -1593,6 +1619,10 @@ mod tests { assert_eq!(tx.built.transaction.output.len(), 5); assert_eq!(tx.built.transaction.output[2].script_pubkey, get_htlc_redeemscript(&received_htlc, true, &keys).to_v0_p2wsh()); assert_eq!(tx.built.transaction.output[3].script_pubkey, get_htlc_redeemscript(&offered_htlc, true, &keys).to_v0_p2wsh()); + assert_eq!(get_htlc_redeemscript(&received_htlc, true, &keys).to_v0_p2wsh().to_hex(), + "002067114123af3f95405bae4fd930fc95de03e3c86baaee8b2dd29b43dd26cf613c"); + assert_eq!(get_htlc_redeemscript(&offered_htlc, true, &keys).to_v0_p2wsh().to_hex(), + "0020a06e3b0d4fcf704f2b9c41e16a70099e39989466c3142b8573a1154542f28f57"); } #[test]