Skip to content

Commit 72688b8

Browse files
committed
test channel balance updates with regular and zero amount invoice payment
1 parent f104879 commit 72688b8

File tree

1 file changed

+175
-19
lines changed

1 file changed

+175
-19
lines changed

xcode/DirectBindingsApp/DirectBindingsAppTests/HumanObjectPeerTestInstance.swift

Lines changed: 175 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,10 @@ public class HumanObjectPeerTestInstance {
6464
private(set) var continuations: [CheckedContinuation<Void, Never>] = []
6565

6666
private func triggerContinuations(){
67-
for continuation in self.continuations {
68-
continuation.resume()
67+
let continuations = self.continuations
68+
self.continuations.removeAll()
69+
for currentContinuation in continuations {
70+
currentContinuation.resume()
6971
}
7072
}
7173

@@ -125,8 +127,10 @@ public class HumanObjectPeerTestInstance {
125127
}
126128

127129
private func triggerContinuations(){
128-
for continuation in self.continuations {
129-
continuation.resume()
130+
let continuations = self.continuations
131+
self.continuations.removeAll()
132+
for currentContinuation in continuations {
133+
currentContinuation.resume()
130134
}
131135
}
132136

@@ -208,6 +212,7 @@ public class HumanObjectPeerTestInstance {
208212

209213
func handle_event(event: Event) {
210214
let eventClone = event.clone()
215+
print("peer \(self.master.seed) received event: \(eventClone.getValueType())")
211216
Task {
212217
// clone to avoid deallocation-related issues
213218
await master.pendingEventTracker.addEvent(event: eventClone)
@@ -282,9 +287,9 @@ public class HumanObjectPeerTestInstance {
282287
// 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)
283288

284289
let scoringParams = ProbabilisticScoringParameters()
285-
let probabalisticScorer = ProbabilisticScorer(params: scoringParams, network_graph: graph)
290+
let probabalisticScorer = ProbabilisticScorer(params: scoringParams.danglingClone(), network_graph: graph)
286291
let score = probabalisticScorer.as_Score()
287-
let multiThreadedScorer = MultiThreadedLockableScore(score: score)
292+
let multiThreadedScorer = MultiThreadedLockableScore(score: score.dangle())
288293

289294
self.constructor?.chain_sync_completed(persister: TestChannelManagerPersister(master: self), scorer: multiThreadedScorer)
290295
self.channelManager = self.constructor!.channelManager
@@ -419,6 +424,8 @@ public class HumanObjectPeerTestInstance {
419424
func do_test_message_handler() async {
420425

421426
let FUNDING_SATOSHI_AMOUNT: UInt64 = 100_000 // 100k satoshis
427+
let SEND_MSAT_AMOUNT_A_TO_B: UInt64 = 10_000_000 // 10k satoshis
428+
let SEND_MSAT_AMOUNT_B_TO_A: UInt64 = 3_000_000 // 3k satoshis
422429

423430
let peer1 = Peer(master: self, seed: 1)
424431
let peer2 = Peer(master: self, seed: 2)
@@ -523,34 +530,183 @@ public class HumanObjectPeerTestInstance {
523530
var usableChannelsB = [ChannelDetails]()
524531
while (usableChannelsA.isEmpty || usableChannelsB.isEmpty) {
525532
usableChannelsA = peer1.channelManager.list_usable_channels()
526-
usableChannelsB = peer1.channelManager.list_usable_channels()
533+
usableChannelsB = peer2.channelManager.list_usable_channels()
527534
// sleep for 100ms
528535
try! await Task.sleep(nanoseconds: 0_100_000_000)
529536
}
530537

531538
XCTAssertEqual(usableChannelsA.count, 1)
532539
XCTAssertEqual(usableChannelsB.count, 1)
533540

534-
let channel = usableChannelsA[0]
535-
XCTAssertEqual(channel.get_channel_value_satoshis(), FUNDING_SATOSHI_AMOUNT)
536-
let shortChannelId = channel.get_short_channel_id().getValue()!
541+
let channelAToB = usableChannelsA[0]
542+
let channelBToA = usableChannelsB[0]
543+
XCTAssertEqual(channelAToB.get_channel_value_satoshis(), FUNDING_SATOSHI_AMOUNT)
544+
let shortChannelId = channelAToB.get_short_channel_id().getValue()!
537545

538546
let fundingTxId = fundingTransaction.calculateId()
539547
XCTAssertEqual(usableChannelsA[0].get_channel_id(), fundingTxId)
540548
XCTAssertEqual(usableChannelsB[0].get_channel_id(), fundingTxId)
541549

542-
// create invoice for 10k satoshis to pay to peer2
543-
let invoiceResult = Bindings.createInvoiceFromChannelManager(channelManager: peer2.channelManager, keysManager: peer2.keysInterface, network: LDKCurrency_Bitcoin, amountMsat: 10_000_000, description: "Invoice description")
544-
guard let invoice = invoiceResult.getValue() else {
545-
XCTAssertTrue(invoiceResult.isOk()) // this step should fail
546-
return
550+
let originalChannelBalanceAToB = channelAToB.get_balance_msat()
551+
let originalChannelBalanceBToA = channelBToA.get_balance_msat()
552+
print("original balance A->B mSats: \(originalChannelBalanceAToB)")
553+
print("original balance B->A mSats: \(originalChannelBalanceBToA)")
554+
555+
do {
556+
// create invoice for 10k satoshis to pay to peer2
557+
558+
let invoiceResult = Bindings.createInvoiceFromChannelManager(channelManager: peer2.channelManager, keysManager: peer2.keysInterface, network: LDKCurrency_Bitcoin, amountMsat: SEND_MSAT_AMOUNT_A_TO_B, description: "Invoice description")
559+
let invoice = invoiceResult.getValue()!
560+
print("Invoice: \(invoice.to_str())")
561+
562+
let recreatedInvoice = Invoice.from_str(s: invoice.to_str())
563+
XCTAssertTrue(recreatedInvoice.isOk())
564+
565+
let invoicePaymentResult = peer1.constructor!.payer!.pay_invoice(invoice: invoice)
566+
XCTAssertTrue(invoicePaymentResult.isOk())
567+
568+
do {
569+
// process HTLCs
570+
let peer2Event = await peer2.getManagerEvents(expectedCount: 1)[0]
571+
XCTAssertEqual(peer2Event.getValueType(), .PendingHTLCsForwardable)
572+
let pendingHTLCsForwardable = peer2Event.getValueAsPendingHTLCsForwardable()!
573+
print("forwardable time: \(pendingHTLCsForwardable.getTime_forwardable())")
574+
peer2.channelManager.process_pending_htlc_forwards()
575+
print("processed pending HTLC forwards")
576+
}
577+
578+
do {
579+
// process payment
580+
let peer2Event = await peer2.getManagerEvents(expectedCount: 1)[0]
581+
XCTAssertEqual(peer2Event.getValueType(), .PaymentReceived)
582+
let paymentReceived = peer2Event.getValueAsPaymentReceived()!
583+
let paymentHash = paymentReceived.getPayment_hash()
584+
print("received payment of \(paymentReceived.getAmt()) with hash \(paymentHash)")
585+
let paymentPurpose = paymentReceived.getPurpose()
586+
XCTAssertEqual(paymentPurpose.getValueType(), .InvoicePayment)
587+
let invoicePayment = paymentPurpose.getValueAsInvoicePayment()!
588+
let preimage = invoicePayment.getPayment_preimage()
589+
let secret = invoicePayment.getPayment_secret()
590+
let claimResult = peer2.channelManager.claim_funds(payment_preimage: preimage)
591+
XCTAssertTrue(claimResult)
592+
print("claimed payment with secret \(secret) using preimage \(preimage)")
593+
}
594+
595+
do {
596+
// process payment
597+
let peer1Events = await peer1.getManagerEvents(expectedCount: 2)
598+
let paymentSentEvent = peer1Events[0]
599+
let paymentPathSuccessfulEvent = peer1Events[1]
600+
XCTAssertEqual(paymentSentEvent.getValueType(), .PaymentSent)
601+
XCTAssertEqual(paymentPathSuccessfulEvent.getValueType(), .PaymentPathSuccessful)
602+
let paymentSent = paymentSentEvent.getValueAsPaymentSent()!
603+
let paymentPathSuccessful = paymentPathSuccessfulEvent.getValueAsPaymentPathSuccessful()!
604+
print("sent payment \(paymentSent.getPayment_id()) with fee \(paymentSent.getFee_paid_msat().getValue()) via \(paymentPathSuccessful.getPath().map { h in h.get_short_channel_id() })")
605+
}
606+
607+
var currentChannelABalance = originalChannelBalanceAToB
608+
var currentChannelBBalance = originalChannelBalanceBToA
609+
while true {
610+
let channelA = peer1.channelManager.list_usable_channels()[0]
611+
let channelB = peer2.channelManager.list_usable_channels()[0]
612+
currentChannelABalance = channelA.get_balance_msat()
613+
currentChannelBBalance = channelB.get_balance_msat()
614+
if currentChannelABalance != originalChannelBalanceAToB && currentChannelBBalance != originalChannelBalanceBToA {
615+
break
616+
}
617+
// sleep for 100ms
618+
try! await Task.sleep(nanoseconds: 0_100_000_000)
619+
}
620+
621+
let invoicePayment = invoicePaymentResult.getValue()!
622+
XCTAssertEqual(currentChannelABalance, originalChannelBalanceAToB - SEND_MSAT_AMOUNT_A_TO_B)
623+
XCTAssertEqual(currentChannelBBalance, originalChannelBalanceBToA + SEND_MSAT_AMOUNT_A_TO_B)
547624
}
548-
print("Invoice: \(invoice.to_str())")
549625

550-
let recreatedInvoice = Invoice.from_str(s: invoice.to_str())
551-
XCTAssertTrue(recreatedInvoice.isOk())
626+
do {
627+
// send some money back
628+
// create invoice for 10k satoshis to pay to peer2
629+
let prePaymentBalanceAToB = peer1.channelManager.list_usable_channels()[0].get_balance_msat()
630+
let prePaymentBalanceBToA = peer2.channelManager.list_usable_channels()[0].get_balance_msat()
631+
print("pre-payment balance A->B mSats: \(prePaymentBalanceAToB)")
632+
print("pre-payment balance B->A mSats: \(prePaymentBalanceBToA)")
633+
634+
let invoiceResult = Bindings.createInvoiceFromChannelManager(channelManager: peer1.channelManager, keysManager: peer1.keysInterface, network: LDKCurrency_Bitcoin, amountMsat: nil, description: "Second invoice description")
635+
let invoice = invoiceResult.getValue()!
636+
print("Implicit amount invoice: \(invoice.to_str())")
637+
638+
let recreatedInvoice = Invoice.from_str(s: invoice.to_str())
639+
XCTAssertTrue(recreatedInvoice.isOk())
640+
641+
let invoicePaymentResult = peer2.constructor!.payer!.pay_zero_value_invoice(invoice: invoice, amount_msats: SEND_MSAT_AMOUNT_B_TO_A)
642+
if let error = invoicePaymentResult.getError() {
643+
print("value type: \(error.getValueType())")
644+
if let routingError = error.getValueAsRouting() {
645+
print("routing error: \(routingError.get_err())")
646+
}
647+
}
648+
XCTAssertTrue(invoicePaymentResult.isOk())
649+
650+
do {
651+
// process HTLCs
652+
let peer1Event = await peer1.getManagerEvents(expectedCount: 1)[0]
653+
XCTAssertEqual(peer1Event.getValueType(), .PendingHTLCsForwardable)
654+
let pendingHTLCsForwardable = peer1Event.getValueAsPendingHTLCsForwardable()!
655+
print("forwardable time: \(pendingHTLCsForwardable.getTime_forwardable())")
656+
peer1.channelManager.process_pending_htlc_forwards()
657+
print("processed pending HTLC forwards")
658+
}
659+
660+
do {
661+
// process payment
662+
let peer1Event = await peer1.getManagerEvents(expectedCount: 1)[0]
663+
XCTAssertEqual(peer1Event.getValueType(), .PaymentReceived)
664+
let paymentReceived = peer1Event.getValueAsPaymentReceived()!
665+
let paymentHash = paymentReceived.getPayment_hash()
666+
print("received payment of \(paymentReceived.getAmt()) with hash \(paymentHash)")
667+
let paymentPurpose = paymentReceived.getPurpose()
668+
XCTAssertEqual(paymentPurpose.getValueType(), .InvoicePayment)
669+
let invoicePayment = paymentPurpose.getValueAsInvoicePayment()!
670+
let preimage = invoicePayment.getPayment_preimage()
671+
let secret = invoicePayment.getPayment_secret()
672+
let claimResult = peer1.channelManager.claim_funds(payment_preimage: preimage)
673+
XCTAssertTrue(claimResult)
674+
print("claimed payment with secret \(secret) using preimage \(preimage)")
675+
}
676+
677+
do {
678+
// process payment
679+
let peer2Events = await peer2.getManagerEvents(expectedCount: 2)
680+
let paymentSentEvent = peer2Events[0]
681+
let paymentPathSuccessfulEvent = peer2Events[1]
682+
XCTAssertEqual(paymentSentEvent.getValueType(), .PaymentSent)
683+
XCTAssertEqual(paymentPathSuccessfulEvent.getValueType(), .PaymentPathSuccessful)
684+
let paymentSent = paymentSentEvent.getValueAsPaymentSent()!
685+
let paymentPathSuccessful = paymentPathSuccessfulEvent.getValueAsPaymentPathSuccessful()!
686+
print("sent payment \(paymentSent.getPayment_id()) with fee \(paymentSent.getFee_paid_msat().getValue()) via \(paymentPathSuccessful.getPath().map { h in h.get_short_channel_id() })")
687+
}
688+
689+
var currentChannelABalance = prePaymentBalanceAToB
690+
var currentChannelBBalance = prePaymentBalanceBToA
691+
while true {
692+
let channelA = peer1.channelManager.list_usable_channels()[0]
693+
let channelB = peer2.channelManager.list_usable_channels()[0]
694+
currentChannelABalance = channelA.get_balance_msat()
695+
currentChannelBBalance = channelB.get_balance_msat()
696+
if currentChannelABalance != prePaymentBalanceAToB && currentChannelBBalance != prePaymentBalanceBToA {
697+
break
698+
}
699+
// sleep for 100ms
700+
try! await Task.sleep(nanoseconds: 0_100_000_000)
701+
}
702+
703+
let invoicePayment = invoicePaymentResult.getValue()!
704+
XCTAssertEqual(currentChannelABalance, prePaymentBalanceAToB + SEND_MSAT_AMOUNT_B_TO_A)
705+
XCTAssertEqual(currentChannelBBalance, prePaymentBalanceBToA - SEND_MSAT_AMOUNT_B_TO_A)
706+
XCTAssertEqual(currentChannelABalance, originalChannelBalanceAToB - SEND_MSAT_AMOUNT_A_TO_B + SEND_MSAT_AMOUNT_B_TO_A)
707+
XCTAssertEqual(currentChannelBBalance, originalChannelBalanceBToA + SEND_MSAT_AMOUNT_A_TO_B - SEND_MSAT_AMOUNT_B_TO_A)
708+
}
552709

553-
let invoicePaymentResult = peer1.constructor!.payer!.pay_invoice(invoice: invoice)
554710

555711
do {
556712
// sleep for 5 seconds to ensure sanity

0 commit comments

Comments
 (0)