Ok((msgs::FundingSigned {
channel_id: self.channel_id,
- signature
+ signature,
+ #[cfg(taproot)]
+ partial_signature_with_nonce: None,
}, channel_monitor))
}
return Err(ChannelError::Close(format!("Got wrong number of HTLC signatures ({}) from remote. It must be {}", msg.htlc_signatures.len(), commitment_stats.num_nondust_htlcs)));
}
- // TODO: Sadly, we pass HTLCs twice to ChannelMonitor: once via the HolderCommitmentTransaction and once via the update
+ // Up to LDK 0.0.115, HTLC information was required to be duplicated in the
+ // `htlcs_and_sigs` vec and in the `holder_commitment_tx` itself, both of which were passed
+ // in the `ChannelMonitorUpdate`. In 0.0.115, support for having a separate set of
+ // outbound-non-dust-HTLCSources in the `ChannelMonitorUpdate` was added, however for
+ // backwards compatibility, we never use it in production. To provide test coverage, here,
+ // we randomly decide (in test/fuzzing builds) to use the new vec sometimes.
+ #[allow(unused_assignments, unused_mut)]
+ let mut separate_nondust_htlc_sources = false;
+ #[cfg(all(feature = "std", any(test, fuzzing)))] {
+ use core::hash::{BuildHasher, Hasher};
+ // Get a random value using the only std API to do so - the DefaultHasher
+ let rand_val = std::collections::hash_map::RandomState::new().build_hasher().finish();
+ separate_nondust_htlc_sources = rand_val % 2 == 0;
+ }
+
+ let mut nondust_htlc_sources = Vec::with_capacity(htlcs_cloned.len());
let mut htlcs_and_sigs = Vec::with_capacity(htlcs_cloned.len());
- for (idx, (htlc, source)) in htlcs_cloned.drain(..).enumerate() {
+ for (idx, (htlc, mut source_opt)) in htlcs_cloned.drain(..).enumerate() {
if let Some(_) = htlc.transaction_output_index {
let htlc_tx = chan_utils::build_htlc_transaction(&commitment_txid, commitment_stats.feerate_per_kw,
self.get_counterparty_selected_contest_delay().unwrap(), &htlc, self.opt_anchors(),
if let Err(_) = self.secp_ctx.verify_ecdsa(&htlc_sighash, &msg.htlc_signatures[idx], &keys.countersignatory_htlc_key) {
return Err(ChannelError::Close("Invalid HTLC tx signature from peer".to_owned()));
}
- htlcs_and_sigs.push((htlc, Some(msg.htlc_signatures[idx]), source));
+ if !separate_nondust_htlc_sources {
+ htlcs_and_sigs.push((htlc, Some(msg.htlc_signatures[idx]), source_opt.take()));
+ }
} else {
- htlcs_and_sigs.push((htlc, None, source));
+ htlcs_and_sigs.push((htlc, None, source_opt.take()));
}
+ if separate_nondust_htlc_sources {
+ if let Some(source) = source_opt.take() {
+ nondust_htlc_sources.push(source);
+ }
+ }
+ debug_assert!(source_opt.is_none(), "HTLCSource should have been put somewhere");
}
let holder_commitment_tx = HolderCommitmentTransaction::new(
commitment_tx: holder_commitment_tx,
htlc_outputs: htlcs_and_sigs,
claimed_htlcs,
+ nondust_htlc_sources,
}]
};
channel_id: self.channel_id,
per_commitment_secret,
next_per_commitment_point,
+ #[cfg(taproot)]
+ next_local_nonce: None,
}
}
None => Builder::new().into_script(),
}),
channel_type: Some(self.channel_type.clone()),
+ #[cfg(taproot)]
+ next_local_nonce: None,
}
}
temporary_channel_id,
funding_txid: funding_txo.txid,
funding_output_index: funding_txo.index,
- signature
+ signature,
+ #[cfg(taproot)]
+ partial_signature_with_nonce: None,
+ #[cfg(taproot)]
+ next_local_nonce: None,
})
}
channel_id: self.channel_id,
signature,
htlc_signatures,
+ #[cfg(taproot)]
+ partial_signature_with_nonce: None,
}, (counterparty_commitment_txid, commitment_stats.htlcs_included)))
}
session_priv: SecretKey::from_slice(&hex::decode("0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()[..]).unwrap(),
first_hop_htlc_msat: 548,
payment_id: PaymentId([42; 32]),
- payment_secret: None,
}
});