Skip to content

Commit 36518b7

Browse files
author
Antoine Riard
committed
Add generation of SpendableOutputDescriptor in closing_signed
Aims to send back closing output descritpor to user wallet Add get_vout_my_output in transaction_utils
1 parent 8add429 commit 36518b7

File tree

3 files changed

+79
-7
lines changed

3 files changed

+79
-7
lines changed

src/ln/channel.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use bitcoin::blockdata::block::BlockHeader;
22
use bitcoin::blockdata::script::{Script,Builder};
33
use bitcoin::blockdata::transaction::{TxIn, TxOut, Transaction, SigHashType};
4+
use bitcoin::blockdata::transaction::OutPoint as BitcoinOutPoint;
45
use bitcoin::blockdata::opcodes;
56
use bitcoin::util::hash::{BitcoinHash, Sha256dHash, Hash160};
67
use bitcoin::util::bip143;
@@ -20,7 +21,7 @@ use ln::chan_utils::{TxCreationKeys,HTLCOutputInCommitment,HTLC_SUCCESS_TX_WEIGH
2021
use ln::chan_utils;
2122
use chain::chaininterface::{FeeEstimator,ConfirmationTarget};
2223
use chain::transaction::OutPoint;
23-
use chain::keysinterface::{ChannelKeys, KeysInterface};
24+
use chain::keysinterface::{ChannelKeys, KeysInterface, SpendableOutputDescriptor};
2425
use util::{transaction_utils,rng};
2526
use util::ser::{Readable, ReadableArgs, Writeable, Writer, WriterWriteAdaptor};
2627
use util::sha2::Sha256;
@@ -2496,7 +2497,7 @@ impl Channel {
24962497
Ok((our_shutdown, self.maybe_propose_first_closing_signed(fee_estimator), dropped_outbound_htlcs))
24972498
}
24982499

2499-
pub fn closing_signed(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::ClosingSigned) -> Result<(Option<msgs::ClosingSigned>, Option<Transaction>), HandleError> {
2500+
pub fn closing_signed(&mut self, fee_estimator: &FeeEstimator, msg: &msgs::ClosingSigned) -> Result<(Option<msgs::ClosingSigned>, Option<SpendableOutputDescriptor>, Option<Transaction>), HandleError> {
25002501
if self.channel_state & BOTH_SIDES_SHUTDOWN_MASK != BOTH_SIDES_SHUTDOWN_MASK {
25012502
return Err(HandleError{err: "Remote end sent us a closing_signed before both sides provided a shutdown", action: None});
25022503
}
@@ -2517,6 +2518,8 @@ impl Channel {
25172518
}
25182519
let mut sighash = Message::from_slice(&bip143::SighashComponents::new(&closing_tx).sighash_all(&closing_tx.input[0], &funding_redeemscript, self.channel_value_satoshis)[..]).unwrap();
25192520

2521+
let our_output_idx = transaction_utils::get_vout_my_output(&closing_tx, self.get_closing_scriptpubkey());
2522+
25202523
match self.secp_ctx.verify(&sighash, &msg.signature, &self.their_funding_pubkey.unwrap()) {
25212524
Ok(_) => {},
25222525
Err(_e) => {
@@ -2533,7 +2536,10 @@ impl Channel {
25332536
self.sign_commitment_transaction(&mut closing_tx, &msg.signature);
25342537
self.channel_state = ChannelState::ShutdownComplete as u32;
25352538
self.channel_update_count += 1;
2536-
return Ok((None, Some(closing_tx)));
2539+
return Ok((None, if our_output_idx.is_some() { Some(SpendableOutputDescriptor::StaticOutput {
2540+
outpoint: BitcoinOutPoint { txid: closing_tx.txid(), vout: our_output_idx.unwrap() },
2541+
output: closing_tx.output[our_output_idx.unwrap() as usize].clone(),
2542+
})} else { None }, Some(closing_tx)));
25372543
}
25382544
}
25392545

@@ -2548,7 +2554,7 @@ impl Channel {
25482554
channel_id: self.channel_id,
25492555
fee_satoshis: used_total_fee,
25502556
signature: our_sig,
2551-
}), None))
2557+
}), None, None))
25522558
}
25532559
}
25542560

@@ -2583,7 +2589,10 @@ impl Channel {
25832589
channel_id: self.channel_id,
25842590
fee_satoshis: msg.fee_satoshis,
25852591
signature: our_sig,
2586-
}), Some(closing_tx)))
2592+
}), if our_output_idx.is_some() { Some(SpendableOutputDescriptor::StaticOutput {
2593+
outpoint: BitcoinOutPoint { txid: closing_tx.txid(), vout: our_output_idx.unwrap() },
2594+
output: closing_tx.output[our_output_idx.unwrap() as usize].clone(),
2595+
})} else { None }, Some(closing_tx)))
25872596
}
25882597

25892598
// Public utilities:

src/ln/channelmanager.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1873,6 +1873,7 @@ impl ChannelManager {
18731873
}
18741874

18751875
fn internal_closing_signed(&self, their_node_id: &PublicKey, msg: &msgs::ClosingSigned) -> Result<(), MsgHandleErrInternal> {
1876+
let mut spendable_output = Vec::with_capacity(1);
18761877
let (tx, chan_option) = {
18771878
let mut channel_state_lock = self.channel_state.lock().unwrap();
18781879
let channel_state = channel_state_lock.borrow_parts();
@@ -1882,13 +1883,16 @@ impl ChannelManager {
18821883
//TODO: here and below MsgHandleErrInternal, #153 case
18831884
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!", msg.channel_id));
18841885
}
1885-
let (closing_signed, tx) = chan_entry.get_mut().closing_signed(&*self.fee_estimator, &msg).map_err(|e| MsgHandleErrInternal::from_maybe_close(e))?;
1886+
let (closing_signed, spendable_outp, tx) = chan_entry.get_mut().closing_signed(&*self.fee_estimator, &msg).map_err(|e| MsgHandleErrInternal::from_maybe_close(e))?;
18861887
if let Some(msg) = closing_signed {
18871888
channel_state.pending_msg_events.push(events::MessageSendEvent::SendClosingSigned {
18881889
node_id: their_node_id.clone(),
18891890
msg,
18901891
});
18911892
}
1893+
if let Some(spendable_outp) = spendable_outp {
1894+
spendable_output.push(spendable_outp);
1895+
}
18921896
if tx.is_some() {
18931897
// We're done with this channel, we've got a signed closing transaction and
18941898
// will send the closing_signed back to the remote peer upon return. This
@@ -1904,6 +1908,9 @@ impl ChannelManager {
19041908
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel", msg.channel_id))
19051909
}
19061910
};
1911+
if spendable_output.len() > 0 {
1912+
self.pending_events.lock().unwrap().push(events::Event::SpendableOutputs { outputs: spendable_output });
1913+
}
19071914
if let Some(broadcast_tx) = tx {
19081915
self.tx_broadcaster.broadcast_transaction(&broadcast_tx);
19091916
}
@@ -3672,6 +3679,23 @@ mod tests {
36723679
}
36733680
}
36743681

3682+
macro_rules! check_closing_output {
3683+
($node: expr) => {
3684+
let events = $node.get_and_clear_pending_events();
3685+
if events.len() > 0 {
3686+
match events[0] {
3687+
Event::SpendableOutputs { ref outputs } => {
3688+
match outputs[0] {
3689+
SpendableOutputDescriptor::StaticOutput { .. } => {},
3690+
_ => panic!("Unexpected event"),
3691+
}
3692+
}
3693+
_ => panic!("Unexpected event"),
3694+
}
3695+
}
3696+
}
3697+
}
3698+
36753699
fn close_channel(outbound_node: &Node, inbound_node: &Node, channel_id: &[u8; 32], funding_tx: Transaction, close_inbound_first: bool) -> (msgs::ChannelUpdate, msgs::ChannelUpdate) {
36763700
let (node_a, broadcaster_a, struct_a) = if close_inbound_first { (&inbound_node.node, &inbound_node.tx_broadcaster, inbound_node) } else { (&outbound_node.node, &outbound_node.tx_broadcaster, outbound_node) };
36773701
let (node_b, broadcaster_b) = if close_inbound_first { (&outbound_node.node, &outbound_node.tx_broadcaster) } else { (&inbound_node.node, &inbound_node.tx_broadcaster) };
@@ -4571,6 +4595,9 @@ mod tests {
45714595
send_payment(&nodes[1], &vec!(&nodes[0])[..], 800000);
45724596
send_payment(&nodes[0], &vec!(&nodes[1])[..], 800000);
45734597
close_channel(&nodes[0], &nodes[1], &chan.2, chan.3, true);
4598+
4599+
check_closing_output!(nodes[0].node);
4600+
check_closing_output!(nodes[1].node);
45744601
}
45754602

45764603
#[test]
@@ -4679,6 +4706,9 @@ mod tests {
46794706
assert_eq!(get_feerate!(nodes[0]), feerate + 30);
46804707
assert_eq!(get_feerate!(nodes[1]), feerate + 30);
46814708
close_channel(&nodes[0], &nodes[1], &chan.2, chan.3, true);
4709+
4710+
check_closing_output!(nodes[0].node);
4711+
check_closing_output!(nodes[1].node);
46824712
}
46834713

46844714
#[test]
@@ -4705,6 +4735,9 @@ mod tests {
47054735

47064736
assert!(nodes[0].node.list_channels().is_empty());
47074737
assert!(nodes[1].node.list_channels().is_empty());
4738+
4739+
check_closing_output!(nodes[0].node);
4740+
check_closing_output!(nodes[1].node);
47084741
}
47094742

47104743
#[test]
@@ -4777,6 +4810,10 @@ mod tests {
47774810
close_channel(&nodes[1], &nodes[2], &chan_2.2, chan_2.3, true);
47784811
assert!(nodes[1].node.list_channels().is_empty());
47794812
assert!(nodes[2].node.list_channels().is_empty());
4813+
4814+
check_closing_output!(nodes[0].node);
4815+
check_closing_output!(nodes[1].node);
4816+
check_closing_output!(nodes[2].node);
47804817
}
47814818

47824819
#[test]
@@ -4843,6 +4880,10 @@ mod tests {
48434880
close_channel(&nodes[1], &nodes[2], &chan_2.2, chan_2.3, true);
48444881
assert!(nodes[1].node.list_channels().is_empty());
48454882
assert!(nodes[2].node.list_channels().is_empty());
4883+
4884+
check_closing_output!(nodes[0].node);
4885+
check_closing_output!(nodes[1].node);
4886+
check_closing_output!(nodes[2].node);
48464887
}
48474888

48484889
#[test]
@@ -4889,6 +4930,9 @@ mod tests {
48894930
nodes[0].node.handle_closing_signed(&nodes[1].node.get_our_node_id(), &node_1_closing_signed.unwrap()).unwrap();
48904931
let (_, node_0_none) = get_closing_signed_broadcast!(nodes[0].node, nodes[1].node.get_our_node_id());
48914932
assert!(node_0_none.is_none());
4933+
4934+
check_closing_output!(nodes[0].node);
4935+
check_closing_output!(nodes[1].node);
48924936
}
48934937

48944938
fn do_test_shutdown_rebroadcast(recv_count: u8) {
@@ -5041,6 +5085,10 @@ mod tests {
50415085
close_channel(&nodes[1], &nodes[2], &chan_2.2, chan_2.3, true);
50425086
assert!(nodes[1].node.list_channels().is_empty());
50435087
assert!(nodes[2].node.list_channels().is_empty());
5088+
5089+
check_closing_output!(nodes[0].node);
5090+
check_closing_output!(nodes[1].node);
5091+
check_closing_output!(nodes[2].node);
50445092
}
50455093

50465094
#[test]
@@ -5160,6 +5208,11 @@ mod tests {
51605208
close_channel(&nodes[2], &nodes[3], &chan_3.2, chan_3.3, true);
51615209
close_channel(&nodes[1], &nodes[3], &chan_4.2, chan_4.3, false);
51625210
close_channel(&nodes[1], &nodes[3], &chan_5.2, chan_5.3, false);
5211+
5212+
check_closing_output!(nodes[0].node);
5213+
check_closing_output!(nodes[1].node);
5214+
check_closing_output!(nodes[2].node);
5215+
check_closing_output!(nodes[3].node);
51635216
}
51645217

51655218
#[test]

src/util/transaction_utils.rs

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use bitcoin::blockdata::transaction::{TxIn, TxOut};
1+
use bitcoin::blockdata::transaction::{Transaction, TxIn, TxOut};
2+
use bitcoin::blockdata::script::Script;
23

34
use std::cmp::Ordering;
45

@@ -34,6 +35,15 @@ pub fn sort_inputs<T>(inputs: &mut Vec<(TxIn, T)>) {
3435
});
3536
}
3637

38+
pub fn get_vout_my_output(tx: &Transaction, match_script: Script) -> Option<u32> {
39+
for (idx, out) in tx.output.iter().enumerate() {
40+
if out.script_pubkey == match_script {
41+
return Some(idx as u32);
42+
}
43+
}
44+
None
45+
}
46+
3747
#[cfg(test)]
3848
mod tests {
3949
use super::*;

0 commit comments

Comments
 (0)