@@ -385,6 +385,9 @@ pub struct ChannelMonitor {
385
385
386
386
destination_script : Script ,
387
387
388
+ htlc_updated_waiting_outpoint_solving : HashMap < BitcoinOutPoint , ( HTLCSource , Option < PaymentPreimage > , PaymentHash ) > ,
389
+ htlc_updated_waiting_threshold_conf : Vec < ( u32 , Option < BitcoinOutPoint > , ( HTLCSource , Option < PaymentPreimage > , PaymentHash ) ) > ,
390
+
388
391
// We simply modify last_block_hash in Channel's block_connected so that serialization is
389
392
// consistent but hopefully the users' copy handles block_connected in a consistent way.
390
393
// (we do *not*, however, update them in insert_combine to ensure any local user copies keep
@@ -414,7 +417,9 @@ impl PartialEq for ChannelMonitor {
414
417
self . current_remote_commitment_number != other. current_remote_commitment_number ||
415
418
self . current_local_signed_commitment_tx != other. current_local_signed_commitment_tx ||
416
419
self . payment_preimages != other. payment_preimages ||
417
- self . destination_script != other. destination_script
420
+ self . destination_script != other. destination_script ||
421
+ self . htlc_updated_waiting_outpoint_solving != other. htlc_updated_waiting_outpoint_solving ||
422
+ self . htlc_updated_waiting_threshold_conf != other. htlc_updated_waiting_threshold_conf
418
423
{
419
424
false
420
425
} else {
@@ -464,6 +469,9 @@ impl ChannelMonitor {
464
469
payment_preimages : HashMap :: new ( ) ,
465
470
destination_script : destination_script,
466
471
472
+ htlc_updated_waiting_outpoint_solving : HashMap :: new ( ) ,
473
+ htlc_updated_waiting_threshold_conf : Vec :: new ( ) ,
474
+
467
475
last_block_hash : Default :: default ( ) ,
468
476
secp_ctx : Secp256k1 :: new ( ) ,
469
477
logger,
@@ -951,6 +959,23 @@ impl ChannelMonitor {
951
959
self . last_block_hash . write ( writer) ?;
952
960
self . destination_script . write ( writer) ?;
953
961
962
+ writer. write_all ( & byte_utils:: be64_to_array ( self . htlc_updated_waiting_outpoint_solving . len ( ) as u64 ) ) ?;
963
+ for ( ref outpoint, ref update) in self . htlc_updated_waiting_outpoint_solving . iter ( ) {
964
+ outpoint. write ( writer) ?;
965
+ update. 0 . write ( writer) ?;
966
+ update. 1 . write ( writer) ?;
967
+ update. 2 . write ( writer) ?;
968
+ }
969
+
970
+ writer. write_all ( & byte_utils:: be64_to_array ( self . htlc_updated_waiting_threshold_conf . len ( ) as u64 ) ) ?;
971
+ for & ( ref conf, ref outpoint, ref update) in self . htlc_updated_waiting_threshold_conf . iter ( ) {
972
+ writer. write_all ( & byte_utils:: be32_to_array ( * conf) ) ?;
973
+ outpoint. write ( writer) ?;
974
+ ( * update) . 0 . write ( writer) ?;
975
+ update. 1 . write ( writer) ?;
976
+ update. 2 . write ( writer) ?;
977
+ }
978
+
954
979
Ok ( ( ) )
955
980
}
956
981
@@ -1014,13 +1039,12 @@ impl ChannelMonitor {
1014
1039
/// HTLC-Success/HTLC-Timeout transactions.
1015
1040
/// Return updates for HTLC pending in the channel and failed automatically by the broadcast of
1016
1041
/// revoked remote commitment tx
1017
- fn check_spend_remote_transaction ( & mut self , tx : & Transaction , height : u32 ) -> ( Vec < Transaction > , ( Sha256dHash , Vec < TxOut > ) , Vec < SpendableOutputDescriptor > , Vec < ( HTLCSource , Option < PaymentPreimage > , PaymentHash ) > ) {
1042
+ fn check_spend_remote_transaction ( & mut self , tx : & Transaction , height : u32 ) -> ( Vec < Transaction > , ( Sha256dHash , Vec < TxOut > ) , Vec < SpendableOutputDescriptor > ) {
1018
1043
// Most secp and related errors trying to create keys means we have no hope of constructing
1019
1044
// a spend transaction...so we return no transactions to broadcast
1020
1045
let mut txn_to_broadcast = Vec :: new ( ) ;
1021
1046
let mut watch_outputs = Vec :: new ( ) ;
1022
1047
let mut spendable_outputs = Vec :: new ( ) ;
1023
- let mut htlc_updated = Vec :: new ( ) ;
1024
1048
1025
1049
let commitment_txid = tx. txid ( ) ; //TODO: This is gonna be a performance bottleneck for watchtowers!
1026
1050
let per_commitment_option = self . remote_claimable_outpoints . get ( & commitment_txid) ;
@@ -1029,7 +1053,7 @@ impl ChannelMonitor {
1029
1053
( $thing : expr ) => {
1030
1054
match $thing {
1031
1055
Ok ( a) => a,
1032
- Err ( _) => return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs, htlc_updated )
1056
+ Err ( _) => return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs)
1033
1057
}
1034
1058
} ;
1035
1059
}
@@ -1054,7 +1078,7 @@ impl ChannelMonitor {
1054
1078
} ;
1055
1079
let delayed_key = ignore_error ! ( chan_utils:: derive_public_key( & self . secp_ctx, & PublicKey :: from_secret_key( & self . secp_ctx, & per_commitment_key) , & self . their_delayed_payment_base_key. unwrap( ) ) ) ;
1056
1080
let a_htlc_key = match self . their_htlc_base_key {
1057
- None => return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs, htlc_updated ) ,
1081
+ None => return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs) ,
1058
1082
Some ( their_htlc_base_key) => ignore_error ! ( chan_utils:: derive_public_key( & self . secp_ctx, & PublicKey :: from_secret_key( & self . secp_ctx, & per_commitment_key) , & their_htlc_base_key) ) ,
1059
1083
} ;
1060
1084
@@ -1134,7 +1158,7 @@ impl ChannelMonitor {
1134
1158
if transaction_output_index as usize >= tx. output . len ( ) ||
1135
1159
tx. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 ||
1136
1160
tx. output [ transaction_output_index as usize ] . script_pubkey != expected_script. to_v0_p2wsh ( ) {
1137
- return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs, htlc_updated ) ; // Corrupted per_commitment_data, fuck this user
1161
+ return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs) ; // Corrupted per_commitment_data, fuck this user
1138
1162
}
1139
1163
let input = TxIn {
1140
1164
previous_output : BitcoinOutPoint {
@@ -1183,7 +1207,7 @@ impl ChannelMonitor {
1183
1207
for & ( ref htlc, ref source_option) in outpoints. iter( ) {
1184
1208
if let & Some ( ref source) = source_option {
1185
1209
log_trace!( self , "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of revoked remote commitment transaction" , log_bytes!( htlc. payment_hash. 0 ) , $commitment_tx) ;
1186
- htlc_updated . push( ( ( * * source) . clone( ) , None , htlc. payment_hash. clone( ) ) ) ;
1210
+ self . htlc_updated_waiting_threshold_conf . push( ( 1 , None , ( ( * * source) . clone( ) , None , htlc. payment_hash. clone( ) ) ) ) ;
1187
1211
}
1188
1212
}
1189
1213
}
@@ -1199,7 +1223,7 @@ impl ChannelMonitor {
1199
1223
}
1200
1224
// No need to check local commitment txn, symmetric HTLCSource must be present as per-htlc data on remote commitment tx
1201
1225
}
1202
- if inputs. is_empty ( ) { return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs, htlc_updated ) ; } // Nothing to be done...probably a false positive/local tx
1226
+ if inputs. is_empty ( ) { return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs) ; } // Nothing to be done...probably a false positive/local tx
1203
1227
1204
1228
let outputs = vec ! ( TxOut {
1205
1229
script_pubkey: self . destination_script. clone( ) ,
@@ -1257,11 +1281,12 @@ impl ChannelMonitor {
1257
1281
// need to here.
1258
1282
for & ( ref broadcast_htlc, ref broadcast_source) in per_commitment_data. iter( ) {
1259
1283
if broadcast_htlc. transaction_output_index. is_some( ) && Some ( source) == broadcast_source. as_ref( ) {
1284
+ self . htlc_updated_waiting_outpoint_solving. insert( BitcoinOutPoint { txid: commitment_txid. clone( ) , vout: broadcast_htlc. transaction_output_index. unwrap( ) } , ( ( * * source) . clone( ) , None , htlc. payment_hash. clone( ) ) ) ;
1260
1285
continue $id;
1261
1286
}
1262
1287
}
1263
1288
log_trace!( self , "Failing HTLC with payment_hash {} from {} remote commitment tx due to broadcast of remote commitment transaction" , log_bytes!( htlc. payment_hash. 0 ) , $commitment_tx) ;
1264
- htlc_updated . push( ( ( * * source) . clone( ) , None , htlc. payment_hash. clone( ) ) ) ;
1289
+ self . htlc_updated_waiting_threshold_conf . push( ( 1 , None , ( ( * * source) . clone( ) , None , htlc. payment_hash. clone( ) ) ) ) ;
1265
1290
}
1266
1291
}
1267
1292
}
@@ -1294,7 +1319,7 @@ impl ChannelMonitor {
1294
1319
} ,
1295
1320
} ;
1296
1321
let a_htlc_key = match self . their_htlc_base_key {
1297
- None => return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs, htlc_updated ) ,
1322
+ None => return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs) ,
1298
1323
Some ( their_htlc_base_key) => ignore_error ! ( chan_utils:: derive_public_key( & self . secp_ctx, revocation_point, & their_htlc_base_key) ) ,
1299
1324
} ;
1300
1325
@@ -1349,7 +1374,7 @@ impl ChannelMonitor {
1349
1374
if transaction_output_index as usize >= tx. output . len ( ) ||
1350
1375
tx. output [ transaction_output_index as usize ] . value != htlc. amount_msat / 1000 ||
1351
1376
tx. output [ transaction_output_index as usize ] . script_pubkey != expected_script. to_v0_p2wsh ( ) {
1352
- return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs, htlc_updated ) ; // Corrupted per_commitment_data, fuck this user
1377
+ return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs) ; // Corrupted per_commitment_data, fuck this user
1353
1378
}
1354
1379
if let Some ( payment_preimage) = self . payment_preimages . get ( & htlc. payment_hash ) {
1355
1380
let input = TxIn {
@@ -1412,7 +1437,7 @@ impl ChannelMonitor {
1412
1437
}
1413
1438
}
1414
1439
1415
- if inputs. is_empty ( ) { return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs, htlc_updated ) ; } // Nothing to be done...probably a false positive/local tx
1440
+ if inputs. is_empty ( ) { return ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs) ; } // Nothing to be done...probably a false positive/local tx
1416
1441
1417
1442
let outputs = vec ! ( TxOut {
1418
1443
script_pubkey: self . destination_script. clone( ) ,
@@ -1442,7 +1467,7 @@ impl ChannelMonitor {
1442
1467
}
1443
1468
}
1444
1469
1445
- ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs, htlc_updated )
1470
+ ( txn_to_broadcast, ( commitment_txid, watch_outputs) , spendable_outputs)
1446
1471
}
1447
1472
1448
1473
/// Attempts to claim a remote HTLC-Success/HTLC-Timeout's outputs using the revocation key
@@ -1714,7 +1739,7 @@ impl ChannelMonitor {
1714
1739
}
1715
1740
} ;
1716
1741
if funding_txo. is_none ( ) || ( prevout. txid == funding_txo. as_ref ( ) . unwrap ( ) . 0 . txid && prevout. vout == funding_txo. as_ref ( ) . unwrap ( ) . 0 . index as u32 ) {
1717
- let ( remote_txn, new_outputs, mut spendable_output, mut updated ) = self . check_spend_remote_transaction ( tx, height) ;
1742
+ let ( remote_txn, new_outputs, mut spendable_output) = self . check_spend_remote_transaction ( tx, height) ;
1718
1743
txn = remote_txn;
1719
1744
spendable_outputs. append ( & mut spendable_output) ;
1720
1745
if !new_outputs. 1 . is_empty ( ) {
@@ -1733,9 +1758,6 @@ impl ChannelMonitor {
1733
1758
spendable_outputs. push ( spendable_output) ;
1734
1759
}
1735
1760
}
1736
- if updated. len ( ) > 0 {
1737
- htlc_updated. append ( & mut updated) ;
1738
- }
1739
1761
} else {
1740
1762
if let Some ( & ( commitment_number, _) ) = self . remote_commitment_txn_on_chain . get ( & prevout. txid ) {
1741
1763
let ( tx, spendable_output) = self . check_spend_remote_htlc ( tx, commitment_number) ;
@@ -1758,6 +1780,15 @@ impl ChannelMonitor {
1758
1780
if updated. len ( ) > 0 {
1759
1781
htlc_updated. append ( & mut updated) ;
1760
1782
}
1783
+ for inp in tx. input . iter ( ) {
1784
+ if let Some ( htlc_update) = self . htlc_updated_waiting_outpoint_solving . remove ( & inp. previous_output ) {
1785
+ if inp. witness . len ( ) == 5 && inp. witness [ 4 ] . len ( ) == ACCEPTED_HTLC_SCRIPT_WEIGHT && inp. witness . len ( ) == 3 && inp. witness [ 2 ] . len ( ) == OFFERED_HTLC_SCRIPT_WEIGHT {
1786
+ htlc_updated. append ( & mut vec ! [ htlc_update] ) ;
1787
+ } else {
1788
+ self . htlc_updated_waiting_threshold_conf . push ( ( 1 , Some ( inp. previous_output . clone ( ) ) , htlc_update) ) ;
1789
+ }
1790
+ }
1791
+ }
1761
1792
}
1762
1793
if let Some ( ref cur_local_tx) = self . current_local_signed_commitment_tx {
1763
1794
if self . would_broadcast_at_height ( height) {
@@ -1786,6 +1817,20 @@ impl ChannelMonitor {
1786
1817
}
1787
1818
}
1788
1819
}
1820
+ let mut outpoint_solved = Vec :: new ( ) ;
1821
+ for & mut ( ref mut confs, ref outpoint, ref update) in self . htlc_updated_waiting_threshold_conf . iter_mut ( ) {
1822
+ * confs += 1 ;
1823
+ //TODO switch to target insread of number of conf
1824
+ if * confs == HTLC_FAIL_ANTI_REORG_DELAY {
1825
+ if let Some ( outpoint) = * outpoint {
1826
+ outpoint_solved. push ( outpoint. clone ( ) ) ;
1827
+ }
1828
+ htlc_updated. push ( update. clone ( ) ) ;
1829
+ }
1830
+ }
1831
+ for outp in outpoint_solved {
1832
+ self . htlc_updated_waiting_outpoint_solving . remove ( & outp) ;
1833
+ }
1789
1834
self . last_block_hash = block_hash. clone ( ) ;
1790
1835
( watch_outputs, spendable_outputs, htlc_updated)
1791
1836
}
@@ -2159,6 +2204,29 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
2159
2204
let last_block_hash: Sha256dHash = Readable :: read ( reader) ?;
2160
2205
let destination_script = Readable :: read ( reader) ?;
2161
2206
2207
+ let waiting_outpoint_solving_len: u64 = Readable :: read ( reader) ?;
2208
+ let mut htlc_updated_waiting_outpoint_solving = HashMap :: with_capacity ( cmp:: min ( waiting_outpoint_solving_len as usize , MAX_ALLOC_SIZE / 128 ) ) ;
2209
+ for _ in 0 ..waiting_outpoint_solving_len {
2210
+ let outpoint = Readable :: read ( reader) ?;
2211
+ let htlc_source = Readable :: read ( reader) ?;
2212
+ let preimage = Readable :: read ( reader) ?;
2213
+ let hash = Readable :: read ( reader) ?;
2214
+ if let Some ( _) = htlc_updated_waiting_outpoint_solving. insert ( outpoint, ( htlc_source, preimage, hash) ) {
2215
+ return Err ( DecodeError :: InvalidValue ) ;
2216
+ }
2217
+ }
2218
+
2219
+ let waiting_threshold_conf_len: u64 = Readable :: read ( reader) ?;
2220
+ let mut htlc_updated_waiting_threshold_conf = Vec :: with_capacity ( cmp:: min ( waiting_threshold_conf_len as usize , MAX_ALLOC_SIZE / 128 ) ) ;
2221
+ for _ in 0 ..waiting_threshold_conf_len {
2222
+ let conf = Readable :: read ( reader) ?;
2223
+ let outpoint = Readable :: read ( reader) ?;
2224
+ let htlc_source = Readable :: read ( reader) ?;
2225
+ let preimage = Readable :: read ( reader) ?;
2226
+ let hash = Readable :: read ( reader) ?;
2227
+ htlc_updated_waiting_threshold_conf. push ( ( conf, outpoint, ( htlc_source, preimage, hash) ) ) ;
2228
+ }
2229
+
2162
2230
Ok ( ( last_block_hash. clone ( ) , ChannelMonitor {
2163
2231
commitment_transaction_number_obscure_factor,
2164
2232
@@ -2182,6 +2250,10 @@ impl<R: ::std::io::Read> ReadableArgs<R, Arc<Logger>> for (Sha256dHash, ChannelM
2182
2250
payment_preimages,
2183
2251
2184
2252
destination_script,
2253
+
2254
+ htlc_updated_waiting_outpoint_solving,
2255
+ htlc_updated_waiting_threshold_conf,
2256
+
2185
2257
last_block_hash,
2186
2258
secp_ctx,
2187
2259
logger,
0 commit comments