@@ -286,12 +286,27 @@ impl ChannelMonitor {
286
286
}
287
287
}
288
288
}
289
- // TODO: Prune payment_preimages no longer needed by the revocation (just have to check
290
- // that non-revoked remote commitment tx(n) do not need it, and our latest local commitment
291
- // tx does not need it.
289
+
290
+ let mut pruned_payment_preimages = HashMap :: with_capacity ( self . payment_preimages . capacity ( ) ) ;
291
+ for ( k, v) in self . payment_preimages . drain ( ) {
292
+ for ( htlc, _s1, _s2) in & self . current_local_signed_commitment_tx . as_ref ( ) . expect ( "Channel need at least an initial commitment tx !" ) . htlc_outputs {
293
+ if k == htlc. payment_hash {
294
+ pruned_payment_preimages. insert ( k, v) ;
295
+ }
296
+ }
297
+ for ( _tx, htlcs) in & self . remote_claimable_outpoints {
298
+ for htlc in htlcs {
299
+ if k == htlc. payment_hash {
300
+ pruned_payment_preimages. insert ( k, v) ;
301
+ }
302
+ }
303
+ }
304
+ }
305
+ self . payment_preimages = pruned_payment_preimages;
306
+
292
307
Ok ( ( ) )
293
308
}
294
-
309
+
295
310
/// Informs this monitor of the latest remote (ie non-broadcastable) commitment transaction.
296
311
/// The monitor watches for it to be broadcasted and then uses the HTLC information (and
297
312
/// possibly future revocation/preimage information) to claim outputs where possible.
@@ -796,9 +811,15 @@ impl ChannelMonitor {
796
811
mod tests {
797
812
use bitcoin:: util:: misc:: hex_bytes;
798
813
use bitcoin:: blockdata:: script:: Script ;
814
+ use bitcoin:: util:: hash:: { Hash160 , Sha256dHash } ;
815
+ use bitcoin:: blockdata:: transaction:: Transaction ;
799
816
use ln:: channelmonitor:: ChannelMonitor ;
817
+ use ln:: channelmonitor:: LocalSignedTx ;
818
+ use ln:: chan_utils:: HTLCOutputInCommitment ;
800
819
use secp256k1:: key:: { SecretKey , PublicKey } ;
801
- use secp256k1:: Secp256k1 ;
820
+ use secp256k1:: { Secp256k1 , Signature } ;
821
+ use rand:: { thread_rng, Rng } ;
822
+ use std:: collections:: HashMap ;
802
823
803
824
#[ test]
804
825
fn test_per_commitment_storage ( ) {
@@ -1154,5 +1175,146 @@ mod tests {
1154
1175
}
1155
1176
}
1156
1177
1178
+ macro_rules! gen_local_tx {
1179
+ ( $hex : expr, $monitor : expr, $htlcs : expr, $rng : expr, $preimage : expr, $hash : expr) => {
1180
+ {
1181
+
1182
+ let mut htlcs = Vec :: new( ) ;
1183
+
1184
+ for _i in 0 ..$htlcs {
1185
+ $rng. fill_bytes( & mut $preimage) ;
1186
+ $hash[ 0 ..20 ] . clone_from_slice( & Hash160 :: from_data( & $preimage) [ 0 ..20 ] ) ;
1187
+ $monitor. provide_payment_preimage( & $hash, & $preimage) ;
1188
+ htlcs. push( ( HTLCOutputInCommitment {
1189
+ offered : true ,
1190
+ amount_msat : 0 ,
1191
+ cltv_expiry : 0 ,
1192
+ payment_hash : $hash. clone( ) ,
1193
+ transaction_output_index : 0 ,
1194
+ } , Signature :: from_der( & Secp256k1 :: new( ) , $hex) . unwrap( ) ,
1195
+ Signature :: from_der( & Secp256k1 :: new( ) , $hex) . unwrap( ) ) )
1196
+ }
1197
+
1198
+ Some ( LocalSignedTx {
1199
+ txid: Sha256dHash :: from_data( & [ ] ) ,
1200
+ tx: Transaction {
1201
+ version: 0 ,
1202
+ lock_time: 0 ,
1203
+ input: Vec :: new( ) ,
1204
+ output: Vec :: new( ) ,
1205
+ } ,
1206
+ revocation_key: PublicKey :: new( ) ,
1207
+ a_htlc_key: PublicKey :: new( ) ,
1208
+ b_htlc_key: PublicKey :: new( ) ,
1209
+ delayed_payment_key: PublicKey :: new( ) ,
1210
+ feerate_per_kw: 0 ,
1211
+ htlc_outputs: htlcs,
1212
+ } )
1213
+ }
1214
+ }
1215
+ }
1216
+
1217
+ macro_rules! gen_remote_htlcs {
1218
+ ( $monitor : expr, $tx : expr, $htlcs : expr, $rng : expr, $preimage : expr, $hash: expr) => {
1219
+ {
1220
+ let mut remote_outpoints = HashMap :: new( ) ;
1221
+
1222
+ for i in 0 ..$tx {
1223
+
1224
+ let tx_zero = Transaction {
1225
+ version : 0 ,
1226
+ lock_time : i,
1227
+ input : Vec :: new( ) ,
1228
+ output: Vec :: new( ) ,
1229
+ } ;
1230
+
1231
+ let mut htlcs = Vec :: new( ) ;
1232
+
1233
+ for _i in 0 ..$htlcs {
1234
+ $rng. fill_bytes( & mut $preimage) ;
1235
+ $hash[ 0 ..20 ] . clone_from_slice( & Hash160 :: from_data( & $preimage) [ 0 ..20 ] ) ;
1236
+ $monitor. provide_payment_preimage( & $hash, & $preimage) ;
1237
+ htlcs. push( HTLCOutputInCommitment {
1238
+ offered : true ,
1239
+ amount_msat : 0 ,
1240
+ cltv_expiry : 0 ,
1241
+ payment_hash : $hash. clone( ) ,
1242
+ transaction_output_index : 0 ,
1243
+ } ) ;
1244
+ }
1245
+ remote_outpoints. insert( tx_zero. txid( ) , htlcs) ;
1246
+ }
1247
+ remote_outpoints
1248
+ }
1249
+ }
1250
+ }
1251
+
1252
+ #[ test]
1253
+ fn test_prune_preimages ( ) {
1254
+
1255
+ let mut monitor : ChannelMonitor ;
1256
+ let secp_ctx = Secp256k1 :: new ( ) ;
1257
+ let mut preimage : [ u8 ; 32 ] = [ 0 ; 32 ] ;
1258
+ let mut hash : [ u8 ; 32 ] = [ 0 ; 32 ] ;
1259
+ let mut rng = thread_rng ( ) ;
1260
+
1261
+ {
1262
+ monitor = ChannelMonitor :: new ( & SecretKey :: from_slice ( & secp_ctx, & [ 42 ; 32 ] ) . unwrap ( ) , & PublicKey :: new ( ) , & SecretKey :: from_slice ( & secp_ctx, & [ 43 ; 32 ] ) . unwrap ( ) , 0 , Script :: new ( ) ) ;
1263
+
1264
+ for _i in 0 ..30 {
1265
+ rng. fill_bytes ( & mut preimage) ;
1266
+ hash[ 0 ..20 ] . clone_from_slice ( & Hash160 :: from_data ( & preimage) [ 0 ..20 ] ) ;
1267
+ monitor. provide_payment_preimage ( & hash, & preimage) ;
1268
+ }
1269
+ monitor. current_local_signed_commitment_tx = gen_local_tx ! ( & hex_bytes( "3045022100fa86fa9a36a8cd6a7bb8f06a541787d51371d067951a9461d5404de6b928782e02201c8b7c334c10aed8976a3a465be9a28abff4cb23acbf00022295b378ce1fa3cd" ) . unwrap( ) [ ..] , monitor, 10 , rng, preimage, hash) ;
1270
+ monitor. remote_claimable_outpoints = gen_remote_htlcs ! ( monitor, 1 , 10 , rng, preimage, hash) ;
1271
+ monitor. provide_secret ( 0 , [ 0 ; 32 ] , None ) ;
1272
+ assert_eq ! ( monitor. payment_preimages. len( ) , 20 ) ;
1273
+ }
1274
+
1275
+
1276
+ {
1277
+ monitor = ChannelMonitor :: new ( & SecretKey :: from_slice ( & secp_ctx, & [ 42 ; 32 ] ) . unwrap ( ) , & PublicKey :: new ( ) , & SecretKey :: from_slice ( & secp_ctx, & [ 43 ; 32 ] ) . unwrap ( ) , 0 , Script :: new ( ) ) ;
1278
+
1279
+ for _i in 0 ..30 {
1280
+ rng. fill_bytes ( & mut preimage) ;
1281
+ hash[ 0 ..20 ] . clone_from_slice ( & Hash160 :: from_data ( & preimage) [ 0 ..20 ] ) ;
1282
+ monitor. provide_payment_preimage ( & hash, & preimage) ;
1283
+ }
1284
+ monitor. current_local_signed_commitment_tx = gen_local_tx ! ( & hex_bytes( "3045022100fa86fa9a36a8cd6a7bb8f06a541787d51371d067951a9461d5404de6b928782e02201c8b7c334c10aed8976a3a465be9a28abff4cb23acbf00022295b378ce1fa3cd" ) . unwrap( ) [ ..] , monitor, 0 , rng, preimage, hash) ;
1285
+ monitor. remote_claimable_outpoints = gen_remote_htlcs ! ( monitor, 0 , 0 , rng, preimage, hash) ;
1286
+ monitor. provide_secret ( 0 , [ 0 ; 32 ] , None ) ;
1287
+ assert_eq ! ( monitor. payment_preimages. len( ) , 0 ) ;
1288
+ }
1289
+
1290
+ {
1291
+ monitor = ChannelMonitor :: new ( & SecretKey :: from_slice ( & secp_ctx, & [ 42 ; 32 ] ) . unwrap ( ) , & PublicKey :: new ( ) , & SecretKey :: from_slice ( & secp_ctx, & [ 43 ; 32 ] ) . unwrap ( ) , 0 , Script :: new ( ) ) ;
1292
+
1293
+ for _i in 0 ..30 {
1294
+ rng. fill_bytes ( & mut preimage) ;
1295
+ hash[ 0 ..20 ] . clone_from_slice ( & Hash160 :: from_data ( & preimage) [ 0 ..20 ] ) ;
1296
+ monitor. provide_payment_preimage ( & hash, & preimage) ;
1297
+ }
1298
+ monitor. current_local_signed_commitment_tx = gen_local_tx ! ( & hex_bytes( "3045022100fa86fa9a36a8cd6a7bb8f06a541787d51371d067951a9461d5404de6b928782e02201c8b7c334c10aed8976a3a465be9a28abff4cb23acbf00022295b378ce1fa3cd" ) . unwrap( ) [ ..] , monitor, 0 , rng, preimage, hash) ;
1299
+ monitor. remote_claimable_outpoints = gen_remote_htlcs ! ( monitor, 5 , 5 , rng, preimage, hash) ;
1300
+ monitor. provide_secret ( 0 , [ 0 ; 32 ] , None ) ;
1301
+ assert_eq ! ( monitor. payment_preimages. len( ) , 25 ) ;
1302
+ }
1303
+
1304
+ {
1305
+ monitor = ChannelMonitor :: new ( & SecretKey :: from_slice ( & secp_ctx, & [ 42 ; 32 ] ) . unwrap ( ) , & PublicKey :: new ( ) , & SecretKey :: from_slice ( & secp_ctx, & [ 43 ; 32 ] ) . unwrap ( ) , 0 , Script :: new ( ) ) ;
1306
+
1307
+ for _i in 0 ..30 {
1308
+ rng. fill_bytes ( & mut preimage) ;
1309
+ hash[ 0 ..20 ] . clone_from_slice ( & Hash160 :: from_data ( & preimage) [ 0 ..20 ] ) ;
1310
+ monitor. provide_payment_preimage ( & hash, & preimage) ;
1311
+ }
1312
+ monitor. current_local_signed_commitment_tx = gen_local_tx ! ( & hex_bytes( "3045022100fa86fa9a36a8cd6a7bb8f06a541787d51371d067951a9461d5404de6b928782e02201c8b7c334c10aed8976a3a465be9a28abff4cb23acbf00022295b378ce1fa3cd" ) . unwrap( ) [ ..] , monitor, 25 , rng, preimage, hash) ;
1313
+ monitor. remote_claimable_outpoints = gen_remote_htlcs ! ( monitor, 0 , 0 , rng, preimage, hash) ;
1314
+ monitor. provide_secret ( 0 , [ 0 ; 32 ] , None ) ;
1315
+ assert_eq ! ( monitor. payment_preimages. len( ) , 25 ) ;
1316
+ }
1317
+ }
1318
+
1157
1319
// Further testing is done in the ChannelManager integration tests.
1158
1320
}
0 commit comments