+ inner: commitment_tx,
+ counterparty_sig,
+ counterparty_htlc_sigs,
+ holder_sig_first: holder_funding_key.serialize()[..] < counterparty_funding_key.serialize()[..],
+ }
+ }
+
+ pub(crate) fn add_holder_sig(&self, funding_redeemscript: &Script, holder_sig: Signature) -> Transaction {
+ // First push the multisig dummy, note that due to BIP147 (NULLDUMMY) it must be a zero-length element.
+ let mut tx = self.inner.built.transaction.clone();
+ tx.input[0].witness.push(Vec::new());
+
+ if self.holder_sig_first {
+ tx.input[0].witness.push_bitcoin_signature(&holder_sig.serialize_der(), EcdsaSighashType::All);
+ tx.input[0].witness.push_bitcoin_signature(&self.counterparty_sig.serialize_der(), EcdsaSighashType::All);
+ } else {
+ tx.input[0].witness.push_bitcoin_signature(&self.counterparty_sig.serialize_der(), EcdsaSighashType::All);
+ tx.input[0].witness.push_bitcoin_signature(&holder_sig.serialize_der(), EcdsaSighashType::All);
+ }
+
+ tx.input[0].witness.push(funding_redeemscript.as_bytes().to_vec());
+ tx
+ }
+}
+
+/// A pre-built Bitcoin commitment transaction and its txid.
+#[derive(Clone, Debug)]
+pub struct BuiltCommitmentTransaction {
+ /// The commitment transaction
+ pub transaction: Transaction,
+ /// The txid for the commitment transaction.
+ ///
+ /// This is provided as a performance optimization, instead of calling transaction.txid()
+ /// multiple times.
+ pub txid: Txid,
+}
+
+impl_writeable_tlv_based!(BuiltCommitmentTransaction, {
+ (0, transaction, required),
+ (2, txid, required),
+});
+
+impl BuiltCommitmentTransaction {
+ /// Get the SIGHASH_ALL sighash value of the transaction.
+ ///
+ /// This can be used to verify a signature.
+ pub fn get_sighash_all(&self, funding_redeemscript: &Script, channel_value_satoshis: u64) -> Message {
+ let sighash = &sighash::SighashCache::new(&self.transaction).segwit_signature_hash(0, funding_redeemscript, channel_value_satoshis, EcdsaSighashType::All).unwrap()[..];
+ hash_to_message!(sighash)
+ }
+
+ /// Signs the counterparty's commitment transaction.
+ pub fn sign_counterparty_commitment<T: secp256k1::Signing>(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) -> Signature {
+ let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis);
+ sign(secp_ctx, &sighash, funding_key)
+ }
+
+ /// Signs the holder commitment transaction because we are about to broadcast it.
+ pub fn sign_holder_commitment<T: secp256k1::Signing, ES: Deref>(
+ &self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64,
+ entropy_source: &ES, secp_ctx: &Secp256k1<T>
+ ) -> Signature where ES::Target: EntropySource {
+ let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis);
+ sign_with_aux_rand(secp_ctx, &sighash, funding_key, entropy_source)
+ }
+}
+
+/// This class tracks the per-transaction information needed to build a closing transaction and will
+/// actually build it and sign.
+///
+/// This class can be used inside a signer implementation to generate a signature given the relevant
+/// secret key.
+#[derive(Clone, Hash, PartialEq, Eq)]
+pub struct ClosingTransaction {
+ to_holder_value_sat: u64,
+ to_counterparty_value_sat: u64,
+ to_holder_script: Script,
+ to_counterparty_script: Script,
+ built: Transaction,
+}
+
+impl ClosingTransaction {
+ /// Construct an object of the class
+ pub fn new(
+ to_holder_value_sat: u64,
+ to_counterparty_value_sat: u64,
+ to_holder_script: Script,
+ to_counterparty_script: Script,
+ funding_outpoint: OutPoint,
+ ) -> Self {
+ let built = build_closing_transaction(
+ to_holder_value_sat, to_counterparty_value_sat,
+ to_holder_script.clone(), to_counterparty_script.clone(),
+ funding_outpoint
+ );
+ ClosingTransaction {
+ to_holder_value_sat,
+ to_counterparty_value_sat,
+ to_holder_script,
+ to_counterparty_script,
+ built
+ }
+ }
+
+ /// Trust our pre-built transaction.
+ ///
+ /// Applies a wrapper which allows access to the transaction.
+ ///
+ /// This should only be used if you fully trust the builder of this object. It should not
+ /// be used by an external signer - instead use the verify function.
+ pub fn trust(&self) -> TrustedClosingTransaction {
+ TrustedClosingTransaction { inner: self }
+ }
+
+ /// Verify our pre-built transaction.
+ ///
+ /// Applies a wrapper which allows access to the transaction.
+ ///
+ /// An external validating signer must call this method before signing
+ /// or using the built transaction.
+ pub fn verify(&self, funding_outpoint: OutPoint) -> Result<TrustedClosingTransaction, ()> {
+ let built = build_closing_transaction(
+ self.to_holder_value_sat, self.to_counterparty_value_sat,
+ self.to_holder_script.clone(), self.to_counterparty_script.clone(),
+ funding_outpoint
+ );
+ if self.built != built {
+ return Err(())
+ }
+ Ok(TrustedClosingTransaction { inner: self })
+ }
+
+ /// The value to be sent to the holder, or zero if the output will be omitted
+ pub fn to_holder_value_sat(&self) -> u64 {
+ self.to_holder_value_sat
+ }
+
+ /// The value to be sent to the counterparty, or zero if the output will be omitted
+ pub fn to_counterparty_value_sat(&self) -> u64 {
+ self.to_counterparty_value_sat
+ }
+
+ /// The destination of the holder's output
+ pub fn to_holder_script(&self) -> &Script {
+ &self.to_holder_script
+ }
+
+ /// The destination of the counterparty's output
+ pub fn to_counterparty_script(&self) -> &Script {
+ &self.to_counterparty_script
+ }
+}
+
+/// A wrapper on ClosingTransaction indicating that the built bitcoin
+/// transaction is trusted.
+///
+/// See trust() and verify() functions on CommitmentTransaction.
+///
+/// This structure implements Deref.
+pub struct TrustedClosingTransaction<'a> {
+ inner: &'a ClosingTransaction,
+}
+
+impl<'a> Deref for TrustedClosingTransaction<'a> {
+ type Target = ClosingTransaction;
+
+ fn deref(&self) -> &Self::Target { self.inner }
+}
+
+impl<'a> TrustedClosingTransaction<'a> {
+ /// The pre-built Bitcoin commitment transaction
+ pub fn built_transaction(&self) -> &'a Transaction {
+ &self.inner.built
+ }
+
+ /// Get the SIGHASH_ALL sighash value of the transaction.
+ ///
+ /// This can be used to verify a signature.
+ pub fn get_sighash_all(&self, funding_redeemscript: &Script, channel_value_satoshis: u64) -> Message {
+ let sighash = &sighash::SighashCache::new(&self.inner.built).segwit_signature_hash(0, funding_redeemscript, channel_value_satoshis, EcdsaSighashType::All).unwrap()[..];
+ hash_to_message!(sighash)
+ }
+
+ /// Sign a transaction, either because we are counter-signing the counterparty's transaction or
+ /// because we are about to broadcast a holder transaction.
+ pub fn sign<T: secp256k1::Signing>(&self, funding_key: &SecretKey, funding_redeemscript: &Script, channel_value_satoshis: u64, secp_ctx: &Secp256k1<T>) -> Signature {
+ let sighash = self.get_sighash_all(funding_redeemscript, channel_value_satoshis);
+ sign(secp_ctx, &sighash, funding_key)
+ }
+}
+
+/// This class tracks the per-transaction information needed to build a commitment transaction and will
+/// actually build it and sign. It is used for holder transactions that we sign only when needed
+/// and for transactions we sign for the counterparty.
+///
+/// This class can be used inside a signer implementation to generate a signature given the relevant
+/// secret key.
+#[derive(Clone, Debug)]
+pub struct CommitmentTransaction {
+ commitment_number: u64,
+ to_broadcaster_value_sat: u64,
+ to_countersignatory_value_sat: u64,
+ to_broadcaster_delay: Option<u16>, // Added in 0.0.117
+ feerate_per_kw: u32,
+ htlcs: Vec<HTLCOutputInCommitment>,
+ // Note that on upgrades, some features of existing outputs may be missed.
+ channel_type_features: ChannelTypeFeatures,
+ // A cache of the parties' pubkeys required to construct the transaction, see doc for trust()
+ keys: TxCreationKeys,
+ // For access to the pre-built transaction, see doc for trust()
+ built: BuiltCommitmentTransaction,
+}
+
+impl Eq for CommitmentTransaction {}
+impl PartialEq for CommitmentTransaction {
+ fn eq(&self, o: &Self) -> bool {
+ let eq = self.commitment_number == o.commitment_number &&
+ self.to_broadcaster_value_sat == o.to_broadcaster_value_sat &&
+ self.to_countersignatory_value_sat == o.to_countersignatory_value_sat &&
+ self.feerate_per_kw == o.feerate_per_kw &&
+ self.htlcs == o.htlcs &&
+ self.channel_type_features == o.channel_type_features &&
+ self.keys == o.keys;
+ if eq {
+ debug_assert_eq!(self.built.transaction, o.built.transaction);
+ debug_assert_eq!(self.built.txid, o.built.txid);
+ }
+ eq
+ }
+}
+
+impl Writeable for CommitmentTransaction {
+ fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
+ let legacy_deserialization_prevention_marker = legacy_deserialization_prevention_marker_for_channel_type_features(&self.channel_type_features);
+ write_tlv_fields!(writer, {
+ (0, self.commitment_number, required),
+ (1, self.to_broadcaster_delay, option),
+ (2, self.to_broadcaster_value_sat, required),
+ (4, self.to_countersignatory_value_sat, required),
+ (6, self.feerate_per_kw, required),
+ (8, self.keys, required),
+ (10, self.built, required),
+ (12, self.htlcs, required_vec),
+ (14, legacy_deserialization_prevention_marker, option),
+ (15, self.channel_type_features, required),
+ });
+ Ok(())
+ }
+}
+
+impl Readable for CommitmentTransaction {
+ fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
+ _init_and_read_len_prefixed_tlv_fields!(reader, {
+ (0, commitment_number, required),
+ (1, to_broadcaster_delay, option),
+ (2, to_broadcaster_value_sat, required),
+ (4, to_countersignatory_value_sat, required),
+ (6, feerate_per_kw, required),
+ (8, keys, required),
+ (10, built, required),
+ (12, htlcs, required_vec),
+ (14, _legacy_deserialization_prevention_marker, option),
+ (15, channel_type_features, option),
+ });
+
+ let mut additional_features = ChannelTypeFeatures::empty();
+ additional_features.set_anchors_nonzero_fee_htlc_tx_required();
+ chain::package::verify_channel_type_features(&channel_type_features, Some(&additional_features))?;
+
+ Ok(Self {
+ commitment_number: commitment_number.0.unwrap(),
+ to_broadcaster_value_sat: to_broadcaster_value_sat.0.unwrap(),
+ to_countersignatory_value_sat: to_countersignatory_value_sat.0.unwrap(),
+ to_broadcaster_delay,
+ feerate_per_kw: feerate_per_kw.0.unwrap(),
+ keys: keys.0.unwrap(),
+ built: built.0.unwrap(),
+ htlcs,
+ channel_type_features: channel_type_features.unwrap_or(ChannelTypeFeatures::only_static_remote_key())
+ })
+ }
+}
+
+impl CommitmentTransaction {
+ /// Construct an object of the class while assigning transaction output indices to HTLCs.
+ ///
+ /// Populates HTLCOutputInCommitment.transaction_output_index in htlcs_with_aux.
+ ///
+ /// The generic T allows the caller to match the HTLC output index with auxiliary data.
+ /// This auxiliary data is not stored in this object.
+ ///
+ /// Only include HTLCs that are above the dust limit for the channel.
+ ///
+ /// This is not exported to bindings users due to the generic though we likely should expose a version without
+ pub fn new_with_auxiliary_htlc_data<T>(commitment_number: u64, to_broadcaster_value_sat: u64, to_countersignatory_value_sat: u64, broadcaster_funding_key: PublicKey, countersignatory_funding_key: PublicKey, keys: TxCreationKeys, feerate_per_kw: u32, htlcs_with_aux: &mut Vec<(HTLCOutputInCommitment, T)>, channel_parameters: &DirectedChannelTransactionParameters) -> CommitmentTransaction {
+ // Sort outputs and populate output indices while keeping track of the auxiliary data
+ let (outputs, htlcs) = Self::internal_build_outputs(&keys, to_broadcaster_value_sat, to_countersignatory_value_sat, htlcs_with_aux, channel_parameters, &broadcaster_funding_key, &countersignatory_funding_key).unwrap();
+
+ let (obscured_commitment_transaction_number, txins) = Self::internal_build_inputs(commitment_number, channel_parameters);
+ let transaction = Self::make_transaction(obscured_commitment_transaction_number, txins, outputs);
+ let txid = transaction.txid();
+ CommitmentTransaction {
+ commitment_number,
+ to_broadcaster_value_sat,
+ to_countersignatory_value_sat,
+ to_broadcaster_delay: Some(channel_parameters.contest_delay()),
+ feerate_per_kw,
+ htlcs,
+ channel_type_features: channel_parameters.channel_type_features().clone(),
+ keys,
+ built: BuiltCommitmentTransaction {
+ transaction,
+ txid