lntest/itest: resolve mempool flake in multi-hop htlc local timeout test
The test assumed that transactions would be broadcast and confirmed at incorrect heights. Due to timing issues, it was possible for the test to still succeed, resulting in a flake. The test assumes that Bob will sweep a pending outgoing HTLC and commit output back to their wallet. This commit ensures that these operations are done when expected, i.e.: 1. Bob force closes the channel due to the HTLC timing out. 2. Once the channel is confirmed, Bob broadcasts their HTLC timeout transaction. 3. Bob broadcasts their commit output sweep transaction once its CSV expires. 4. Bob broadcasts their second layer sweep transaction for the timed out HTLC once its CSV expires.
This commit is contained in:
parent
06206f09b5
commit
578df81fb2
@ -10153,6 +10153,10 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to get txid: %v", err)
|
t.Fatalf("unable to get txid: %v", err)
|
||||||
}
|
}
|
||||||
|
closeTxid, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to find closing txid: %v", err)
|
||||||
|
}
|
||||||
assertSpendingTxInMempool(
|
assertSpendingTxInMempool(
|
||||||
t, net.Miner.Node, minerMempoolTimeout, wire.OutPoint{
|
t, net.Miner.Node, minerMempoolTimeout, wire.OutPoint{
|
||||||
Hash: *bobFundingTxid,
|
Hash: *bobFundingTxid,
|
||||||
@ -10179,24 +10183,22 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
t.Fatalf("htlc mismatch: %v", predErr)
|
t.Fatalf("htlc mismatch: %v", predErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll mine defaultCSV blocks in order to generate the sweep
|
// With the closing transaction confirmed, we should expect Bob's HTLC
|
||||||
// transaction of Bob's funding output. This will also bring us to the
|
// timeout transaction to be broadcast due to the expiry being reached.
|
||||||
// maturity height of the htlc tx output.
|
htlcTimeout, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout)
|
||||||
if _, err := net.Miner.Node.Generate(defaultCSV); err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to generate blocks: %v", err)
|
t.Fatalf("unable to find bob's htlc timeout tx: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout)
|
// We'll mine the remaining blocks in order to generate the sweep
|
||||||
if err != nil {
|
// transaction of Bob's commitment output.
|
||||||
t.Fatalf("unable to find bob's funding output sweep tx: %v", err)
|
mineBlocks(t, net, defaultCSV, 1)
|
||||||
}
|
assertSpendingTxInMempool(
|
||||||
|
t, net.Miner.Node, minerMempoolTimeout, wire.OutPoint{
|
||||||
// The second layer HTLC timeout transaction should now have been
|
Hash: *closeTxid,
|
||||||
// broadcast on-chain.
|
Index: 1,
|
||||||
secondLayerHash, err := waitForTxInMempool(net.Miner.Node, minerMempoolTimeout)
|
},
|
||||||
if err != nil {
|
)
|
||||||
t.Fatalf("unable to find bob's second layer transaction")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bob's pending channel report should show that he has a commitment
|
// Bob's pending channel report should show that he has a commitment
|
||||||
// output awaiting sweeping, and also that there's an outgoing HTLC
|
// output awaiting sweeping, and also that there's an outgoing HTLC
|
||||||
@ -10220,14 +10222,20 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
t.Fatalf("bob should have pending htlc but doesn't")
|
t.Fatalf("bob should have pending htlc but doesn't")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now we'll mine an additional block, which should include the second
|
// Now we'll mine an additional block, which should confirm Bob's commit
|
||||||
// layer sweep tx.
|
// sweep. This block should also prompt Bob to broadcast their second
|
||||||
block := mineBlocks(t, net, 1, 1)[0]
|
// layer sweep due to the CSV on the HTLC timeout output.
|
||||||
|
mineBlocks(t, net, 1, 1)
|
||||||
|
assertSpendingTxInMempool(
|
||||||
|
t, net.Miner.Node, minerMempoolTimeout, wire.OutPoint{
|
||||||
|
Hash: *htlcTimeout,
|
||||||
|
Index: 0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
// The block should have confirmed Bob's second layer sweeping
|
// The block should have confirmed Bob's HTLC timeout transaction.
|
||||||
// transaction. Therefore, at this point, there should be no active
|
// Therefore, at this point, there should be no active HTLC's on the
|
||||||
// HTLC's on the commitment transaction from Alice -> Bob.
|
// commitment transaction from Alice -> Bob.
|
||||||
assertTxInBlock(t, block, secondLayerHash)
|
|
||||||
nodes = []*lntest.HarnessNode{net.Alice}
|
nodes = []*lntest.HarnessNode{net.Alice}
|
||||||
err = lntest.WaitPredicate(func() bool {
|
err = lntest.WaitPredicate(func() bool {
|
||||||
predErr = assertNumActiveHtlcs(nodes, 0)
|
predErr = assertNumActiveHtlcs(nodes, 0)
|
||||||
@ -10252,16 +10260,6 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
t.Fatalf("bob's htlc should have advanced to the second stage: %v", err)
|
t.Fatalf("bob's htlc should have advanced to the second stage: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll now mine four more blocks. After the 4th block, a transaction
|
|
||||||
// sweeping the HTLC output should be broadcast.
|
|
||||||
if _, err := net.Miner.Node.Generate(4); err != nil {
|
|
||||||
t.Fatalf("unable to generate blocks: %v", err)
|
|
||||||
}
|
|
||||||
_, err = waitForTxInMempool(net.Miner.Node, minerMempoolTimeout)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to find bob's sweeping transaction: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Next, we'll mine a final block that should confirm the second-layer
|
// Next, we'll mine a final block that should confirm the second-layer
|
||||||
// sweeping transaction.
|
// sweeping transaction.
|
||||||
if _, err := net.Miner.Node.Generate(1); err != nil {
|
if _, err := net.Miner.Node.Generate(1); err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user