+impl_writeable_tlv_based!(HolderCommitmentTransaction, {
+ (0, inner, required),
+ (2, counterparty_sig, required),
+ (4, holder_sig_first, required),
+ (6, counterparty_htlc_sigs, vec_type),
+});
+
+impl HolderCommitmentTransaction {
+ #[cfg(test)]
+ pub fn dummy() -> Self {
+ let secp_ctx = Secp256k1::new();
+ let dummy_key = PublicKey::from_secret_key(&secp_ctx, &SecretKey::from_slice(&[42; 32]).unwrap());
+ let dummy_sig = secp_ctx.sign(&secp256k1::Message::from_slice(&[42; 32]).unwrap(), &SecretKey::from_slice(&[42; 32]).unwrap());
+
+ let keys = TxCreationKeys {
+ per_commitment_point: dummy_key.clone(),
+ revocation_key: dummy_key.clone(),
+ broadcaster_htlc_key: dummy_key.clone(),
+ countersignatory_htlc_key: dummy_key.clone(),
+ broadcaster_delayed_payment_key: dummy_key.clone(),
+ };
+ let channel_pubkeys = ChannelPublicKeys {
+ funding_pubkey: dummy_key.clone(),
+ revocation_basepoint: dummy_key.clone(),
+ payment_point: dummy_key.clone(),
+ delayed_payment_basepoint: dummy_key.clone(),
+ htlc_basepoint: dummy_key.clone()
+ };
+ let channel_parameters = ChannelTransactionParameters {
+ holder_pubkeys: channel_pubkeys.clone(),
+ holder_selected_contest_delay: 0,
+ is_outbound_from_holder: false,
+ counterparty_parameters: Some(CounterpartyChannelTransactionParameters { pubkeys: channel_pubkeys.clone(), selected_contest_delay: 0 }),
+ funding_outpoint: Some(chain::transaction::OutPoint { txid: Default::default(), index: 0 })
+ };
+ let mut htlcs_with_aux: Vec<(_, ())> = Vec::new();
+ let inner = CommitmentTransaction::new_with_auxiliary_htlc_data(0, 0, 0, keys, 0, &mut htlcs_with_aux, &channel_parameters.as_counterparty_broadcastable());
+ HolderCommitmentTransaction {
+ inner,
+ counterparty_sig: dummy_sig,
+ counterparty_htlc_sigs: Vec::new(),
+ holder_sig_first: false
+ }
+ }
+
+ /// Create a new holder transaction with the given counterparty signatures.
+ /// The funding keys are used to figure out which signature should go first when building the transaction for broadcast.
+ pub fn new(commitment_tx: CommitmentTransaction, counterparty_sig: Signature, counterparty_htlc_sigs: Vec<Signature>, holder_funding_key: &PublicKey, counterparty_funding_key: &PublicKey) -> Self {
+ Self {
+ 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(holder_sig.serialize_der().to_vec());
+ tx.input[0].witness.push(self.counterparty_sig.serialize_der().to_vec());