@@ -3102,7 +3102,7 @@ fn test_blocked_chan_preimage_release() {
3102
3102
expect_payment_sent ( & nodes[ 2 ] , payment_preimage_2, None , true , true ) ;
3103
3103
}
3104
3104
3105
- fn do_test_inverted_mon_completion_order ( complete_bc_commitment_dance : bool ) {
3105
+ fn do_test_inverted_mon_completion_order ( with_latest_manager : bool , complete_bc_commitment_dance : bool ) {
3106
3106
// When we forward a payment and receive an `update_fulfill_htlc` message from the downstream
3107
3107
// channel, we immediately claim the HTLC on the upstream channel, before even doing a
3108
3108
// `commitment_signed` dance on the downstream channel. This implies that our
@@ -3130,6 +3130,10 @@ fn do_test_inverted_mon_completion_order(complete_bc_commitment_dance: bool) {
3130
3130
let ( payment_preimage, payment_hash, ..) = route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] ] , 100_000 ) ;
3131
3131
3132
3132
let mon_ab = get_monitor ! ( nodes[ 1 ] , chan_id_ab) . encode ( ) ;
3133
+ let mut manager_b = Vec :: new ( ) ;
3134
+ if !with_latest_manager {
3135
+ manager_b = nodes[ 1 ] . node . encode ( ) ;
3136
+ }
3133
3137
3134
3138
nodes[ 2 ] . node . claim_funds ( payment_preimage) ;
3135
3139
check_added_monitors ( & nodes[ 2 ] , 1 ) ;
@@ -3166,63 +3170,262 @@ fn do_test_inverted_mon_completion_order(complete_bc_commitment_dance: bool) {
3166
3170
}
3167
3171
3168
3172
// Now reload node B
3169
- let manager_b = nodes[ 1 ] . node . encode ( ) ;
3173
+ if with_latest_manager {
3174
+ manager_b = nodes[ 1 ] . node . encode ( ) ;
3175
+ }
3170
3176
3171
3177
let mon_bc = get_monitor ! ( nodes[ 1 ] , chan_id_bc) . encode ( ) ;
3172
3178
reload_node ! ( nodes[ 1 ] , & manager_b, & [ & mon_ab, & mon_bc] , persister, new_chain_monitor, nodes_1_deserialized) ;
3173
3179
3174
3180
nodes[ 0 ] . node . peer_disconnected ( & nodes[ 1 ] . node . get_our_node_id ( ) ) ;
3175
3181
nodes[ 2 ] . node . peer_disconnected ( & nodes[ 1 ] . node . get_our_node_id ( ) ) ;
3176
3182
3177
- // If we used the latest ChannelManager to reload from, we should have both channels still
3178
- // live. The B <-> C channel's final RAA ChannelMonitorUpdate must still be blocked as
3179
- // before - the ChannelMonitorUpdate for the A <-> B channel hasn't completed.
3180
- // When we call `timer_tick_occurred` we will get that monitor update back, which we'll
3181
- // complete after reconnecting to our peers.
3182
- persister. set_update_ret ( ChannelMonitorUpdateStatus :: InProgress ) ;
3183
- nodes[ 1 ] . node . timer_tick_occurred ( ) ;
3184
- check_added_monitors ( & nodes[ 1 ] , 1 ) ;
3185
- assert ! ( nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
3183
+ if with_latest_manager {
3184
+ // If we used the latest ChannelManager to reload from, we should have both channels still
3185
+ // live. The B <-> C channel's final RAA ChannelMonitorUpdate must still be blocked as
3186
+ // before - the ChannelMonitorUpdate for the A <-> B channel hasn't completed.
3187
+ // When we call `timer_tick_occurred` we will get that monitor update back, which we'll
3188
+ // complete after reconnecting to our peers.
3189
+ persister. set_update_ret ( ChannelMonitorUpdateStatus :: InProgress ) ;
3190
+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
3191
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
3192
+ assert ! ( nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
3186
3193
3187
- // Now reconnect B to both A and C. If the B <-> C commitment signed dance wasn't run to
3188
- // the end go ahead and do that, though the
3189
- // `pending_responding_commitment_signed_dup_monitor` in `reconnect_args` indicates that we
3190
- // expect to *not* receive the final RAA ChannelMonitorUpdate.
3191
- if complete_bc_commitment_dance {
3192
- reconnect_nodes ( ReconnectArgs :: new ( & nodes[ 1 ] , & nodes[ 2 ] ) ) ;
3194
+ // Now reconnect B to both A and C. If the B <-> C commitment signed dance wasn't run to
3195
+ // the end go ahead and do that, though the
3196
+ // `pending_responding_commitment_signed_dup_monitor` in `reconnect_args` indicates that we
3197
+ // expect to *not* receive the final RAA ChannelMonitorUpdate.
3198
+ if complete_bc_commitment_dance {
3199
+ reconnect_nodes ( ReconnectArgs :: new ( & nodes[ 1 ] , & nodes[ 2 ] ) ) ;
3200
+ } else {
3201
+ let mut reconnect_args = ReconnectArgs :: new ( & nodes[ 1 ] , & nodes[ 2 ] ) ;
3202
+ reconnect_args. pending_responding_commitment_signed . 1 = true ;
3203
+ reconnect_args. pending_responding_commitment_signed_dup_monitor . 1 = true ;
3204
+ reconnect_args. pending_raa = ( false , true ) ;
3205
+ reconnect_nodes ( reconnect_args) ;
3206
+ }
3207
+
3208
+ reconnect_nodes ( ReconnectArgs :: new ( & nodes[ 0 ] , & nodes[ 1 ] ) ) ;
3209
+
3210
+ // (Finally) complete the A <-> B ChannelMonitorUpdate, ensuring the preimage is durably on
3211
+ // disk in the proper ChannelMonitor, unblocking the B <-> C ChannelMonitor updating
3212
+ // process.
3213
+ let ( outpoint, _, ab_update_id) = nodes[ 1 ] . chain_monitor . latest_monitor_update_id . lock ( ) . unwrap ( ) . get ( & chan_id_ab) . unwrap ( ) . clone ( ) ;
3214
+ nodes[ 1 ] . chain_monitor . chain_monitor . channel_monitor_updated ( outpoint, ab_update_id) . unwrap ( ) ;
3215
+
3216
+ // When we fetch B's HTLC update messages next (now that the ChannelMonitorUpdate has
3217
+ // completed), it will also release the final RAA ChannelMonitorUpdate on the B <-> C
3218
+ // channel.
3193
3219
} else {
3194
- let mut reconnect_args = ReconnectArgs :: new ( & nodes[ 1 ] , & nodes[ 2 ] ) ;
3195
- reconnect_args. pending_responding_commitment_signed . 1 = true ;
3196
- reconnect_args. pending_responding_commitment_signed_dup_monitor . 1 = true ;
3197
- reconnect_args. pending_raa = ( false , true ) ;
3198
- reconnect_nodes ( reconnect_args) ;
3199
- }
3220
+ // If the ChannelManager used in the reload was stale, check that the B <-> C channel was
3221
+ // closed.
3222
+ //
3223
+ // Note that this will also process the ChannelMonitorUpdates which were queued up when we
3224
+ // reloaded the ChannelManager. This will re-emit the A<->B preimage as well as the B<->C
3225
+ // force-closure ChannelMonitorUpdate. Once the A<->B preimage update completes, the claim
3226
+ // commitment update will be allowed to go out.
3227
+ check_added_monitors ( & nodes[ 1 ] , 0 ) ;
3228
+ persister. set_update_ret ( ChannelMonitorUpdateStatus :: InProgress ) ;
3229
+ persister. set_update_ret ( ChannelMonitorUpdateStatus :: InProgress ) ;
3230
+ check_closed_event ( & nodes[ 1 ] , 1 , ClosureReason :: OutdatedChannelManager , false , & [ nodes[ 2 ] . node . get_our_node_id ( ) ] , 100_000 ) ;
3231
+ check_added_monitors ( & nodes[ 1 ] , 2 ) ;
3232
+
3233
+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
3234
+ check_added_monitors ( & nodes[ 1 ] , 0 ) ;
3200
3235
3201
- reconnect_nodes ( ReconnectArgs :: new ( & nodes[ 0 ] , & nodes[ 1 ] ) ) ;
3236
+ // Don't bother to reconnect B to C - that channel has been closed. We don't need to
3237
+ // exchange any messages here even though there's a pending commitment update because the
3238
+ // ChannelMonitorUpdate hasn't yet completed.
3239
+ reconnect_nodes ( ReconnectArgs :: new ( & nodes[ 0 ] , & nodes[ 1 ] ) ) ;
3202
3240
3203
- // (Finally) complete the A <-> B ChannelMonitorUpdate, ensuring the preimage is durably on
3204
- // disk in the proper ChannelMonitor, unblocking the B <-> C ChannelMonitor updating
3205
- // process.
3206
- let ( outpoint, _, ab_update_id) = nodes[ 1 ] . chain_monitor . latest_monitor_update_id . lock ( ) . unwrap ( ) . get ( & chan_id_ab) . unwrap ( ) . clone ( ) ;
3207
- nodes[ 1 ] . chain_monitor . chain_monitor . channel_monitor_updated ( outpoint, ab_update_id) . unwrap ( ) ;
3241
+ let ( outpoint, _, ab_update_id) = nodes[ 1 ] . chain_monitor . latest_monitor_update_id . lock ( ) . unwrap ( ) . get ( & chan_id_ab) . unwrap ( ) . clone ( ) ;
3242
+ nodes[ 1 ] . chain_monitor . chain_monitor . channel_monitor_updated ( outpoint, ab_update_id) . unwrap ( ) ;
3243
+
3244
+ // The ChannelMonitorUpdate which was completed prior to the reconnect only contained the
3245
+ // preimage (as it was a replay of the original ChannelMonitorUpdate from before we
3246
+ // restarted). When we go to fetch the commitment transaction updates we'll poll the
3247
+ // ChannelMonitorUpdate completion, then generate (and complete) a new ChannelMonitorUpdate
3248
+ // with the actual commitment transaction, which will allow us to fulfill the HTLC with
3249
+ // node A.
3250
+ }
3208
3251
3209
- // When we fetch B's HTLC update messages here (now that the ChannelMonitorUpdate has
3210
- // completed), it will also release the final RAA ChannelMonitorUpdate on the B <-> C
3211
- // channel.
3212
3252
let bs_updates = get_htlc_update_msgs ( & nodes[ 1 ] , & nodes[ 0 ] . node . get_our_node_id ( ) ) ;
3213
3253
check_added_monitors ( & nodes[ 1 ] , 1 ) ;
3214
3254
3215
3255
nodes[ 0 ] . node . handle_update_fulfill_htlc ( & nodes[ 1 ] . node . get_our_node_id ( ) , & bs_updates. update_fulfill_htlcs [ 0 ] ) ;
3216
3256
do_commitment_signed_dance ( & nodes[ 0 ] , & nodes[ 1 ] , & bs_updates. commitment_signed , false , false ) ;
3217
3257
3218
- expect_payment_forwarded ! ( nodes[ 1 ] , & nodes[ 0 ] , & nodes[ 2 ] , Some ( 1_000 ) , false , false ) ;
3258
+ expect_payment_forwarded ! ( nodes[ 1 ] , & nodes[ 0 ] , & nodes[ 2 ] , Some ( 1_000 ) , false , !with_latest_manager ) ;
3219
3259
3220
3260
// Finally, check that the payment was, ultimately, seen as sent by node A.
3221
3261
expect_payment_sent ( & nodes[ 0 ] , payment_preimage, None , true , true ) ;
3222
3262
}
3223
3263
3224
3264
#[ test]
3225
3265
fn test_inverted_mon_completion_order ( ) {
3226
- do_test_inverted_mon_completion_order ( true ) ;
3227
- do_test_inverted_mon_completion_order ( false ) ;
3266
+ do_test_inverted_mon_completion_order ( true , true ) ;
3267
+ do_test_inverted_mon_completion_order ( true , false ) ;
3268
+ do_test_inverted_mon_completion_order ( false , true ) ;
3269
+ do_test_inverted_mon_completion_order ( false , false ) ;
3270
+ }
3271
+
3272
+ fn do_test_durable_preimages_on_closed_channel ( close_chans_before_reload : bool , close_only_a : bool , hold_post_reload_mon_update : bool ) {
3273
+ // Test that we can apply a `ChannelMonitorUpdate` with a payment preimage even if the channel
3274
+ // is force-closed between when we generate the update on reload and when we go to handle the
3275
+ // update or prior to generating the update at all.
3276
+
3277
+ if !close_chans_before_reload && close_only_a {
3278
+ // If we're not closing, it makes no sense to "only close A"
3279
+ panic ! ( ) ;
3280
+ }
3281
+
3282
+ let chanmon_cfgs = create_chanmon_cfgs ( 3 ) ;
3283
+ let node_cfgs = create_node_cfgs ( 3 , & chanmon_cfgs) ;
3284
+
3285
+ let persister;
3286
+ let new_chain_monitor;
3287
+ let nodes_1_deserialized;
3288
+
3289
+ let node_chanmgrs = create_node_chanmgrs ( 3 , & node_cfgs, & [ None , None , None ] ) ;
3290
+ let mut nodes = create_network ( 3 , & node_cfgs, & node_chanmgrs) ;
3291
+
3292
+ let chan_id_ab = create_announced_chan_between_nodes ( & nodes, 0 , 1 ) . 2 ;
3293
+ let chan_id_bc = create_announced_chan_between_nodes ( & nodes, 1 , 2 ) . 2 ;
3294
+
3295
+ // Route a payment from A, through B, to C, then claim it on C. Once we pass B the
3296
+ // `update_fulfill_htlc` we have a monitor update for both of B's channels. We complete the one
3297
+ // on the B<->C channel but leave the A<->B monitor update pending, then reload B.
3298
+ let ( payment_preimage, payment_hash, ..) = route_payment ( & nodes[ 0 ] , & [ & nodes[ 1 ] , & nodes[ 2 ] ] , 1_000_000 ) ;
3299
+
3300
+ let mon_ab = get_monitor ! ( nodes[ 1 ] , chan_id_ab) . encode ( ) ;
3301
+
3302
+ nodes[ 2 ] . node . claim_funds ( payment_preimage) ;
3303
+ check_added_monitors ( & nodes[ 2 ] , 1 ) ;
3304
+ expect_payment_claimed ! ( nodes[ 2 ] , payment_hash, 1_000_000 ) ;
3305
+
3306
+ chanmon_cfgs[ 1 ] . persister . set_update_ret ( ChannelMonitorUpdateStatus :: InProgress ) ;
3307
+ let cs_updates = get_htlc_update_msgs ( & nodes[ 2 ] , & nodes[ 1 ] . node . get_our_node_id ( ) ) ;
3308
+ nodes[ 1 ] . node . handle_update_fulfill_htlc ( & nodes[ 2 ] . node . get_our_node_id ( ) , & cs_updates. update_fulfill_htlcs [ 0 ] ) ;
3309
+
3310
+ // B generates a new monitor update for the A <-> B channel, but doesn't send the new messages
3311
+ // for it since the monitor update is marked in-progress.
3312
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
3313
+ assert ! ( nodes[ 1 ] . node. get_and_clear_pending_msg_events( ) . is_empty( ) ) ;
3314
+
3315
+ // Now step the Commitment Signed Dance between B and C forward a bit, ensuring we won't get
3316
+ // the preimage when the nodes reconnect, at which point we have to ensure we get it from the
3317
+ // ChannelMonitor.
3318
+ nodes[ 1 ] . node . handle_commitment_signed ( & nodes[ 2 ] . node . get_our_node_id ( ) , & cs_updates. commitment_signed ) ;
3319
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
3320
+ let _ = get_revoke_commit_msgs ! ( nodes[ 1 ] , nodes[ 2 ] . node. get_our_node_id( ) ) ;
3321
+
3322
+ let mon_bc = get_monitor ! ( nodes[ 1 ] , chan_id_bc) . encode ( ) ;
3323
+
3324
+ if close_chans_before_reload {
3325
+ if !close_only_a {
3326
+ chanmon_cfgs[ 1 ] . persister . set_update_ret ( ChannelMonitorUpdateStatus :: InProgress ) ;
3327
+ nodes[ 1 ] . node . force_close_broadcasting_latest_txn ( & chan_id_bc, & nodes[ 2 ] . node . get_our_node_id ( ) ) . unwrap ( ) ;
3328
+ check_closed_broadcast ( & nodes[ 1 ] , 1 , true ) ;
3329
+ check_closed_event ( & nodes[ 1 ] , 1 , ClosureReason :: HolderForceClosed , false , & [ nodes[ 2 ] . node . get_our_node_id ( ) ] , 100000 ) ;
3330
+ }
3331
+
3332
+ chanmon_cfgs[ 1 ] . persister . set_update_ret ( ChannelMonitorUpdateStatus :: InProgress ) ;
3333
+ nodes[ 1 ] . node . force_close_broadcasting_latest_txn ( & chan_id_ab, & nodes[ 0 ] . node . get_our_node_id ( ) ) . unwrap ( ) ;
3334
+ check_closed_broadcast ( & nodes[ 1 ] , 1 , true ) ;
3335
+ check_closed_event ( & nodes[ 1 ] , 1 , ClosureReason :: HolderForceClosed , false , & [ nodes[ 0 ] . node . get_our_node_id ( ) ] , 100000 ) ;
3336
+ }
3337
+
3338
+ // Now reload node B
3339
+ let manager_b = nodes[ 1 ] . node . encode ( ) ;
3340
+ reload_node ! ( nodes[ 1 ] , & manager_b, & [ & mon_ab, & mon_bc] , persister, new_chain_monitor, nodes_1_deserialized) ;
3341
+
3342
+ nodes[ 0 ] . node . peer_disconnected ( & nodes[ 1 ] . node . get_our_node_id ( ) ) ;
3343
+ nodes[ 2 ] . node . peer_disconnected ( & nodes[ 1 ] . node . get_our_node_id ( ) ) ;
3344
+
3345
+ if close_chans_before_reload {
3346
+ // If the channels were already closed, B will rebroadcast its closing transactions here.
3347
+ let bs_close_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ;
3348
+ if close_only_a {
3349
+ assert_eq ! ( bs_close_txn. len( ) , 2 ) ;
3350
+ } else {
3351
+ assert_eq ! ( bs_close_txn. len( ) , 3 ) ;
3352
+ }
3353
+ }
3354
+
3355
+ nodes[ 0 ] . node . force_close_broadcasting_latest_txn ( & chan_id_ab, & nodes[ 1 ] . node . get_our_node_id ( ) ) . unwrap ( ) ;
3356
+ check_closed_event ( & nodes[ 0 ] , 1 , ClosureReason :: HolderForceClosed , false , & [ nodes[ 1 ] . node . get_our_node_id ( ) ] , 100000 ) ;
3357
+ let as_closing_tx = nodes[ 0 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ;
3358
+ assert_eq ! ( as_closing_tx. len( ) , 1 ) ;
3359
+
3360
+ // In order to give A's closing transaction to B without processing background events first,
3361
+ // use the _without_consistency_checks utility method. This is similar to connecting blocks
3362
+ // during startup prior to the node being full initialized.
3363
+ mine_transaction_without_consistency_checks ( & nodes[ 1 ] , & as_closing_tx[ 0 ] ) ;
3364
+
3365
+ // After a timer tick a payment preimage ChannelMonitorUpdate is applied to the A<->B
3366
+ // ChannelMonitor (possible twice), even though the channel has since been closed.
3367
+ check_added_monitors ( & nodes[ 1 ] , 0 ) ;
3368
+ let mons_added = if close_chans_before_reload { if !close_only_a { 4 } else { 3 } } else { 2 } ;
3369
+ if hold_post_reload_mon_update {
3370
+ for _ in 0 ..mons_added {
3371
+ persister. set_update_ret ( ChannelMonitorUpdateStatus :: InProgress ) ;
3372
+ }
3373
+ }
3374
+ nodes[ 1 ] . node . timer_tick_occurred ( ) ;
3375
+ check_added_monitors ( & nodes[ 1 ] , mons_added) ;
3376
+
3377
+ // Finally, check that B created a payment preimage transaction and close out the payment.
3378
+ let bs_txn = nodes[ 1 ] . tx_broadcaster . txn_broadcasted . lock ( ) . unwrap ( ) . split_off ( 0 ) ;
3379
+ assert_eq ! ( bs_txn. len( ) , if close_chans_before_reload && !close_only_a { 2 } else { 1 } ) ;
3380
+ let bs_preimage_tx = & bs_txn[ 0 ] ;
3381
+ check_spends ! ( bs_preimage_tx, as_closing_tx[ 0 ] ) ;
3382
+
3383
+ if !close_chans_before_reload {
3384
+ check_closed_broadcast ( & nodes[ 1 ] , 1 , true ) ;
3385
+ check_closed_event ( & nodes[ 1 ] , 1 , ClosureReason :: CommitmentTxConfirmed , false , & [ nodes[ 0 ] . node . get_our_node_id ( ) ] , 100000 ) ;
3386
+ } else {
3387
+ // While we forwarded the payment a while ago, we don't want to process events too early or
3388
+ // we'll run background tasks we wanted to test individually.
3389
+ expect_payment_forwarded ! ( nodes[ 1 ] , nodes[ 0 ] , nodes[ 2 ] , None , true , !close_only_a) ;
3390
+ }
3391
+
3392
+ mine_transactions ( & nodes[ 0 ] , & [ & as_closing_tx[ 0 ] , bs_preimage_tx] ) ;
3393
+ check_closed_broadcast ( & nodes[ 0 ] , 1 , true ) ;
3394
+ expect_payment_sent ( & nodes[ 0 ] , payment_preimage, None , true , true ) ;
3395
+
3396
+ if !close_chans_before_reload || close_only_a {
3397
+ // Make sure the B<->C channel is still alive and well by sending a payment over it.
3398
+ let mut reconnect_args = ReconnectArgs :: new ( & nodes[ 1 ] , & nodes[ 2 ] ) ;
3399
+ reconnect_args. pending_responding_commitment_signed . 1 = true ;
3400
+ if !close_chans_before_reload {
3401
+ // TODO: If the A<->B channel was closed before we reloaded, the `ChannelManager`
3402
+ // will consider the forwarded payment complete and allow the B<->C
3403
+ // `ChannelMonitorUpdate` to complete, wiping the payment preimage. This should not
3404
+ // be allowed, and needs fixing.
3405
+ reconnect_args. pending_responding_commitment_signed_dup_monitor . 1 = true ;
3406
+ }
3407
+ reconnect_args. pending_raa . 1 = true ;
3408
+
3409
+ reconnect_nodes ( reconnect_args) ;
3410
+ let ( outpoint, ab_update_id, _) = nodes[ 1 ] . chain_monitor . latest_monitor_update_id . lock ( ) . unwrap ( ) . get ( & chan_id_ab) . unwrap ( ) . clone ( ) ;
3411
+ nodes[ 1 ] . chain_monitor . chain_monitor . force_channel_monitor_updated ( outpoint, ab_update_id) ;
3412
+ expect_payment_forwarded ! ( nodes[ 1 ] , nodes[ 0 ] , nodes[ 2 ] , Some ( 1000 ) , true , false ) ;
3413
+ if !close_chans_before_reload {
3414
+ // Once we call `process_pending_events` the final `ChannelMonitor` for the B<->C
3415
+ // channel will fly, removing the payment preimage from it.
3416
+ check_added_monitors ( & nodes[ 1 ] , 1 ) ;
3417
+ }
3418
+ assert ! ( nodes[ 1 ] . node. get_and_clear_pending_events( ) . is_empty( ) ) ;
3419
+ send_payment ( & nodes[ 1 ] , & [ & nodes[ 2 ] ] , 100_000 ) ;
3420
+ }
3421
+ }
3422
+
3423
+ #[ test]
3424
+ fn test_durable_preimages_on_closed_channel ( ) {
3425
+ do_test_durable_preimages_on_closed_channel ( true , true , true ) ;
3426
+ do_test_durable_preimages_on_closed_channel ( true , true , false ) ;
3427
+ do_test_durable_preimages_on_closed_channel ( true , false , true ) ;
3428
+ do_test_durable_preimages_on_closed_channel ( true , false , false ) ;
3429
+ do_test_durable_preimages_on_closed_channel ( false , false , true ) ;
3430
+ do_test_durable_preimages_on_closed_channel ( false , false , false ) ;
3228
3431
}
0 commit comments