max_level_warn = []
max_level_info = []
max_level_debug = []
+# Allow signing of local transactions that may have been revoked or will be revoked, for functional testing (e.g. justice tx handling).
+# This is unsafe to use in production because it may result in the counterparty publishing taking our funds.
+unsafe_revoked_tx_signing = []
[dependencies]
bitcoin = "0.23"
/// transactions which will be broadcasted later, after the channel has moved on to a newer
/// state. Thus, needs its own method as sign_local_commitment may enforce that we only ever
/// get called once.
- #[cfg(test)]
+ #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()>;
/// Create a signature for each HTLC transaction spending a local commitment transaction.
Ok(local_commitment_tx.get_local_sig(&self.funding_key, &channel_funding_redeemscript, self.channel_value_satoshis, secp_ctx))
}
- #[cfg(test)]
+ #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
let funding_pubkey = PublicKey::from_secret_key(secp_ctx, &self.funding_key);
let remote_channel_pubkeys = &self.accepted_channel_data.as_ref().expect("must accept before signing").remote_channel_pubkeys;
}
/// Generate a new LocalCommitmentTransaction based on a raw commitment transaction,
- /// remote signature and both parties keys
- pub(crate) fn new_missing_local_sig(unsigned_tx: Transaction, their_sig: Signature, our_funding_key: &PublicKey, their_funding_key: &PublicKey, local_keys: TxCreationKeys, feerate_per_kw: u32, htlc_data: Vec<(HTLCOutputInCommitment, Option<Signature>)>) -> LocalCommitmentTransaction {
+ /// remote signature and both parties keys.
+ ///
+ /// The unsigned transaction outputs must be consistent with htlc_data. This function
+ /// only checks that the shape and amounts are consistent, but does not check the scriptPubkey.
+ pub fn new_missing_local_sig(unsigned_tx: Transaction, their_sig: Signature, our_funding_key: &PublicKey, their_funding_key: &PublicKey, local_keys: TxCreationKeys, feerate_per_kw: u32, htlc_data: Vec<(HTLCOutputInCommitment, Option<Signature>)>) -> LocalCommitmentTransaction {
if unsigned_tx.input.len() != 1 { panic!("Tried to store a commitment transaction that had input count != 1!"); }
if unsigned_tx.input[0].witness.len() != 0 { panic!("Tried to store a signed commitment transaction?"); }
+ for htlc in &htlc_data {
+ if let Some(index) = htlc.0.transaction_output_index {
+ let out = &unsigned_tx.output[index as usize];
+ if out.value != htlc.0.amount_msat / 1000 {
+ panic!("HTLC at index {} has incorrect amount", index);
+ }
+ if !out.script_pubkey.is_v0_p2wsh() {
+ panic!("HTLC at index {} doesn't have p2wsh scriptPubkey", index);
+ }
+ }
+ }
+
Self {
unsigned_tx,
their_sig,
L::Target: Logger,
C::Target: ChainWatchInterface,
{
- #[cfg(test)] // Used in ChannelManager tests to manipulate channels directly
+ /// The monitors
pub monitors: Mutex<HashMap<Key, ChannelMonitor<ChanSigner>>>,
- #[cfg(not(test))]
- monitors: Mutex<HashMap<Key, ChannelMonitor<ChanSigner>>>,
chain_monitor: C,
broadcaster: T,
logger: L,
/// Unsafe test-only version of get_latest_local_commitment_txn used by our test framework
/// to bypass LocalCommitmentTransaction state update lockdown after signature and generate
/// revoked commitment transaction.
- #[cfg(test)]
+ #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
pub fn unsafe_get_latest_local_commitment_txn<L: Deref>(&mut self, logger: &L) -> Vec<Transaction> where L::Target: Logger {
log_trace!(logger, "Getting signed copy of latest local commitment transaction!");
if let Some(commitment_tx) = self.onchain_tx_handler.get_fully_signed_copy_local_tx(&self.funding_redeemscript) {
}
}
- #[cfg(test)]
+ #[cfg(any(test, feature="unsafe_revoked_tx_signing"))]
pub(super) fn get_fully_signed_copy_local_tx(&mut self, funding_redeemscript: &Script) -> Option<Transaction> {
if let Some(ref mut local_commitment) = self.local_commitment {
let local_commitment = local_commitment.clone();
htlc_tx
}
- #[cfg(test)]
+ #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
pub(super) fn unsafe_get_fully_signed_htlc_tx(&mut self, outp: &::bitcoin::OutPoint, preimage: &Option<PaymentPreimage>) -> Option<Transaction> {
let latest_had_sigs = self.local_htlc_sigs.is_some();
let prev_had_sigs = self.prev_local_htlc_sigs.is_some();
Ok(self.inner.sign_local_commitment(local_commitment_tx, secp_ctx).unwrap())
}
- #[cfg(test)]
+ #[cfg(any(test,feature = "unsafe_revoked_tx_signing"))]
fn unsafe_sign_local_commitment<T: secp256k1::Signing + secp256k1::Verification>(&self, local_commitment_tx: &LocalCommitmentTransaction, secp_ctx: &Secp256k1<T>) -> Result<Signature, ()> {
Ok(self.inner.unsafe_sign_local_commitment(local_commitment_tx, secp_ctx).unwrap())
}