@@ -1168,6 +1168,41 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1168
1168
L :: Target : Logger ,
1169
1169
{
1170
1170
self . payment_preimages . insert ( payment_hash. clone ( ) , payment_preimage. clone ( ) ) ;
1171
+
1172
+ // If the channel is force closed, try to claim the output from this preimage.
1173
+ // First check if a counterparty commitment transaction has been broadcasted:
1174
+ macro_rules! claim_htlcs {
1175
+ ( $commitment_number: expr, $txid: expr) => {
1176
+ let htlc_claim_reqs = self . get_counterparty_htlc_output_claim_reqs( $commitment_number, $txid, None ) ;
1177
+ self . onchain_tx_handler. update_claims_view( & Vec :: new( ) , htlc_claim_reqs, None , broadcaster, fee_estimator, logger) ;
1178
+ }
1179
+ }
1180
+ if let Some ( txid) = self . current_counterparty_commitment_txid {
1181
+ if let Some ( commitment_number) = self . counterparty_commitment_txn_on_chain . get ( & txid) {
1182
+ claim_htlcs ! ( * commitment_number, txid) ;
1183
+ return ;
1184
+ }
1185
+ }
1186
+ if let Some ( txid) = self . prev_counterparty_commitment_txid {
1187
+ if let Some ( commitment_number) = self . counterparty_commitment_txn_on_chain . get ( & txid) {
1188
+ claim_htlcs ! ( * commitment_number, txid) ;
1189
+ return ;
1190
+ }
1191
+ }
1192
+
1193
+ // Then if a holder commitment transaction has been seen on-chain, broadcast transactions
1194
+ // claiming the HTLC output from each of the holder commitment transactions.
1195
+ // Note that we can't just use `self.holder_tx_signed`, because that only covers the case where
1196
+ // *we* sign a holder commitment transaction, not when e.g. a watchtower broadcasts one of our
1197
+ // holder commitment transactions.
1198
+ if self . broadcasted_holder_revokable_script . is_some ( ) {
1199
+ let ( claim_reqs, _, _) = self . broadcast_by_holder_state ( None , & self . current_holder_commitment_tx ) ;
1200
+ self . onchain_tx_handler . update_claims_view ( & Vec :: new ( ) , claim_reqs, None , broadcaster, fee_estimator, logger) ;
1201
+ if let Some ( ref tx) = self . prev_holder_signed_commitment_tx {
1202
+ let ( claim_reqs, _, _) = self . broadcast_by_holder_state ( None , & tx) ;
1203
+ self . onchain_tx_handler . update_claims_view ( & Vec :: new ( ) , claim_reqs, None , broadcaster, fee_estimator, logger) ;
1204
+ }
1205
+ }
1171
1206
}
1172
1207
1173
1208
pub ( crate ) fn broadcast_latest_holder_commitment_txn < B : Deref , L : Deref > ( & mut self , broadcaster : & B , logger : & L )
@@ -1467,39 +1502,49 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1467
1502
check_htlc_fails ! ( txid, "previous" , ' prev_loop) ;
1468
1503
}
1469
1504
1505
+ let htlc_claim_reqs = self . get_counterparty_htlc_output_claim_reqs ( commitment_number, commitment_txid, Some ( tx) ) ;
1506
+ for req in htlc_claim_reqs {
1507
+ claimable_outpoints. push ( req) ;
1508
+ }
1509
+
1510
+ }
1511
+ ( claimable_outpoints, ( commitment_txid, watch_outputs) )
1512
+ }
1513
+
1514
+ fn get_counterparty_htlc_output_claim_reqs ( & self , commitment_number : u64 , commitment_txid : Txid , tx : Option < & Transaction > ) -> Vec < ClaimRequest > {
1515
+ let mut claims = Vec :: new ( ) ;
1516
+ if let Some ( htlc_outputs) = self . counterparty_claimable_outpoints . get ( & commitment_txid) {
1470
1517
if let Some ( revocation_points) = self . their_cur_revocation_points {
1471
1518
let revocation_point_option =
1472
1519
if revocation_points. 0 == commitment_number { Some ( & revocation_points. 1 ) }
1473
- else if let Some ( point) = revocation_points. 2 . as_ref ( ) {
1474
- if revocation_points. 0 == commitment_number + 1 { Some ( point) } else { None }
1475
- } else { None } ;
1520
+ else if let Some ( point) = revocation_points. 2 . as_ref ( ) {
1521
+ if revocation_points. 0 == commitment_number + 1 { Some ( point) } else { None }
1522
+ } else { None } ;
1476
1523
if let Some ( revocation_point) = revocation_point_option {
1477
- self . counterparty_payment_script = {
1478
- // Note that the Network here is ignored as we immediately drop the address for the
1479
- // script_pubkey version
1480
- let payment_hash160 = WPubkeyHash :: hash ( & self . keys . pubkeys ( ) . payment_point . serialize ( ) ) ;
1481
- Builder :: new ( ) . push_opcode ( opcodes:: all:: OP_PUSHBYTES_0 ) . push_slice ( & payment_hash160[ ..] ) . into_script ( )
1482
- } ;
1483
-
1484
- // Then, try to find htlc outputs
1485
- for ( _, & ( ref htlc, _) ) in per_commitment_data. iter ( ) . enumerate ( ) {
1524
+ for ( _, & ( ref htlc, _) ) in htlc_outputs. iter ( ) . enumerate ( ) {
1486
1525
if let Some ( transaction_output_index) = htlc. transaction_output_index {
1487
- if transaction_output_index as usize >= tx. output . len ( ) ||
1488
- tx. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 {
1489
- return ( claimable_outpoints, ( commitment_txid, watch_outputs) ) ; // Corrupted per_commitment_data, fuck this user
1526
+ if let Some ( transaction) = tx {
1527
+ if transaction_output_index as usize >= transaction. output . len ( ) ||
1528
+ transaction. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 {
1529
+ return claims; // Corrupted per_commitment_data, fuck this user
1530
+ }
1490
1531
}
1491
- let preimage = if htlc. offered { if let Some ( p) = self . payment_preimages . get ( & htlc. payment_hash ) { Some ( * p) } else { None } } else { None } ;
1532
+ let preimage = if htlc. offered {
1533
+ if let Some ( p) = self . payment_preimages . get ( & htlc. payment_hash ) {
1534
+ Some ( * p)
1535
+ } else { None }
1536
+ } else { None } ;
1492
1537
let aggregable = if !htlc. offered { false } else { true } ;
1493
1538
if preimage. is_some ( ) || !htlc. offered {
1494
1539
let witness_data = InputMaterial :: CounterpartyHTLC { per_commitment_point : * revocation_point, counterparty_delayed_payment_base_key : self . counterparty_tx_cache . counterparty_delayed_payment_base_key , counterparty_htlc_base_key : self . counterparty_tx_cache . counterparty_htlc_base_key , preimage, htlc : htlc. clone ( ) } ;
1495
- claimable_outpoints . push ( ClaimRequest { absolute_timelock : htlc. cltv_expiry , aggregable, outpoint : BitcoinOutPoint { txid : commitment_txid, vout : transaction_output_index } , witness_data } ) ;
1540
+ claims . push ( ClaimRequest { absolute_timelock : htlc. cltv_expiry , aggregable, outpoint : BitcoinOutPoint { txid : commitment_txid, vout : transaction_output_index } , witness_data } ) ;
1496
1541
}
1497
1542
}
1498
1543
}
1499
1544
}
1500
1545
}
1501
1546
}
1502
- ( claimable_outpoints , ( commitment_txid , watch_outputs ) )
1547
+ claims
1503
1548
}
1504
1549
1505
1550
/// Attempts to claim a counterparty HTLC-Success/HTLC-Timeout's outputs using the revocation key
@@ -1529,7 +1574,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1529
1574
( claimable_outpoints, Some ( ( htlc_txid, outputs) ) )
1530
1575
}
1531
1576
1532
- fn broadcast_by_holder_state ( & self , commitment_tx : & Transaction , holder_tx : & HolderSignedTx ) -> ( Vec < ClaimRequest > , Vec < ( u32 , TxOut ) > , Option < ( Script , PublicKey , PublicKey ) > ) {
1577
+ fn broadcast_by_holder_state ( & self , commitment_tx : Option < & Transaction > , holder_tx : & HolderSignedTx ) -> ( Vec < ClaimRequest > , Vec < ( u32 , TxOut ) > , Option < ( Script , PublicKey , PublicKey ) > ) {
1533
1578
let mut claim_requests = Vec :: with_capacity ( holder_tx. htlc_outputs . len ( ) ) ;
1534
1579
let mut watch_outputs = Vec :: with_capacity ( holder_tx. htlc_outputs . len ( ) ) ;
1535
1580
@@ -1550,7 +1595,9 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1550
1595
} else { None } ,
1551
1596
amount : htlc. amount_msat ,
1552
1597
} } ) ;
1553
- watch_outputs. push ( ( transaction_output_index, commitment_tx. output [ transaction_output_index as usize ] . clone ( ) ) ) ;
1598
+ if let Some ( commitment_tx) = commitment_tx {
1599
+ watch_outputs. push ( ( transaction_output_index, commitment_tx. output [ transaction_output_index as usize ] . clone ( ) ) ) ;
1600
+ }
1554
1601
}
1555
1602
}
1556
1603
@@ -1602,13 +1649,13 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1602
1649
if self . current_holder_commitment_tx . txid == commitment_txid {
1603
1650
is_holder_tx = true ;
1604
1651
log_trace ! ( logger, "Got latest holder commitment tx broadcast, searching for available HTLCs to claim" ) ;
1605
- let mut res = self . broadcast_by_holder_state ( tx , & self . current_holder_commitment_tx ) ;
1652
+ let mut res = self . broadcast_by_holder_state ( Some ( tx ) , & self . current_holder_commitment_tx ) ;
1606
1653
append_onchain_update ! ( res) ;
1607
1654
} else if let & Some ( ref holder_tx) = & self . prev_holder_signed_commitment_tx {
1608
1655
if holder_tx. txid == commitment_txid {
1609
1656
is_holder_tx = true ;
1610
1657
log_trace ! ( logger, "Got previous holder commitment tx broadcast, searching for available HTLCs to claim" ) ;
1611
- let mut res = self . broadcast_by_holder_state ( tx , holder_tx) ;
1658
+ let mut res = self . broadcast_by_holder_state ( Some ( tx ) , holder_tx) ;
1612
1659
append_onchain_update ! ( res) ;
1613
1660
}
1614
1661
}
@@ -1777,7 +1824,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1777
1824
self . pending_monitor_events . push ( MonitorEvent :: CommitmentTxBroadcasted ( self . funding_info . 0 ) ) ;
1778
1825
if let Some ( commitment_tx) = self . onchain_tx_handler . get_fully_signed_holder_tx ( & self . funding_redeemscript ) {
1779
1826
self . holder_tx_signed = true ;
1780
- let ( mut new_outpoints, new_outputs, _) = self . broadcast_by_holder_state ( & commitment_tx, & self . current_holder_commitment_tx ) ;
1827
+ let ( mut new_outpoints, new_outputs, _) = self . broadcast_by_holder_state ( Some ( & commitment_tx) , & self . current_holder_commitment_tx ) ;
1781
1828
if !new_outputs. is_empty ( ) {
1782
1829
watch_outputs. push ( ( self . current_holder_commitment_tx . txid . clone ( ) , new_outputs) ) ;
1783
1830
}
@@ -1805,7 +1852,7 @@ impl<ChanSigner: ChannelKeys> ChannelMonitor<ChanSigner> {
1805
1852
}
1806
1853
}
1807
1854
1808
- self . onchain_tx_handler . block_connected ( & txn_matched, claimable_outpoints, height, & * broadcaster, & * fee_estimator, & * logger) ;
1855
+ self . onchain_tx_handler . update_claims_view ( & txn_matched, claimable_outpoints, Some ( height) , & & * broadcaster, & & * fee_estimator, & & * logger) ;
1809
1856
self . last_block_hash = block_hash;
1810
1857
1811
1858
// Determine new outputs to watch by comparing against previously known outputs to watch,
0 commit comments