X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fchain%2Fpackage.rs;h=866ff66b48fd6d95ddc8f470782984138e2b435e;hb=40b1d4f027c8827f057d77abbc4f3b46b1b67abd;hp=a2922d27d2914add018053cdcb970c3954b9d982;hpb=519ec902aa62aaa83eb5c6a513f63bc7035a8c61;p=rust-lightning diff --git a/lightning/src/chain/package.rs b/lightning/src/chain/package.rs index a2922d27..866ff66b 100644 --- a/lightning/src/chain/package.rs +++ b/lightning/src/chain/package.rs @@ -286,18 +286,29 @@ impl_writeable_tlv_based!(HolderHTLCOutput, { #[derive(Clone, PartialEq, Eq)] pub(crate) struct HolderFundingOutput { funding_redeemscript: Script, + funding_amount: Option, + opt_anchors: Option<()>, } + impl HolderFundingOutput { - pub(crate) fn build(funding_redeemscript: Script) -> Self { + pub(crate) fn build(funding_redeemscript: Script, funding_amount: u64, opt_anchors: bool) -> Self { HolderFundingOutput { funding_redeemscript, + funding_amount: Some(funding_amount), + opt_anchors: if opt_anchors { Some(()) } else { None }, } } + + fn opt_anchors(&self) -> bool { + self.opt_anchors.is_some() + } } impl_writeable_tlv_based!(HolderFundingOutput, { (0, funding_redeemscript, required), + (1, opt_anchors, option), + (3, funding_amount, option), }); /// A wrapper encapsulating all in-protocol differing outputs types. @@ -317,15 +328,18 @@ pub(crate) enum PackageSolvingData { impl PackageSolvingData { fn amount(&self) -> u64 { let amt = match self { - PackageSolvingData::RevokedOutput(ref outp) => { outp.amount }, - PackageSolvingData::RevokedHTLCOutput(ref outp) => { outp.amount }, - PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => { outp.htlc.amount_msat / 1000 }, - PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => { outp.htlc.amount_msat / 1000 }, + PackageSolvingData::RevokedOutput(ref outp) => outp.amount, + PackageSolvingData::RevokedHTLCOutput(ref outp) => outp.amount, + PackageSolvingData::CounterpartyOfferedHTLCOutput(ref outp) => outp.htlc.amount_msat / 1000, + PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => outp.htlc.amount_msat / 1000, // Note: Currently, amounts of holder outputs spending witnesses aren't used // as we can't malleate spending package to increase their feerate. This // should change with the remaining anchor output patchset. - PackageSolvingData::HolderHTLCOutput(..) => { unreachable!() }, - PackageSolvingData::HolderFundingOutput(..) => { unreachable!() }, + PackageSolvingData::HolderHTLCOutput(..) => unreachable!(), + PackageSolvingData::HolderFundingOutput(ref outp) => { + debug_assert!(outp.opt_anchors()); + outp.funding_amount.unwrap() + } }; amt } @@ -622,47 +636,46 @@ impl PackageTemplate { let output_weight = (8 + 1 + destination_script.len()) * WITNESS_SCALE_FACTOR; inputs_weight + witnesses_weight + transaction_weight + output_weight } - pub(crate) fn finalize_package(&self, onchain_handler: &mut OnchainTxHandler, value: u64, destination_script: Script, logger: &L) -> Option - where L::Target: Logger, - { - match self.malleability { - PackageMalleability::Malleable => { - let mut bumped_tx = Transaction { - version: 2, - lock_time: PackedLockTime::ZERO, - input: vec![], - output: vec![TxOut { - script_pubkey: destination_script, - value, - }], - }; - for (outpoint, _) in self.inputs.iter() { - bumped_tx.input.push(TxIn { - previous_output: *outpoint, - script_sig: Script::new(), - sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, - witness: Witness::new(), - }); - } - for (i, (outpoint, out)) in self.inputs.iter().enumerate() { - log_debug!(logger, "Adding claiming input for outpoint {}:{}", outpoint.txid, outpoint.vout); - if !out.finalize_input(&mut bumped_tx, i, onchain_handler) { return None; } - } - log_debug!(logger, "Finalized transaction {} ready to broadcast", bumped_tx.txid()); - return Some(bumped_tx); - }, - PackageMalleability::Untractable => { - debug_assert_eq!(value, 0, "value is ignored for non-malleable packages, should be zero to ensure callsites are correct"); - if let Some((outpoint, outp)) = self.inputs.first() { - if let Some(final_tx) = outp.get_finalized_tx(outpoint, onchain_handler) { - log_debug!(logger, "Adding claiming input for outpoint {}:{}", outpoint.txid, outpoint.vout); - log_debug!(logger, "Finalized transaction {} ready to broadcast", final_tx.txid()); - return Some(final_tx); - } - return None; - } else { panic!("API Error: Package must not be inputs empty"); } - }, + pub(crate) fn finalize_malleable_package( + &self, onchain_handler: &mut OnchainTxHandler, value: u64, destination_script: Script, logger: &L, + ) -> Option where L::Target: Logger { + debug_assert!(self.is_malleable()); + let mut bumped_tx = Transaction { + version: 2, + lock_time: PackedLockTime::ZERO, + input: vec![], + output: vec![TxOut { + script_pubkey: destination_script, + value, + }], + }; + for (outpoint, _) in self.inputs.iter() { + bumped_tx.input.push(TxIn { + previous_output: *outpoint, + script_sig: Script::new(), + sequence: Sequence::ENABLE_RBF_NO_LOCKTIME, + witness: Witness::new(), + }); + } + for (i, (outpoint, out)) in self.inputs.iter().enumerate() { + log_debug!(logger, "Adding claiming input for outpoint {}:{}", outpoint.txid, outpoint.vout); + if !out.finalize_input(&mut bumped_tx, i, onchain_handler) { return None; } } + log_debug!(logger, "Finalized transaction {} ready to broadcast", bumped_tx.txid()); + Some(bumped_tx) + } + pub(crate) fn finalize_untractable_package( + &self, onchain_handler: &mut OnchainTxHandler, logger: &L, + ) -> Option where L::Target: Logger { + debug_assert!(!self.is_malleable()); + if let Some((outpoint, outp)) = self.inputs.first() { + if let Some(final_tx) = outp.get_finalized_tx(outpoint, onchain_handler) { + log_debug!(logger, "Adding claiming input for outpoint {}:{}", outpoint.txid, outpoint.vout); + log_debug!(logger, "Finalized transaction {} ready to broadcast", final_tx.txid()); + return Some(final_tx); + } + return None; + } else { panic!("API Error: Package must not be inputs empty"); } } /// In LN, output claimed are time-sensitive, which means we have to spend them before reaching some timelock expiration. At in-channel /// output detection, we generate a first version of a claim tx and associate to it a height timer. A height timer is an absolute block