@@ -1564,61 +1564,14 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1564
1564
}
1565
1565
}
1566
1566
1567
- /// Call this upon creation of a funding transaction for the given channel.
1568
- ///
1569
- /// Returns an [`APIError::APIMisuseError`] if the funding_transaction spent non-SegWit outputs
1570
- /// or if no output was found which matches the parameters in [`Event::FundingGenerationReady`].
1571
- ///
1572
- /// Panics if a funding transaction has already been provided for this channel.
1573
- ///
1574
- /// May panic if the output found in the funding transaction is duplicative with some other
1575
- /// channel (note that this should be trivially prevented by using unique funding transaction
1576
- /// keys per-channel).
1577
- ///
1578
- /// Do NOT broadcast the funding transaction yourself. When we have safely received our
1579
- /// counterparty's signature the funding transaction will automatically be broadcast via the
1580
- /// [`BroadcasterInterface`] provided when this `ChannelManager` was constructed.
1581
- ///
1582
- /// Note that this includes RBF or similar transaction replacement strategies - lightning does
1583
- /// not currently support replacing a funding transaction on an existing channel. Instead,
1584
- /// create a new channel with a conflicting funding transaction.
1585
- pub fn funding_transaction_generated ( & self , temporary_channel_id : & [ u8 ; 32 ] , funding_transaction : Transaction ) -> Result < ( ) , APIError > {
1586
- let _persistence_guard = PersistenceNotifierGuard :: new ( & self . total_consistency_lock , & self . persistence_notifier ) ;
1587
-
1588
- for inp in funding_transaction. input . iter ( ) {
1589
- if inp. witness . is_empty ( ) {
1590
- return Err ( APIError :: APIMisuseError {
1591
- err : "Funding transaction must be fully signed and spend Segwit outputs" . to_owned ( )
1592
- } ) ;
1593
- }
1594
- }
1595
-
1567
+ /// Handles the generation of a funding transaction, optionally (for tests) with a function
1568
+ /// which checks the correctness of the funding transaction given the associated channel.
1569
+ fn funding_transaction_generated_intern < FundingOutput : Fn ( & Channel < Signer > , & Transaction ) -> Result < OutPoint , APIError > >
1570
+ ( & self , temporary_channel_id : & [ u8 ; 32 ] , funding_transaction : Transaction , find_funding_output : FundingOutput ) -> Result < ( ) , APIError > {
1596
1571
let ( chan, msg) = {
1597
1572
let ( res, chan) = match self . channel_state . lock ( ) . unwrap ( ) . by_id . remove ( temporary_channel_id) {
1598
1573
Some ( mut chan) => {
1599
- let mut output_index = None ;
1600
- let expected_spk = chan. get_funding_redeemscript ( ) . to_v0_p2wsh ( ) ;
1601
- for ( idx, outp) in funding_transaction. output . iter ( ) . enumerate ( ) {
1602
- if outp. script_pubkey == expected_spk && outp. value == chan. get_value_satoshis ( ) {
1603
- if output_index. is_some ( ) {
1604
- return Err ( APIError :: APIMisuseError {
1605
- err : "Multiple outputs matched the expected script and value" . to_owned ( )
1606
- } ) ;
1607
- }
1608
- if idx > u16:: max_value ( ) as usize {
1609
- return Err ( APIError :: APIMisuseError {
1610
- err : "Transaction had more than 2^16 outputs, which is not supported" . to_owned ( )
1611
- } ) ;
1612
- }
1613
- output_index = Some ( idx as u16 ) ;
1614
- }
1615
- }
1616
- if output_index. is_none ( ) {
1617
- return Err ( APIError :: APIMisuseError {
1618
- err : "No output matched the script_pubkey and value in the FundingGenerationReady event" . to_owned ( )
1619
- } ) ;
1620
- }
1621
- let funding_txo = OutPoint { txid : funding_transaction. txid ( ) , index : output_index. unwrap ( ) } ;
1574
+ let funding_txo = find_funding_output ( & chan, & funding_transaction) ?;
1622
1575
1623
1576
( chan. get_outbound_funding_created ( funding_transaction, funding_txo, & self . logger )
1624
1577
. map_err ( |e| if let ChannelError :: Close ( msg) = e {
@@ -1654,6 +1607,68 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
1654
1607
Ok ( ( ) )
1655
1608
}
1656
1609
1610
+ #[ cfg( test) ]
1611
+ pub ( crate ) fn funding_transaction_generated_unchecked ( & self , temporary_channel_id : & [ u8 ; 32 ] , funding_transaction : Transaction , output_index : u16 ) -> Result < ( ) , APIError > {
1612
+ self . funding_transaction_generated_intern ( temporary_channel_id, funding_transaction, |_, tx| {
1613
+ Ok ( OutPoint { txid : tx. txid ( ) , index : output_index } )
1614
+ } )
1615
+ }
1616
+
1617
+ /// Call this upon creation of a funding transaction for the given channel.
1618
+ ///
1619
+ /// Returns an [`APIError::APIMisuseError`] if the funding_transaction spent non-SegWit outputs
1620
+ /// or if no output was found which matches the parameters in [`Event::FundingGenerationReady`].
1621
+ ///
1622
+ /// Panics if a funding transaction has already been provided for this channel.
1623
+ ///
1624
+ /// May panic if the output found in the funding transaction is duplicative with some other
1625
+ /// channel (note that this should be trivially prevented by using unique funding transaction
1626
+ /// keys per-channel).
1627
+ ///
1628
+ /// Do NOT broadcast the funding transaction yourself. When we have safely received our
1629
+ /// counterparty's signature the funding transaction will automatically be broadcast via the
1630
+ /// [`BroadcasterInterface`] provided when this `ChannelManager` was constructed.
1631
+ ///
1632
+ /// Note that this includes RBF or similar transaction replacement strategies - lightning does
1633
+ /// not currently support replacing a funding transaction on an existing channel. Instead,
1634
+ /// create a new channel with a conflicting funding transaction.
1635
+ pub fn funding_transaction_generated ( & self , temporary_channel_id : & [ u8 ; 32 ] , funding_transaction : Transaction ) -> Result < ( ) , APIError > {
1636
+ let _persistence_guard = PersistenceNotifierGuard :: new ( & self . total_consistency_lock , & self . persistence_notifier ) ;
1637
+
1638
+ for inp in funding_transaction. input . iter ( ) {
1639
+ if inp. witness . is_empty ( ) {
1640
+ return Err ( APIError :: APIMisuseError {
1641
+ err : "Funding transaction must be fully signed and spend Segwit outputs" . to_owned ( )
1642
+ } ) ;
1643
+ }
1644
+ }
1645
+ self . funding_transaction_generated_intern ( temporary_channel_id, funding_transaction, |chan, tx| {
1646
+ let mut output_index = None ;
1647
+ let expected_spk = chan. get_funding_redeemscript ( ) . to_v0_p2wsh ( ) ;
1648
+ for ( idx, outp) in tx. output . iter ( ) . enumerate ( ) {
1649
+ if outp. script_pubkey == expected_spk && outp. value == chan. get_value_satoshis ( ) {
1650
+ if output_index. is_some ( ) {
1651
+ return Err ( APIError :: APIMisuseError {
1652
+ err : "Multiple outputs matched the expected script and value" . to_owned ( )
1653
+ } ) ;
1654
+ }
1655
+ if idx > u16:: max_value ( ) as usize {
1656
+ return Err ( APIError :: APIMisuseError {
1657
+ err : "Transaction had more than 2^16 outputs, which is not supported" . to_owned ( )
1658
+ } ) ;
1659
+ }
1660
+ output_index = Some ( idx as u16 ) ;
1661
+ }
1662
+ }
1663
+ if output_index. is_none ( ) {
1664
+ return Err ( APIError :: APIMisuseError {
1665
+ err : "No output matched the script_pubkey and value in the FundingGenerationReady event" . to_owned ( )
1666
+ } ) ;
1667
+ }
1668
+ Ok ( OutPoint { txid : tx. txid ( ) , index : output_index. unwrap ( ) } )
1669
+ } )
1670
+ }
1671
+
1657
1672
fn get_announcement_sigs ( & self , chan : & Channel < Signer > ) -> Option < msgs:: AnnouncementSignatures > {
1658
1673
if !chan. should_announce ( ) {
1659
1674
log_trace ! ( self . logger, "Can't send announcement_signatures for private channel {}" , log_bytes!( chan. channel_id( ) ) ) ;
0 commit comments