+/// Gets the witnessScript for the to_remote output when anchors are enabled.
+#[inline]
+pub fn get_to_countersignatory_with_anchors_redeemscript(payment_point: &PublicKey) -> Script {
+ Builder::new()
+ .push_slice(&payment_point.serialize()[..])
+ .push_opcode(opcodes::all::OP_CHECKSIGVERIFY)
+ .push_int(1)
+ .push_opcode(opcodes::all::OP_CSV)
+ .into_script()
+}
+
+/// Gets the witnessScript for an anchor output from the funding public key.
+/// The witness in the spending input must be:
+/// <BIP 143 funding_signature>
+/// After 16 blocks of confirmation, an alternative satisfying witness could be:
+/// <>
+/// (empty vector required to satisfy compliance with MINIMALIF-standard rule)
+#[inline]
+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)
+ .push_opcode(opcodes::all::OP_NOTIF)
+ .push_int(16)
+ .push_opcode(opcodes::all::OP_CSV)
+ .push_opcode(opcodes::all::OP_ENDIF)
+ .into_script()
+}
+
+#[cfg(anchors)]
+/// Locates the output with an anchor script paying to `funding_pubkey` within `commitment_tx`.
+pub(crate) fn get_anchor_output<'a>(commitment_tx: &'a Transaction, funding_pubkey: &PublicKey) -> Option<(u32, &'a TxOut)> {
+ let anchor_script = chan_utils::get_anchor_redeemscript(funding_pubkey).to_v0_p2wsh();
+ commitment_tx.output.iter().enumerate()
+ .find(|(_, txout)| txout.script_pubkey == anchor_script)
+ .map(|(idx, txout)| (idx as u32, txout))
+}
+
+/// Returns the witness required to satisfy and spend an anchor input.
+pub fn build_anchor_input_witness(funding_key: &PublicKey, funding_sig: &Signature) -> Witness {
+ let anchor_redeem_script = chan_utils::get_anchor_redeemscript(funding_key);
+ let mut ret = Witness::new();
+ ret.push_bitcoin_signature(&funding_sig.serialize_der(), EcdsaSighashType::All);
+ ret.push(anchor_redeem_script.as_bytes());
+ ret
+}
+
+/// Per-channel data used to build transactions in conjunction with the per-commitment data (CommitmentTransaction).
+/// The fields are organized by holder/counterparty.
+///
+/// Normally, this is converted to the broadcaster/countersignatory-organized DirectedChannelTransactionParameters
+/// before use, via the as_holder_broadcastable and as_counterparty_broadcastable functions.
+#[derive(Clone, Debug, PartialEq)]
+pub struct ChannelTransactionParameters {
+ /// Holder public keys
+ pub holder_pubkeys: ChannelPublicKeys,
+ /// The contest delay selected by the holder, which applies to counterparty-broadcast transactions
+ pub holder_selected_contest_delay: u16,
+ /// Whether the holder is the initiator of this channel.
+ /// This is an input to the commitment number obscure factor computation.
+ pub is_outbound_from_holder: bool,
+ /// The late-bound counterparty channel transaction parameters.
+ /// These parameters are populated at the point in the protocol where the counterparty provides them.
+ pub counterparty_parameters: Option<CounterpartyChannelTransactionParameters>,
+ /// The late-bound funding outpoint
+ pub funding_outpoint: Option<chain::transaction::OutPoint>,
+ /// Are anchors (zero fee HTLC transaction variant) used for this channel. Boolean is
+ /// serialization backwards-compatible.
+ pub opt_anchors: Option<()>,
+ /// Are non-zero-fee anchors are enabled (used in conjuction with opt_anchors)
+ /// It is intended merely for backwards compatibility with signers that need it.
+ /// There is no support for this feature in LDK channel negotiation.
+ pub opt_non_zero_fee_anchors: Option<()>,
+}
+
+/// Late-bound per-channel counterparty data used to build transactions.
+#[derive(Clone, Debug, PartialEq)]
+pub struct CounterpartyChannelTransactionParameters {
+ /// Counter-party public keys
+ pub pubkeys: ChannelPublicKeys,
+ /// The contest delay selected by the counterparty, which applies to holder-broadcast transactions
+ pub selected_contest_delay: u16,
+}
+
+impl ChannelTransactionParameters {
+ /// Whether the late bound parameters are populated.
+ pub fn is_populated(&self) -> bool {
+ self.counterparty_parameters.is_some() && self.funding_outpoint.is_some()
+ }
+
+ /// Convert the holder/counterparty parameters to broadcaster/countersignatory-organized parameters,
+ /// given that the holder is the broadcaster.
+ ///
+ /// self.is_populated() must be true before calling this function.
+ pub fn as_holder_broadcastable(&self) -> DirectedChannelTransactionParameters {
+ assert!(self.is_populated(), "self.late_parameters must be set before using as_holder_broadcastable");
+ DirectedChannelTransactionParameters {
+ inner: self,
+ holder_is_broadcaster: true
+ }
+ }
+
+ /// Convert the holder/counterparty parameters to broadcaster/countersignatory-organized parameters,
+ /// given that the counterparty is the broadcaster.
+ ///
+ /// self.is_populated() must be true before calling this function.
+ pub fn as_counterparty_broadcastable(&self) -> DirectedChannelTransactionParameters {
+ assert!(self.is_populated(), "self.late_parameters must be set before using as_counterparty_broadcastable");
+ DirectedChannelTransactionParameters {
+ inner: self,
+ holder_is_broadcaster: false
+ }
+ }
+}
+
+impl_writeable_tlv_based!(CounterpartyChannelTransactionParameters, {
+ (0, pubkeys, required),
+ (2, selected_contest_delay, required),
+});
+
+impl_writeable_tlv_based!(ChannelTransactionParameters, {
+ (0, holder_pubkeys, required),
+ (2, holder_selected_contest_delay, required),
+ (4, is_outbound_from_holder, required),
+ (6, counterparty_parameters, option),
+ (8, funding_outpoint, option),
+ (10, opt_anchors, option),
+ (12, opt_non_zero_fee_anchors, option),
+});
+
+/// Static channel fields used to build transactions given per-commitment fields, organized by
+/// broadcaster/countersignatory.
+///
+/// This is derived from the holder/counterparty-organized ChannelTransactionParameters via the
+/// as_holder_broadcastable and as_counterparty_broadcastable functions.
+pub struct DirectedChannelTransactionParameters<'a> {
+ /// The holder's channel static parameters
+ inner: &'a ChannelTransactionParameters,
+ /// Whether the holder is the broadcaster
+ holder_is_broadcaster: bool,
+}
+
+impl<'a> DirectedChannelTransactionParameters<'a> {
+ /// Get the channel pubkeys for the broadcaster
+ pub fn broadcaster_pubkeys(&self) -> &ChannelPublicKeys {
+ if self.holder_is_broadcaster {
+ &self.inner.holder_pubkeys
+ } else {
+ &self.inner.counterparty_parameters.as_ref().unwrap().pubkeys
+ }
+ }
+
+ /// Get the channel pubkeys for the countersignatory
+ pub fn countersignatory_pubkeys(&self) -> &ChannelPublicKeys {
+ if self.holder_is_broadcaster {
+ &self.inner.counterparty_parameters.as_ref().unwrap().pubkeys
+ } else {
+ &self.inner.holder_pubkeys
+ }
+ }
+
+ /// Get the contest delay applicable to the transactions.
+ /// Note that the contest delay was selected by the countersignatory.
+ pub fn contest_delay(&self) -> u16 {
+ let counterparty_parameters = self.inner.counterparty_parameters.as_ref().unwrap();
+ if self.holder_is_broadcaster { counterparty_parameters.selected_contest_delay } else { self.inner.holder_selected_contest_delay }
+ }
+
+ /// Whether the channel is outbound from the broadcaster.
+ ///
+ /// The boolean representing the side that initiated the channel is
+ /// an input to the commitment number obscure factor computation.
+ pub fn is_outbound(&self) -> bool {
+ if self.holder_is_broadcaster { self.inner.is_outbound_from_holder } else { !self.inner.is_outbound_from_holder }
+ }
+
+ /// The funding outpoint
+ 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.
+///
+/// The transaction is only signed once we are ready to broadcast.