Skip to content

Commit 61216fa

Browse files
committed
Take the full funding transaction from the user on generation
Instead of relying on the user to ensure the funding transaction is correct (and panicing when it is confirmed), we should check it is correct when it is generated. By taking the full funding transaciton from the user on generation, we can also handle broadcasting for them instead of doing so via an event.
1 parent fe85696 commit 61216fa

File tree

7 files changed

+93
-114
lines changed

7 files changed

+93
-114
lines changed

background-processor/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ mod tests {
203203
_ => panic!("Unexpected event"),
204204
};
205205

206-
$node_a.node.funding_transaction_generated(&temporary_channel_id, funding_output);
206+
$node_a.node.funding_transaction_generated(&temporary_channel_id, tx.clone(), funding_output.index).unwrap();
207207
$node_b.node.handle_funding_created(&$node_a.node.get_our_node_id(), &get_event_msg!($node_a, MessageSendEvent::SendFundingCreated, $node_b.node.get_our_node_id()));
208208
$node_a.node.handle_funding_signed(&$node_b.node.get_our_node_id(), &get_event_msg!($node_b, MessageSendEvent::SendFundingSigned, $node_a.node.get_our_node_id()));
209209
tx

lightning/src/ln/chanmon_update_fail_tests.rs

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1825,7 +1825,7 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf:
18251825

18261826
let (temporary_channel_id, funding_tx, funding_output) = create_funding_transaction(&nodes[0], 100000, 43);
18271827

1828-
nodes[0].node.funding_transaction_generated(&temporary_channel_id, funding_output);
1828+
nodes[0].node.funding_transaction_generated(&temporary_channel_id, funding_tx.clone(), funding_output.index).unwrap();
18291829
check_added_monitors!(nodes[0], 0);
18301830

18311831
*nodes[1].chain_monitor.update_ret.lock().unwrap() = Some(Err(ChannelMonitorUpdateErr::TemporaryFailure));
@@ -1846,14 +1846,9 @@ fn do_during_funding_monitor_fail(confirm_a_first: bool, restore_b_before_conf:
18461846
check_added_monitors!(nodes[0], 0);
18471847

18481848
let events = nodes[0].node.get_and_clear_pending_events();
1849-
assert_eq!(events.len(), 1);
1850-
match events[0] {
1851-
Event::FundingBroadcastSafe { ref funding_txo, user_channel_id } => {
1852-
assert_eq!(user_channel_id, 43);
1853-
assert_eq!(*funding_txo, funding_output);
1854-
},
1855-
_ => panic!("Unexpected event"),
1856-
};
1849+
assert_eq!(events.len(), 0);
1850+
assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
1851+
assert_eq!(nodes[0].tx_broadcaster.txn_broadcasted.lock().unwrap().split_off(0)[0].txid(), funding_output.txid);
18571852

18581853
if confirm_a_first {
18591854
confirm_transaction(&nodes[0], &funding_tx);

lightning/src/ln/channel.rs

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -409,9 +409,9 @@ pub(super) struct Channel<Signer: Sign> {
409409
counterparty_forwarding_info: Option<CounterpartyForwardingInfo>,
410410

411411
pub(crate) channel_transaction_parameters: ChannelTransactionParameters,
412+
funding_transaction: Option<Transaction>,
412413

413414
counterparty_cur_commitment_point: Option<PublicKey>,
414-
415415
counterparty_prev_commitment_point: Option<PublicKey>,
416416
counterparty_node_id: PublicKey,
417417

@@ -603,8 +603,9 @@ impl<Signer: Sign> Channel<Signer> {
603603
counterparty_parameters: None,
604604
funding_outpoint: None
605605
},
606-
counterparty_cur_commitment_point: None,
606+
funding_transaction: None,
607607

608+
counterparty_cur_commitment_point: None,
608609
counterparty_prev_commitment_point: None,
609610
counterparty_node_id,
610611

@@ -844,8 +845,9 @@ impl<Signer: Sign> Channel<Signer> {
844845
}),
845846
funding_outpoint: None
846847
},
847-
counterparty_cur_commitment_point: Some(msg.first_per_commitment_point),
848+
funding_transaction: None,
848849

850+
counterparty_cur_commitment_point: Some(msg.first_per_commitment_point),
849851
counterparty_prev_commitment_point: None,
850852
counterparty_node_id,
851853

@@ -1608,7 +1610,7 @@ impl<Signer: Sign> Channel<Signer> {
16081610

16091611
/// Handles a funding_signed message from the remote end.
16101612
/// If this call is successful, broadcast the funding transaction (and not before!)
1611-
pub fn funding_signed<L: Deref>(&mut self, msg: &msgs::FundingSigned, last_block_hash: BlockHash, logger: &L) -> Result<ChannelMonitor<Signer>, ChannelError> where L::Target: Logger {
1613+
pub fn funding_signed<L: Deref>(&mut self, msg: &msgs::FundingSigned, last_block_hash: BlockHash, logger: &L) -> Result<(ChannelMonitor<Signer>, Transaction), ChannelError> where L::Target: Logger {
16121614
if !self.is_outbound() {
16131615
return Err(ChannelError::Close("Received funding_signed for an inbound channel?".to_owned()));
16141616
}
@@ -1670,7 +1672,7 @@ impl<Signer: Sign> Channel<Signer> {
16701672
self.cur_holder_commitment_transaction_number -= 1;
16711673
self.cur_counterparty_commitment_transaction_number -= 1;
16721674

1673-
Ok(channel_monitor)
1675+
Ok((channel_monitor, self.funding_transaction.as_ref().cloned().unwrap()))
16741676
}
16751677

16761678
pub fn funding_locked(&mut self, msg: &msgs::FundingLocked) -> Result<(), ChannelError> {
@@ -2771,11 +2773,13 @@ impl<Signer: Sign> Channel<Signer> {
27712773
/// Indicates that the latest ChannelMonitor update has been committed by the client
27722774
/// successfully and we should restore normal operation. Returns messages which should be sent
27732775
/// to the remote side.
2774-
pub fn monitor_updating_restored<L: Deref>(&mut self, logger: &L) -> (Option<msgs::RevokeAndACK>, Option<msgs::CommitmentUpdate>, RAACommitmentOrder, Vec<(PendingHTLCInfo, u64)>, Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, bool, Option<msgs::FundingLocked>) where L::Target: Logger {
2776+
pub fn monitor_updating_restored<L: Deref>(&mut self, logger: &L) -> (Option<msgs::RevokeAndACK>, Option<msgs::CommitmentUpdate>, RAACommitmentOrder, Vec<(PendingHTLCInfo, u64)>, Vec<(HTLCSource, PaymentHash, HTLCFailReason)>, Option<Transaction>, Option<msgs::FundingLocked>) where L::Target: Logger {
27752777
assert_eq!(self.channel_state & ChannelState::MonitorUpdateFailed as u32, ChannelState::MonitorUpdateFailed as u32);
27762778
self.channel_state &= !(ChannelState::MonitorUpdateFailed as u32);
27772779

2778-
let needs_broadcast_safe = self.channel_state & (ChannelState::FundingSent as u32) != 0 && self.is_outbound();
2780+
let funding_broadcastable = if self.channel_state & (ChannelState::FundingSent as u32) != 0 && self.is_outbound() {
2781+
self.funding_transaction.take()
2782+
} else { None };
27792783

27802784
// Because we will never generate a FundingBroadcastSafe event when we're in
27812785
// MonitorUpdateFailed, if we assume the user only broadcast the funding transaction when
@@ -2801,7 +2805,7 @@ impl<Signer: Sign> Channel<Signer> {
28012805
if self.channel_state & (ChannelState::PeerDisconnected as u32) != 0 {
28022806
self.monitor_pending_revoke_and_ack = false;
28032807
self.monitor_pending_commitment_signed = false;
2804-
return (None, None, RAACommitmentOrder::RevokeAndACKFirst, forwards, failures, needs_broadcast_safe, funding_locked);
2808+
return (None, None, RAACommitmentOrder::RevokeAndACKFirst, forwards, failures, funding_broadcastable, funding_locked);
28052809
}
28062810

28072811
let raa = if self.monitor_pending_revoke_and_ack {
@@ -2815,11 +2819,11 @@ impl<Signer: Sign> Channel<Signer> {
28152819
self.monitor_pending_commitment_signed = false;
28162820
let order = self.resend_order.clone();
28172821
log_trace!(logger, "Restored monitor updating resulting in {}{} commitment update and {} RAA, with {} first",
2818-
if needs_broadcast_safe { "a funding broadcast safe, " } else { "" },
2822+
if funding_broadcastable.is_some() { "a funding broadcast safe, " } else { "" },
28192823
if commitment_update.is_some() { "a" } else { "no" },
28202824
if raa.is_some() { "an" } else { "no" },
28212825
match order { RAACommitmentOrder::CommitmentFirst => "commitment", RAACommitmentOrder::RevokeAndACKFirst => "RAA"});
2822-
(raa, commitment_update, order, forwards, failures, needs_broadcast_safe, funding_locked)
2826+
(raa, commitment_update, order, forwards, failures, funding_broadcastable, funding_locked)
28232827
}
28242828

28252829
pub fn update_fee<F: Deref>(&mut self, fee_estimator: &F, msg: &msgs::UpdateFee) -> Result<(), ChannelError>
@@ -3734,7 +3738,7 @@ impl<Signer: Sign> Channel<Signer> {
37343738
/// Note that channel_id changes during this call!
37353739
/// Do NOT broadcast the funding transaction until after a successful funding_signed call!
37363740
/// If an Err is returned, it is a ChannelError::Close.
3737-
pub fn get_outbound_funding_created<L: Deref>(&mut self, funding_txo: OutPoint, logger: &L) -> Result<msgs::FundingCreated, ChannelError> where L::Target: Logger {
3741+
pub fn get_outbound_funding_created<L: Deref>(&mut self, funding_transaction: Transaction, funding_txo: OutPoint, logger: &L) -> Result<msgs::FundingCreated, ChannelError> where L::Target: Logger {
37383742
if !self.is_outbound() {
37393743
panic!("Tried to create outbound funding_created message on an inbound channel!");
37403744
}
@@ -3765,6 +3769,7 @@ impl<Signer: Sign> Channel<Signer> {
37653769

37663770
self.channel_state = ChannelState::FundingCreated as u32;
37673771
self.channel_id = funding_txo.to_channel_id();
3772+
self.funding_transaction = Some(funding_transaction);
37683773

37693774
Ok(msgs::FundingCreated {
37703775
temporary_channel_id,
@@ -4489,8 +4494,9 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
44894494
}
44904495

44914496
self.channel_transaction_parameters.write(writer)?;
4492-
self.counterparty_cur_commitment_point.write(writer)?;
4497+
self.funding_transaction.write(writer)?;
44934498

4499+
self.counterparty_cur_commitment_point.write(writer)?;
44944500
self.counterparty_prev_commitment_point.write(writer)?;
44954501
self.counterparty_node_id.write(writer)?;
44964502

@@ -4659,6 +4665,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
46594665
};
46604666

46614667
let channel_parameters = Readable::read(reader)?;
4668+
let funding_transaction = Readable::read(reader)?;
4669+
46624670
let counterparty_cur_commitment_point = Readable::read(reader)?;
46634671

46644672
let counterparty_prev_commitment_point = Readable::read(reader)?;
@@ -4731,8 +4739,9 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
47314739
counterparty_forwarding_info,
47324740

47334741
channel_transaction_parameters: channel_parameters,
4734-
counterparty_cur_commitment_point,
4742+
funding_transaction,
47354743

4744+
counterparty_cur_commitment_point,
47364745
counterparty_prev_commitment_point,
47374746
counterparty_node_id,
47384747

@@ -5000,7 +5009,7 @@ mod tests {
50005009
value: 10000000, script_pubkey: output_script.clone(),
50015010
}]};
50025011
let funding_outpoint = OutPoint{ txid: tx.txid(), index: 0 };
5003-
let funding_created_msg = node_a_chan.get_outbound_funding_created(funding_outpoint, &&logger).unwrap();
5012+
let funding_created_msg = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).unwrap();
50045013
let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, last_block_hash, &&logger).unwrap();
50055014

50065015
// Node B --> Node A: funding signed

lightning/src/ln/channelmanager.rs

Lines changed: 32 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
//!
2020
2121
use bitcoin::blockdata::block::{Block, BlockHeader};
22+
use bitcoin::blockdata::transaction::Transaction;
2223
use bitcoin::blockdata::constants::genesis_block;
2324
use bitcoin::network::constants::Network;
2425

@@ -1528,29 +1529,48 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
15281529
/// Note that ALL inputs in the transaction pointed to by funding_txo MUST spend SegWit outputs
15291530
/// or your counterparty can steal your funds!
15301531
///
1532+
/// Returns an [`APIError::APIMisuseError`] if the funding_transaction spent non-SegWit outputs
1533+
/// or the output didn't match the parameters in [`Event::FundingGenerationReady`].
1534+
///
15311535
/// Panics if a funding transaction has already been provided for this channel.
15321536
///
15331537
/// May panic if the funding_txo is duplicative with some other channel (note that this should
15341538
/// be trivially prevented by using unique funding transaction keys per-channel).
1535-
pub fn funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], funding_txo: OutPoint) {
1539+
pub fn funding_transaction_generated(&self, temporary_channel_id: &[u8; 32], funding_transaction: Transaction, output_index: u16) -> Result<(), APIError> {
15361540
let _persistence_guard = PersistenceNotifierGuard::new(&self.total_consistency_lock, &self.persistence_notifier);
15371541

1542+
for inp in funding_transaction.input.iter() {
1543+
if inp.witness.is_empty() {
1544+
return Err(APIError::APIMisuseError {
1545+
err: "Funding transaction must be fully signed and spend Segwit outputs".to_owned()
1546+
});
1547+
}
1548+
}
1549+
let funding_txo = OutPoint { txid: funding_transaction.txid(), index: output_index };
1550+
15381551
let (chan, msg) = {
15391552
let (res, chan) = match self.channel_state.lock().unwrap().by_id.remove(temporary_channel_id) {
15401553
Some(mut chan) => {
1541-
(chan.get_outbound_funding_created(funding_txo, &self.logger)
1554+
if output_index as usize >= funding_transaction.output.len() ||
1555+
funding_transaction.output[output_index as usize].script_pubkey != chan.get_funding_redeemscript().to_v0_p2wsh() ||
1556+
funding_transaction.output[output_index as usize].value != chan.get_value_satoshis() {
1557+
return Err(APIError::APIMisuseError {
1558+
err: "Funding Transaction Output did not match the script_pubkey or value in the FundingGenerationReady event".to_owned()
1559+
});
1560+
}
1561+
(chan.get_outbound_funding_created(funding_transaction, funding_txo, &self.logger)
15421562
.map_err(|e| if let ChannelError::Close(msg) = e {
15431563
MsgHandleErrInternal::from_finish_shutdown(msg, chan.channel_id(), chan.force_shutdown(true), None)
15441564
} else { unreachable!(); })
15451565
, chan)
15461566
},
1547-
None => return
1567+
None => { return Err(APIError::ChannelUnavailable { err: "No such channel".to_owned() }) },
15481568
};
15491569
match handle_error!(self, res, chan.get_counterparty_node_id()) {
15501570
Ok(funding_msg) => {
15511571
(chan, funding_msg)
15521572
},
1553-
Err(_) => { return; }
1573+
Err(_) => { return Err(APIError::ChannelUnavailable { err: "Error deriving keys - either our RNG or our counterparty's RNG is broken".to_owned() }) },
15541574
}
15551575
};
15561576

@@ -1567,6 +1587,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
15671587
e.insert(chan);
15681588
}
15691589
}
1590+
Ok(())
15701591
}
15711592

15721593
fn get_announcement_sigs(&self, chan: &Channel<Signer>) -> Option<msgs::AnnouncementSignatures> {
@@ -2359,7 +2380,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
23592380
return;
23602381
}
23612382

2362-
let (raa, commitment_update, order, pending_forwards, mut pending_failures, needs_broadcast_safe, funding_locked) = channel.monitor_updating_restored(&self.logger);
2383+
let (raa, commitment_update, order, pending_forwards, mut pending_failures, funding_broadcastable, funding_locked) = channel.monitor_updating_restored(&self.logger);
23632384
if !pending_forwards.is_empty() {
23642385
htlc_forwards.push((channel.get_short_channel_id().expect("We can't have pending forwards before funding confirmation"), funding_txo.clone(), pending_forwards));
23652386
}
@@ -2391,11 +2412,8 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
23912412
handle_cs!();
23922413
},
23932414
}
2394-
if needs_broadcast_safe {
2395-
pending_events.push(events::Event::FundingBroadcastSafe {
2396-
funding_txo: channel.get_funding_txo().unwrap(),
2397-
user_channel_id: channel.get_user_id(),
2398-
});
2415+
if let Some(tx) = funding_broadcastable {
2416+
self.tx_broadcaster.broadcast_transaction(&tx);
23992417
}
24002418
if let Some(msg) = funding_locked {
24012419
pending_msg_events.push(events::MessageSendEvent::SendFundingLocked {
@@ -2529,7 +2547,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
25292547
}
25302548

25312549
fn internal_funding_signed(&self, counterparty_node_id: &PublicKey, msg: &msgs::FundingSigned) -> Result<(), MsgHandleErrInternal> {
2532-
let (funding_txo, user_id) = {
2550+
let funding_tx = {
25332551
let last_block_hash = *self.last_block_hash.read().unwrap();
25342552
let mut channel_lock = self.channel_state.lock().unwrap();
25352553
let channel_state = &mut *channel_lock;
@@ -2538,23 +2556,19 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
25382556
if chan.get().get_counterparty_node_id() != *counterparty_node_id {
25392557
return Err(MsgHandleErrInternal::send_err_msg_no_close("Got a message for a channel from the wrong node!".to_owned(), msg.channel_id));
25402558
}
2541-
let monitor = match chan.get_mut().funding_signed(&msg, last_block_hash, &self.logger) {
2559+
let (monitor, funding_tx) = match chan.get_mut().funding_signed(&msg, last_block_hash, &self.logger) {
25422560
Ok(update) => update,
25432561
Err(e) => try_chan_entry!(self, Err(e), channel_state, chan),
25442562
};
25452563
if let Err(e) = self.chain_monitor.watch_channel(chan.get().get_funding_txo().unwrap(), monitor) {
25462564
return_monitor_err!(self, e, channel_state, chan, RAACommitmentOrder::RevokeAndACKFirst, false, false);
25472565
}
2548-
(chan.get().get_funding_txo().unwrap(), chan.get().get_user_id())
2566+
funding_tx
25492567
},
25502568
hash_map::Entry::Vacant(_) => return Err(MsgHandleErrInternal::send_err_msg_no_close("Failed to find corresponding channel".to_owned(), msg.channel_id))
25512569
}
25522570
};
2553-
let mut pending_events = self.pending_events.lock().unwrap();
2554-
pending_events.push(events::Event::FundingBroadcastSafe {
2555-
funding_txo,
2556-
user_channel_id: user_id,
2557-
});
2571+
self.tx_broadcaster.broadcast_transaction(&funding_tx);
25582572
Ok(())
25592573
}
25602574

lightning/src/ln/functional_test_utils.rs

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -421,7 +421,7 @@ pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, '
421421

422422
let (temporary_channel_id, tx, funding_output) = create_funding_transaction(node_a, channel_value, 42);
423423

424-
node_a.node.funding_transaction_generated(&temporary_channel_id, funding_output);
424+
node_a.node.funding_transaction_generated(&temporary_channel_id, tx.clone(), funding_output.index).unwrap();
425425
check_added_monitors!(node_a, 0);
426426

427427
node_b.node.handle_funding_created(&node_a.node.get_our_node_id(), &get_event_msg!(node_a, MessageSendEvent::SendFundingCreated, node_b.node.get_our_node_id()));
@@ -441,14 +441,11 @@ pub fn create_chan_between_nodes_with_value_init<'a, 'b, 'c>(node_a: &Node<'a, '
441441
}
442442

443443
let events_4 = node_a.node.get_and_clear_pending_events();
444-
assert_eq!(events_4.len(), 1);
445-
match events_4[0] {
446-
Event::FundingBroadcastSafe { ref funding_txo, user_channel_id } => {
447-
assert_eq!(user_channel_id, 42);
448-
assert_eq!(*funding_txo, funding_output);
449-
},
450-
_ => panic!("Unexpected event"),
451-
};
444+
assert_eq!(events_4.len(), 0);
445+
446+
assert_eq!(node_a.tx_broadcaster.txn_broadcasted.lock().unwrap().len(), 1);
447+
assert_eq!(node_a.tx_broadcaster.txn_broadcasted.lock().unwrap()[0], tx);
448+
node_a.tx_broadcaster.txn_broadcasted.lock().unwrap().clear();
452449

453450
tx
454451
}

0 commit comments

Comments
 (0)