test: extend testMultiHopPayments to test a 4 node, 3 hop payment

In this commit, we extend the testMultiHopPayments test case to add an
additional node to the multi-hop payment route: Dave.

Related to #391 as it uses the provided code fragment to reproduce the
bug. With this test in place, we’ll now be able to notice any
regressions in this area.
This commit is contained in:
Olaoluwa Osuntokun 2017-10-24 18:33:55 -07:00
parent 21446c2872
commit 885753cae4
No known key found for this signature in database
GPG Key ID: 964EA263DD637C21

@ -1264,17 +1264,45 @@ func testMultiHopPayments(net *networkHarness, t *harnessTest) {
Index: chanPointAlice.OutputIndex, Index: chanPointAlice.OutputIndex,
} }
// Create a new node (Carol), load her with some funds, then establish // As preliminary setup, we'll create two new nodes: Carol and Dave,
// a connection between Carol and Alice with a channel that has // such that we now have a 4 ndoe, 3 channel topology. Dave will make
// identical capacity to the one created above. // a channel with Alice, and Carol with Dave. After this setup, the
// network topology should now look like:
// Carol -> Dave -> Alice -> Bob
// //
// The network topology should now look like: Carol -> Alice -> Bob // First, we'll create Dave and establish a channel to Alice.
dave, err := net.NewNode(nil)
if err != nil {
t.Fatalf("unable to create new nodes: %v", err)
}
if err := net.ConnectNodes(ctxb, dave, net.Alice); err != nil {
t.Fatalf("unable to connect dave to alice: %v", err)
}
err = net.SendCoins(ctxb, btcutil.SatoshiPerBitcoin, dave)
if err != nil {
t.Fatalf("unable to send coins to dave: %v", err)
}
ctxt, _ = context.WithTimeout(ctxb, timeout)
chanPointDave := openChannelAndAssert(ctxt, t, net, dave,
net.Alice, chanAmt, 0)
ctxt, _ = context.WithTimeout(ctxb, timeout)
daveChanTXID, err := chainhash.NewHash(chanPointDave.FundingTxid)
if err != nil {
t.Fatalf("unable to create sha hash: %v", err)
}
daveFundPoint := wire.OutPoint{
Hash: *daveChanTXID,
Index: chanPointDave.OutputIndex,
}
// Next, we'll create Carol and establish a channel to from her to
// Dave.
carol, err := net.NewNode(nil) carol, err := net.NewNode(nil)
if err != nil { if err != nil {
t.Fatalf("unable to create new nodes: %v", err) t.Fatalf("unable to create new nodes: %v", err)
} }
if err := net.ConnectNodes(ctxb, carol, net.Alice); err != nil { if err := net.ConnectNodes(ctxb, carol, dave); err != nil {
t.Fatalf("unable to connect carol to alice: %v", err) t.Fatalf("unable to connect carol to dave: %v", err)
} }
err = net.SendCoins(ctxb, btcutil.SatoshiPerBitcoin, carol) err = net.SendCoins(ctxb, btcutil.SatoshiPerBitcoin, carol)
if err != nil { if err != nil {
@ -1282,8 +1310,8 @@ func testMultiHopPayments(net *networkHarness, t *harnessTest) {
} }
ctxt, _ = context.WithTimeout(ctxb, timeout) ctxt, _ = context.WithTimeout(ctxb, timeout)
chanPointCarol := openChannelAndAssert(ctxt, t, net, carol, chanPointCarol := openChannelAndAssert(ctxt, t, net, carol,
net.Alice, chanAmt, 0) dave, chanAmt, 0)
ctxt, _ = context.WithTimeout(ctxb, timeout)
carolChanTXID, err := chainhash.NewHash(chanPointCarol.FundingTxid) carolChanTXID, err := chainhash.NewHash(chanPointCarol.FundingTxid)
if err != nil { if err != nil {
t.Fatalf("unable to create sha hash: %v", err) t.Fatalf("unable to create sha hash: %v", err)
@ -1311,20 +1339,22 @@ func testMultiHopPayments(net *networkHarness, t *harnessTest) {
payReqs[i] = resp.PaymentRequest payReqs[i] = resp.PaymentRequest
} }
// Wait for carol to recognize both the Channel from herself to Carol, // We'll wait for all parties to recognize the new channels within the
// and also the channel from Alice to Bob. // network.
ctxt, _ = context.WithTimeout(ctxb, timeout)
err = dave.WaitForNetworkChannelOpen(ctxt, chanPointDave)
if err != nil {
t.Fatalf("dave didn't advertise his channel: %v", err)
}
ctxt, _ = context.WithTimeout(ctxb, timeout) ctxt, _ = context.WithTimeout(ctxb, timeout)
err = carol.WaitForNetworkChannelOpen(ctxt, chanPointCarol) err = carol.WaitForNetworkChannelOpen(ctxt, chanPointCarol)
if err != nil { if err != nil {
t.Fatalf("carol didn't advertise her channel: %v", err) t.Fatalf("carol didn't advertise her channel in time: %v",
} err)
ctxt, _ = context.WithTimeout(ctxb, timeout)
err = carol.WaitForNetworkChannelOpen(ctxt, chanPointAlice)
if err != nil {
t.Fatalf("carol didn't see the alice->bob channel before timeout: %v", err)
} }
// Using Carol as the source, pay to the 5 invoices from Bob created above. // Using Carol as the source, pay to the 5 invoices from Bob created
// above.
carolPayStream, err := carol.SendPayment(ctxb) carolPayStream, err := carol.SendPayment(ctxb)
if err != nil { if err != nil {
t.Fatalf("unable to create payment stream for carol: %v", err) t.Fatalf("unable to create payment stream for carol: %v", err)
@ -1368,16 +1398,17 @@ func testMultiHopPayments(net *networkHarness, t *harnessTest) {
// creating the seed nodes in the network. // creating the seed nodes in the network.
const baseFee = 1 const baseFee = 1
assertAmountPaid := func(node *lightningNode, assertAmountPaid := func(node *lightningNode, chanPoint wire.OutPoint,
chanPoint wire.OutPoint, amountSent, amountSent, amountReceived int64) {
amountReceived int64) {
channelName := "" channelName := ""
switch chanPoint { switch chanPoint {
case carolFundPoint:
channelName = "Carol(local) => Alice(remote)"
case aliceFundPoint: case aliceFundPoint:
channelName = "Alice(local) => Bob(remote)" channelName = "Alice(local) => Bob(remote)"
case daveFundPoint:
channelName = "Dave(local) => Alice(remote)"
case carolFundPoint:
channelName = "Carol(local) => Dave(remote)"
} }
checkAmountPaid := func() error { checkAmountPaid := func() error {
@ -1413,8 +1444,8 @@ func testMultiHopPayments(net *networkHarness, t *harnessTest) {
} }
// As far as HTLC inclusion in commitment transaction might be // As far as HTLC inclusion in commitment transaction might be
// postponed we will try to check the balance couple of // postponed we will try to check the balance couple of times,
// times, and then if after some period of time we receive wrong // and then if after some period of time we receive wrong
// balance return the error. // balance return the error.
// TODO(roasbeef): remove sleep after invoice notification hooks // TODO(roasbeef): remove sleep after invoice notification hooks
// are in place // are in place
@ -1440,26 +1471,36 @@ func testMultiHopPayments(net *networkHarness, t *harnessTest) {
// shifted by 5k satoshis in the direction of Bob, the sink within the // shifted by 5k satoshis in the direction of Bob, the sink within the
// payment flow generated above. The order of asserts corresponds to // payment flow generated above. The order of asserts corresponds to
// increasing of time is needed to embed the HTLC in commitment // increasing of time is needed to embed the HTLC in commitment
// transaction, in channel Carol->Alice->Bob, order is Bob,Alice,Carol. // transaction, in channel Carol->David->Alice->Bob, order is Bob,
// Alice, David, Carol.
const amountPaid = int64(5000) const amountPaid = int64(5000)
assertAmountPaid(net.Bob, aliceFundPoint, int64(0), amountPaid) assertAmountPaid(net.Bob, aliceFundPoint, int64(0), amountPaid)
assertAmountPaid(net.Alice, aliceFundPoint, amountPaid, int64(0)) assertAmountPaid(net.Alice, aliceFundPoint, amountPaid, int64(0))
assertAmountPaid(net.Alice, carolFundPoint, int64(0), assertAmountPaid(net.Alice, daveFundPoint, int64(0),
amountPaid+(baseFee*numPayments)) amountPaid+(baseFee*numPayments))
assertAmountPaid(carol, carolFundPoint, amountPaid+(baseFee*numPayments), assertAmountPaid(dave, daveFundPoint, amountPaid+(baseFee*numPayments),
int64(0))
assertAmountPaid(dave, carolFundPoint, int64(0),
amountPaid+((baseFee*numPayments)*2))
assertAmountPaid(carol, carolFundPoint, amountPaid+(baseFee*numPayments)*2,
int64(0)) int64(0))
ctxt, _ = context.WithTimeout(ctxb, timeout) ctxt, _ = context.WithTimeout(ctxb, timeout)
closeChannelAndAssert(ctxt, t, net, net.Alice, chanPointAlice, false) closeChannelAndAssert(ctxt, t, net, net.Alice, chanPointAlice, false)
ctxt, _ = context.WithTimeout(ctxb, timeout) ctxt, _ = context.WithTimeout(ctxb, timeout)
closeChannelAndAssert(ctxt, t, net, dave, chanPointDave, false)
ctxt, _ = context.WithTimeout(ctxb, timeout)
closeChannelAndAssert(ctxt, t, net, carol, chanPointCarol, false) closeChannelAndAssert(ctxt, t, net, carol, chanPointCarol, false)
// Finally, shutdown the node we created for the duration of the tests, // Finally, shutdown the nodes we created for the duration of the
// only leaving the two seed nodes (Alice and Bob) within our test // tests, only leaving the two seed nodes (Alice and Bob) within our
// network. // test network.
if err := carol.Shutdown(); err != nil { if err := carol.Shutdown(); err != nil {
t.Fatalf("unable to shutdown carol: %v", err) t.Fatalf("unable to shutdown carol: %v", err)
} }
if err := dave.Shutdown(); err != nil {
t.Fatalf("unable to shutdown dave: %v", err)
}
} }
func testInvoiceSubscriptions(net *networkHarness, t *harnessTest) { func testInvoiceSubscriptions(net *networkHarness, t *harnessTest) {