From bb619352be5bee0a8e8682238ff49c4f913e6fec Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 12 Jun 2019 10:25:53 +0200 Subject: [PATCH 1/2] lntest: check payment status settled after claim test --- ...d_multi-hop_htlc_local_chain_claim_test.go | 64 +++++++++++++++++++ ...ulti-hop_htlc_receiver_chain_claim_test.go | 10 +++ ..._multi-hop_htlc_remote_chain_claim_test.go | 10 +++ 3 files changed, 84 insertions(+) diff --git a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go index 0b155c97..7d79eacb 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go @@ -393,6 +393,16 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) if err != nil { t.Fatalf(predErr.Error()) } + + // Finally, check that the Alice's payment is correctly marked + // succeeded. + ctxt, _ = context.WithTimeout(ctxt, defaultTimeout) + err = checkPaymentStatus( + ctxt, net.Alice, preimage, lnrpc.Payment_SUCCEEDED, + ) + if err != nil { + t.Fatalf(err.Error()) + } } // waitForInvoiceAccepted waits until the specified invoice moved to the @@ -421,3 +431,57 @@ func waitForInvoiceAccepted(t *harnessTest, node *lntest.HarnessNode, } } } + +// checkPaymentStatus asserts that the given node list a payment with the given +// preimage has the expected status. +func checkPaymentStatus(ctxt context.Context, node *lntest.HarnessNode, + preimage lntypes.Preimage, status lnrpc.Payment_PaymentStatus) error { + + req := &lnrpc.ListPaymentsRequest{ + IncludeIncomplete: true, + } + paymentsResp, err := node.ListPayments(ctxt, req) + if err != nil { + return fmt.Errorf("error when obtaining Alice payments: %v", + err) + } + + payHash := preimage.Hash() + var found bool + for _, p := range paymentsResp.Payments { + if p.PaymentHash != payHash.String() { + continue + } + + found = true + if p.Status != status { + return fmt.Errorf("expected payment status "+ + "%v, got %v", status, p.Status) + } + + switch status { + + // If this expected status is SUCCEEDED, we expect the final preimage. + case lnrpc.Payment_SUCCEEDED: + if p.PaymentPreimage != preimage.String() { + return fmt.Errorf("preimage doesn't match: %v vs %v", + p.PaymentPreimage, preimage.String()) + } + + // Otherwise we expect an all-zero preimage. + default: + if p.PaymentPreimage != (lntypes.Preimage{}).String() { + return fmt.Errorf("expected zero preimage, got %v", + p.PaymentPreimage) + } + } + + } + + if !found { + return fmt.Errorf("payment with payment hash %v not found "+ + "in response", payHash) + } + + return nil +} diff --git a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go index fc497aec..8a017633 100644 --- a/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_receiver_chain_claim_test.go @@ -298,6 +298,16 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest) "%d sat", invoiceAmt, invoice.AmtPaidSat) } + // Finally, check that the Alice's payment is correctly marked + // succeeded. + ctxt, _ = context.WithTimeout(ctxt, defaultTimeout) + err = checkPaymentStatus( + ctxt, net.Alice, preimage, lnrpc.Payment_SUCCEEDED, + ) + if err != nil { + t.Fatalf(err.Error()) + } + // We'll close out the channel between Alice and Bob, then shutdown // carol to conclude the test. ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout) diff --git a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go index 14894e99..b96bc17f 100644 --- a/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_remote_chain_claim_test.go @@ -332,4 +332,14 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest t.Fatalf("expected invoice to be settled with %d sat, got "+ "%d sat", invoiceAmt, invoice.AmtPaidSat) } + + // Finally, check that the Alice's payment is correctly marked + // succeeded. + ctxt, _ = context.WithTimeout(ctxt, defaultTimeout) + err = checkPaymentStatus( + ctxt, net.Alice, preimage, lnrpc.Payment_SUCCEEDED, + ) + if err != nil { + t.Fatalf(err.Error()) + } } From 80ad0fdd5ca906d540db56f05486dc79496d9e8c Mon Sep 17 00:00:00 2001 From: "Johan T. Halseth" Date: Wed, 12 Jun 2019 10:44:22 +0200 Subject: [PATCH 2/2] lntest: restart Alice after on-chain settle To ensure lnd is able to pick up an on-chain preimage properly after a restart, we suspend Alice and check that the payment is listed correctly as succeeded after a restart. --- .../lnd_multi-hop_htlc_local_chain_claim_test.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go index 7d79eacb..123359dc 100644 --- a/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go +++ b/lntest/itest/lnd_multi-hop_htlc_local_chain_claim_test.go @@ -195,6 +195,13 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) } } + // At this point we suspend Alice to make sure she'll handle the + // on-chain settle after a restart. + restartAlice, err := net.SuspendNode(net.Alice) + if err != nil { + t.Fatalf("unable to suspend alice: %v", err) + } + // Mine a block to confirm the two transactions (+ the coinbase). block = mineBlocks(t, net, 1, 2)[0] if len(block.Transactions) != 3 { @@ -285,6 +292,12 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest) bobSecondLevelCSV := uint32(defaultCSV) carolSecondLevelCSV-- + // Now that the preimage from Bob has hit the chain, restart Alice to + // ensure she'll pick it up. + if err := restartAlice(); err != nil { + t.Fatalf("unable to restart alice: %v", err) + } + // If we then mine 3 additional blocks, Carol's second level tx should // mature, and she can pull the funds from it with a sweep tx. if _, err := net.Miner.Node.Generate(carolSecondLevelCSV); err != nil {