From 5df65d2e7eb12c103787e0a1e9da79a6bfa629c6 Mon Sep 17 00:00:00 2001 From: Elias Rohrer Date: Mon, 22 May 2023 12:42:24 +0200 Subject: [PATCH] f Account for nLockTime given in `spend_spendable_outputs` --- src/event.rs | 12 +++++++++++- src/wallet.rs | 9 +++++---- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/event.rs b/src/event.rs index d02634d9b..05b7fa6d6 100644 --- a/src/event.rs +++ b/src/event.rs @@ -22,7 +22,7 @@ use lightning::util::errors::APIError; use lightning::util::ser::{Readable, ReadableArgs, Writeable, Writer}; use bitcoin::secp256k1::{PublicKey, Secp256k1}; -use bitcoin::OutPoint; +use bitcoin::{LockTime, OutPoint, PackedLockTime}; use rand::{thread_rng, Rng}; use std::collections::VecDeque; use std::ops::Deref; @@ -292,11 +292,15 @@ where // channel. let confirmation_target = ConfirmationTarget::Normal; + let cur_height = self.channel_manager.current_best_block().height(); + let locktime = LockTime::from_height(cur_height).unwrap_or(LockTime::ZERO); + // Sign the final funding transaction and broadcast it. match self.wallet.create_funding_transaction( output_script, channel_value_satoshis, confirmation_target, + locktime, ) { Ok(final_tx) => { // Give the funding transaction back to LDK for opening the channel. @@ -552,11 +556,17 @@ where let output_descriptors = &outputs.iter().collect::>(); let tx_feerate = self.wallet.get_est_sat_per_1000_weight(ConfirmationTarget::Normal); + + // We set nLockTime to the current height to discourage fee sniping. + let cur_height = self.channel_manager.current_best_block().height(); + let locktime: PackedLockTime = + LockTime::from_height(cur_height).map_or(PackedLockTime::ZERO, |l| l.into()); let res = self.keys_manager.spend_spendable_outputs( output_descriptors, Vec::new(), destination_address.script_pubkey(), tx_feerate, + Some(locktime), &Secp256k1::new(), ); match res { diff --git a/src/wallet.rs b/src/wallet.rs index d7eb0f3c7..50b60b7ea 100644 --- a/src/wallet.rs +++ b/src/wallet.rs @@ -22,7 +22,7 @@ use bitcoin::bech32::u5; use bitcoin::secp256k1::ecdh::SharedSecret; use bitcoin::secp256k1::ecdsa::{RecoverableSignature, Signature}; use bitcoin::secp256k1::{PublicKey, Scalar, Secp256k1, Signing}; -use bitcoin::{Script, Transaction, TxOut, Txid}; +use bitcoin::{PackedLockTime, LockTime, Script, Transaction, TxOut, Txid}; use std::collections::HashMap; use std::sync::{Arc, Condvar, Mutex, RwLock}; @@ -156,14 +156,14 @@ where } pub(crate) fn create_funding_transaction( - &self, output_script: Script, value_sats: u64, confirmation_target: ConfirmationTarget, + &self, output_script: Script, value_sats: u64, confirmation_target: ConfirmationTarget, locktime: LockTime, ) -> Result { let fee_rate = self.estimate_fee_rate(confirmation_target); let locked_wallet = self.inner.lock().unwrap(); let mut tx_builder = locked_wallet.build_tx(); - tx_builder.add_recipient(output_script, value_sats).fee_rate(fee_rate).enable_rbf(); + tx_builder.add_recipient(output_script, value_sats).fee_rate(fee_rate).nlocktime(locktime).enable_rbf(); let mut psbt = match tx_builder.finish() { Ok((psbt, _)) => { @@ -363,7 +363,7 @@ where pub fn spend_spendable_outputs( &self, descriptors: &[&SpendableOutputDescriptor], outputs: Vec, change_destination_script: Script, feerate_sat_per_1000_weight: u32, - secp_ctx: &Secp256k1, + locktime: Option, secp_ctx: &Secp256k1, ) -> Result { let only_non_static = &descriptors .iter() @@ -375,6 +375,7 @@ where outputs, change_destination_script, feerate_sat_per_1000_weight, + locktime, secp_ctx, ) }