lnd_test: set --nolisten for node being cheated
In this commit we modify the integration tests slightly, by setting the parties that gets breached during the breach tests to --nolisten. We do this to ensure that once the data protection logic is in place, they nodes won't automatically connect, detect the state desync and recover before we are able to trigger the breach.
This commit is contained in:
parent
22e21da370
commit
f8751350bc
157
lnd_test.go
157
lnd_test.go
@ -5084,7 +5084,7 @@ func testGarbageCollectLinkNodes(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
closeChannelAndAssert(ctxt, t, net, net.Alice, persistentChanPoint, false)
|
||||
}
|
||||
|
||||
// testRevokedCloseRetribution tests that Alice is able carry out
|
||||
// testRevokedCloseRetribution tests that Carol is able carry out
|
||||
// retribution in the event that she fails immediately after detecting Bob's
|
||||
// breach txn in the mempool.
|
||||
func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
@ -5096,16 +5096,41 @@ func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
numInvoices = 6
|
||||
)
|
||||
|
||||
// In order to test Alice's response to an uncooperative channel
|
||||
// Carol will be the breached party. We set --nolisten to ensure Bob
|
||||
// won't be able to connect to her and trigger the channel data
|
||||
// protection logic automatically.
|
||||
carol, err := net.NewNode(
|
||||
"Carol",
|
||||
[]string{"--debughtlc", "--hodl.exit-settle", "--nolisten"},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create new carol node: %v", err)
|
||||
}
|
||||
defer shutdownAndAssert(net, t, carol)
|
||||
|
||||
// We must let Bob communicate with Carol before they are able to open
|
||||
// channel, so we connect Bob and Carol,
|
||||
if err := net.ConnectNodes(ctxb, carol, net.Bob); err != nil {
|
||||
t.Fatalf("unable to connect dave to carol: %v", err)
|
||||
}
|
||||
|
||||
// Before we make a channel, we'll load up Carol with some coins sent
|
||||
// directly from the miner.
|
||||
err = net.SendCoins(ctxb, btcutil.SatoshiPerBitcoin, carol)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to send coins to carol: %v", err)
|
||||
}
|
||||
|
||||
// In order to test Carol's response to an uncooperative channel
|
||||
// closure by Bob, we'll first open up a channel between them with a
|
||||
// 0.5 BTC value.
|
||||
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
||||
chanPoint := openChannelAndAssert(
|
||||
ctxt, t, net, net.Alice, net.Bob, chanAmt, 0, false,
|
||||
ctxt, t, net, carol, net.Bob, chanAmt, 0, false,
|
||||
)
|
||||
|
||||
// With the channel open, we'll create a few invoices for Bob that
|
||||
// Alice will pay to in order to advance the state of the channel.
|
||||
// Carol will pay to in order to advance the state of the channel.
|
||||
bobPayReqs := make([]string, numInvoices)
|
||||
for i := 0; i < numInvoices; i++ {
|
||||
preimage := bytes.Repeat([]byte{byte(255 - i)}, 32)
|
||||
@ -5138,18 +5163,18 @@ func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
return bobChannelInfo.Channels[0], nil
|
||||
}
|
||||
|
||||
// Wait for Alice to receive the channel edge from the funding manager.
|
||||
// Wait for Carol to receive the channel edge from the funding manager.
|
||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
||||
err := net.Alice.WaitForNetworkChannelOpen(ctxt, chanPoint)
|
||||
err = carol.WaitForNetworkChannelOpen(ctxt, chanPoint)
|
||||
if err != nil {
|
||||
t.Fatalf("alice didn't see the alice->bob channel before "+
|
||||
t.Fatalf("carol didn't see the carol->bob channel before "+
|
||||
"timeout: %v", err)
|
||||
}
|
||||
|
||||
// Send payments from Alice to Bob using 3 of Bob's payment hashes
|
||||
// Send payments from Carol to Bob using 3 of Bob's payment hashes
|
||||
// generated above.
|
||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
||||
err = completePaymentRequests(ctxt, net.Alice, bobPayReqs[:numInvoices/2],
|
||||
err = completePaymentRequests(ctxt, carol, bobPayReqs[:numInvoices/2],
|
||||
true)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to send payments: %v", err)
|
||||
@ -5199,10 +5224,10 @@ func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
t.Fatalf("unable to copy database files: %v", err)
|
||||
}
|
||||
|
||||
// Finally, send payments from Alice to Bob, consuming Bob's remaining
|
||||
// Finally, send payments from Carol to Bob, consuming Bob's remaining
|
||||
// payment hashes.
|
||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
||||
err = completePaymentRequests(ctxt, net.Alice, bobPayReqs[numInvoices/2:],
|
||||
err = completePaymentRequests(ctxt, carol, bobPayReqs[numInvoices/2:],
|
||||
true)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to send payments: %v", err)
|
||||
@ -5236,7 +5261,7 @@ func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
// Now force Bob to execute a *force* channel closure by unilaterally
|
||||
// broadcasting his current channel state. This is actually the
|
||||
// commitment transaction of a prior *revoked* state, so he'll soon
|
||||
// feel the wrath of Alice's retribution.
|
||||
// feel the wrath of Carol's retribution.
|
||||
var closeUpdates lnrpc.Lightning_CloseChannelClient
|
||||
force := true
|
||||
err = lntest.WaitPredicate(func() bool {
|
||||
@ -5253,19 +5278,19 @@ func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
}
|
||||
|
||||
// Wait for Bob's breach transaction to show up in the mempool to ensure
|
||||
// that Alice's node has started waiting for confirmations.
|
||||
// that Carol's node has started waiting for confirmations.
|
||||
_, err = waitForTxInMempool(net.Miner.Node, 5*time.Second)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find Bob's breach tx in mempool: %v", err)
|
||||
}
|
||||
|
||||
// Here, Alice sees Bob's breach transaction in the mempool, but is waiting
|
||||
// for it to confirm before continuing her retribution. We restart Alice to
|
||||
// Here, Carol sees Bob's breach transaction in the mempool, but is waiting
|
||||
// for it to confirm before continuing her retribution. We restart Carol to
|
||||
// ensure that she is persisting her retribution state and continues
|
||||
// watching for the breach transaction to confirm even after her node
|
||||
// restarts.
|
||||
if err := net.RestartNode(net.Alice, nil); err != nil {
|
||||
t.Fatalf("unable to restart Alice's node: %v", err)
|
||||
if err := net.RestartNode(carol, nil); err != nil {
|
||||
t.Fatalf("unable to restart Carol's node: %v", err)
|
||||
}
|
||||
|
||||
// Finally, generate a single block, wait for the final close status
|
||||
@ -5279,12 +5304,12 @@ func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
}
|
||||
assertTxInBlock(t, block, breachTXID)
|
||||
|
||||
// Query the mempool for Alice's justice transaction, this should be
|
||||
// Query the mempool for Carol's justice transaction, this should be
|
||||
// broadcast as Bob's contract breaching transaction gets confirmed
|
||||
// above.
|
||||
justiceTXID, err := waitForTxInMempool(net.Miner.Node, 5*time.Second)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find Alice's justice tx in mempool: %v", err)
|
||||
t.Fatalf("unable to find Carol's justice tx in mempool: %v", err)
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
@ -5302,16 +5327,16 @@ func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
}
|
||||
}
|
||||
|
||||
// We restart Alice here to ensure that she persists her retribution state
|
||||
// We restart Carol here to ensure that she persists her retribution state
|
||||
// and successfully continues exacting retribution after restarting. At
|
||||
// this point, Alice has broadcast the justice transaction, but it hasn't
|
||||
// been confirmed yet; when Alice restarts, she should start waiting for
|
||||
// this point, Carol has broadcast the justice transaction, but it hasn't
|
||||
// been confirmed yet; when Carol restarts, she should start waiting for
|
||||
// the justice transaction to confirm again.
|
||||
if err := net.RestartNode(net.Alice, nil); err != nil {
|
||||
t.Fatalf("unable to restart Alice's node: %v", err)
|
||||
if err := net.RestartNode(carol, nil); err != nil {
|
||||
t.Fatalf("unable to restart Carol's node: %v", err)
|
||||
}
|
||||
|
||||
// Now mine a block, this transaction should include Alice's justice
|
||||
// Now mine a block, this transaction should include Carol's justice
|
||||
// transaction which was just accepted into the mempool.
|
||||
block = mineBlocks(t, net, 1)[0]
|
||||
|
||||
@ -5325,10 +5350,10 @@ func testRevokedCloseRetribution(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
t.Fatalf("justice tx wasn't mined")
|
||||
}
|
||||
|
||||
assertNodeNumChannels(t, ctxb, net.Alice, 0)
|
||||
assertNodeNumChannels(t, ctxb, carol, 0)
|
||||
}
|
||||
|
||||
// testRevokedCloseRetributionZeroValueRemoteOutput tests that Alice is able
|
||||
// testRevokedCloseRetributionZeroValueRemoteOutput tests that Dave is able
|
||||
// carry out retribution in the event that she fails in state where the remote
|
||||
// commitment output has zero-value.
|
||||
func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness,
|
||||
@ -5350,22 +5375,41 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness
|
||||
}
|
||||
defer shutdownAndAssert(net, t, carol)
|
||||
|
||||
// We must let Alice have an open channel before she can send a node
|
||||
// Dave will be the breached party. We set --nolisten to ensure Carol
|
||||
// won't be able to connect to him and trigger the channel data
|
||||
// protection logic automatically.
|
||||
dave, err := net.NewNode(
|
||||
"Dave",
|
||||
[]string{"--debughtlc", "--hodl.exit-settle", "--nolisten"},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create new node: %v", err)
|
||||
}
|
||||
defer shutdownAndAssert(net, t, dave)
|
||||
|
||||
// We must let Dave have an open channel before she can send a node
|
||||
// announcement, so we open a channel with Carol,
|
||||
if err := net.ConnectNodes(ctxb, net.Alice, carol); err != nil {
|
||||
t.Fatalf("unable to connect alice to carol: %v", err)
|
||||
if err := net.ConnectNodes(ctxb, dave, carol); err != nil {
|
||||
t.Fatalf("unable to connect dave to carol: %v", err)
|
||||
}
|
||||
|
||||
// In order to test Alice's response to an uncooperative channel
|
||||
// Before we make a channel, we'll load up Dave with some coins sent
|
||||
// directly from the miner.
|
||||
err = net.SendCoins(ctxb, btcutil.SatoshiPerBitcoin, dave)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to send coins to dave: %v", err)
|
||||
}
|
||||
|
||||
// In order to test Dave's response to an uncooperative channel
|
||||
// closure by Carol, we'll first open up a channel between them with a
|
||||
// 0.5 BTC value.
|
||||
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
||||
chanPoint := openChannelAndAssert(
|
||||
ctxt, t, net, net.Alice, carol, chanAmt, 0, false,
|
||||
ctxt, t, net, dave, carol, chanAmt, 0, false,
|
||||
)
|
||||
|
||||
// With the channel open, we'll create a few invoices for Carol that
|
||||
// Alice will pay to in order to advance the state of the channel.
|
||||
// Dave will pay to in order to advance the state of the channel.
|
||||
carolPayReqs := make([]string, numInvoices)
|
||||
for i := 0; i < numInvoices; i++ {
|
||||
preimage := bytes.Repeat([]byte{byte(192 - i)}, 32)
|
||||
@ -5398,11 +5442,11 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness
|
||||
return carolChannelInfo.Channels[0], nil
|
||||
}
|
||||
|
||||
// Wait for Alice to receive the channel edge from the funding manager.
|
||||
// Wait for Dave to receive the channel edge from the funding manager.
|
||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
||||
err = net.Alice.WaitForNetworkChannelOpen(ctxt, chanPoint)
|
||||
err = dave.WaitForNetworkChannelOpen(ctxt, chanPoint)
|
||||
if err != nil {
|
||||
t.Fatalf("alice didn't see the alice->carol channel before "+
|
||||
t.Fatalf("dave didn't see the dave->carol channel before "+
|
||||
"timeout: %v", err)
|
||||
}
|
||||
|
||||
@ -5438,9 +5482,9 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness
|
||||
t.Fatalf("unable to copy database files: %v", err)
|
||||
}
|
||||
|
||||
// Finally, send payments from Alice to Carol, consuming Carol's remaining
|
||||
// Finally, send payments from Dave to Carol, consuming Carol's remaining
|
||||
// payment hashes.
|
||||
err = completePaymentRequests(ctxb, net.Alice, carolPayReqs, false)
|
||||
err = completePaymentRequests(ctxb, dave, carolPayReqs, false)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to send payments: %v", err)
|
||||
}
|
||||
@ -5473,7 +5517,7 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness
|
||||
// Now force Carol to execute a *force* channel closure by unilaterally
|
||||
// broadcasting his current channel state. This is actually the
|
||||
// commitment transaction of a prior *revoked* state, so he'll soon
|
||||
// feel the wrath of Alice's retribution.
|
||||
// feel the wrath of Dave's retribution.
|
||||
var (
|
||||
closeUpdates lnrpc.Lightning_CloseChannelClient
|
||||
closeTxId *chainhash.Hash
|
||||
@ -5507,11 +5551,11 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness
|
||||
// block.
|
||||
block := mineBlocks(t, net, 1)[0]
|
||||
|
||||
// Here, Alice receives a confirmation of Carol's breach transaction.
|
||||
// We restart Alice to ensure that she is persisting her retribution
|
||||
// Here, Dave receives a confirmation of Carol's breach transaction.
|
||||
// We restart Dave to ensure that she is persisting her retribution
|
||||
// state and continues exacting justice after her node restarts.
|
||||
if err := net.RestartNode(net.Alice, nil); err != nil {
|
||||
t.Fatalf("unable to stop Alice's node: %v", err)
|
||||
if err := net.RestartNode(dave, nil); err != nil {
|
||||
t.Fatalf("unable to stop Dave's node: %v", err)
|
||||
}
|
||||
|
||||
breachTXID, err := net.WaitForChannelClose(ctxb, closeUpdates)
|
||||
@ -5520,12 +5564,12 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness
|
||||
}
|
||||
assertTxInBlock(t, block, breachTXID)
|
||||
|
||||
// Query the mempool for Alice's justice transaction, this should be
|
||||
// Query the mempool for Dave's justice transaction, this should be
|
||||
// broadcast as Carol's contract breaching transaction gets confirmed
|
||||
// above.
|
||||
justiceTXID, err := waitForTxInMempool(net.Miner.Node, 15*time.Second)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to find Alice's justice tx in mempool: %v",
|
||||
t.Fatalf("unable to find Dave's justice tx in mempool: %v",
|
||||
err)
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
@ -5544,16 +5588,16 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness
|
||||
}
|
||||
}
|
||||
|
||||
// We restart Alice here to ensure that she persists her retribution state
|
||||
// We restart Dave here to ensure that he persists her retribution state
|
||||
// and successfully continues exacting retribution after restarting. At
|
||||
// this point, Alice has broadcast the justice transaction, but it hasn't
|
||||
// been confirmed yet; when Alice restarts, she should start waiting for
|
||||
// this point, Dave has broadcast the justice transaction, but it hasn't
|
||||
// been confirmed yet; when Dave restarts, she should start waiting for
|
||||
// the justice transaction to confirm again.
|
||||
if err := net.RestartNode(net.Alice, nil); err != nil {
|
||||
t.Fatalf("unable to restart Alice's node: %v", err)
|
||||
if err := net.RestartNode(dave, nil); err != nil {
|
||||
t.Fatalf("unable to restart Dave's node: %v", err)
|
||||
}
|
||||
|
||||
// Now mine a block, this transaction should include Alice's justice
|
||||
// Now mine a block, this transaction should include Dave's justice
|
||||
// transaction which was just accepted into the mempool.
|
||||
block = mineBlocks(t, net, 1)[0]
|
||||
|
||||
@ -5567,7 +5611,7 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(net *lntest.NetworkHarness
|
||||
t.Fatalf("justice tx wasn't mined")
|
||||
}
|
||||
|
||||
assertNodeNumChannels(t, ctxb, net.Alice, 0)
|
||||
assertNodeNumChannels(t, ctxb, dave, 0)
|
||||
}
|
||||
|
||||
// testRevokedCloseRetributionRemoteHodl tests that Dave properly responds to a
|
||||
@ -5596,8 +5640,13 @@ func testRevokedCloseRetributionRemoteHodl(net *lntest.NetworkHarness,
|
||||
|
||||
// We'll also create a new node Dave, who will have a channel with
|
||||
// Carol, and also use similar settings so we can broadcast a commit
|
||||
// with active HTLCs.
|
||||
dave, err := net.NewNode("Dave", []string{"--debughtlc", "--hodl.exit-settle"})
|
||||
// with active HTLCs. Dave will be the breached party. We set
|
||||
// --nolisten to ensure Carol won't be able to connect to him and
|
||||
// trigger the channel data protection logic automatically.
|
||||
dave, err := net.NewNode(
|
||||
"Dave",
|
||||
[]string{"--debughtlc", "--hodl.exit-settle", "--nolisten"},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create new dave node: %v", err)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user