Skip to content

Commit 0aa3d31

Browse files
committed
adjust unit test to verify paymentpathfailed networkupdate deallocation
1 parent 962ce9e commit 0aa3d31

File tree

2 files changed

+116
-100
lines changed

2 files changed

+116
-100
lines changed

ci/LDKSwift/Tests/LDKSwiftTests/HumanObjectPeerTestInstance.swift

Lines changed: 86 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,36 @@ import LDKHeaders
1212
import XCTest
1313

1414
public class HumanObjectPeerTestInstance {
15-
16-
private let nice_close: Bool;
17-
private let use_km_wrapper: Bool;
18-
private let use_manual_watch: Bool;
19-
private let reload_peers: Bool;
20-
private let break_cross_peer_refs: Bool;
21-
private let use_nio_peer_handler: Bool;
22-
private let use_filter: Bool;
23-
private let use_chan_manager_constructor: Bool;
24-
25-
26-
public init(nice_close: Bool, use_km_wrapper: Bool, use_manual_watch: Bool, reload_peers: Bool, break_cross_peer_refs: Bool, use_nio_peer_handler: Bool, use_filter: Bool, use_chan_manager_constructor: Bool) {
27-
self.nice_close = nice_close
28-
self.use_km_wrapper = use_km_wrapper
29-
self.use_manual_watch = use_manual_watch
30-
self.reload_peers = reload_peers
31-
self.break_cross_peer_refs = break_cross_peer_refs
32-
self.use_nio_peer_handler = use_nio_peer_handler
33-
self.use_filter = use_filter
34-
self.use_chan_manager_constructor = use_chan_manager_constructor
15+
16+
private let configuration: Configuration
17+
18+
public class Configuration {
19+
//
20+
public var useFilter: Bool = false;
21+
public var useRouter: Bool = false;
22+
public var shouldRecipientRejectPayment: Bool = false;
23+
24+
// public var nice_close: Bool = false;
25+
// public var use_km_wrapper: Bool = false;
26+
// public var use_manual_watch: Bool = false;
27+
// public var reload_peers: Bool = false;
28+
// public var break_cross_peer_refs: Bool = false;
29+
// public var use_nio_peer_handler: Bool = false;
30+
31+
private class func listCustomizeableProperties() -> [String] {
32+
return ["useFilter", "useRouter", "shouldRecipientRejectPayment"]
33+
}
34+
35+
public class func combinationCount() -> UInt {
36+
return 1 << self.listCustomizeableProperties().count
37+
}
38+
39+
}
40+
41+
42+
43+
public init(configuration: Configuration) {
44+
self.configuration = configuration
3545
}
3646

3747
fileprivate class Peer {
@@ -259,15 +269,14 @@ public class HumanObjectPeerTestInstance {
259269

260270
self.txBroadcaster = TestBroadcaster(master: self)
261271

262-
if master.use_filter {
272+
if master.configuration.useFilter {
263273
self.filter = Option_FilterZ(value: TestFilter(master: self))
264274
} else {
265275
self.filter = Option_FilterZ(value: nil)
266276
}
267277

268-
if master.use_manual_watch || false { // don't support manual watch yet
269-
// self.chainMonitor
270-
} else {
278+
// never use manual watch
279+
do {
271280
self.chainMonitor = ChainMonitor(chain_source: self.filter, broadcaster: self.txBroadcaster, logger: self.logger, feeest: self.feeEstimator, persister: persister)
272281
self.chainWatch = self.chainMonitor!.as_Watch()
273282
}
@@ -280,29 +289,28 @@ public class HumanObjectPeerTestInstance {
280289
let timestamp_seconds = UInt64(NSDate().timeIntervalSince1970)
281290
let timestamp_nanos = UInt32(truncating: NSNumber(value: timestamp_seconds * 1000 * 1000))
282291
let keysManager = KeysManager(seed: keySeed, starting_time_secs: timestamp_seconds, starting_time_nanos: timestamp_nanos)
292+
293+
self.keysInterface = keysManager.as_KeysInterface()
294+
self.explicitKeysManager = keysManager
283295

284-
if master.use_km_wrapper {
285-
// self.keysInterface = manual_
286-
} else {
287-
self.keysInterface = keysManager.as_KeysInterface()
288-
self.explicitKeysManager = keysManager
296+
if master.configuration.useRouter {
297+
let networkGraph = NetworkGraph(genesis_hash: [UInt8](repeating: 0, count: 32), logger: self.logger)
298+
self.router = GossipSync.p2_p(a: P2PGossipSync(network_graph: networkGraph, chain_access: Option_AccessZ.none(), logger: self.logger))
299+
}else{
300+
self.router = GossipSync.none()
289301
}
290-
291-
// self.router = NetGraphMsgHandlerConstructor.initNetGraphMsgHandler(networkGraph: NetworkGraph(genesis_hash: [UInt8](repeating: 0, count: 32)), chainAccess: nil, logger: self.logger)
292-
self.router = GossipSync.none()
293302
}
294303

295304
fileprivate convenience init(master: HumanObjectPeerTestInstance, seed: UInt8) {
296305
self.init(master: master, _dummy: (), seed: seed)
297306

298-
if master.use_chan_manager_constructor {
307+
do {
308+
// channel manager constructor is mandatory
299309

300310
let graph = NetworkGraph(genesis_hash: [UInt8](repeating: 0, count: 32), logger: self.logger)
301311

302312
self.constructor = ChannelManagerConstructor(network: LDKNetwork_Bitcoin, config: UserConfig(), current_blockchain_tip_hash: [UInt8](repeating: 0, count: 32), current_blockchain_tip_height: 0, keys_interface: self.keysInterface, fee_estimator: self.feeEstimator, chain_monitor: self.chainMonitor!, net_graph: graph, tx_broadcaster: self.txBroadcaster, logger: self.logger)
303313

304-
// self.constructor = ChannelManagerConstructor(network: LDKNetwork_Bitcoin, config: UserConfig(), current_blockchain_tip_hash: [UInt8](repeating: 0, count: 32), current_blockchain_tip_height: 0, keys_interface: self.keysInterface, fee_estimator: self.feeEstimator, chain_monitor: self.chainMonitor!, net_graph: nil, tx_broadcaster: self.txBroadcaster, logger: self.logger)
305-
306314
let scoringParams = ProbabilisticScoringParameters()
307315
let probabalisticScorer = ProbabilisticScorer(params: scoringParams, network_graph: graph, logger: self.logger)
308316
let score = probabalisticScorer.as_Score()
@@ -311,15 +319,6 @@ public class HumanObjectPeerTestInstance {
311319
self.constructor?.chain_sync_completed(persister: TestChannelManagerPersister(master: self), scorer: multiThreadedScorer)
312320
self.channelManager = self.constructor!.channelManager
313321
self.peerManager = self.constructor!.peerManager
314-
} else {
315-
let chainParameters = ChainParameters(network_arg: LDKNetwork_Bitcoin, best_block_arg: BestBlock(block_hash: [UInt8](repeating: 0, count: 32), height: 0))
316-
self.channelManager = ChannelManager(fee_est: self.feeEstimator, chain_monitor: self.chainWatch!, tx_broadcaster: self.txBroadcaster, logger: self.logger, keys_manager: self.keysInterface, config: UserConfig(), params: chainParameters)
317-
let randomData = self.keysInterface.get_secure_random_bytes()
318-
let ignoringMessageHandler = IgnoringMessageHandler()
319-
let messageHandler = MessageHandler(chan_handler_arg: self.channelManager.as_ChannelMessageHandler(), route_handler_arg: self.router.getValueAsP2P()!.as_RoutingMessageHandler(), onion_message_handler_arg: ignoringMessageHandler.as_OnionMessageHandler())
320-
let nodeSecret = self.keysInterface.get_node_secret(recipient: LDKRecipient_Node).getValue()!
321-
let timestampSeconds = UInt32(NSDate().timeIntervalSince1970)
322-
self.peerManager = PeerManager(message_handler: messageHandler, our_node_secret: nodeSecret, current_time: timestampSeconds, ephemeral_random_data: randomData, logger: self.logger, custom_message_handler: IgnoringMessageHandler().as_CustomMessageHandler())
323322
}
324323
self.nodeId = self.channelManager.get_our_node_id()
325324
try! self.bindSocketHandler()
@@ -328,7 +327,8 @@ public class HumanObjectPeerTestInstance {
328327
fileprivate convenience init(original: Peer) {
329328
self.init(master: original.master, _dummy: (), seed: original.seed)
330329

331-
if master.use_chan_manager_constructor {
330+
do {
331+
// channel manager constructor is mandatory
332332
let graph = NetworkGraph(genesis_hash: [UInt8](repeating: 0, count: 32), logger: self.logger)
333333
self.constructor = ChannelManagerConstructor(network: LDKNetwork_Bitcoin, config: UserConfig(), current_blockchain_tip_hash: [UInt8](repeating: 0, count: 32), current_blockchain_tip_height: 0, keys_interface: self.keysInterface, fee_estimator: self.feeEstimator, chain_monitor: self.chainMonitor!, net_graph: graph, tx_broadcaster: self.txBroadcaster, logger: self.logger)
334334
self.constructor?.chain_sync_completed(persister: TestChannelManagerPersister(master: self), scorer: nil)
@@ -337,23 +337,12 @@ public class HumanObjectPeerTestInstance {
337337
let events = await original.pendingEventTracker.getEvents()
338338
await self.pendingEventTracker.addEvents(events: events)
339339
}
340-
} else {
341-
var monitors: [ChannelMonitor] = []
342-
var nativeMonitors: [LDKChannelMonitor] = []
343-
// let serialized = original.monitors[0].wr
344-
let serializedManager = original.channelManager.write()
345-
let managerResult = UtilMethods.constructor_BlockHashChannelManagerZ_read(ser: serializedManager, arg_keys_manager: self.keysInterface, arg_fee_estimator: self.feeEstimator, arg_chain_monitor: self.chainWatch!, arg_tx_broadcaster: self.txBroadcaster, arg_logger: self.logger, arg_default_config: UserConfig(), arg_channel_monitors: nativeMonitors)
346-
assert(managerResult.isOk())
347-
managerResult.getValue()!
348340
}
349341
self.nodeId = self.channelManager.get_our_node_id()
350342
try! self.bindSocketHandler()
351343
}
352344

353345
private func bindSocketHandler() throws {
354-
if !self.master.use_nio_peer_handler {
355-
return
356-
}
357346
self.tcpSocketHandler = self.constructor!.getTCPPeerHandler()
358347
print("Attempting to bind socket…")
359348
for i in 10000...65535 {
@@ -378,16 +367,15 @@ public class HumanObjectPeerTestInstance {
378367
}
379368

380369
fileprivate func getManagerEvents(expectedCount: UInt) async throws -> [Event] {
381-
guard self.master.use_chan_manager_constructor else {
382-
throw ChannelManagerEventError.notUsingChannelManagerConstructor
383-
}
384370
while true {
385371
if await self.pendingEventTracker.getCount() >= expectedCount {
386372
print("Found enough events for expected count of \(expectedCount)")
387373
let events = await self.pendingEventTracker.getAndClearEvents()
388374
print("Found event count: \(events.count)")
389375
return events
390376
}
377+
// sleep for 0.1 seconds
378+
// try await Task.sleep(nanoseconds: 0_100_000_000)
391379
await self.pendingEventTracker.awaitAddition()
392380
}
393381
}
@@ -438,12 +426,10 @@ public class HumanObjectPeerTestInstance {
438426

439427

440428
fileprivate func connectPeers(peerA: Peer, peerB: Peer) {
441-
if self.use_nio_peer_handler {
442-
let connectionResult = peerA.tcpSocketHandler?.connect(address: "127.0.0.1", port: peerB.tcpPort!, theirNodeId: peerB.nodeId!)
443-
print("connection result: \(connectionResult)")
444-
} else {
445-
// not currently relevant; we need the TCP connection simulation
446-
}
429+
430+
let connectionResult = peerA.tcpSocketHandler?.connect(address: "127.0.0.1", port: peerB.tcpPort!, theirNodeId: peerB.nodeId!)
431+
print("connection result: \(connectionResult)")
432+
447433
}
448434

449435
func test_multiple_peer_connections() async {
@@ -493,7 +479,7 @@ public class HumanObjectPeerTestInstance {
493479
}
494480
}
495481

496-
func do_test_message_handler() async {
482+
func testMessageHandling() async {
497483

498484
let FUNDING_SATOSHI_AMOUNT: UInt64 = 100_000 // 100k satoshis
499485
let SEND_MSAT_AMOUNT_A_TO_B: UInt64 = 10_000_000 // 10k satoshis
@@ -671,11 +657,42 @@ public class HumanObjectPeerTestInstance {
671657
let invoicePayment = paymentPurpose.getValueAsInvoicePayment()!
672658
let preimage = invoicePayment.getPayment_preimage()
673659
let secret = invoicePayment.getPayment_secret()
674-
peer2.channelManager.claim_funds(payment_preimage: preimage)
675-
print("claimed payment with secret \(secret) using preimage \(preimage)")
660+
if self.configuration.shouldRecipientRejectPayment {
661+
print("about to fail payment because shouldRecipientRejectPayment flag is set")
662+
peer2.channelManager.fail_htlc_backwards(payment_hash: paymentHash)
663+
print("deliberately failed payment with hash \(paymentHash)")
664+
for _ in 0..<10{
665+
// this may have a random delay, run it repeatedly
666+
peer2.channelManager.process_pending_htlc_forwards()
667+
try! await Task.sleep(nanoseconds: 0_100_000_000)
668+
}
669+
} else {
670+
peer2.channelManager.claim_funds(payment_preimage: preimage)
671+
print("claimed payment with secret \(secret) using preimage \(preimage)")
672+
}
676673
}
677674

678-
do {
675+
if self.configuration.shouldRecipientRejectPayment {
676+
let peer1Events = try! await peer1.getManagerEvents(expectedCount: 1)
677+
let paymentPathFailedEvent = peer1Events[0]
678+
guard case .PaymentPathFailed = paymentPathFailedEvent.getValueType() else {
679+
return XCTAssert(false, "Expected .PaymentPathFailed, got \(paymentPathFailedEvent.getValueType())")
680+
}
681+
let paymentPathFailed = paymentPathFailedEvent.getValueAsPaymentPathFailed()!
682+
let failureDescriptor: [String: Any] = [
683+
"payment_id": paymentPathFailed.getPayment_id(),
684+
"payment_hash": paymentPathFailed.getPayment_hash(),
685+
"payment_failed_permanently": paymentPathFailed.getPayment_failed_permanently(),
686+
"short_channel_id": paymentPathFailed.getShort_channel_id(),
687+
"path": paymentPathFailed.getPath().map { $0.get_short_channel_id() },
688+
"network_update": paymentPathFailed.getNetwork_update().getValue().debugDescription
689+
]
690+
691+
print("payent path failure: \(failureDescriptor)")
692+
print("here")
693+
return
694+
695+
} else {
679696
// process payment
680697
let peer1Events = try! await peer1.getManagerEvents(expectedCount: 2)
681698
let paymentSentEvent = peer1Events[0]

ci/LDKSwift/Tests/LDKSwiftTests/LDKSwiftTests.swift

Lines changed: 30 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -408,45 +408,44 @@ class LDKSwiftTests: XCTestCase {
408408

409409
func testExtendedActivity() async throws {
410410
// for i in 0...(1 << 7) {
411-
for i in 0..<1 { // only do one test run initially
412-
let nice_close = (i & (1 << 0)) != 0;
413-
let use_km_wrapper = (i & (1 << 1)) != 0;
414-
let use_manual_watch = (i & (1 << 2)) != 0;
415-
let reload_peers = (i & (1 << 3)) != 0;
416-
let break_cross_refs = (i & (1 << 4)) != 0;
417-
let nio_peer_handler = true // (i & (1 << 5)) != 0;
418-
let use_chan_manager_constructor = true // (i & (1 << 6)) != 0;
419-
420-
if (break_cross_refs && !reload_peers) {
411+
let combinationCount = HumanObjectPeerTestInstance.Configuration.combinationCount()
412+
for i in 0..<combinationCount { // only do one test run initially
413+
414+
print("Running test with flags \(i)");
415+
416+
let config = HumanObjectPeerTestInstance.Configuration()
417+
418+
config.shouldRecipientRejectPayment = (i & (1 << 0)) != 0
419+
print("shouldRecipientRejectPayment: \(config.shouldRecipientRejectPayment)")
420+
421+
config.useFilter = (i & (1 << 1)) != 0
422+
print("useFilter: \(config.useFilter)")
423+
424+
config.useRouter = (i & (1 << 2)) != 0
425+
print("useRouter: \(config.useRouter)")
426+
427+
/*
428+
config.nice_close = (i & (1 << 0)) != 0;
429+
config.use_km_wrapper = (i & (1 << 1)) != 0;
430+
config.use_manual_watch = (i & (1 << 2)) != 0;
431+
config.reload_peers = (i & (1 << 3)) != 0;
432+
config.break_cross_peer_refs = (i & (1 << 4)) != 0;
433+
config.use_nio_peer_handler = true // (i & (1 << 5)) != 0;
434+
config.useChannelManagerConstructor = true // (i & (1 << 6)) != 0;
435+
436+
if (config.break_cross_peer_refs && !config.reload_peers) {
421437
// There are no cross refs to break without reloading peers.
422438
continue;
423439
}
424440

425-
if (use_chan_manager_constructor && (use_manual_watch || !nio_peer_handler)) {
441+
if (config.useChannelManagerConstructor && (config.use_manual_watch || !config.use_nio_peer_handler)) {
426442
// ChannelManagerConstructor requires a ChainMonitor as the Watch and creates a NioPeerHandler for us.
427443
continue;
428444
}
445+
*/
429446

430-
print("Running test with flags \(i)");
431-
try await SimulationRunner.do_test(nice_close: nice_close, use_km_wrapper: use_km_wrapper, use_manual_watch: use_manual_watch, reload_peers: reload_peers, break_cross_peer_refs: break_cross_refs, nio_peer_handler: nio_peer_handler, use_chan_manager_constructor: use_chan_manager_constructor)
432-
}
433-
434-
}
435-
436-
fileprivate class SimulationRunner {
437-
438-
class func do_test(nice_close: Bool, use_km_wrapper: Bool, use_manual_watch: Bool, reload_peers: Bool, break_cross_peer_refs: Bool, nio_peer_handler: Bool, use_chan_manager_constructor: Bool) async throws {
439-
440-
let instance = await do_test_run(nice_close: nice_close, use_km_wrapper: use_km_wrapper, use_manual_watch: use_manual_watch, reload_peers: reload_peers, break_cross_peer_refs: break_cross_peer_refs, nio_peer_handler: nio_peer_handler, use_chan_manager_constructor: use_chan_manager_constructor)
441-
442-
}
443-
444-
class func do_test_run(nice_close: Bool, use_km_wrapper: Bool, use_manual_watch: Bool, reload_peers: Bool, break_cross_peer_refs: Bool, nio_peer_handler: Bool, use_chan_manager_constructor: Bool) async -> HumanObjectPeerTestInstance {
445-
446-
let instance = HumanObjectPeerTestInstance(nice_close: nice_close, use_km_wrapper: use_km_wrapper, use_manual_watch: use_manual_watch, reload_peers: reload_peers, break_cross_peer_refs: break_cross_peer_refs, use_nio_peer_handler: nio_peer_handler, use_filter: !nio_peer_handler, use_chan_manager_constructor: use_chan_manager_constructor)
447-
448-
await instance.do_test_message_handler()
449-
return instance
447+
let instance = HumanObjectPeerTestInstance(configuration: config)
448+
await instance.testMessageHandling()
450449
}
451450

452451
}

0 commit comments

Comments
 (0)