Skip to content

Commit 3f2efcd

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 3f2efcd

File tree

9 files changed

+148
-151
lines changed

9 files changed

+148
-151
lines changed

background-processor/src/lib.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -189,21 +189,20 @@ mod tests {
189189
$node_a.node.handle_accept_channel(&$node_b.node.get_our_node_id(), InitFeatures::known(), &get_event_msg!($node_b, MessageSendEvent::SendAcceptChannel, $node_a.node.get_our_node_id()));
190190
let events = $node_a.node.get_and_clear_pending_events();
191191
assert_eq!(events.len(), 1);
192-
let (temporary_channel_id, tx, funding_output) = match events[0] {
192+
let (temporary_channel_id, tx) = match events[0] {
193193
Event::FundingGenerationReady { ref temporary_channel_id, ref channel_value_satoshis, ref output_script, user_channel_id } => {
194194
assert_eq!(*channel_value_satoshis, $channel_value);
195195
assert_eq!(user_channel_id, 42);
196196

197197
let tx = Transaction { version: 1 as i32, lock_time: 0, input: Vec::new(), output: vec![TxOut {
198198
value: *channel_value_satoshis, script_pubkey: output_script.clone(),
199199
}]};
200-
let funding_outpoint = OutPoint { txid: tx.txid(), index: 0 };
201-
(*temporary_channel_id, tx, funding_outpoint)
200+
(*temporary_channel_id, tx)
202201
},
203202
_ => panic!("Unexpected event"),
204203
};
205204

206-
$node_a.node.funding_transaction_generated(&temporary_channel_id, funding_output);
205+
$node_a.node.funding_transaction_generated(&temporary_channel_id, tx.clone()).unwrap();
207206
$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()));
208207
$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()));
209208
tx

fuzz/src/chanmon_consistency.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -397,7 +397,7 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
397397
value: *channel_value_satoshis, script_pubkey: output_script.clone(),
398398
}]};
399399
funding_output = OutPoint { txid: tx.txid(), index: 0 };
400-
$source.funding_transaction_generated(&temporary_channel_id, funding_output);
400+
$source.funding_transaction_generated(&temporary_channel_id, tx.clone()).unwrap();
401401
channel_txn.push(tx);
402402
} else { panic!("Wrong event type"); }
403403
}
@@ -420,12 +420,6 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
420420
};
421421
$source.handle_funding_signed(&$dest.get_our_node_id(), &funding_signed);
422422

423-
{
424-
let events = $source.get_and_clear_pending_events();
425-
assert_eq!(events.len(), 1);
426-
if let events::Event::FundingBroadcastSafe { .. } = events[0] {
427-
} else { panic!("Wrong event type"); }
428-
}
429423
funding_output
430424
} }
431425
}

fuzz/src/full_stack.rs

Lines changed: 13 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use bitcoin::secp256k1::Secp256k1;
5151
use std::cell::RefCell;
5252
use std::collections::{HashMap, hash_map};
5353
use std::cmp;
54-
use std::sync::Arc;
54+
use std::sync::{Arc, Mutex};
5555
use std::sync::atomic::{AtomicU64,AtomicUsize,Ordering};
5656

5757
#[inline]
@@ -116,9 +116,13 @@ impl FeeEstimator for FuzzEstimator {
116116
}
117117
}
118118

119-
struct TestBroadcaster {}
119+
struct TestBroadcaster {
120+
txn_broadcasted: Mutex<Vec<Transaction>>,
121+
}
120122
impl BroadcasterInterface for TestBroadcaster {
121-
fn broadcast_transaction(&self, _tx: &Transaction) {}
123+
fn broadcast_transaction(&self, tx: &Transaction) {
124+
self.txn_broadcasted.lock().unwrap().push(tx.clone());
125+
}
122126
}
123127

124128
#[derive(Clone)]
@@ -340,7 +344,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
340344
Err(_) => return,
341345
};
342346

343-
let broadcast = Arc::new(TestBroadcaster{});
347+
let broadcast = Arc::new(TestBroadcaster{ txn_broadcasted: Mutex::new(Vec::new()) });
344348
let monitor = Arc::new(chainmonitor::ChainMonitor::new(None, broadcast.clone(), Arc::clone(&logger), fee_est.clone(), Arc::new(TestPersister{})));
345349

346350
let keys_manager = Arc::new(KeyProvider { node_secret: our_network_key.clone(), counter: AtomicU64::new(0) });
@@ -370,7 +374,6 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
370374
let mut payments_sent = 0;
371375
let mut pending_funding_generation: Vec<([u8; 32], u64, Script)> = Vec::new();
372376
let mut pending_funding_signatures = HashMap::new();
373-
let mut pending_funding_relay = Vec::new();
374377

375378
loop {
376379
match get_slice!(1)[0] {
@@ -513,18 +516,19 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
513516
continue 'outer_loop;
514517
}
515518
};
516-
channelmanager.funding_transaction_generated(&funding_generation.0, funding_output.clone());
519+
channelmanager.funding_transaction_generated(&funding_generation.0, tx.clone()).unwrap();
517520
pending_funding_signatures.insert(funding_output, tx);
518521
}
519522
},
520523
11 => {
521-
if !pending_funding_relay.is_empty() {
522-
loss_detector.connect_block(&pending_funding_relay[..]);
524+
let mut txn = broadcast.txn_broadcasted.lock().unwrap();
525+
if !txn.is_empty() {
526+
loss_detector.connect_block(&txn[..]);
523527
for _ in 2..100 {
524528
loss_detector.connect_block(&[]);
525529
}
526530
}
527-
for tx in pending_funding_relay.drain(..) {
531+
for tx in txn.drain(..) {
528532
loss_detector.funding_txn.push(tx);
529533
}
530534
},
@@ -566,9 +570,6 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
566570
Event::FundingGenerationReady { temporary_channel_id, channel_value_satoshis, output_script, .. } => {
567571
pending_funding_generation.push((temporary_channel_id, channel_value_satoshis, output_script));
568572
},
569-
Event::FundingBroadcastSafe { funding_txo, .. } => {
570-
pending_funding_relay.push(pending_funding_signatures.remove(&funding_txo).unwrap());
571-
},
572573
Event::PaymentReceived { payment_hash, payment_secret, amt } => {
573574
//TODO: enhance by fetching random amounts from fuzz input?
574575
payments_received.push((payment_hash, payment_secret, amt));

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()).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: 29 additions & 21 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,20 +2773,21 @@ 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

2780-
// Because we will never generate a FundingBroadcastSafe event when we're in
2781-
// MonitorUpdateFailed, if we assume the user only broadcast the funding transaction when
2782-
// they received the FundingBroadcastSafe event, we can only ever hit
2783-
// monitor_pending_funding_locked when we're an inbound channel which failed to persist the
2784-
// monitor on funding_created, and we even got the funding transaction confirmed before the
2785-
// monitor was persisted.
2784+
// We will never broadcast the funding transaction when we're in MonitorUpdateFailed (and
2785+
// we assume the user never directly broadcasts the funding transaction and waits for us to
2786+
// do it). Thus, we can only ever hit monitor_pending_funding_locked when we're an inbound
2787+
// channel which failed to persist the monitor on funding_created, and we got the funding
2788+
// transaction confirmed before the monitor was persisted.
27862789
let funding_locked = if self.monitor_pending_funding_locked {
2787-
assert!(!self.is_outbound(), "Funding transaction broadcast without FundingBroadcastSafe!");
2790+
assert!(!self.is_outbound(), "Funding transaction broadcast by the local client before it should have - LDK didn't do it!");
27882791
self.monitor_pending_funding_locked = false;
27892792
let next_per_commitment_point = self.holder_signer.get_per_commitment_point(self.cur_holder_commitment_transaction_number, &self.secp_ctx);
27902793
Some(msgs::FundingLocked {
@@ -2801,7 +2804,7 @@ impl<Signer: Sign> Channel<Signer> {
28012804
if self.channel_state & (ChannelState::PeerDisconnected as u32) != 0 {
28022805
self.monitor_pending_revoke_and_ack = false;
28032806
self.monitor_pending_commitment_signed = false;
2804-
return (None, None, RAACommitmentOrder::RevokeAndACKFirst, forwards, failures, needs_broadcast_safe, funding_locked);
2807+
return (None, None, RAACommitmentOrder::RevokeAndACKFirst, forwards, failures, funding_broadcastable, funding_locked);
28052808
}
28062809

28072810
let raa = if self.monitor_pending_revoke_and_ack {
@@ -2815,11 +2818,11 @@ impl<Signer: Sign> Channel<Signer> {
28152818
self.monitor_pending_commitment_signed = false;
28162819
let order = self.resend_order.clone();
28172820
log_trace!(logger, "Restored monitor updating resulting in {}{} commitment update and {} RAA, with {} first",
2818-
if needs_broadcast_safe { "a funding broadcast safe, " } else { "" },
2821+
if funding_broadcastable.is_some() { "a funding broadcastable, " } else { "" },
28192822
if commitment_update.is_some() { "a" } else { "no" },
28202823
if raa.is_some() { "an" } else { "no" },
28212824
match order { RAACommitmentOrder::CommitmentFirst => "commitment", RAACommitmentOrder::RevokeAndACKFirst => "RAA"});
2822-
(raa, commitment_update, order, forwards, failures, needs_broadcast_safe, funding_locked)
2825+
(raa, commitment_update, order, forwards, failures, funding_broadcastable, funding_locked)
28232826
}
28242827

28252828
pub fn update_fee<F: Deref>(&mut self, fee_estimator: &F, msg: &msgs::UpdateFee) -> Result<(), ChannelError>
@@ -3734,7 +3737,7 @@ impl<Signer: Sign> Channel<Signer> {
37343737
/// Note that channel_id changes during this call!
37353738
/// Do NOT broadcast the funding transaction until after a successful funding_signed call!
37363739
/// 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 {
3740+
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 {
37383741
if !self.is_outbound() {
37393742
panic!("Tried to create outbound funding_created message on an inbound channel!");
37403743
}
@@ -3765,6 +3768,7 @@ impl<Signer: Sign> Channel<Signer> {
37653768

37663769
self.channel_state = ChannelState::FundingCreated as u32;
37673770
self.channel_id = funding_txo.to_channel_id();
3771+
self.funding_transaction = Some(funding_transaction);
37683772

37693773
Ok(msgs::FundingCreated {
37703774
temporary_channel_id,
@@ -4489,8 +4493,9 @@ impl<Signer: Sign> Writeable for Channel<Signer> {
44894493
}
44904494

44914495
self.channel_transaction_parameters.write(writer)?;
4492-
self.counterparty_cur_commitment_point.write(writer)?;
4496+
self.funding_transaction.write(writer)?;
44934497

4498+
self.counterparty_cur_commitment_point.write(writer)?;
44944499
self.counterparty_prev_commitment_point.write(writer)?;
44954500
self.counterparty_node_id.write(writer)?;
44964501

@@ -4659,6 +4664,8 @@ impl<'a, Signer: Sign, K: Deref> ReadableArgs<&'a K> for Channel<Signer>
46594664
};
46604665

46614666
let channel_parameters = Readable::read(reader)?;
4667+
let funding_transaction = Readable::read(reader)?;
4668+
46624669
let counterparty_cur_commitment_point = Readable::read(reader)?;
46634670

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

47334740
channel_transaction_parameters: channel_parameters,
4734-
counterparty_cur_commitment_point,
4741+
funding_transaction,
47354742

4743+
counterparty_cur_commitment_point,
47364744
counterparty_prev_commitment_point,
47374745
counterparty_node_id,
47384746

@@ -5000,7 +5008,7 @@ mod tests {
50005008
value: 10000000, script_pubkey: output_script.clone(),
50015009
}]};
50025010
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();
5011+
let funding_created_msg = node_a_chan.get_outbound_funding_created(tx.clone(), funding_outpoint, &&logger).unwrap();
50045012
let (funding_signed_msg, _) = node_b_chan.funding_created(&funding_created_msg, last_block_hash, &&logger).unwrap();
50055013

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

0 commit comments

Comments
 (0)