Skip to content

Commit 4268562

Browse files
committed
Factor out low-level build_closing_transaction
1 parent 731773c commit 4268562

File tree

2 files changed

+62
-45
lines changed

2 files changed

+62
-45
lines changed

lightning/src/ln/chan_utils.rs

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use bitcoin::hash_types::{Txid, PubkeyHash};
2323
use ln::{PaymentHash, PaymentPreimage};
2424
use ln::msgs::DecodeError;
2525
use util::ser::{Readable, Writeable, Writer};
26-
use util::byte_utils;
26+
use util::{byte_utils, transaction_utils};
2727

2828
use bitcoin::hash_types::WPubkeyHash;
2929
use bitcoin::secp256k1::key::{SecretKey, PublicKey};
@@ -80,6 +80,50 @@ pub fn build_commitment_secret(commitment_seed: &[u8; 32], idx: u64) -> [u8; 32]
8080
res
8181
}
8282

83+
/// Build a closing transaction
84+
pub fn build_closing_transaction(value_to_holder: u64, value_to_counterparty: u64, holder_shutdown_script: Script, counterparty_shutdown_script: Script, funding_outpoint: OutPoint) -> Transaction {
85+
let txins = {
86+
let mut ins: Vec<TxIn> = Vec::new();
87+
ins.push(TxIn {
88+
previous_output: funding_outpoint,
89+
script_sig: Script::new(),
90+
sequence: 0xffffffff,
91+
witness: Vec::new(),
92+
});
93+
ins
94+
};
95+
96+
let mut txouts: Vec<(TxOut, ())> = Vec::new();
97+
98+
if value_to_counterparty > 0 {
99+
txouts.push((TxOut {
100+
script_pubkey: counterparty_shutdown_script,
101+
value: value_to_counterparty
102+
}, ()));
103+
}
104+
105+
if value_to_holder > 0 {
106+
txouts.push((TxOut {
107+
script_pubkey: holder_shutdown_script,
108+
value: value_to_holder
109+
}, ()));
110+
}
111+
112+
transaction_utils::sort_outputs(&mut txouts, |_, _| { cmp::Ordering::Equal }); // Ordering doesnt matter if they used our pubkey...
113+
114+
let mut outputs: Vec<TxOut> = Vec::new();
115+
for out in txouts.drain(..) {
116+
outputs.push(out.0);
117+
}
118+
119+
Transaction {
120+
version: 2,
121+
lock_time: 0,
122+
input: txins,
123+
output: outputs,
124+
}
125+
}
126+
83127
/// Implements the per-commitment secret storage scheme from
84128
/// [BOLT 3](https://github.com/lightningnetwork/lightning-rfc/blob/dcbf8583976df087c79c3ce0b535311212e6812d/03-transactions.md#efficient-per-commitment-secret-storage).
85129
///

lightning/src/ln/channel.rs

Lines changed: 17 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// licenses.
99

1010
use bitcoin::blockdata::script::{Script,Builder};
11-
use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType};
11+
use bitcoin::blockdata::transaction::{Transaction, SigHashType};
1212
use bitcoin::util::bip143;
1313
use bitcoin::consensus::encode;
1414

@@ -28,14 +28,13 @@ use ln::msgs;
2828
use ln::msgs::{DecodeError, OptionalField, DataLossProtect};
2929
use ln::script::ShutdownScript;
3030
use ln::channelmanager::{PendingHTLCStatus, HTLCSource, HTLCFailReason, HTLCFailureMsg, PendingHTLCInfo, RAACommitmentOrder, BREAKDOWN_TIMEOUT, MIN_CLTV_EXPIRY_DELTA, MAX_LOCAL_BREAKDOWN_TIMEOUT};
31-
use ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor};
31+
use ln::chan_utils::{CounterpartyCommitmentSecrets, TxCreationKeys, HTLCOutputInCommitment, HTLC_SUCCESS_TX_WEIGHT, HTLC_TIMEOUT_TX_WEIGHT, make_funding_redeemscript, ChannelPublicKeys, CommitmentTransaction, HolderCommitmentTransaction, ChannelTransactionParameters, CounterpartyChannelTransactionParameters, MAX_HTLCS, get_commitment_transaction_number_obscure_factor, build_closing_transaction};
3232
use ln::chan_utils;
3333
use chain::BestBlock;
3434
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
3535
use chain::channelmonitor::{ChannelMonitor, ChannelMonitorUpdate, ChannelMonitorUpdateStep, HTLC_FAIL_BACK_BUFFER};
3636
use chain::transaction::{OutPoint, TransactionData};
3737
use chain::keysinterface::{Sign, KeysInterface};
38-
use util::transaction_utils;
3938
use util::ser::{Readable, ReadableArgs, Writeable, Writer, VecWriter};
4039
use util::logger::Logger;
4140
use util::errors::APIError;
@@ -1277,62 +1276,36 @@ impl<Signer: Sign> Channel<Signer> {
12771276

12781277
#[inline]
12791278
fn build_closing_transaction(&self, proposed_total_fee_satoshis: u64, skip_remote_output: bool) -> (Transaction, u64) {
1280-
let txins = {
1281-
let mut ins: Vec<TxIn> = Vec::new();
1282-
ins.push(TxIn {
1283-
previous_output: self.funding_outpoint().into_bitcoin_outpoint(),
1284-
script_sig: Script::new(),
1285-
sequence: 0xffffffff,
1286-
witness: Vec::new(),
1287-
});
1288-
ins
1289-
};
1290-
12911279
assert!(self.pending_inbound_htlcs.is_empty());
12921280
assert!(self.pending_outbound_htlcs.is_empty());
12931281
assert!(self.pending_update_fee.is_none());
1294-
let mut txouts: Vec<(TxOut, ())> = Vec::new();
12951282

12961283
let mut total_fee_satoshis = proposed_total_fee_satoshis;
1297-
let value_to_self: i64 = (self.value_to_self_msat as i64) / 1000 - if self.is_outbound() { total_fee_satoshis as i64 } else { 0 };
1298-
let value_to_remote: i64 = ((self.channel_value_satoshis * 1000 - self.value_to_self_msat) as i64 / 1000) - if self.is_outbound() { 0 } else { total_fee_satoshis as i64 };
1284+
let mut value_to_holder: i64 = (self.value_to_self_msat as i64) / 1000 - if self.is_outbound() { total_fee_satoshis as i64 } else { 0 };
1285+
let mut value_to_counterparty: i64 = ((self.channel_value_satoshis * 1000 - self.value_to_self_msat) as i64 / 1000) - if self.is_outbound() { 0 } else { total_fee_satoshis as i64 };
12991286

1300-
if value_to_self < 0 {
1287+
if value_to_holder < 0 {
13011288
assert!(self.is_outbound());
1302-
total_fee_satoshis += (-value_to_self) as u64;
1303-
} else if value_to_remote < 0 {
1289+
total_fee_satoshis += (-value_to_holder) as u64;
1290+
} else if value_to_counterparty < 0 {
13041291
assert!(!self.is_outbound());
1305-
total_fee_satoshis += (-value_to_remote) as u64;
1292+
total_fee_satoshis += (-value_to_counterparty) as u64;
13061293
}
13071294

1308-
if !skip_remote_output && value_to_remote as u64 > self.holder_dust_limit_satoshis {
1309-
txouts.push((TxOut {
1310-
script_pubkey: self.counterparty_shutdown_scriptpubkey.clone().unwrap(),
1311-
value: value_to_remote as u64
1312-
}, ()));
1295+
if skip_remote_output || value_to_counterparty as u64 <= self.holder_dust_limit_satoshis {
1296+
value_to_counterparty = 0;
13131297
}
13141298

1315-
assert!(self.shutdown_scriptpubkey.is_some());
1316-
if value_to_self as u64 > self.holder_dust_limit_satoshis {
1317-
txouts.push((TxOut {
1318-
script_pubkey: self.get_closing_scriptpubkey(),
1319-
value: value_to_self as u64
1320-
}, ()));
1299+
if value_to_holder as u64 <= self.holder_dust_limit_satoshis {
1300+
value_to_holder = 0;
13211301
}
13221302

1323-
transaction_utils::sort_outputs(&mut txouts, |_, _| { cmp::Ordering::Equal }); // Ordering doesnt matter if they used our pubkey...
1324-
1325-
let mut outputs: Vec<TxOut> = Vec::new();
1326-
for out in txouts.drain(..) {
1327-
outputs.push(out.0);
1328-
}
1303+
assert!(self.shutdown_scriptpubkey.is_some());
1304+
let holder_shutdown_script = self.get_closing_scriptpubkey();
1305+
let counterparty_shutdown_script = self.counterparty_shutdown_scriptpubkey.clone().unwrap();
1306+
let funding_outpoint = self.funding_outpoint().into_bitcoin_outpoint();
13291307

1330-
(Transaction {
1331-
version: 2,
1332-
lock_time: 0,
1333-
input: txins,
1334-
output: outputs,
1335-
}, total_fee_satoshis)
1308+
(build_closing_transaction(value_to_holder as u64, value_to_counterparty as u64, holder_shutdown_script, counterparty_shutdown_script, funding_outpoint), total_fee_satoshis)
13361309
}
13371310

13381311
fn funding_outpoint(&self) -> OutPoint {

0 commit comments

Comments
 (0)