diff --git a/discovery/gossiper.go b/discovery/gossiper.go index 4805369ad5..53bfd38c2a 100644 --- a/discovery/gossiper.go +++ b/discovery/gossiper.go @@ -750,8 +750,8 @@ func (d *AuthenticatedGossiper) Stop() error { } func (d *AuthenticatedGossiper) stop() { - log.Info("Authenticated Gossiper is stopping") - defer log.Info("Authenticated Gossiper stopped") + log.Debug("Authenticated Gossiper is stopping") + defer log.Debug("Authenticated Gossiper stopped") d.blockEpochs.Cancel() diff --git a/docs/release-notes/release-notes-0.18.3.md b/docs/release-notes/release-notes-0.18.3.md index f784065a21..8d658624fc 100644 --- a/docs/release-notes/release-notes-0.18.3.md +++ b/docs/release-notes/release-notes-0.18.3.md @@ -116,6 +116,11 @@ ## Tooling and Documentation +* [`lntest.HarnessTest` no longer exposes `Miner` + instance](https://github.com/lightningnetwork/lnd/pull/8892). Instead, it's + changed into a private `miner` instance and all mining related assertions are + now only accessible via the harness. + # Contributors (Alphabetical Order) * Andras Banki-Horvath diff --git a/htlcswitch/decayedlog.go b/htlcswitch/decayedlog.go index 026c6d6410..ca7e19e7d8 100644 --- a/htlcswitch/decayedlog.go +++ b/htlcswitch/decayedlog.go @@ -149,6 +149,9 @@ func (d *DecayedLog) initBuckets() error { // Stop halts the garbage collector and closes boltdb. func (d *DecayedLog) Stop() error { + log.Debugf("DecayedLog shutting down...") + defer log.Debugf("DecayedLog shutdown complete") + if !atomic.CompareAndSwapInt32(&d.stopped, 0, 1) { return nil } diff --git a/itest/lnd_channel_backup_test.go b/itest/lnd_channel_backup_test.go index 0e7393dc3f..474cd663a0 100644 --- a/itest/lnd_channel_backup_test.go +++ b/itest/lnd_channel_backup_test.go @@ -94,7 +94,7 @@ func newChanRestoreScenario(ht *lntest.HarnessTest, ct lnrpc.CommitmentType, ht.FundCoinsUnconfirmed(btcutil.SatoshiPerBitcoin, dave) // Mine a block to confirm the funds. - ht.MineBlocks(1) + ht.MineBlocksAndAssertNumTxes(1, 2) // For the anchor output case we need two UTXOs for Carol so she can // sweep both the local and remote anchor. @@ -267,7 +267,7 @@ func testChannelBackupRestoreBasic(ht *lntest.HarnessTest) { // the node from seed, then manually recover // the channel backup. return chanRestoreViaRPC( - st, password, mnemonic, multi, oldNode, + st, password, mnemonic, multi, ) }, }, @@ -291,7 +291,7 @@ func testChannelBackupRestoreBasic(ht *lntest.HarnessTest) { // create a new nodeRestorer that will restore // using the on-disk channel.backup. return chanRestoreViaRPC( - st, password, mnemonic, multi, oldNode, + st, password, mnemonic, multi, ) }, }, @@ -523,7 +523,7 @@ func runChanRestoreScenarioUnConfirmed(ht *lntest.HarnessTest, useFile bool) { // In our nodeRestorer function, we'll restore the node from seed, then // manually recover the channel backup. restoredNodeFunc := chanRestoreViaRPC( - ht, crs.password, crs.mnemonic, multi, dave, + ht, crs.password, crs.mnemonic, multi, ) // Test the scenario. @@ -624,8 +624,8 @@ func runChanRestoreScenarioCommitTypes(ht *lntest.HarnessTest, var fundingShim *lnrpc.FundingShim if ct == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE { - _, minerHeight := ht.Miner.GetBestBlock() - thawHeight := uint32(minerHeight + thawHeightDelta) + minerHeight := ht.CurrentHeight() + thawHeight := minerHeight + thawHeightDelta fundingShim, _ = deriveFundingShim( ht, dave, carol, crs.params.Amt, thawHeight, true, ct, @@ -658,7 +658,7 @@ func runChanRestoreScenarioCommitTypes(ht *lntest.HarnessTest, // Now that we have Dave's backup file, we'll create a new nodeRestorer // that we'll restore using the on-disk channels.backup. restoredNodeFunc := chanRestoreViaRPC( - ht, crs.password, crs.mnemonic, multi, dave, + ht, crs.password, crs.mnemonic, multi, ) // Test the scenario. @@ -687,7 +687,7 @@ func testChannelBackupRestoreLegacy(ht *lntest.HarnessTest) { // In our nodeRestorer function, we'll restore the node from seed, then // manually recover the channel backup. restoredNodeFunc := chanRestoreViaRPC( - ht, crs.password, crs.mnemonic, multi, dave, + ht, crs.password, crs.mnemonic, multi, ) // Test the scenario. @@ -779,11 +779,11 @@ func runChanRestoreScenarioForceClose(ht *lntest.HarnessTest, zeroConf bool) { // Now that we have Dave's backup file, we'll create a new nodeRestorer // that will restore using the on-disk channel.backup. restoredNodeFunc := chanRestoreViaRPC( - ht, crs.password, crs.mnemonic, multi, dave, + ht, crs.password, crs.mnemonic, multi, ) // We now wait until both Dave's closing tx. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // Now that we're able to make our restored now, we'll shutdown the old // Dave node as we'll be storing it shortly below. @@ -1272,7 +1272,7 @@ func testDataLossProtection(ht *lntest.HarnessTest) { ht.MineBlocks(1) // Dave should sweep his funds. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // Mine a block to confirm the sweep, and make sure Dave got his // balance back. @@ -1388,8 +1388,7 @@ func createLegacyRevocationChannel(ht *lntest.HarnessTest, // instance which will restore the target node from a password+seed, then // trigger a SCB restore using the RPC interface. func chanRestoreViaRPC(ht *lntest.HarnessTest, password []byte, - mnemonic []string, multi []byte, - oldNode *node.HarnessNode) nodeRestorer { + mnemonic []string, multi []byte) nodeRestorer { backup := &lnrpc.RestoreChanBackupRequest_MultiChanBackup{ MultiChanBackup: multi, @@ -1428,7 +1427,7 @@ func assertTimeLockSwept(ht *lntest.HarnessTest, carol, dave *node.HarnessNode, // Mine a block to trigger the sweeps. ht.MineBlocks(1) - ht.Miner.AssertNumTxsInMempool(expectedTxes) + ht.AssertNumTxsInMempool(expectedTxes) // Carol should consider the channel pending force close (since she is // waiting for her sweep to confirm). @@ -1462,9 +1461,9 @@ func assertTimeLockSwept(ht *lntest.HarnessTest, carol, dave *node.HarnessNode, // Mine a block to trigger the sweeps. ht.MineEmptyBlocks(1) - daveSweep := ht.Miner.AssertNumTxsInMempool(1)[0] + daveSweep := ht.AssertNumTxsInMempool(1)[0] block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, daveSweep) + ht.AssertTxInBlock(block, daveSweep) // Now the channel should be fully closed also from Dave's POV. ht.AssertNumPendingForceClose(dave, 0) @@ -1510,7 +1509,7 @@ func assertDLPExecuted(ht *lntest.HarnessTest, // Upon reconnection, the nodes should detect that Dave is out of sync. // Carol should force close the channel using her latest commitment. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // Channel should be in the state "waiting close" for Carol since she // broadcasted the force close tx. diff --git a/itest/lnd_channel_force_close_test.go b/itest/lnd_channel_force_close_test.go index 592669f32c..34df5ab591 100644 --- a/itest/lnd_channel_force_close_test.go +++ b/itest/lnd_channel_force_close_test.go @@ -160,7 +160,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // Fetch starting height of this test so we can compute the block // heights we expect certain events to take place. - _, curHeight := ht.Miner.GetBestBlock() + curHeight := int32(ht.CurrentHeight()) // Using the current height of the chain, derive the relevant heights // for incubating two-stage htlcs. @@ -214,7 +214,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, ht.AssertNumUTXOs(alice, expectedUtxos) // We expect to see Alice's force close tx in the mempool. - ht.Miner.GetNumTxsFromMempool(1) + ht.GetNumTxsFromMempool(1) // Mine a block which should confirm the commitment transaction // broadcast as a result of the force closure. Once mined, we also @@ -278,7 +278,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // Carol's sweep tx should be in the mempool already, as her output is // not timelocked. - carolTx := ht.Miner.GetNumTxsFromMempool(1)[0] + carolTx := ht.GetNumTxsFromMempool(1)[0] // Carol's sweeping tx should have 2-input-1-output shape. require.Len(ht, carolTx.TxIn, 2) @@ -389,11 +389,11 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // So we fetch the node's mempool to ensure it has been properly // broadcast. ht.MineEmptyBlocks(1) - sweepingTXID := ht.Miner.AssertNumTxsInMempool(1)[0] + sweepingTXID := ht.AssertNumTxsInMempool(1)[0] // Fetch the sweep transaction, all input it's spending should be from // the commitment transaction which was broadcast on-chain. - sweepTx := ht.Miner.GetRawTransaction(sweepingTXID) + sweepTx := ht.GetRawTransaction(sweepingTXID) for _, txIn := range sweepTx.MsgTx().TxIn { require.Equal(ht, &txIn.PreviousOutPoint.Hash, closingTxID, "sweep transaction not spending from commit") @@ -431,7 +431,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, ht.MineBlocksAndAssertNumTxes(1, 1) // Update current height - _, curHeight = ht.Miner.GetBestBlock() + curHeight = int32(ht.CurrentHeight()) // checkForceClosedChannelNumHtlcs verifies that a force closed channel // has the proper number of htlcs. @@ -485,7 +485,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // number of blocks we have generated since adding it to the nursery, // and take an additional block off so that we end up one block shy of // the expiry height, and add the block padding. - _, currentHeight := ht.Miner.GetBestBlock() + currentHeight := int32(ht.CurrentHeight()) cltvHeightDelta := int(htlcExpiryHeight - uint32(currentHeight) - 1) // Advance the blockchain until just before the CLTV expires, nothing @@ -547,7 +547,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // NOTE: after restart, all the htlc timeout txns will be offered to // the sweeper with `Immediate` set to true, so they won't be // aggregated. - htlcTxIDs := ht.Miner.AssertNumTxsInMempool(numInvoices) + htlcTxIDs := ht.AssertNumTxsInMempool(numInvoices) // Retrieve each htlc timeout txn from the mempool, and ensure it is // well-formed. This entails verifying that each only spends from @@ -567,7 +567,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // on-chain. In case of an anchor type channel, we expect one // extra input that is not spending from the commitment, that // is added for fees. - htlcTx := ht.Miner.GetRawTransaction(htlcTxID) + htlcTx := ht.GetRawTransaction(htlcTxID) // Ensure the htlc transaction has the expected number of // inputs. @@ -662,7 +662,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // Advance the chain until just before the 2nd-layer CSV delays expire. // For anchor channels this is one block earlier. - _, currentHeight = ht.Miner.GetBestBlock() + currentHeight = int32(ht.CurrentHeight()) ht.Logf("current height: %v, htlcCsvMaturityHeight=%v", currentHeight, htlcCsvMaturityHeight) numBlocks := int(htlcCsvMaturityHeight - uint32(currentHeight) - 2) @@ -709,7 +709,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // NOTE: we don't check `len(mempool) == 1` because it will // give us false positive. err := wait.NoError(func() error { - mempool := ht.Miner.GetRawMempool() + mempool := ht.Miner().GetRawMempool() if len(mempool) == 2 { return nil } @@ -733,10 +733,10 @@ func channelForceClosureTest(ht *lntest.HarnessTest, } // Wait for the single sweep txn to appear in the mempool. - htlcSweepTxID := ht.Miner.AssertNumTxsInMempool(1)[0] + htlcSweepTxID := ht.AssertNumTxsInMempool(1)[0] // Fetch the htlc sweep transaction from the mempool. - htlcSweepTx := ht.Miner.GetRawTransaction(htlcSweepTxID) + htlcSweepTx := ht.GetRawTransaction(htlcSweepTxID) // Ensure the htlc sweep transaction only has one input for each htlc // Alice extended before force closing. @@ -818,7 +818,7 @@ func channelForceClosureTest(ht *lntest.HarnessTest, // Generate the final block that sweeps all htlc funds into the user's // wallet, and make sure the sweep is in this block. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, htlcSweepTxID) + ht.AssertTxInBlock(block, htlcSweepTxID) // Now that the channel has been fully swept, it should no longer show // up within the pending channels RPC. @@ -935,7 +935,7 @@ func testFailingChannel(ht *lntest.HarnessTest) { ht.MineEmptyBlocks(1) // Carol should have broadcast her sweeping tx. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // Mine two blocks to confirm Carol's sweeping tx, which will by now // Alice's commit output should be offered to her sweeper. diff --git a/itest/lnd_channel_funding_fund_max_test.go b/itest/lnd_channel_funding_fund_max_test.go index fb19877053..b836bdf621 100644 --- a/itest/lnd_channel_funding_fund_max_test.go +++ b/itest/lnd_channel_funding_fund_max_test.go @@ -15,7 +15,6 @@ import ( "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" - "github.com/stretchr/testify/require" ) type chanFundMaxTestCase struct { @@ -317,8 +316,7 @@ func fundingFee(numInput int, change bool) btcutil.Amount { // sweepNodeWalletAndAssert sweeps funds from a node wallet. func sweepNodeWalletAndAssert(ht *lntest.HarnessTest, node *node.HarnessNode) { // New miner address we will sweep all funds to. - minerAddr, err := ht.Miner.NewAddress() - require.NoError(ht, err) + minerAddr := ht.NewMinerAddress() // Send all funds back to the miner node. node.RPC.SendCoins(&lnrpc.SendCoinsRequest{ diff --git a/itest/lnd_channel_graph_test.go b/itest/lnd_channel_graph_test.go index 73a9266b70..cf97bcf390 100644 --- a/itest/lnd_channel_graph_test.go +++ b/itest/lnd_channel_graph_test.go @@ -316,7 +316,7 @@ func testGraphTopologyNtfns(ht *lntest.HarnessTest, pinned bool) { ht.AssertNumNodeAnns(alice, alice.PubKeyStr, 1) ht.AssertNumNodeAnns(alice, bob.PubKeyStr, 1) - _, blockHeight := ht.Miner.GetBestBlock() + blockHeight := ht.CurrentHeight() // Now we'll test that updates are properly sent after channels are // closed within the network. @@ -326,7 +326,7 @@ func testGraphTopologyNtfns(ht *lntest.HarnessTest, pinned bool) { // notification indicating so. closedChan := ht.AssertTopologyChannelClosed(alice, chanPoint) - require.Equal(ht, uint32(blockHeight+1), closedChan.ClosedHeight, + require.Equal(ht, blockHeight+1, closedChan.ClosedHeight, "close heights of channel mismatch") fundingTxid := ht.OutPointFromChannelPoint(chanPoint) diff --git a/itest/lnd_coop_close_with_htlcs_test.go b/itest/lnd_coop_close_with_htlcs_test.go index 50f1a3401d..56f9e801b0 100644 --- a/itest/lnd_coop_close_with_htlcs_test.go +++ b/itest/lnd_coop_close_with_htlcs_test.go @@ -117,7 +117,7 @@ func coopCloseWithHTLCs(ht *lntest.HarnessTest) { ) // Wait for the close tx to be in the Mempool. - ht.Miner.AssertTxInMempool(&closeTxid) + ht.AssertTxInMempool(&closeTxid) // Wait for it to get mined and finish tearing down. ht.AssertStreamChannelCoopClosed(alice, chanPoint, false, closeClient) diff --git a/itest/lnd_estimate_route_fee_test.go b/itest/lnd_estimate_route_fee_test.go index 352dfe5ce2..8ed0be2725 100644 --- a/itest/lnd_estimate_route_fee_test.go +++ b/itest/lnd_estimate_route_fee_test.go @@ -359,6 +359,8 @@ func testEstimateRouteFee(ht *lntest.HarnessTest) { mts.ht.CloseChannelAssertPending(mts.bob, channelPointBobPaula, false) mts.ht.CloseChannelAssertPending(mts.eve, channelPointEvePaula, false) + ht.MineBlocksAndAssertNumTxes(1, 2) + mts.closeChannels() } diff --git a/itest/lnd_funding_test.go b/itest/lnd_funding_test.go index 38ca71d92f..8f43620ee1 100644 --- a/itest/lnd_funding_test.go +++ b/itest/lnd_funding_test.go @@ -12,7 +12,6 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/chainreg" - "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/funding" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/labels" @@ -292,6 +291,24 @@ func testUnconfirmedChannelFunding(ht *lntest.HarnessTest) { // We'll send her some unconfirmed funds. ht.FundCoinsUnconfirmed(2*chanAmt, carol) + // For neutrino backend, we will confirm the coins sent above and let + // Carol send all her funds to herself to create unconfirmed output. + if ht.IsNeutrinoBackend() { + // Confirm the above coins. + ht.MineBlocksAndAssertNumTxes(1, 1) + + // Create a new address and send to herself. + resp := carol.RPC.NewAddress(&lnrpc.NewAddressRequest{ + Type: lnrpc.AddressType_TAPROOT_PUBKEY, + }) + + // Once sent, Carol would have one unconfirmed UTXO. + carol.RPC.SendCoins(&lnrpc.SendCoinsRequest{ + Addr: resp.Address, + SendAll: true, + }) + } + // Now, we'll connect her to Alice so that they can open a channel // together. The funding flow should select Carol's unconfirmed output // as she doesn't have any other funds since it's a new node. @@ -362,11 +379,7 @@ func testUnconfirmedChannelFunding(ht *lntest.HarnessTest) { // parties. For neutrino backend, the funding transaction should be // mined. Otherwise, two transactions should be mined, the unconfirmed // spend and the funding tx. - if ht.IsNeutrinoBackend() { - ht.MineBlocksAndAssertNumTxes(6, 1) - } else { - ht.MineBlocksAndAssertNumTxes(6, 2) - } + ht.MineBlocksAndAssertNumTxes(6, 2) chanPoint := ht.WaitForChannelOpenEvent(chanOpenUpdate) @@ -859,10 +872,10 @@ func testChannelFundingPersistence(ht *lntest.HarnessTest) { // channel has been opened. The funding transaction should be found // within the newly mined block. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, fundingTxID) + ht.AssertTxInBlock(block, fundingTxID) // Get the height that our transaction confirmed at. - _, height := ht.Miner.GetBestBlock() + height := int32(ht.CurrentHeight()) // Restart both nodes to test that the appropriate state has been // persisted and that both nodes recover gracefully. @@ -1047,13 +1060,13 @@ func testBatchChanFunding(ht *lntest.HarnessTest) { // Mine the batch transaction and check the network topology. block := ht.MineBlocksAndAssertNumTxes(6, 1)[0] - ht.Miner.AssertTxInBlock(block, txHash) + ht.AssertTxInBlock(block, txHash) ht.AssertTopologyChannelOpen(alice, chanPoint1) ht.AssertTopologyChannelOpen(alice, chanPoint2) ht.AssertTopologyChannelOpen(alice, chanPoint3) // Check if the change type from the batch_open_channel funding is P2TR. - rawTx := ht.Miner.GetRawTransaction(txHash) + rawTx := ht.GetRawTransaction(txHash) require.Len(ht, rawTx.MsgTx().TxOut, 5) // For calculating the change output index we use the formula for the @@ -1182,9 +1195,9 @@ func deriveFundingShim(ht *lntest.HarnessTest, carol, dave *node.HarnessNode, var txid *chainhash.Hash targetOutputs := []*wire.TxOut{fundingOutput} if publish { - txid = ht.Miner.SendOutputsWithoutChange(targetOutputs, 5) + txid = ht.SendOutputsWithoutChange(targetOutputs, 5) } else { - tx := ht.Miner.CreateTransaction(targetOutputs, 5) + tx := ht.CreateTransaction(targetOutputs, 5) txHash := tx.TxHash() txid = &txHash @@ -1341,22 +1354,22 @@ func testChannelFundingWithUnstableUtxos(ht *lntest.HarnessTest) { // that by dave force-closing the channel. Which let's carol sweep its // to_remote output which is not encumbered by any relative locktime. ht.CloseChannelAssertPending(dave, chanPoint2, true) + // Mine the force close commitment transaction. ht.MineBlocksAndAssertNumTxes(1, 1) + // Make sure Carol sees her to_remote output from the force close tx. + ht.AssertNumPendingSweeps(carol, 1) + // Mine one block to trigger the sweep transaction. ht.MineEmptyBlocks(1) // We need to wait for carol initiating the sweep of the to_remote // output of chanPoint2. - utxos := ht.AssertNumUTXOsUnconfirmed(carol, 1) + utxo := ht.AssertNumUTXOsUnconfirmed(carol, 1)[0] - // We filter for the unconfirmed utxo and try to open a channel with - // that utxo. - utxoOpt := fn.Find(func(u *lnrpc.Utxo) bool { - return u.Confirmations == 0 - }, utxos) - fundingUtxo := utxoOpt.UnwrapOrFail(ht.T) + // We now try to open channel using the unconfirmed utxo. + fundingUtxo := utxo // Now try to open the channel with this utxo and expect an error. expectedErr := fmt.Errorf("outpoint already spent or "+ @@ -1405,6 +1418,9 @@ func testChannelFundingWithUnstableUtxos(ht *lntest.HarnessTest) { ht.CloseChannelAssertPending(dave, chanPoint3, true) ht.MineBlocksAndAssertNumTxes(1, 1) + // Make sure Carol sees her to_remote output from the force close tx. + ht.AssertNumPendingSweeps(carol, 1) + // Mine one block to trigger the sweep transaction. ht.MineEmptyBlocks(1) diff --git a/itest/lnd_hold_invoice_force_test.go b/itest/lnd_hold_invoice_force_test.go index a3d8326143..2b251b3cb9 100644 --- a/itest/lnd_hold_invoice_force_test.go +++ b/itest/lnd_hold_invoice_force_test.go @@ -59,14 +59,14 @@ func testHoldInvoiceForceClose(ht *lntest.HarnessTest) { require.Len(ht, channel.PendingHtlcs, 1) activeHtlc := channel.PendingHtlcs[0] - _, currentHeight := ht.Miner.GetBestBlock() + currentHeight := ht.CurrentHeight() // Now we will mine blocks until the htlc expires, and wait for each // node to sync to our latest height. Sanity check that we won't // underflow. - require.Greater(ht, activeHtlc.ExpirationHeight, uint32(currentHeight), + require.Greater(ht, activeHtlc.ExpirationHeight, currentHeight, "expected expiry after current height") - blocksTillExpiry := activeHtlc.ExpirationHeight - uint32(currentHeight) + blocksTillExpiry := activeHtlc.ExpirationHeight - currentHeight // Alice will go to chain with some delta, sanity check that we won't // underflow and subtract this from our mined blocks. @@ -93,7 +93,7 @@ func testHoldInvoiceForceClose(ht *lntest.HarnessTest) { // TODO(yy): fix block height asymmetry among all the subsystems. // // We first mine enough blocks to trigger an invoice cancelation. - ht.MineBlocks(blocksTillCancel) + ht.MineBlocks(int(blocksTillCancel)) // Wait for the nodes to be synced. ht.WaitForBlockchainSync(alice) @@ -133,7 +133,7 @@ func testHoldInvoiceForceClose(ht *lntest.HarnessTest) { // happen in bitcoind backend, as Alice's CNCT was syncing way faster // than Bob's INVC, causing the channel being force closed before the // invoice cancelation message was received by Alice. - ht.MineBlocks(blocksTillForce - blocksTillCancel) + ht.MineBlocks(int(blocksTillForce - blocksTillCancel)) // Wait for the nodes to be synced. ht.WaitForBlockchainSync(alice) diff --git a/itest/lnd_misc_test.go b/itest/lnd_misc_test.go index 206d5748db..cf3220eaba 100644 --- a/itest/lnd_misc_test.go +++ b/itest/lnd_misc_test.go @@ -416,7 +416,7 @@ func testMaxPendingChannels(ht *lntest.HarnessTest) { // Ensure that the funding transaction enters a block, and is // properly advertised by Alice. - ht.Miner.AssertTxInBlock(block, fundingTxID) + ht.AssertTxInBlock(block, fundingTxID) ht.AssertTopologyChannelOpen(alice, fundingChanPoint) // The channel should be listed in the peer information @@ -823,14 +823,14 @@ func testSweepAllCoins(ht *lntest.HarnessTest) { // Send coins to a compatible address without specifying fee rate or // conf target. // ainz.RPC.SendCoinsAssertErr(&lnrpc.SendCoinsRequest{ - // Addr: ht.Miner.NewMinerAddress().String(), + // Addr: ht.NewMinerAddress().String(), // SendAll: true, // Label: sendCoinsLabel, // }) // Send coins to a compatible address. ainz.RPC.SendCoins(&lnrpc.SendCoinsRequest{ - Addr: ht.Miner.NewMinerAddress().String(), + Addr: ht.NewMinerAddress().String(), SendAll: true, Label: sendCoinsLabel, TargetConf: 6, @@ -930,7 +930,7 @@ func testSweepAllCoins(ht *lntest.HarnessTest) { // If we try again, but this time specifying an amount, then the call // should fail. ainz.RPC.SendCoinsAssertErr(&lnrpc.SendCoinsRequest{ - Addr: ht.Miner.NewMinerAddress().String(), + Addr: ht.NewMinerAddress().String(), Amount: 10000, SendAll: true, Label: sendCoinsLabel, diff --git a/itest/lnd_mpp_test.go b/itest/lnd_mpp_test.go index bf26798465..b5cd147dd7 100644 --- a/itest/lnd_mpp_test.go +++ b/itest/lnd_mpp_test.go @@ -208,7 +208,8 @@ func newMppTestScenario(ht *lntest.HarnessTest) *mppTestScenario { ht.FundCoinsUnconfirmed(btcutil.SatoshiPerBitcoin, carol) ht.FundCoinsUnconfirmed(btcutil.SatoshiPerBitcoin, dave) ht.FundCoinsUnconfirmed(btcutil.SatoshiPerBitcoin, eve) - ht.MineBlocks(1) + + ht.MineBlocksAndAssertNumTxes(1, 3) } mts := &mppTestScenario{ @@ -318,7 +319,7 @@ func (m *mppTestScenario) closeChannels() { m.ht.CloseChannelAssertPending(m.eve, m.channelPoints[5], false) // Now mine a block to include all the closing transactions. - m.ht.MineBlocks(1) + m.ht.MineBlocksAndAssertNumTxes(1, 6) // Assert that the channels are closed. for _, hn := range m.nodes { diff --git a/itest/lnd_multi-hop_test.go b/itest/lnd_multi-hop_test.go index 09b2cdf466..d095936196 100644 --- a/itest/lnd_multi-hop_test.go +++ b/itest/lnd_multi-hop_test.go @@ -243,12 +243,12 @@ func runMultiHopHtlcLocalTimeout(ht *lntest.HarnessTest, numBlocks := padCLTV( uint32(finalCltvDelta - lncfg.DefaultOutgoingBroadcastDelta), ) - ht.MineBlocks(numBlocks) + ht.MineBlocks(int(numBlocks)) // Bob's force close transaction should now be found in the mempool. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) op := ht.OutPointFromChannelPoint(bobChanPoint) - closeTx := ht.Miner.AssertOutpointInMempool(op) + closeTx := ht.AssertOutpointInMempool(op) // Bob's anchor output should be offered to his sweep since Bob has // time-sensitive HTLCs - we expect both anchors are offered. @@ -276,11 +276,11 @@ func runMultiHopHtlcLocalTimeout(ht *lntest.HarnessTest, // 1. Bob's sweeping tx anchor sweep should now be found in the mempool. // 2. Bob's HTLC timeout tx sweep should now be found in the mempool. // Carol's anchor sweep should be failed due to output being dust. - ht.Miner.AssertNumTxsInMempool(2) + ht.AssertNumTxsInMempool(2) htlcOutpoint := wire.OutPoint{Hash: closeTx.TxHash(), Index: 2} commitOutpoint := wire.OutPoint{Hash: closeTx.TxHash(), Index: 3} - htlcTimeoutTxid := ht.Miner.AssertOutpointInMempool( + htlcTimeoutTxid := ht.AssertOutpointInMempool( htlcOutpoint, ).TxHash() @@ -330,7 +330,7 @@ func runMultiHopHtlcLocalTimeout(ht *lntest.HarnessTest, ht.AssertNumPendingSweeps(bob, 2) // Assert that the HTLC timeout tx is now in the mempool. - ht.Miner.AssertOutpointInMempool(htlcTimeoutOutpoint) + ht.AssertOutpointInMempool(htlcTimeoutOutpoint) // We now wait for 30 seconds to overcome the flake - there's a // block race between contractcourt and sweeper, causing the @@ -339,7 +339,7 @@ func runMultiHopHtlcLocalTimeout(ht *lntest.HarnessTest, // TODO(yy): remove this once `blockbeat` is in place. numExpected := 1 err := wait.NoError(func() error { - mem := ht.Miner.GetRawMempool() + mem := ht.GetRawMempool() if len(mem) == 2 { numExpected = 2 return nil @@ -363,7 +363,7 @@ func runMultiHopHtlcLocalTimeout(ht *lntest.HarnessTest, pendingChanResp := bob.RPC.PendingChannels() if len(pendingChanResp.PendingForceClosingChannels) != 0 { // Check that the sweep spends the expected inputs. - ht.Miner.AssertOutpointInMempool(commitOutpoint) + ht.AssertOutpointInMempool(commitOutpoint) ht.MineBlocksAndAssertNumTxes(1, 1) } } else { @@ -381,14 +381,14 @@ func runMultiHopHtlcLocalTimeout(ht *lntest.HarnessTest, ht.MineEmptyBlocks(1) // Check that the sweep spends from the mined commitment. - ht.Miner.AssertOutpointInMempool(commitOutpoint) + ht.AssertOutpointInMempool(commitOutpoint) // Mine one more block to trigger the timeout path. ht.MineBlocksAndAssertNumTxes(1, 1) // Bob's sweeper should now broadcast his second layer sweep // due to the CSV on the HTLC timeout output. - ht.Miner.AssertOutpointInMempool(htlcTimeoutOutpoint) + ht.AssertOutpointInMempool(htlcTimeoutOutpoint) // Next, we'll mine a final block that should confirm the // sweeping transactions left. @@ -501,9 +501,9 @@ func runMultiHopReceiverChainClaim(ht *lntest.HarnessTest, // At this point, Carol should broadcast her active commitment // transaction in order to go to the chain and sweep her HTLC. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) - closingTx := ht.Miner.AssertOutpointInMempool( + closingTx := ht.AssertOutpointInMempool( ht.OutPointFromChannelPoint(bobChanPoint), ) closingTxid := closingTx.TxHash() @@ -526,7 +526,7 @@ func runMultiHopReceiverChainClaim(ht *lntest.HarnessTest, // scenarios, as we are using a wallet utxo, which means any txns using // that wallet utxo must pay more fees. On the other hand, there's no // way to remove that anchor-CPFP tx from the mempool. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // After the force close transaction is mined, Carol should offer her // second level HTLC tx to the sweeper, which means we should see two @@ -572,7 +572,7 @@ func runMultiHopReceiverChainClaim(ht *lntest.HarnessTest, ht.MineEmptyBlocks(1) // All transactions should be spending from the commitment transaction. - txes := ht.Miner.GetNumTxsFromMempool(expectedTxes) + txes := ht.GetNumTxsFromMempool(expectedTxes) ht.AssertAllTxesSpendFrom(txes, closingTxid) // We'll now mine an additional block which should confirm both the @@ -600,7 +600,7 @@ func runMultiHopReceiverChainClaim(ht *lntest.HarnessTest, ht.MineEmptyBlocks(1) // We should have a new transaction in the mempool. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // Finally, if we mine an additional block to confirm Carol's second // level success transaction. Carol should not show a pending channel @@ -644,7 +644,7 @@ func runMultiHopReceiverChainClaim(ht *lntest.HarnessTest, ht.MineEmptyBlocks(1) commitOutpoint := wire.OutPoint{Hash: closingTxid, Index: 3} - ht.Miner.AssertOutpointInMempool(commitOutpoint) + ht.AssertOutpointInMempool(commitOutpoint) ht.MineBlocksAndAssertNumTxes(1, 1) } @@ -756,12 +756,12 @@ func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest, ht.MineEmptyBlocks(1) blocksMined++ - commitSweepTx := ht.Miner.AssertOutpointInMempool( + commitSweepTx := ht.AssertOutpointInMempool( bobCommitOutpoint, ) txid := commitSweepTx.TxHash() block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, &txid) + ht.AssertTxInBlock(block, &txid) blocksMined++ } @@ -784,12 +784,12 @@ func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest, // We should also now find a transaction in the mempool, as Bob should // have broadcast his second layer timeout transaction. - timeoutTx := ht.Miner.AssertOutpointInMempool(htlcOutpoint).TxHash() + timeoutTx := ht.AssertOutpointInMempool(htlcOutpoint).TxHash() // Next, we'll mine an additional block. This should serve to confirm // the second layer timeout transaction. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, &timeoutTx) + ht.AssertTxInBlock(block, &timeoutTx) // With the second layer timeout transaction confirmed, Bob should have // canceled backwards the HTLC that carol sent. @@ -837,7 +837,7 @@ func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest, // Assert the sweeping tx is found in the mempool. htlcTimeoutOutpoint := wire.OutPoint{Hash: timeoutTx, Index: 0} - ht.Miner.AssertOutpointInMempool(htlcTimeoutOutpoint) + ht.AssertOutpointInMempool(htlcTimeoutOutpoint) // Mine a block to confirm the sweep. ht.MineBlocksAndAssertNumTxes(1, numExpected) @@ -1007,12 +1007,12 @@ func runMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest, // Bob's sweeping transaction should now be found in the mempool at // this point. - sweepTx := ht.Miner.AssertNumTxsInMempool(1)[0] + sweepTx := ht.AssertNumTxsInMempool(1)[0] // If we mine an additional block, then this should confirm Bob's // transaction which sweeps the direct HTLC output. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, sweepTx) + ht.AssertTxInBlock(block, sweepTx) // Now that the sweeping transaction has been confirmed, Bob should // cancel back that HTLC. As a result, Alice should not know of any @@ -1042,12 +1042,12 @@ func runMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest, ht.MineEmptyBlocks(1) bobCommitOutpoint := wire.OutPoint{Hash: *closeTx, Index: 3} - bobCommitSweep := ht.Miner.AssertOutpointInMempool( + bobCommitSweep := ht.AssertOutpointInMempool( bobCommitOutpoint, ) bobCommitSweepTxid := bobCommitSweep.TxHash() block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, &bobCommitSweepTxid) + ht.AssertTxInBlock(block, &bobCommitSweepTxid) } ht.AssertNumPendingForceClose(bob, 0) @@ -1191,7 +1191,7 @@ func runMultiHopHtlcLocalChainClaim(ht *lntest.HarnessTest, blocksMined++ // Assert the expected num of txns are found in the mempool. - ht.Miner.AssertNumTxsInMempool(expectedTxes) + ht.AssertNumTxsInMempool(expectedTxes) // Mine a block to clean up the mempool for the rest of the test. ht.MineBlocksAndAssertNumTxes(1, expectedTxes) @@ -1215,18 +1215,18 @@ func runMultiHopHtlcLocalChainClaim(ht *lntest.HarnessTest, ht.MineEmptyBlocks(int(numBlocks - blocksMined)) // Carol's commitment transaction should now be in the mempool. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // Look up the closing transaction. It should be spending from the // funding transaction, - closingTx := ht.Miner.AssertOutpointInMempool( + closingTx := ht.AssertOutpointInMempool( ht.OutPointFromChannelPoint(bobChanPoint), ) closingTxid := closingTx.TxHash() // Mine a block that should confirm the commit tx. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, &closingTxid) + ht.AssertTxInBlock(block, &closingTxid) // After the force close transaction is mined, Carol should offer her // second-level success HTLC tx and anchor to the sweeper. @@ -1273,7 +1273,7 @@ func runMultiHopHtlcLocalChainClaim(ht *lntest.HarnessTest, ht.MineEmptyBlocks(1) // Assert transactions can be found in the mempool. - ht.Miner.AssertNumTxsInMempool(expectedTxes) + ht.AssertNumTxsInMempool(expectedTxes) // At this point we suspend Alice to make sure she'll handle the // on-chain settle after a restart. @@ -1300,7 +1300,7 @@ func runMultiHopHtlcLocalChainClaim(ht *lntest.HarnessTest, carolSecondLevelCSV-- // Check Bob's second level tx. - bobSecondLvlTx := ht.Miner.GetNumTxsFromMempool(1)[0] + bobSecondLvlTx := ht.GetNumTxsFromMempool(1)[0] // It should spend from the commitment in the channel with Alice. ht.AssertTxSpendFrom(bobSecondLvlTx, *bobForceClose) @@ -1345,7 +1345,7 @@ func runMultiHopHtlcLocalChainClaim(ht *lntest.HarnessTest, bobSecondLevelCSV-- // Carol's sweep tx should be broadcast. - carolSweep := ht.Miner.AssertNumTxsInMempool(1)[0] + carolSweep := ht.AssertNumTxsInMempool(1)[0] // Bob should offer his second level tx to his sweeper. ht.AssertNumPendingSweeps(bob, 1) @@ -1353,16 +1353,16 @@ func runMultiHopHtlcLocalChainClaim(ht *lntest.HarnessTest, // Mining one additional block, Bob's second level tx is mature, and he // can sweep the output. block = ht.MineBlocksAndAssertNumTxes(bobSecondLevelCSV, 1)[0] - ht.Miner.AssertTxInBlock(block, carolSweep) + ht.AssertTxInBlock(block, carolSweep) - bobSweep := ht.Miner.GetNumTxsFromMempool(1)[0] + bobSweep := ht.GetNumTxsFromMempool(1)[0] bobSweepTxid := bobSweep.TxHash() // When we mine one additional block, that will confirm Bob's sweep. // Now Bob should have no pending channels anymore, as this just // resolved it by the confirmation of the sweep transaction. block = ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, &bobSweepTxid) + ht.AssertTxInBlock(block, &bobSweepTxid) // With the script-enforced lease commitment type, Alice and Bob still // haven't been able to sweep their respective commit outputs due to the @@ -1399,11 +1399,11 @@ func runMultiHopHtlcLocalChainClaim(ht *lntest.HarnessTest, aliceCommitOutpoint := wire.OutPoint{ Hash: *bobForceClose, Index: 3, } - ht.Miner.AssertOutpointInMempool( + ht.AssertOutpointInMempool( aliceCommitOutpoint, ).TxHash() bobCommitOutpoint := wire.OutPoint{Hash: closingTxid, Index: 3} - ht.Miner.AssertOutpointInMempool( + ht.AssertOutpointInMempool( bobCommitOutpoint, ).TxHash() @@ -1558,11 +1558,11 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest, ht.MineEmptyBlocks(int(numBlocks) - blocksMined) // Carol's commitment transaction should now be in the mempool. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // The closing transaction should be spending from the funding // transaction. - closingTx := ht.Miner.AssertOutpointInMempool( + closingTx := ht.AssertOutpointInMempool( ht.OutPointFromChannelPoint(bobChanPoint), ) closingTxid := closingTx.TxHash() @@ -1574,7 +1574,7 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest, // Mine a block, which should contain: the commitment. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, &closingTxid) + ht.AssertTxInBlock(block, &closingTxid) // After the force close transaction is mined, Carol should offer her // second level HTLC tx to the sweeper, along with her anchor output. @@ -1612,7 +1612,7 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest, // anchor sweeping. ht.MineBlocksAndAssertNumTxes(1, 1) carolSecondLevelCSV-- - ht.Miner.AssertNumTxsInMempool(2) + ht.AssertNumTxsInMempool(2) // Mine a block to confirm the expected transactions. ht.MineBlocksAndAssertNumTxes(1, 2) @@ -1624,7 +1624,7 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest, // NOTE: after Bob is restarted, the sweeping of the direct preimage // spent will happen immediately so we don't need to mine a block to // trigger Bob's sweeper to sweep it. - bobHtlcSweep := ht.Miner.GetNumTxsFromMempool(1)[0] + bobHtlcSweep := ht.GetNumTxsFromMempool(1)[0] bobHtlcSweepTxid := bobHtlcSweep.TxHash() // It should spend from the commitment in the channel with Alice. @@ -1633,7 +1633,7 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest, // We'll now mine a block which should confirm Bob's HTLC sweep // transaction. block = ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, &bobHtlcSweepTxid) + ht.AssertTxInBlock(block, &bobHtlcSweepTxid) carolSecondLevelCSV-- // Now that the sweeping transaction has been confirmed, Bob should now @@ -1656,12 +1656,12 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest, // Mine a block to trigger the sweep of the second level tx. ht.MineEmptyBlocks(1) - carolSweep := ht.Miner.AssertNumTxsInMempool(1)[0] + carolSweep := ht.AssertNumTxsInMempool(1)[0] // When Carol's sweep gets confirmed, she should have no more pending // channels. block = ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, carolSweep) + ht.AssertTxInBlock(block, carolSweep) ht.AssertNumPendingForceClose(carol, 0) // With the script-enforced lease commitment type, Alice and Bob still @@ -1692,9 +1692,9 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest, aliceCommitOutpoint := wire.OutPoint{ Hash: *aliceForceClose, Index: 3, } - ht.Miner.AssertOutpointInMempool(aliceCommitOutpoint) + ht.AssertOutpointInMempool(aliceCommitOutpoint) bobCommitOutpoint := wire.OutPoint{Hash: closingTxid, Index: 3} - ht.Miner.AssertOutpointInMempool(bobCommitOutpoint) + ht.AssertOutpointInMempool(bobCommitOutpoint) // Confirm their sweeps. ht.MineBlocksAndAssertNumTxes(1, 2) @@ -1881,13 +1881,13 @@ func runMultiHopHtlcAggregation(ht *lntest.HarnessTest, // Bob's force close transaction should now be found in the mempool. If // there are anchors, we expect it to be offered to Bob's sweeper. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // Bob has two anchor sweep requests, one for remote (invalid) and the // other for local. ht.AssertNumPendingSweeps(bob, 2) - closeTx := ht.Miner.AssertOutpointInMempool( + closeTx := ht.AssertOutpointInMempool( ht.OutPointFromChannelPoint(bobChanPoint), ) closeTxid := closeTx.TxHash() @@ -1925,7 +1925,7 @@ func runMultiHopHtlcAggregation(ht *lntest.HarnessTest, ht.MineBlocksAndAssertNumTxes(1, 1) // The above mined block will trigger Bob to sweep his anchor output. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // Let Alice settle her invoices. When Bob now gets the preimages, he // has no other option than to broadcast his second-level transactions @@ -1977,7 +1977,7 @@ func runMultiHopHtlcAggregation(ht *lntest.HarnessTest, ht.MineBlocksAndAssertNumTxes(1, 1) // Assert the sweeping txns are found in the mempool. - txes := ht.Miner.GetNumTxsFromMempool(expectedTxes) + txes := ht.GetNumTxsFromMempool(expectedTxes) // Since Bob can aggregate the transactions, we expect a single // transaction, that have multiple spends from the commitment. @@ -2048,7 +2048,7 @@ func runMultiHopHtlcAggregation(ht *lntest.HarnessTest, ht.MineEmptyBlocks(1) // Find the commitment sweep. - bobCommitSweep := ht.Miner.GetNumTxsFromMempool(1)[0] + bobCommitSweep := ht.GetNumTxsFromMempool(1)[0] ht.AssertTxSpendFrom(bobCommitSweep, closeTxid) // Also ensure it is not spending from any of the HTLC output. @@ -2092,7 +2092,7 @@ func runMultiHopHtlcAggregation(ht *lntest.HarnessTest, numBlocks := uint32(forceCloseChan.BlocksTilMaturity) // Add debug log. - _, height := ht.Miner.GetBestBlock() + height := ht.CurrentHeight() bob.AddToLogf("itest: now mine %d blocks at height %d", numBlocks, height) ht.MineEmptyBlocks(int(numBlocks) - 1) @@ -2120,7 +2120,7 @@ func runMultiHopHtlcAggregation(ht *lntest.HarnessTest, // TODO(yy): remove this once `blockbeat` is in place. numExpected := 1 err := wait.NoError(func() error { - mem := ht.Miner.GetRawMempool() + mem := ht.GetRawMempool() if len(mem) == numExpected { return nil } @@ -2135,7 +2135,7 @@ func runMultiHopHtlcAggregation(ht *lntest.HarnessTest, ht.Logf("Checking mempool got: %v", err) // Make sure it spends from the second level tx. - secondLevelSweep := ht.Miner.GetNumTxsFromMempool(numExpected)[0] + secondLevelSweep := ht.GetNumTxsFromMempool(numExpected)[0] bobSweep := secondLevelSweep.TxHash() // It should be sweeping all the second-level outputs. @@ -2162,7 +2162,7 @@ func runMultiHopHtlcAggregation(ht *lntest.HarnessTest, // level sweep. Now Bob should have no pending channels anymore, as // this just resolved it by the confirmation of the sweep transaction. block := ht.MineBlocksAndAssertNumTxes(1, numExpected)[0] - ht.Miner.AssertTxInBlock(block, &bobSweep) + ht.AssertTxInBlock(block, &bobSweep) // For leased channels, we need to mine one more block to confirm Bob's // commit output sweep. @@ -2223,7 +2223,7 @@ func createThreeHopNetwork(ht *lntest.HarnessTest, ht.FundCoinsUnconfirmed(btcutil.SatoshiPerBitcoin, carol) // Mine 1 block to get the above coins confirmed. - ht.MineBlocks(1) + ht.MineBlocksAndAssertNumTxes(1, 3) } // We'll start the test by creating a channel between Alice and Bob, @@ -2232,8 +2232,8 @@ func createThreeHopNetwork(ht *lntest.HarnessTest, var aliceFundingShim *lnrpc.FundingShim var thawHeight uint32 if c == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE { - _, minerHeight := ht.Miner.GetBestBlock() - thawHeight = uint32(minerHeight + thawHeightDelta) + minerHeight := ht.CurrentHeight() + thawHeight = minerHeight + thawHeightDelta aliceFundingShim, _ = deriveFundingShim( ht, alice, bob, chanAmt, thawHeight, true, c, ) @@ -2441,7 +2441,7 @@ func runExtraPreimageFromRemoteCommit(ht *lntest.HarnessTest, // Mine a block to trigger the sweep, and clean up the anchor sweeping // tx. ht.MineBlocksAndAssertNumTxes(1, 1) - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // Restart Bob. Once he finishes syncing the channel state, he should // notice the force close from Carol. @@ -2449,15 +2449,15 @@ func runExtraPreimageFromRemoteCommit(ht *lntest.HarnessTest, // Get the current height to compute number of blocks to mine to // trigger the htlc timeout resolver from Bob. - _, height := ht.Miner.GetBestBlock() + height := ht.CurrentHeight() // We'll now mine enough blocks to trigger Bob's timeout resolver. - numBlocks = htlc.ExpirationHeight - uint32(height) - + numBlocks = htlc.ExpirationHeight - height - lncfg.DefaultOutgoingBroadcastDelta // We should now have Carol's htlc success tx in the mempool. numTxesMempool := 1 - ht.Miner.AssertNumTxsInMempool(numTxesMempool) + ht.AssertNumTxsInMempool(numTxesMempool) // For neutrino backend, the timeout resolver needs to extract the // preimage from the blocks. @@ -2667,25 +2667,25 @@ func runExtraPreimageFromLocalCommit(ht *lntest.HarnessTest, switch c { case lnrpc.CommitmentType_LEGACY: htlcOutpoint.Index = 0 - ht.Miner.AssertNumTxsInMempool(2) + ht.AssertNumTxsInMempool(2) case lnrpc.CommitmentType_ANCHORS, lnrpc.CommitmentType_SIMPLE_TAPROOT: htlcOutpoint.Index = 2 - ht.Miner.AssertNumTxsInMempool(2) + ht.AssertNumTxsInMempool(2) case lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE: htlcOutpoint.Index = 2 - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) } // Get the current height to compute number of blocks to mine to // trigger the timeout resolver from Bob. - _, height := ht.Miner.GetBestBlock() + height := ht.CurrentHeight() // We'll now mine enough blocks to trigger Bob's htlc timeout resolver // to act. Once his timeout resolver starts, it will extract the // preimage from Carol's direct spend tx found in the mempool. - numBlocks = htlc.ExpirationHeight - uint32(height) - + numBlocks = htlc.ExpirationHeight - height - lncfg.DefaultOutgoingBroadcastDelta // Decrease the fee rate used by the sweeper so Bob's timeout tx will @@ -2701,10 +2701,16 @@ func runExtraPreimageFromLocalCommit(ht *lntest.HarnessTest, // preimage from the blocks. if ht.IsNeutrinoBackend() { // Make sure the direct spend tx is still in the mempool. - ht.Miner.AssertOutpointInMempool(htlcOutpoint) - - // Mine a block to confirm Carol's direct spend tx. - ht.MineBlocks(1) + ht.AssertOutpointInMempool(htlcOutpoint) + + // Mine a block to confirm two txns, + // - Carol's direct spend tx. + // - Bob's to_local output sweep tx. + if c != lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE { + ht.MineBlocksAndAssertNumTxes(1, 2) + } else { + ht.MineBlocksAndAssertNumTxes(1, 1) + } } // Finally, check that the Alice's payment is marked as succeeded as diff --git a/itest/lnd_nonstd_sweep_test.go b/itest/lnd_nonstd_sweep_test.go index a85fbc786a..f83daa669f 100644 --- a/itest/lnd_nonstd_sweep_test.go +++ b/itest/lnd_nonstd_sweep_test.go @@ -96,8 +96,8 @@ func testNonStdSweepInner(ht *lntest.HarnessTest, address string) { carol.RPC.SendCoins(sendReq) // Fetch the txid so we can grab the raw transaction. - txid := ht.Miner.AssertNumTxsInMempool(1)[0] - tx := ht.Miner.GetRawTransaction(txid) + txid := ht.AssertNumTxsInMempool(1)[0] + tx := ht.GetRawTransaction(txid) msgTx := tx.MsgTx() @@ -111,7 +111,7 @@ func testNonStdSweepInner(ht *lntest.HarnessTest, address string) { for _, inp := range msgTx.TxIn { // Fetch the previous outpoint's value. prevOut := inp.PreviousOutPoint - ptx := ht.Miner.GetRawTransaction(&prevOut.Hash) + ptx := ht.GetRawTransaction(&prevOut.Hash) pout := ptx.MsgTx().TxOut[prevOut.Index] inputVal += int(pout.Value) @@ -125,7 +125,7 @@ func testNonStdSweepInner(ht *lntest.HarnessTest, address string) { // Fetch the vsize of the transaction so we can determine if the // transaction pays >= 1 sat/vbyte. - rawTx := ht.Miner.GetRawTransactionVerbose(txid) + rawTx := ht.Miner().GetRawTransactionVerbose(txid) // Require fee >= vbytes. require.True(ht, fee >= int(rawTx.Vsize)) diff --git a/itest/lnd_onchain_test.go b/itest/lnd_onchain_test.go index e66fc1b4d2..a34b9a2e47 100644 --- a/itest/lnd_onchain_test.go +++ b/itest/lnd_onchain_test.go @@ -321,7 +321,7 @@ func testAnchorReservedValue(ht *lntest.HarnessTest) { // Alice tries to send all funds to an external address, the reserved // value must stay in her wallet. - minerAddr := ht.Miner.NewMinerAddress() + minerAddr := ht.NewMinerAddress() sweepReq = &lnrpc.SendCoinsRequest{ Addr: minerAddr.String(), @@ -486,7 +486,7 @@ func testAnchorThirdPartySpend(ht *lntest.HarnessTest) { // We now update the anchor sweep's deadline to be different than the // commit sweep so they can won't grouped together. - _, currentHeight := ht.Miner.GetBestBlock() + currentHeight := int32(ht.CurrentHeight()) deadline := int32(commit.DeadlineHeight) - currentHeight require.Positive(ht, deadline) ht.Logf("Found commit deadline %d, anchor deadline %d", @@ -520,7 +520,7 @@ func testAnchorThirdPartySpend(ht *lntest.HarnessTest) { // Mine one block to trigger Alice's sweeper to reconsider the anchor // sweeping - it will be swept with her commit output together in one // tx. - txns := ht.Miner.GetNumTxsFromMempool(2) + txns := ht.GetNumTxsFromMempool(2) aliceSweep := txns[0] if aliceSweep.TxOut[0].Value > txns[1].TxOut[0].Value { aliceSweep = txns[1] @@ -544,7 +544,7 @@ func testAnchorThirdPartySpend(ht *lntest.HarnessTest) { // With the anchor output located, and the main commitment mined we'll // instruct the wallet to send all coins in the wallet to a new address // (to the miner), including unconfirmed change. - minerAddr := ht.Miner.NewMinerAddress() + minerAddr := ht.NewMinerAddress() sweepReq := &lnrpc.SendCoinsRequest{ Addr: minerAddr.String(), SendAll: true, @@ -574,7 +574,7 @@ func testAnchorThirdPartySpend(ht *lntest.HarnessTest) { // mine a transaction that double spends the output. thirdPartyAnchorSweep := genAnchorSweep(ht, aliceSweep, anchor.Outpoint) ht.Logf("Third party tx=%v", thirdPartyAnchorSweep.TxHash()) - ht.Miner.MineBlockWithTx(thirdPartyAnchorSweep) + ht.MineBlockWithTx(thirdPartyAnchorSweep) // At this point, we should no longer find Alice's transaction that // tried to sweep the anchor in her wallet. @@ -600,8 +600,8 @@ func testAnchorThirdPartySpend(ht *lntest.HarnessTest) { Hash: *forceCloseTxID, Index: 1, } - ht.Miner.AssertOutpointInMempool(commitSweepOp) - ht.MineBlocks(1) + ht.AssertOutpointInMempool(commitSweepOp) + ht.MineBlocksAndAssertNumTxes(1, 1) ht.AssertNumWaitingClose(alice, 0) } @@ -673,7 +673,7 @@ func genAnchorSweep(ht *lntest.HarnessTest, aliceSweep *wire.MsgTx, aliceAnchorTxIn.Witness[0] = nil aliceAnchorTxIn.Sequence = 16 - minerAddr := ht.Miner.NewMinerAddress() + minerAddr := ht.NewMinerAddress() addrScript, err := txscript.PayToAddrScript(minerAddr) require.NoError(ht, err, "unable to gen addr script") @@ -717,7 +717,7 @@ func testRemoveTx(ht *lntest.HarnessTest) { TargetConf: 6, } alice.RPC.SendCoins(sendReq) - txID := ht.Miner.AssertNumTxsInMempool(1)[0] + txID := ht.AssertNumTxsInMempool(1)[0] // Make sure the unspent number of utxos is 2 and the unconfirmed // balances add up. @@ -727,7 +727,7 @@ func testRemoveTx(ht *lntest.HarnessTest) { require.Lenf(ht, unconfirmed, 2, "number of unconfirmed tx") // Get the raw transaction to calculate the exact fee. - tx := ht.Miner.GetNumTxsFromMempool(1)[0] + tx := ht.GetNumTxsFromMempool(1)[0] // Calculate the tx fee so we can compare the end amounts. We are // sending from the internal wallet to the internal wallet so only @@ -766,8 +766,8 @@ func testRemoveTx(ht *lntest.HarnessTest) { // Mine a block and make sure the transaction previously broadcasted // shows up in alice's wallet although we removed the transaction from // the wallet when it was unconfirmed. - block := ht.Miner.MineBlocks(1)[0] - ht.Miner.AssertTxInBlock(block, txID) + block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] + ht.AssertTxInBlock(block, txID) // Verify that alice has 2 confirmed unspent utxos in her default // wallet. @@ -836,7 +836,7 @@ func testListSweeps(ht *lntest.HarnessTest) { ht.MineEmptyBlocks(1) // Get the current block height. - _, blockHeight := ht.Miner.GetBestBlock() + blockHeight := int32(ht.CurrentHeight()) // Close the second channel and also sweep the funds. ht.ForceCloseChannel(alice, chanPoints[1]) @@ -861,7 +861,7 @@ func testListSweeps(ht *lntest.HarnessTest) { ht.MineEmptyBlocks(1) // Now we can expect that the sweep has been broadcast. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // List all unconfirmed sweeps that alice's node had broadcast. sweepResp := alice.RPC.ListSweeps(false, -1) diff --git a/itest/lnd_open_channel_test.go b/itest/lnd_open_channel_test.go index d28a211dbd..52ec622cf7 100644 --- a/itest/lnd_open_channel_test.go +++ b/itest/lnd_open_channel_test.go @@ -4,6 +4,7 @@ import ( "fmt" "strings" "testing" + "time" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg/chainhash" @@ -30,9 +31,9 @@ func testOpenChannelAfterReorg(ht *lntest.HarnessTest) { } // Create a temp miner. - tempMiner := ht.Miner.SpawnTempMiner() + tempMiner := ht.SpawnTempMiner() - miner := ht.Miner + miner := ht.Miner() alice, bob := ht.Alice, ht.Bob // Create a new channel that requires 1 confs before it's considered @@ -45,7 +46,7 @@ func testOpenChannelAfterReorg(ht *lntest.HarnessTest) { // Wait for miner to have seen the funding tx. The temporary miner is // disconnected, and won't see the transaction. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // At this point, the channel's funding transaction will have been // broadcast, but not confirmed, and the channel should be pending. @@ -58,8 +59,8 @@ func testOpenChannelAfterReorg(ht *lntest.HarnessTest) { // and our new miner mine 15. This will also confirm our pending // channel on the original miner's chain, which should be considered // open. - block := ht.MineBlocks(10)[0] - ht.Miner.AssertTxInBlock(block, fundingTxID) + block := ht.MineBlocksAndAssertNumTxes(10, 1)[0] + ht.AssertTxInBlock(block, fundingTxID) _, err = tempMiner.Client.Generate(15) require.NoError(ht, err, "unable to generate blocks") @@ -115,7 +116,7 @@ func testOpenChannelAfterReorg(ht *lntest.HarnessTest) { // Cleanup by mining the funding tx again, then closing the channel. block = ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, fundingTxID) + ht.AssertTxInBlock(block, fundingTxID) ht.CloseChannel(alice, chanPoint) } @@ -767,6 +768,18 @@ func testFundingExpiryBlocksOnPending(ht *lntest.HarnessTest) { // channel. ht.MineBlocksAndAssertNumTxes(1, 1) chanPoint := lntest.ChanPointFromPendingUpdate(update) + + // TODO(yy): remove the sleep once the following bug is fixed. + // + // We may get the error `unable to gracefully close channel + // while peer is offline (try force closing it instead): + // channel link not found`. This happens because the channel + // link hasn't been added yet but we now proceed to closing the + // channel. We may need to revisit how the channel open event + // is created and make sure the event is only sent after all + // relevant states have been updated. + time.Sleep(2 * time.Second) + ht.CloseChannel(alice, chanPoint) } diff --git a/itest/lnd_psbt_test.go b/itest/lnd_psbt_test.go index 2d41185999..91d67ba376 100644 --- a/itest/lnd_psbt_test.go +++ b/itest/lnd_psbt_test.go @@ -261,7 +261,7 @@ func runPsbtChanFunding(ht *lntest.HarnessTest, carol, dave *node.HarnessNode, } // No transaction should have been published yet. - ht.Miner.AssertNumTxsInMempool(0) + ht.AssertNumTxsInMempool(0) // Let's progress the second channel now. This time we'll use the raw // wire format transaction directly. @@ -295,7 +295,7 @@ func runPsbtChanFunding(ht *lntest.HarnessTest, carol, dave *node.HarnessNode, txHash := finalTx.TxHash() block := ht.MineBlocksAndAssertNumTxes(6, 1)[0] - ht.Miner.AssertTxInBlock(block, &txHash) + ht.AssertTxInBlock(block, &txHash) ht.AssertTopologyChannelOpen(carol, chanPoint) ht.AssertTopologyChannelOpen(carol, chanPoint2) @@ -456,7 +456,7 @@ func runPsbtChanFundingExternal(ht *lntest.HarnessTest, carol, finalizeRes := alice.RPC.FinalizePsbt(finalizeReq) // No transaction should have been published yet. - ht.Miner.AssertNumTxsInMempool(0) + ht.AssertNumTxsInMempool(0) // Great, now let's publish the final raw transaction. var finalTx wire.MsgTx @@ -464,13 +464,13 @@ func runPsbtChanFundingExternal(ht *lntest.HarnessTest, carol, require.NoError(ht, err) txHash := finalTx.TxHash() - _, err = ht.Miner.Client.SendRawTransaction(&finalTx, false) + _, err = ht.SendRawTransaction(&finalTx, false) require.NoError(ht, err) // Now we can mine a block to get the transaction confirmed, then wait // for the new channel to be propagated through the network. block := ht.MineBlocksAndAssertNumTxes(6, 1)[0] - ht.Miner.AssertTxInBlock(block, &txHash) + ht.AssertTxInBlock(block, &txHash) ht.AssertTopologyChannelOpen(carol, chanPoint) ht.AssertTopologyChannelOpen(carol, chanPoint2) @@ -627,7 +627,7 @@ func runPsbtChanFundingSingleStep(ht *lntest.HarnessTest, carol, txHash := finalTx.TxHash() block := ht.MineBlocksAndAssertNumTxes(6, 1)[0] - ht.Miner.AssertTxInBlock(block, &txHash) + ht.AssertTxInBlock(block, &txHash) ht.AssertTopologyChannelOpen(carol, chanPoint) // Next, to make sure the channel functions as normal, we'll make some @@ -1326,7 +1326,7 @@ func extractPublishAndMine(ht *lntest.HarnessTest, node *node.HarnessNode, // Mine one block which should contain two transactions. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] txHash := finalTx.TxHash() - ht.Miner.AssertTxInBlock(block, &txHash) + ht.AssertTxInBlock(block, &txHash) return finalTx } @@ -1432,8 +1432,8 @@ func assertPsbtSpend(ht *lntest.HarnessTest, alice *node.HarnessNode, block := ht.MineBlocksAndAssertNumTxes(1, 2)[0] firstTxHash := prevTx.TxHash() secondTxHash := finalTx.TxHash() - ht.Miner.AssertTxInBlock(block, &firstTxHash) - ht.Miner.AssertTxInBlock(block, &secondTxHash) + ht.AssertTxInBlock(block, &firstTxHash) + ht.AssertTxInBlock(block, &secondTxHash) } // assertPsbtFundSignSpend funds a PSBT from the internal wallet and then @@ -1683,6 +1683,9 @@ func testPsbtChanFundingWithUnstableUtxos(ht *lntest.HarnessTest) { ht.CloseChannelAssertPending(dave, channelPoint, true) ht.MineBlocksAndAssertNumTxes(1, 1) + // Make sure Carol sees her to_remote output from the force close tx. + ht.AssertNumPendingSweeps(carol, 1) + // Mine one block to trigger the sweep transaction. ht.MineEmptyBlocks(1) @@ -1794,7 +1797,7 @@ func testPsbtChanFundingWithUnstableUtxos(ht *lntest.HarnessTest) { txHash := finalTx.TxHash() block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, &txHash) + ht.AssertTxInBlock(block, &txHash) // Now we do the same but instead use preselected utxos to verify that // these utxos respects the utxo restrictions on sweeper unconfirmed @@ -1805,6 +1808,9 @@ func testPsbtChanFundingWithUnstableUtxos(ht *lntest.HarnessTest) { ht.CloseChannelAssertPending(dave, channelPoint2, true) ht.MineBlocksAndAssertNumTxes(1, 1) + // Make sure Carol sees her to_remote output from the force close tx. + ht.AssertNumPendingSweeps(carol, 1) + // Mine one block to trigger the sweep transaction. ht.MineEmptyBlocks(1) @@ -1929,19 +1935,11 @@ func testPsbtChanFundingWithUnstableUtxos(ht *lntest.HarnessTest) { updateResp = ht.ReceiveOpenChannelUpdate(chanUpdates) upd, ok = updateResp.Update.(*lnrpc.OpenStatusUpdate_ChanPending) require.True(ht, ok) - channelPoint3 := &lnrpc.ChannelPoint{ - FundingTxid: &lnrpc.ChannelPoint_FundingTxidBytes{ - FundingTxidBytes: upd.ChanPending.Txid, - }, - OutputIndex: upd.ChanPending.OutputIndex, - } err = finalTx.Deserialize(bytes.NewReader(finalizeRes.RawFinalTx)) require.NoError(ht, err) txHash = finalTx.TxHash() block = ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, &txHash) - - ht.CloseChannel(carol, channelPoint3) + ht.AssertTxInBlock(block, &txHash) } diff --git a/itest/lnd_recovery_test.go b/itest/lnd_recovery_test.go index 766d109562..ea93f373eb 100644 --- a/itest/lnd_recovery_test.go +++ b/itest/lnd_recovery_test.go @@ -252,7 +252,7 @@ func testOnchainFundRecovery(ht *lntest.HarnessTest) { promptChangeAddr := func(node *node.HarnessNode) { ht.Helper() - minerAddr := ht.Miner.NewMinerAddress() + minerAddr := ht.NewMinerAddress() req := &lnrpc.SendCoinsRequest{ Addr: minerAddr.String(), Amount: minerAmt, @@ -260,11 +260,11 @@ func testOnchainFundRecovery(ht *lntest.HarnessTest) { } resp := node.RPC.SendCoins(req) - txid := ht.Miner.AssertNumTxsInMempool(1)[0] + txid := ht.AssertNumTxsInMempool(1)[0] require.Equal(ht, txid.String(), resp.Txid) - block := ht.MineBlocks(1)[0] - ht.Miner.AssertTxInBlock(block, txid) + block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] + ht.AssertTxInBlock(block, txid) } restoreCheckBalance(finalBalance, 9, 20, promptChangeAddr) @@ -428,8 +428,7 @@ func testRescanAddressDetection(ht *lntest.HarnessTest) { }) // Wait until the spending tx is found and mine a block to confirm it. - ht.Miner.AssertNumTxsInMempool(1) - ht.MineBlocks(1) + ht.MineBlocksAndAssertNumTxes(1, 1) // The wallet should still just see a single UTXO of the change output // created earlier. diff --git a/itest/lnd_res_handoff_test.go b/itest/lnd_res_handoff_test.go index 8fc2f10434..941cc52837 100644 --- a/itest/lnd_res_handoff_test.go +++ b/itest/lnd_res_handoff_test.go @@ -66,7 +66,7 @@ func testResHandoff(ht *lntest.HarnessTest) { ht.AssertNumWaitingClose(bob, 1) // Mine a block to confirm the closing tx. - ht.MineBlocks(1) + ht.MineBlocksAndAssertNumTxes(1, 1) // We sleep here so we can be sure that the hand-off has occurred from // Bob's contractcourt to Bob's htlcswitch. This sleep could be removed diff --git a/itest/lnd_rest_api_test.go b/itest/lnd_rest_api_test.go index 78648b70dd..ce2884e776 100644 --- a/itest/lnd_rest_api_test.go +++ b/itest/lnd_rest_api_test.go @@ -238,7 +238,7 @@ func testRestAPI(ht *lntest.HarnessTest) { func wsTestCaseSubscription(ht *lntest.HarnessTest) { // Find out the current best block so we can subscribe to the next one. - hash, height := ht.Miner.GetBestBlock() + hash, height := ht.GetBestBlock() // Create a new subscription to get block epoch events. req := &chainrpc.BlockEpoch{ @@ -296,7 +296,7 @@ func wsTestCaseSubscription(ht *lntest.HarnessTest) { }() // Mine a block and make sure we get a message for it. - blockHashes := ht.Miner.GenerateBlocks(1) + blockHashes := ht.Miner().GenerateBlocks(1) select { case msg := <-msgChan: require.Equal( @@ -314,7 +314,7 @@ func wsTestCaseSubscription(ht *lntest.HarnessTest) { func wsTestCaseSubscriptionMacaroon(ht *lntest.HarnessTest) { // Find out the current best block so we can subscribe to the next one. - hash, height := ht.Miner.GetBestBlock() + hash, height := ht.GetBestBlock() // Create a new subscription to get block epoch events. req := &chainrpc.BlockEpoch{ @@ -388,7 +388,7 @@ func wsTestCaseSubscriptionMacaroon(ht *lntest.HarnessTest) { }() // Mine a block and make sure we get a message for it. - blockHashes := ht.Miner.GenerateBlocks(1) + blockHashes := ht.Miner().GenerateBlocks(1) select { case msg := <-msgChan: require.Equal( diff --git a/itest/lnd_revocation_test.go b/itest/lnd_revocation_test.go index be87d8a75e..82415e0396 100644 --- a/itest/lnd_revocation_test.go +++ b/itest/lnd_revocation_test.go @@ -122,7 +122,7 @@ func breachRetributionTestCase(ht *lntest.HarnessTest, // update, then ensure that the closing transaction was included in the // block. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] - ht.Miner.AssertTxInBlock(block, breachTXID) + ht.AssertTxInBlock(block, breachTXID) // Construct to_remote output which pays to Bob. Based on the output // ordering, the first output in this breach tx is the to_remote @@ -146,7 +146,7 @@ func breachRetributionTestCase(ht *lntest.HarnessTest, // sweeping transactions in the mempool. Thus we directly assert that // the breach transaction's outpoint is seen in the mempool instead of // checking the number of transactions. - justiceTx := ht.Miner.AssertOutpointInMempool(toRemoteOp) + justiceTx := ht.AssertOutpointInMempool(toRemoteOp) // Assert that all the inputs of this transaction are spending outputs // generated by Bob's breach transaction above. @@ -174,7 +174,7 @@ func breachRetributionTestCase(ht *lntest.HarnessTest, // transaction which was just accepted into the mempool. block = ht.MineBlocksAndAssertNumTxes(1, 1)[0] justiceTxid := justiceTx.TxHash() - ht.Miner.AssertTxInBlock(block, &justiceTxid) + ht.AssertTxInBlock(block, &justiceTxid) ht.AssertNodeNumChannels(carol, 0) @@ -338,7 +338,7 @@ func revokedCloseRetributionZeroValueRemoteOutputCase(ht *lntest.HarnessTest, // sweeping transactions in the mempool. Thus we directly assert that // the breach transaction's outpoint is seen in the mempool instead of // checking the number of transactions. - justiceTx := ht.Miner.AssertOutpointInMempool(toLocalOp) + justiceTx := ht.AssertOutpointInMempool(toLocalOp) // Assert that all the inputs of this transaction are spending outputs // generated by Carol's breach transaction above. @@ -363,7 +363,7 @@ func revokedCloseRetributionZeroValueRemoteOutputCase(ht *lntest.HarnessTest, // transaction which was just accepted into the mempool. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] justiceTxid := justiceTx.TxHash() - ht.Miner.AssertTxInBlock(block, &justiceTxid) + ht.AssertTxInBlock(block, &justiceTxid) // At this point, Dave should have no pending channels. ht.AssertNodeNumChannels(dave, 0) @@ -559,7 +559,7 @@ func revokedCloseRetributionRemoteHodlCase(ht *lntest.HarnessTest, breachTXID := ht.WaitForChannelCloseEvent(closeUpdates) require.Equal(ht, closeTxID[:], breachTXID[:], "expected breach ID to be equal to close ID") - ht.Miner.AssertTxInBlock(block, breachTXID) + ht.AssertTxInBlock(block, breachTXID) // Query the mempool for Dave's justice transaction, this should be // broadcast as Carol's contract breaching transaction gets confirmed @@ -570,16 +570,16 @@ func revokedCloseRetributionRemoteHodlCase(ht *lntest.HarnessTest, var justiceTxid *chainhash.Hash errNotFound := errors.New("justice tx not found") findJusticeTx := func() (*chainhash.Hash, error) { - mempool := ht.Miner.GetRawMempool() + mempool := ht.GetRawMempool() for _, txid := range mempool { // Check that the justice tx has the appropriate number // of inputs. // - // NOTE: We don't use `ht.Miner.GetRawTransaction` + // NOTE: We don't use `ht.GetRawTransaction` // which asserts a txid must be found as the HTLC // spending txes might be aggregated. - tx, err := ht.Miner.Client.GetRawTransaction(txid) + tx, err := ht.Miner().Client.GetRawTransaction(txid) if err != nil { return nil, err } @@ -626,14 +626,14 @@ func revokedCloseRetributionRemoteHodlCase(ht *lntest.HarnessTest, } require.NoError(ht, err, "timeout finding justice tx") - justiceTx := ht.Miner.GetRawTransaction(justiceTxid) + justiceTx := ht.GetRawTransaction(justiceTxid) // isSecondLevelSpend checks that the passed secondLevelTxid is a // potentitial second level spend spending from the commit tx. isSecondLevelSpend := func(commitTxid, secondLevelTxid *chainhash.Hash) bool { - secondLevel := ht.Miner.GetRawTransaction(secondLevelTxid) + secondLevel := ht.GetRawTransaction(secondLevelTxid) // A second level spend should have only one input, and one // output. diff --git a/itest/lnd_route_blinding_test.go b/itest/lnd_route_blinding_test.go index 514e856d89..a2899657ba 100644 --- a/itest/lnd_route_blinding_test.go +++ b/itest/lnd_route_blinding_test.go @@ -1010,7 +1010,7 @@ func testErrorHandlingOnChainFailure(ht *lntest.HarnessTest) { ht.MineBlocks(node.DefaultCSV - 1) ht.AssertNumPendingSweeps(ht.Bob, 1) ht.MineEmptyBlocks(1) - ht.Miner.MineBlocksAndAssertNumTxes(1, 1) + ht.MineBlocksAndAssertNumTxes(1, 1) // Restart bob so that we can test that he's able to recover everything // he needs to claim a blinded HTLC. @@ -1021,13 +1021,13 @@ func testErrorHandlingOnChainFailure(ht *lntest.HarnessTest) { // value. info := ht.Bob.RPC.GetInfo() target := carolHTLC.IncomingExpiry - info.BlockHeight - ht.MineBlocks(target) + ht.MineBlocks(int(target)) // Wait for Bob's timeout transaction in the mempool, since we've // suspended Carol we don't need to account for her commitment output // claim. - ht.Miner.MineBlocksAndAssertNumTxes(1, 1) ht.AssertNumPendingSweeps(ht.Bob, 0) + ht.MineBlocksAndAssertNumTxes(1, 1) // Assert that the HTLC has cleared. ht.WaitForBlockchainSync(ht.Bob) @@ -1049,7 +1049,7 @@ func testErrorHandlingOnChainFailure(ht *lntest.HarnessTest) { // Clean up the rest of our force close: mine blocks so that Bob's CSV // expires plus one block to trigger his sweep and then mine it. ht.MineBlocks(node.DefaultCSV + 1) - ht.Miner.MineBlocksAndAssertNumTxes(1, 1) + ht.MineBlocksAndAssertNumTxes(1, 1) // Bring carol back up so that we can close out the rest of our // channels cooperatively. She requires an interceptor to start up diff --git a/itest/lnd_routing_test.go b/itest/lnd_routing_test.go index 93a890bad5..1e627c7d70 100644 --- a/itest/lnd_routing_test.go +++ b/itest/lnd_routing_test.go @@ -117,7 +117,7 @@ func testSingleHopSendToRouteCase(ht *lntest.HarnessTest, // Assert Carol and Dave are synced to the chain before proceeding, to // ensure the queried route will have a valid final CLTV once the HTLC // reaches Dave. - _, minerHeight := ht.Miner.GetBestBlock() + minerHeight := int32(ht.CurrentHeight()) ht.WaitForNodeBlockHeight(carol, minerHeight) ht.WaitForNodeBlockHeight(dave, minerHeight) diff --git a/itest/lnd_signer_test.go b/itest/lnd_signer_test.go index 23773eb71d..bf9033cad8 100644 --- a/itest/lnd_signer_test.go +++ b/itest/lnd_signer_test.go @@ -296,7 +296,7 @@ func assertSignOutputRaw(ht *lntest.HarnessTest, alice.RPC.SendCoins(req) // Wait until the TX is found in the mempool. - txid := ht.Miner.AssertNumTxsInMempool(1)[0] + txid := ht.AssertNumTxsInMempool(1)[0] targetOutputIndex := ht.GetOutputIndex(txid, targetAddr.String()) @@ -359,7 +359,7 @@ func assertSignOutputRaw(ht *lntest.HarnessTest, }) // Wait until the spending tx is found. - txid = ht.Miner.AssertNumTxsInMempool(1)[0] + txid = ht.AssertNumTxsInMempool(1)[0] p2wkhOutputIndex := ht.GetOutputIndex(txid, p2wkhAdrr.String()) op := &lnrpc.OutPoint{ diff --git a/itest/lnd_sweep_test.go b/itest/lnd_sweep_test.go index 27ad132664..b95bc0513d 100644 --- a/itest/lnd_sweep_test.go +++ b/itest/lnd_sweep_test.go @@ -168,11 +168,11 @@ func testSweepCPFPAnchorOutgoingTimeout(ht *lntest.HarnessTest) { ht.MineEmptyBlocks(int(numBlocks)) // Assert Bob's force closing tx has been broadcast. - closeTxid := ht.Miner.AssertNumTxsInMempool(1)[0] + closeTxid := ht.AssertNumTxsInMempool(1)[0] // Remember the force close height so we can calculate the deadline // height. - _, forceCloseHeight := ht.Miner.GetBestBlock() + forceCloseHeight := ht.CurrentHeight() // Bob should have two pending sweeps, // - anchor sweeping from his local commitment. @@ -188,7 +188,7 @@ func testSweepCPFPAnchorOutgoingTimeout(ht *lntest.HarnessTest) { sweeps := ht.AssertNumPendingSweeps(bob, 2) // The two anchor sweeping should have the same deadline height. - deadlineHeight := uint32(forceCloseHeight) + deadlineDeltaAnchor + deadlineHeight := forceCloseHeight + deadlineDeltaAnchor require.Equal(ht, deadlineHeight, sweeps[0].DeadlineHeight) require.Equal(ht, deadlineHeight, sweeps[1].DeadlineHeight) @@ -209,7 +209,7 @@ func testSweepCPFPAnchorOutgoingTimeout(ht *lntest.HarnessTest) { // // We should see Bob's anchor sweeping tx triggered by the above // block, along with his force close tx. - txns := ht.Miner.GetNumTxsFromMempool(2) + txns := ht.GetNumTxsFromMempool(2) // Find the sweeping tx. sweepTx := ht.FindSweepingTxns(txns, 1, *closeTxid)[0] @@ -261,12 +261,12 @@ func testSweepCPFPAnchorOutgoingTimeout(ht *lntest.HarnessTest) { // Make sure Bob's old sweeping tx has been removed from the // mempool. - ht.Miner.AssertTxNotInMempool(sweepTx.TxHash()) + ht.AssertTxNotInMempool(sweepTx.TxHash()) // We expect to see two txns in the mempool, // - Bob's force close tx. // - Bob's anchor sweep tx. - ht.Miner.AssertNumTxsInMempool(2) + ht.AssertNumTxsInMempool(2) // We expect the fees to increase by i*delta. expectedFee := startFeeAnchor + feeDelta.MulF64(float64(i)) @@ -276,7 +276,7 @@ func testSweepCPFPAnchorOutgoingTimeout(ht *lntest.HarnessTest) { // We should see Bob's anchor sweeping tx being fee bumped // since it's not confirmed, along with his force close tx. - txns = ht.Miner.GetNumTxsFromMempool(2) + txns = ht.GetNumTxsFromMempool(2) // Find the sweeping tx. sweepTx = ht.FindSweepingTxns(txns, 1, *closeTxid)[0] @@ -304,18 +304,18 @@ func testSweepCPFPAnchorOutgoingTimeout(ht *lntest.HarnessTest) { // // Once out of the above loop, we expect to be 2 blocks before the CPFP // deadline. - _, currentHeight := ht.Miner.GetBestBlock() + currentHeight := ht.CurrentHeight() require.Equal(ht, int(anchorDeadline-2), int(currentHeight)) // Mine one more block, we'd use up all the CPFP budget. ht.MineEmptyBlocks(1) // Make sure Bob's old sweeping tx has been removed from the mempool. - ht.Miner.AssertTxNotInMempool(sweepTx.TxHash()) + ht.AssertTxNotInMempool(sweepTx.TxHash()) // Get the last sweeping tx - we should see two txns here, Bob's anchor // sweeping tx and his force close tx. - txns = ht.Miner.GetNumTxsFromMempool(2) + txns = ht.GetNumTxsFromMempool(2) // Find the sweeping tx. sweepTx = ht.FindSweepingTxns(txns, 1, *closeTxid)[0] @@ -336,7 +336,7 @@ func testSweepCPFPAnchorOutgoingTimeout(ht *lntest.HarnessTest) { // // We expect two txns here, one for the anchor sweeping, the other for // the force close tx. - txns = ht.Miner.GetNumTxsFromMempool(2) + txns = ht.GetNumTxsFromMempool(2) // Find the sweeping tx. currentSweepTx := ht.FindSweepingTxns(txns, 1, *closeTxid)[0] @@ -512,12 +512,12 @@ func testSweepCPFPAnchorIncomingTimeout(ht *lntest.HarnessTest) { forceCloseHeight := htlc.ExpirationHeight - goToChainDelta // Mine till the goToChainHeight is reached. - _, currentHeight := ht.Miner.GetBestBlock() - numBlocks := forceCloseHeight - uint32(currentHeight) + currentHeight := ht.CurrentHeight() + numBlocks := forceCloseHeight - currentHeight ht.MineEmptyBlocks(int(numBlocks)) // Assert Bob's force closing tx has been broadcast. - closeTxid := ht.Miner.AssertNumTxsInMempool(1)[0] + closeTxid := ht.AssertNumTxsInMempool(1)[0] // Bob should have two pending sweeps, // - anchor sweeping from his local commitment. @@ -546,7 +546,7 @@ func testSweepCPFPAnchorIncomingTimeout(ht *lntest.HarnessTest) { // // We should see Bob's anchor sweeping tx triggered by the above // block, along with his force close tx. - txns := ht.Miner.GetNumTxsFromMempool(2) + txns := ht.GetNumTxsFromMempool(2) // Find the sweeping tx. sweepTx := ht.FindSweepingTxns(txns, 1, *closeTxid)[0] @@ -598,12 +598,12 @@ func testSweepCPFPAnchorIncomingTimeout(ht *lntest.HarnessTest) { // Make sure Bob's old sweeping tx has been removed from the // mempool. - ht.Miner.AssertTxNotInMempool(sweepTx.TxHash()) + ht.AssertTxNotInMempool(sweepTx.TxHash()) // We expect to see two txns in the mempool, // - Bob's force close tx. // - Bob's anchor sweep tx. - ht.Miner.AssertNumTxsInMempool(2) + ht.AssertNumTxsInMempool(2) // We expect the fees to increase by i*delta. expectedFee := startFeeAnchor + feeDelta.MulF64(float64(i)) @@ -613,7 +613,7 @@ func testSweepCPFPAnchorIncomingTimeout(ht *lntest.HarnessTest) { // We should see Bob's anchor sweeping tx being fee bumped // since it's not confirmed, along with his force close tx. - txns = ht.Miner.GetNumTxsFromMempool(2) + txns = ht.GetNumTxsFromMempool(2) // Find the sweeping tx. sweepTx = ht.FindSweepingTxns(txns, 1, *closeTxid)[0] @@ -641,18 +641,18 @@ func testSweepCPFPAnchorIncomingTimeout(ht *lntest.HarnessTest) { // // Once out of the above loop, we expect to be 2 blocks before the CPFP // deadline. - _, currentHeight = ht.Miner.GetBestBlock() + currentHeight = ht.CurrentHeight() require.Equal(ht, int(anchorDeadline-2), int(currentHeight)) // Mine one more block, we'd use up all the CPFP budget. ht.MineEmptyBlocks(1) // Make sure Bob's old sweeping tx has been removed from the mempool. - ht.Miner.AssertTxNotInMempool(sweepTx.TxHash()) + ht.AssertTxNotInMempool(sweepTx.TxHash()) // Get the last sweeping tx - we should see two txns here, Bob's anchor // sweeping tx and his force close tx. - txns = ht.Miner.GetNumTxsFromMempool(2) + txns = ht.GetNumTxsFromMempool(2) // Find the sweeping tx. sweepTx = ht.FindSweepingTxns(txns, 1, *closeTxid)[0] @@ -673,7 +673,7 @@ func testSweepCPFPAnchorIncomingTimeout(ht *lntest.HarnessTest) { // // We expect two txns here, one for the anchor sweeping, the other for // the force close tx. - txns = ht.Miner.GetNumTxsFromMempool(2) + txns = ht.GetNumTxsFromMempool(2) // Find the sweeping tx. currentSweepTx := ht.FindSweepingTxns(txns, 1, *closeTxid)[0] @@ -872,7 +872,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { numBlocks := padCLTV(uint32( invoiceReqHold.CltvExpiry - lncfg.DefaultOutgoingBroadcastDelta, )) - ht.MineBlocks(numBlocks) + ht.MineBlocks(int(numBlocks)) // Before we mine empty blocks to check the RBF behavior, we need to be // aware that Bob's incoming HTLC will expire before his outgoing HTLC @@ -887,7 +887,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { ht.AssertNumPendingSweeps(bob, 2) // Assert Bob's force closing tx has been broadcast. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // Mine the force close tx, which triggers Bob's contractcourt to offer // his outgoing HTLC to his sweeper. @@ -912,7 +912,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { // Bob should now have one sweep and one sweeping tx in the mempool. ht.AssertNumPendingSweeps(bob, 1) - outgoingSweep := ht.Miner.GetNumTxsFromMempool(1)[0] + outgoingSweep := ht.GetNumTxsFromMempool(1)[0] // Check the shape of the sweeping tx - we expect it to be // 2-input-2-output as a wallet utxo is used and a required output is @@ -982,17 +982,17 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { outgoingFuncPosition++ // We should see Bob's sweeping tx in the mempool. - ht.Miner.AssertNumTxsInMempool(1) + ht.AssertNumTxsInMempool(1) // Make sure Bob's old sweeping tx has been removed from the // mempool. - ht.Miner.AssertTxNotInMempool(outgoingSweep.TxHash()) + ht.AssertTxNotInMempool(outgoingSweep.TxHash()) // Bob should still have the outgoing HTLC sweep. ht.AssertNumPendingSweeps(bob, 1) // We should see Bob's replacement tx in the mempool. - outgoingSweep = ht.Miner.GetNumTxsFromMempool(1)[0] + outgoingSweep = ht.GetNumTxsFromMempool(1)[0] // Bob's outgoing HTLC sweeping tx should be fee bumped. assertSweepFeeRate( @@ -1018,7 +1018,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { // We should see two txns in the mempool: // 1. Bob's outgoing HTLC sweeping tx. // 2. Bob's force close tx for Alice->Bob. - txns := ht.Miner.GetNumTxsFromMempool(2) + txns := ht.GetNumTxsFromMempool(2) // Find the force close tx - we expect it to have a single input. closeTx := txns[0] @@ -1029,7 +1029,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { // We don't care the behavior of the anchor sweep in this test, so we // mine the force close tx to trigger Bob's contractcourt to offer his // incoming HTLC to his sweeper. - ht.Miner.MineBlockWithTx(closeTx) + ht.MineBlockWithTx(closeTx) // Update Bob's fee function position. outgoingFuncPosition++ @@ -1051,7 +1051,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { // 1. the outgoing HTLC sweeping tx. // 2. the incoming HTLC sweeping tx. // 3. the anchor sweeping tx. - txns = ht.Miner.GetNumTxsFromMempool(3) + txns = ht.GetNumTxsFromMempool(3) abCloseTxid := closeTx.TxHash() @@ -1088,7 +1088,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { incomingFuncPosition := int32(0) // Mine the anchor sweeping tx to reduce noise in this test. - ht.Miner.MineBlockWithTxes([]*btcutil.Tx{btcutil.NewTx(anchorSweep)}) + ht.MineBlockWithTx(anchorSweep) // Update the fee function's positions. outgoingFuncPosition++ @@ -1102,7 +1102,7 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { // We should see two txns in the mempool: // 1. the outgoing HTLC sweeping tx. // 2. the incoming HTLC sweeping tx. - txns = ht.Miner.GetNumTxsFromMempool(2) + txns = ht.GetNumTxsFromMempool(2) var incoming, outgoing *wire.MsgTx @@ -1156,12 +1156,12 @@ func testSweepHTLCs(ht *lntest.HarnessTest) { // We should see two txns in the mempool, // - the incoming HTLC sweeping tx. // - the outgoing HTLC sweeping tx. - ht.Miner.AssertNumTxsInMempool(2) + ht.AssertNumTxsInMempool(2) // Make sure Bob's old sweeping txns have been removed from the // mempool. - ht.Miner.AssertTxNotInMempool(outgoingSweep.TxHash()) - ht.Miner.AssertTxNotInMempool(incomingSweep.TxHash()) + ht.AssertTxNotInMempool(outgoingSweep.TxHash()) + ht.AssertTxNotInMempool(incomingSweep.TxHash()) // Bob should have two pending sweeps: // 1. the outgoing HTLC output on Bob->Carol. @@ -1370,7 +1370,7 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { // - Alice's anchor sweeping tx must have been failed due to the fee // rate chosen in this test - the anchor sweep tx has no output. // - Bob's sweeping tx, which sweeps both his anchor and commit outputs. - bobSweepTx := ht.Miner.GetNumTxsFromMempool(1)[0] + bobSweepTx := ht.GetNumTxsFromMempool(1)[0] // We expect two pending sweeps for Bob - anchor and commit outputs. pendingSweepBob := ht.AssertNumPendingSweeps(bob, 2)[0] @@ -1380,7 +1380,7 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { // // TODO(yy): assert they are equal once blocks are synced via // `blockbeat`. - _, currentHeight := ht.Miner.GetBestBlock() + currentHeight := int32(ht.CurrentHeight()) actualDeadline := int32(pendingSweepBob.DeadlineHeight) - currentHeight if actualDeadline != int32(deadlineB) { ht.Logf("!!! Found unsynced block between sweeper and "+ @@ -1438,7 +1438,7 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { // // TODO(yy): assert they are equal once blocks are synced via // `blockbeat`. - _, currentHeight = ht.Miner.GetBestBlock() + currentHeight = int32(ht.CurrentHeight()) actualDeadline = int32(aliceCommit.DeadlineHeight) - currentHeight if actualDeadline != int32(deadlineA) { ht.Logf("!!! Found unsynced block between Alice's sweeper and "+ @@ -1456,7 +1456,7 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { aliceStartPosition := 0 var aliceFirstSweepTx *wire.MsgTx err := wait.NoError(func() error { - mem := ht.Miner.GetRawMempool() + mem := ht.GetRawMempool() if len(mem) != 2 { return fmt.Errorf("want 2, got %v in mempool: %v", len(mem), mem) @@ -1466,7 +1466,7 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { // created and published. aliceStartPosition = 1 - txns := ht.Miner.GetNumTxsFromMempool(2) + txns := ht.GetNumTxsFromMempool(2) aliceFirstSweepTx = txns[0] // Reassign if the second tx is larger. @@ -1486,7 +1486,7 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { // block would trigger an RBF. We now need to assert the mempool has // removed the replaced tx. if aliceFirstSweepTx != nil { - ht.Miner.AssertTxNotInMempool(aliceFirstSweepTx.TxHash()) + ht.AssertTxNotInMempool(aliceFirstSweepTx.TxHash()) } // We also remember the positions of fee functions used by Alice and @@ -1503,7 +1503,7 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { // commit output together because they have different deadlines. // - Bob's previous sweeping tx, which sweeps both his anchor and // commit outputs, at the starting fee rate. - txns := ht.Miner.GetNumTxsFromMempool(2) + txns := ht.GetNumTxsFromMempool(2) // Assume the first tx is Alice's sweeping tx, if the second tx has a // larger output value, then that's Alice's as her to_local value is @@ -1600,18 +1600,18 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { // We expect to see both Alice's and Bob's sweeping txns in the // mempool. - ht.Miner.AssertNumTxsInMempool(2) + ht.AssertNumTxsInMempool(2) // Make sure Alice's old sweeping tx has been removed from the // mempool. - ht.Miner.AssertTxNotInMempool(aliceSweepTx.TxHash()) + ht.AssertTxNotInMempool(aliceSweepTx.TxHash()) // We should see two txns in the mempool: // - Alice's sweeping tx, which sweeps both her anchor and // commit outputs, using the increased fee rate. // - Bob's previous sweeping tx, which sweeps both his anchor // and commit outputs, at the possible increased fee rate. - txns = ht.Miner.GetNumTxsFromMempool(2) + txns = ht.GetNumTxsFromMempool(2) // Assume the first tx is Alice's sweeping tx, if the second tx // has a larger output value, then that's Alice's as her @@ -1687,18 +1687,18 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { // We expect to see both Alice's and Bob's sweeping txns in the // mempool. - ht.Miner.AssertNumTxsInMempool(2) + ht.AssertNumTxsInMempool(2) // Make sure Alice's old sweeping tx has been removed from the // mempool. - ht.Miner.AssertTxNotInMempool(aliceSweepTx.TxHash()) + ht.AssertTxNotInMempool(aliceSweepTx.TxHash()) // Make sure Bob's old sweeping tx has been removed from the // mempool. Since Bob's sweeping tx will only be successfully // RBFed every 4 blocks, his old sweeping tx only will be // removed when there are 4 blocks increased. if bobPosition%4 == 0 { - ht.Miner.AssertTxNotInMempool(bobSweepTx.TxHash()) + ht.AssertTxNotInMempool(bobSweepTx.TxHash()) } // We should see two txns in the mempool: @@ -1706,7 +1706,7 @@ func testSweepCommitOutputAndAnchor(ht *lntest.HarnessTest) { // commit outputs, using the increased fee rate. // - Bob's previous sweeping tx, which sweeps both his anchor // and commit outputs, at the possible increased fee rate. - txns := ht.Miner.GetNumTxsFromMempool(2) + txns := ht.GetNumTxsFromMempool(2) // Assume the first tx is Alice's sweeping tx, if the second tx // has a larger output value, then that's Alice's as her @@ -1804,7 +1804,7 @@ func createSimpleNetwork(ht *lntest.HarnessTest, nodeCfg []string, } // Mine 1 block to get the above coins confirmed. - ht.MineBlocks(1) + ht.MineBlocksAndAssertNumTxes(1, numNodes-1) // Open channels in batch to save blocks mined. reqs := make([]*lntest.OpenChannelRequest, 0, len(nodes)-1) @@ -1911,7 +1911,7 @@ func runBumpFee(ht *lntest.HarnessTest, alice *node.HarnessNode) { // We expect to see Alice's original tx and her CPFP tx in the // mempool. - txns := ht.Miner.GetNumTxsFromMempool(2) + txns := ht.GetNumTxsFromMempool(2) // Find the sweeping tx - assume it's the first item, if it has // the same txid as the parent tx, use the second item. @@ -1972,7 +1972,7 @@ func runBumpFee(ht *lntest.HarnessTest, alice *node.HarnessNode) { // Since the request doesn't specify a deadline, we expect the default // deadline to be used. - _, currentHeight := ht.Miner.GetBestBlock() + currentHeight := int32(ht.CurrentHeight()) deadline := uint32(currentHeight + sweep.DefaultDeadlineDelta) // Assert the pending sweep is created with the expected values: @@ -2003,7 +2003,7 @@ func runBumpFee(ht *lntest.HarnessTest, alice *node.HarnessNode) { alice.RPC.BumpFee(bumpFeeReq) // Alice's old sweeping tx should be replaced. - ht.Miner.AssertTxNotInMempool(sweepTx1.TxHash()) + ht.AssertTxNotInMempool(sweepTx1.TxHash()) // Assert the pending sweep is created with the expected values: // - broadcast attempts: 2. @@ -2035,7 +2035,7 @@ func runBumpFee(ht *lntest.HarnessTest, alice *node.HarnessNode) { alice.RPC.BumpFee(bumpFeeReq) // Alice's old sweeping tx should be replaced. - ht.Miner.AssertTxNotInMempool(sweepTx2.TxHash()) + ht.AssertTxNotInMempool(sweepTx2.TxHash()) // Assert the pending sweep is created with the expected values: // - broadcast attempts: 3. @@ -2066,7 +2066,7 @@ func runBumpFee(ht *lntest.HarnessTest, alice *node.HarnessNode) { alice.RPC.BumpFee(bumpFeeReq) // Alice's old sweeping tx should be replaced. - ht.Miner.AssertTxNotInMempool(sweepTx3.TxHash()) + ht.AssertTxNotInMempool(sweepTx3.TxHash()) // Assert the pending sweep is created with the expected values: // - broadcast attempts: 4. @@ -2093,7 +2093,7 @@ func runBumpFee(ht *lntest.HarnessTest, alice *node.HarnessNode) { alice.RPC.BumpFee(bumpFeeReq) // Alice's old sweeping tx should be replaced. - ht.Miner.AssertTxNotInMempool(sweepTx4.TxHash()) + ht.AssertTxNotInMempool(sweepTx4.TxHash()) // Assert the pending sweep is created with the expected values: // - broadcast attempts: 5. diff --git a/itest/lnd_taproot_test.go b/itest/lnd_taproot_test.go index 3b5cb4799a..9434586a40 100644 --- a/itest/lnd_taproot_test.go +++ b/itest/lnd_taproot_test.go @@ -96,7 +96,7 @@ func testTaprootSendCoinsKeySpendBip86(ht *lntest.HarnessTest, // Assert this is a segwit v1 address that starts with bcrt1p. require.Contains( - ht, p2trResp.Address, ht.Miner.ActiveNet.Bech32HRPSegwit+"1p", + ht, p2trResp.Address, ht.Miner().ActiveNet.Bech32HRPSegwit+"1p", ) // Send the coins from Alice's wallet to her own, but to the new p2tr @@ -107,7 +107,7 @@ func testTaprootSendCoinsKeySpendBip86(ht *lntest.HarnessTest, TargetConf: 6, }) - txid := ht.Miner.AssertNumTxsInMempool(1)[0] + txid := ht.AssertNumTxsInMempool(1)[0] // Wait until bob has seen the tx and considers it as owned. p2trOutputIndex := ht.GetOutputIndex(txid, p2trResp.Address) @@ -162,7 +162,7 @@ func testTaprootComputeInputScriptKeySpendBip86(ht *lntest.HarnessTest, alice.RPC.SendCoins(req) // Wait until bob has seen the tx and considers it as owned. - txid := ht.Miner.AssertNumTxsInMempool(1)[0] + txid := ht.AssertNumTxsInMempool(1)[0] p2trOutputIndex := ht.GetOutputIndex(txid, p2trAddr.String()) op := &lnrpc.OutPoint{ TxidBytes: txid[:], @@ -1413,7 +1413,7 @@ func clearWalletImportedTapscriptBalance(ht *lntest.HarnessTest, // Mine one block which should contain the sweep transaction. block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] sweepTxHash := sweepTx.TxHash() - ht.Miner.AssertTxInBlock(block, &sweepTxHash) + ht.AssertTxInBlock(block, &sweepTxHash) } // testScriptHashLock returns a simple bitcoin script that locks the funds to @@ -1481,7 +1481,7 @@ func sendToTaprootOutput(ht *lntest.HarnessTest, hn *node.HarnessNode, hn.RPC.SendCoins(req) // Wait until the TX is found in the mempool. - txid := ht.Miner.AssertNumTxsInMempool(1)[0] + txid := ht.AssertNumTxsInMempool(1)[0] p2trOutputIndex := ht.GetOutputIndex(txid, tapScriptAddr.String()) p2trOutpoint := wire.OutPoint{ Hash: *txid, @@ -1535,13 +1535,13 @@ func publishTxAndConfirmSweep(ht *lntest.HarnessTest, node *node.HarnessNode, // Before we publish the tx that spends the p2tr transaction, we want to // register a spend listener that we expect to fire after mining the // block. - _, currentHeight := ht.Miner.GetBestBlock() + currentHeight := ht.CurrentHeight() // For a Taproot output we cannot leave the outpoint empty. Let's make // sure the API returns the correct error here. req := &chainrpc.SpendRequest{ Script: spendRequest.Script, - HeightHint: uint32(currentHeight), + HeightHint: currentHeight, } spendClient := node.RPC.RegisterSpendNtfn(req) @@ -1556,7 +1556,7 @@ func publishTxAndConfirmSweep(ht *lntest.HarnessTest, node *node.HarnessNode, req = &chainrpc.SpendRequest{ Outpoint: spendRequest.Outpoint, Script: spendRequest.Script, - HeightHint: uint32(currentHeight), + HeightHint: currentHeight, } spendClient = node.RPC.RegisterSpendNtfn(req) @@ -1582,7 +1582,7 @@ func publishTxAndConfirmSweep(ht *lntest.HarnessTest, node *node.HarnessNode, require.NoError(ht, err) spend := spendMsg.GetSpend() require.NotNil(ht, spend) - require.Equal(ht, spend.SpendingHeight, uint32(currentHeight+1)) + require.Equal(ht, spend.SpendingHeight, currentHeight+1) } // confirmAddress makes sure that a transaction in the mempool spends funds to @@ -1592,7 +1592,7 @@ func confirmAddress(ht *lntest.HarnessTest, hn *node.HarnessNode, addrString string) { // Wait until the tx that sends to the address is found. - txid := ht.Miner.AssertNumTxsInMempool(1)[0] + txid := ht.AssertNumTxsInMempool(1)[0] // Wait until bob has seen the tx and considers it as owned. addrOutputIndex := ht.GetOutputIndex(txid, addrString) @@ -1609,11 +1609,11 @@ func confirmAddress(ht *lntest.HarnessTest, hn *node.HarnessNode, addrPkScript, err := txscript.PayToAddrScript(parsedAddr) require.NoError(ht, err) - _, currentHeight := ht.Miner.GetBestBlock() + currentHeight := ht.CurrentHeight() req := &chainrpc.ConfRequest{ Script: addrPkScript, Txid: txid[:], - HeightHint: uint32(currentHeight), + HeightHint: currentHeight, NumConfs: 1, IncludeBlock: true, } @@ -1628,7 +1628,7 @@ func confirmAddress(ht *lntest.HarnessTest, hn *node.HarnessNode, require.NoError(ht, err) conf := confMsg.GetConf() require.NotNil(ht, conf) - require.Equal(ht, conf.BlockHeight, uint32(currentHeight+1)) + require.Equal(ht, conf.BlockHeight, currentHeight+1) require.NotNil(ht, conf.RawBlock) // We should also be able to decode the raw block. @@ -1850,7 +1850,7 @@ func testTaprootCoopClose(ht *lntest.HarnessTest) { // assertTaprootDeliveryUsed returns true if a Taproot addr was used in // the co-op close transaction. assertTaprootDeliveryUsed := func(closingTxid *chainhash.Hash) bool { - tx := ht.Miner.GetRawTransaction(closingTxid) + tx := ht.GetRawTransaction(closingTxid) for _, txOut := range tx.MsgTx().TxOut { if !txscript.IsPayToTaproot(txOut.PkScript) { return false diff --git a/itest/lnd_test.go b/itest/lnd_test.go index b5886bc299..5b9105694d 100644 --- a/itest/lnd_test.go +++ b/itest/lnd_test.go @@ -151,7 +151,7 @@ func TestLightningNetworkDaemon(t *testing.T) { } } - _, height := harnessTest.Miner.GetBestBlock() + height := harnessTest.CurrentHeight() t.Logf("=========> tests finished for tranche: %v, tested %d "+ "cases, end height: %d\n", trancheIndex, len(testCases), height) } diff --git a/itest/lnd_wallet_import_test.go b/itest/lnd_wallet_import_test.go index 2d41da893b..b9cce9f1e5 100644 --- a/itest/lnd_wallet_import_test.go +++ b/itest/lnd_wallet_import_test.go @@ -372,7 +372,7 @@ func fundChanAndCloseFromImportedAccount(ht *lntest.HarnessTest, srcNode, ) block := ht.MineBlocksAndAssertNumTxes(6, 1)[0] - ht.Miner.AssertTxInBlock(block, txHash) + ht.AssertTxInBlock(block, txHash) confBalanceAfterChan += chanChangeUtxoAmt ht.AssertWalletAccountBalance(srcNode, account, 0, 0) @@ -389,7 +389,7 @@ func fundChanAndCloseFromImportedAccount(ht *lntest.HarnessTest, srcNode, ) block := ht.MineBlocksAndAssertNumTxes(6, 1)[0] - ht.Miner.AssertTxInBlock(block, txHash) + ht.AssertTxInBlock(block, txHash) confBalanceAfterChan += chanChangeUtxoAmt ht.AssertWalletAccountBalance( diff --git a/itest/lnd_watchtower_test.go b/itest/lnd_watchtower_test.go index c64b1e43ae..4fee5d6c44 100644 --- a/itest/lnd_watchtower_test.go +++ b/itest/lnd_watchtower_test.go @@ -86,7 +86,7 @@ func testTowerClientTowerAndSessionManagement(ht *lntest.HarnessTest) { } if mineOnFail { - ht.Miner.MineBlocksSlow(1) + ht.MineBlocks(1) } return fmt.Errorf("expected %d sessions, got %d", @@ -502,7 +502,7 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, block := ht.MineBlocksAndAssertNumTxes(1, 1)[0] breachTXID := ht.WaitForChannelCloseEvent(closeUpdates) - ht.Miner.AssertTxInBlock(block, breachTXID) + ht.AssertTxInBlock(block, breachTXID) // The breachTXID should match the above closeTxID. require.EqualValues(ht, breachTXID, closeTxID) @@ -510,12 +510,12 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest, // Query the mempool for Dave's justice transaction, this should be // broadcast as Carol's contract breaching transaction gets confirmed // above. - justiceTXID := ht.Miner.AssertNumTxsInMempool(1)[0] + justiceTXID := ht.AssertNumTxsInMempool(1)[0] // Query for the mempool transaction found above. Then assert that all // the inputs of this transaction are spending outputs generated by // Carol's breach transaction above. - justiceTx := ht.Miner.GetRawTransaction(justiceTXID) + justiceTx := ht.GetRawTransaction(justiceTXID) for _, txIn := range justiceTx.MsgTx().TxIn { require.Equal(ht, breachTXID[:], txIn.PreviousOutPoint.Hash[:], "justice tx not spending commitment utxo") @@ -702,7 +702,7 @@ func assertNumBackups(ht *lntest.HarnessTest, node *rpc.HarnessRPC, } if mineOnFail { - ht.Miner.MineBlocksSlow(1) + ht.MineBlocks(1) } return fmt.Errorf("expected %d backups, got %d", diff --git a/itest/lnd_zero_conf_test.go b/itest/lnd_zero_conf_test.go index a02e5c0063..d638703769 100644 --- a/itest/lnd_zero_conf_test.go +++ b/itest/lnd_zero_conf_test.go @@ -110,7 +110,7 @@ func testZeroConfChannelOpen(ht *lntest.HarnessTest) { fundingTxID := ht.GetChanPointFundingTxid(fundingPoint2) - ht.Miner.AssertTxInBlock(block, fundingTxID) + ht.AssertTxInBlock(block, fundingTxID) daveInvoiceResp3 := dave.RPC.AddInvoice(daveInvoiceParams) ht.CompletePaymentRequests( @@ -159,7 +159,7 @@ func testZeroConfChannelOpen(ht *lntest.HarnessTest) { block = ht.MineBlocksAndAssertNumTxes(6, 1)[0] fundingTxID = ht.GetChanPointFundingTxid(fundingPoint3) - ht.Miner.AssertTxInBlock(block, fundingTxID) + ht.AssertTxInBlock(block, fundingTxID) // Wait until Eve's ZeroConf channel is replaced by the confirmed SCID // in her graph. @@ -950,7 +950,7 @@ func testZeroConfReorg(ht *lntest.HarnessTest) { // exists in the graph. // // First, we'll setup a new miner that we can use to cause a reorg. - tempMiner := ht.Miner.SpawnTempMiner() + tempMiner := ht.SpawnTempMiner() // We now cause a fork, by letting our original miner mine 1 block and // our new miner will mine 2. We also expect the funding transition to @@ -959,10 +959,10 @@ func testZeroConfReorg(ht *lntest.HarnessTest) { tempMiner.MineEmptyBlocks(2) // Ensure the temp miner is one block ahead. - ht.Miner.AssertMinerBlockHeightDelta(tempMiner, 1) + ht.AssertMinerBlockHeightDelta(tempMiner, 1) // Wait for Carol to sync to the original miner's chain. - _, minerHeight := ht.Miner.GetBestBlock() + minerHeight := int32(ht.CurrentHeight()) ht.WaitForNodeBlockHeight(carol, minerHeight) // Now we'll disconnect Carol's chain backend from the original miner @@ -972,14 +972,14 @@ func testZeroConfReorg(ht *lntest.HarnessTest) { // Connecting to the temporary miner should cause the original miner to // reorg to the longer chain. - ht.Miner.ConnectMiner(tempMiner) + ht.ConnectToMiner(tempMiner) // They should now be on the same chain. - ht.Miner.AssertMinerBlockHeightDelta(tempMiner, 0) + ht.AssertMinerBlockHeightDelta(tempMiner, 0) // Now we disconnect the two miners and reconnect our original chain // backend. - ht.Miner.DisconnectMiner(tempMiner) + ht.DisconnectFromMiner(tempMiner) ht.ConnectMiner() diff --git a/lntest/btcd.go b/lntest/btcd.go index 2d735fa2bd..6b607978eb 100644 --- a/lntest/btcd.go +++ b/lntest/btcd.go @@ -14,6 +14,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/integration/rpctest" "github.com/btcsuite/btcd/rpcclient" + "github.com/lightningnetwork/lnd/lntest/miner" "github.com/lightningnetwork/lnd/lntest/node" ) @@ -53,12 +54,14 @@ func (b BtcdBackendConfig) GenArgs() []string { // ConnectMiner is called to establish a connection to the test miner. func (b BtcdBackendConfig) ConnectMiner() error { - return b.harness.Client.Node(btcjson.NConnect, b.minerAddr, &temp) + return b.harness.Client.Node(btcjson.NConnect, b.minerAddr, &miner.Temp) } // DisconnectMiner is called to disconnect the miner. func (b BtcdBackendConfig) DisconnectMiner() error { - return b.harness.Client.Node(btcjson.NDisconnect, b.minerAddr, &temp) + return b.harness.Client.Node( + btcjson.NDisconnect, b.minerAddr, &miner.Temp, + ) } // Credentials returns the rpc username, password and host for the backend. diff --git a/lntest/harness.go b/lntest/harness.go index 92549427f1..eefdcfec10 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -18,6 +18,7 @@ import ( "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" + "github.com/lightningnetwork/lnd/lntest/miner" "github.com/lightningnetwork/lnd/lntest/node" "github.com/lightningnetwork/lnd/lntest/rpc" "github.com/lightningnetwork/lnd/lntest/wait" @@ -76,9 +77,9 @@ type HarnessTest struct { // Embed the standbyNodes so we can easily access them via `ht.Alice`. standbyNodes - // Miner is a reference to a running full node that can be used to + // miner is a reference to a running full node that can be used to // create new blocks on the network. - Miner *HarnessMiner + miner *miner.HarnessMiner // manager handles the start and stop of a given node. manager *nodeManager @@ -104,6 +105,9 @@ type HarnessTest struct { // cleaned specifies whether the cleanup has been applied for the // current HarnessTest. cleaned bool + + // currentHeight is the current height of the chain backend. + currentHeight uint32 } // harnessOpts contains functional option to modify the behavior of the various @@ -158,7 +162,9 @@ func NewHarnessTest(t *testing.T, lndBinary string, feeService WebFeeService, // Start will assemble the chain backend and the miner for the HarnessTest. It // also starts the fee service and watches lnd process error. -func (h *HarnessTest) Start(chain node.BackendConfig, miner *HarnessMiner) { +func (h *HarnessTest) Start(chain node.BackendConfig, + miner *miner.HarnessMiner) { + // Spawn a new goroutine to watch for any fatal errors that any of the // running lnd processes encounter. If an error occurs, then the test // case should naturally as a result and we log the server error here @@ -185,7 +191,7 @@ func (h *HarnessTest) Start(chain node.BackendConfig, miner *HarnessMiner) { h.manager.feeServiceURL = h.feeService.URL() // Assemble the miner. - h.Miner = miner + h.miner = miner } // ChainBackendName returns the chain backend name used in the test. @@ -251,7 +257,7 @@ func (h *HarnessTest) createAndSendOutput(target *node.HarnessNode, PkScript: addrScript, Value: int64(amt), } - h.Miner.SendOutput(output, defaultMinerFeeRate) + h.miner.SendOutput(output, defaultMinerFeeRate) } // SetupRemoteSigningStandbyNodes starts the initial seeder nodes within the @@ -353,11 +359,6 @@ func (h *HarnessTest) Stop() { return } - // Stop all running nodes. - for _, node := range h.manager.activeNodes { - h.Shutdown(node) - } - close(h.lndErrorChan) // Stop the fee service. @@ -368,7 +369,7 @@ func (h *HarnessTest) Stop() { h.stopChainBackend() // Stop the miner. - h.Miner.Stop() + h.miner.Stop() } // RunTestCase executes a harness test case. Any errors or panics will be @@ -411,7 +412,7 @@ func (h *HarnessTest) Subtest(t *testing.T) *HarnessTest { st := &HarnessTest{ T: t, manager: h.manager, - Miner: h.Miner, + miner: h.miner, standbyNodes: h.standbyNodes, feeService: h.feeService, lndErrorChan: make(chan error, lndErrorChanSize), @@ -421,7 +422,7 @@ func (h *HarnessTest) Subtest(t *testing.T) *HarnessTest { st.runCtx, st.cancel = context.WithCancel(h.runCtx) // Inherit the subtest for the miner. - st.Miner.T = st.T + st.miner.T = st.T // Reset the standby nodes. st.resetStandbyNodes(t) @@ -430,10 +431,11 @@ func (h *HarnessTest) Subtest(t *testing.T) *HarnessTest { st.feeService.Reset() // Record block height. - _, startHeight := h.Miner.GetBestBlock() + h.updateCurrentHeight() + startHeight := int32(h.CurrentHeight()) st.Cleanup(func() { - _, endHeight := h.Miner.GetBestBlock() + _, endHeight := h.GetBestBlock() st.Logf("finished test: %s, start height=%d, end height=%d, "+ "mined blocks=%d", st.manager.currentTestCase, @@ -464,7 +466,7 @@ func (h *HarnessTest) Subtest(t *testing.T) *HarnessTest { st.shutdownNonStandbyNodes() // We require the mempool to be cleaned from the test. - require.Empty(st, st.Miner.GetRawMempool(), "mempool not "+ + require.Empty(st, st.miner.GetRawMempool(), "mempool not "+ "cleaned, please mine blocks to clean them all.") // Finally, cancel the run context. We have to do it here @@ -1190,7 +1192,7 @@ func (h *HarnessTest) openChannel(alice, bob *node.HarnessNode, // Check that the funding tx is found in the first block. fundingTxID := h.GetChanPointFundingTxid(fundingChanPoint) - h.Miner.AssertTxInBlock(block, fundingTxID) + h.AssertTxInBlock(block, fundingTxID) // Check that both alice and bob have seen the channel from their // network topology. @@ -1295,7 +1297,7 @@ func (h *HarnessTest) CloseChannelAssertPending(hn *node.HarnessNode, pendingClose.ClosePending.Txid) // Assert the closing tx is in the mempool. - h.Miner.AssertTxInMempool(closeTxid) + h.miner.AssertTxInMempool(closeTxid) return stream, closeTxid } @@ -1393,7 +1395,7 @@ func (h *HarnessTest) fundCoins(amt btcutil.Amount, target *node.HarnessNode, PkScript: addrScript, Value: int64(amt), } - h.Miner.SendOutput(output, defaultMinerFeeRate) + h.miner.SendOutput(output, defaultMinerFeeRate) // Encode the pkScript in hex as this the format that it will be // returned via rpc. @@ -1411,24 +1413,24 @@ func (h *HarnessTest) fundCoins(amt btcutil.Amount, target *node.HarnessNode, pkScriptStr := utxos[0].PkScript require.Equal(h, pkScriptStr, expPkScriptStr, "pkscript mismatch") - } - // If the transaction should remain unconfirmed, then we'll wait until - // the target node's unconfirmed balance reflects the expected balance - // and exit. - if !confirmed && !h.IsNeutrinoBackend() { expectedBalance := btcutil.Amount( initialBalance.UnconfirmedBalance, ) + amt h.WaitForBalanceUnconfirmed(target, expectedBalance) + } + // If the transaction should remain unconfirmed, then we'll wait until + // the target node's unconfirmed balance reflects the expected balance + // and exit. + if !confirmed { return } // Otherwise, we'll generate 1 new blocks to ensure the output gains a // sufficient number of confirmations and wait for the balance to // reflect what's expected. - h.MineBlocks(1) + h.MineBlocksAndAssertNumTxes(1, 1) expectedBalance := btcutil.Amount(initialBalance.ConfirmedBalance) + amt h.WaitForBalanceConfirmed(target, expectedBalance) @@ -1599,7 +1601,7 @@ func (h *HarnessTest) OpenChannelPsbt(srcNode, destNode *node.HarnessNode, // Make sure the channel funding address has the correct type for the // given commitment type. fundingAddr, err := btcutil.DecodeAddress( - upd.PsbtFund.FundingAddress, harnessNetParams, + upd.PsbtFund.FundingAddress, miner.HarnessNetParams, ) require.NoError(h, err) @@ -1646,40 +1648,6 @@ func (h *HarnessTest) CleanupForceClose(hn *node.HarnessNode) { h.mineTillForceCloseResolved(hn) } -// mineTillForceCloseResolved asserts that the number of pending close channels -// are zero. Each time it checks, a new block is mined using MineBlocksSlow to -// give the node some time to catch up the chain. -// -// NOTE: this method is a workaround to make sure we have a clean mempool at -// the end of a channel force closure. We cannot directly mine blocks and -// assert channels being fully closed because the subsystems in lnd don't share -// the same block height. This is especially the case when blocks are produced -// too fast. -// TODO(yy): remove this workaround when syncing blocks are unified in all the -// subsystems. -func (h *HarnessTest) mineTillForceCloseResolved(hn *node.HarnessNode) { - _, startHeight := h.Miner.GetBestBlock() - - err := wait.NoError(func() error { - resp := hn.RPC.PendingChannels() - total := len(resp.PendingForceClosingChannels) - if total != 0 { - h.MineBlocks(1) - - return fmt.Errorf("expected num of pending force " + - "close channel to be zero") - } - - _, height := h.Miner.GetBestBlock() - h.Logf("Mined %d blocks while waiting for force closed "+ - "channel to be resolved", height-startHeight) - - return nil - }, DefaultTimeout) - - require.NoErrorf(h, err, "assert force close resolved timeout") -} - // CreatePayReqs is a helper method that will create a slice of payment // requests for the given node. func (h *HarnessTest) CreatePayReqs(hn *node.HarnessNode, @@ -1739,92 +1707,6 @@ func (h *HarnessTest) RestartNodeAndRestoreDB(hn *node.HarnessNode) { h.WaitForBlockchainSync(hn) } -// MineBlocks mines blocks and asserts all active nodes have synced to the -// chain. -// -// NOTE: this differs from miner's `MineBlocks` as it requires the nodes to be -// synced. -func (h *HarnessTest) MineBlocks(num uint32) []*wire.MsgBlock { - require.Less(h, num, uint32(maxBlocksAllowed), - "too many blocks to mine") - - // Mining the blocks slow to give `lnd` more time to sync. - blocks := h.Miner.MineBlocksSlow(num) - - // Make sure all the active nodes are synced. - bestBlock := blocks[len(blocks)-1] - h.AssertActiveNodesSyncedTo(bestBlock) - - return blocks -} - -// MineBlocksAndAssertNumTxes mines blocks and asserts the number of -// transactions are found in the first block. It also asserts all active nodes -// have synced to the chain. -// -// NOTE: this differs from miner's `MineBlocks` as it requires the nodes to be -// synced. -// -// TODO(yy): change the APIs to force callers to think about blocks and txns: -// - MineBlocksAndAssertNumTxes -> MineBlocks -// - add more APIs to mine a single tx. -func (h *HarnessTest) MineBlocksAndAssertNumTxes(num uint32, - numTxs int) []*wire.MsgBlock { - - // If we expect transactions to be included in the blocks we'll mine, - // we wait here until they are seen in the miner's mempool. - txids := h.Miner.AssertNumTxsInMempool(numTxs) - - // Mine blocks. - blocks := h.Miner.MineBlocksSlow(num) - - // Assert that all the transactions were included in the first block. - for _, txid := range txids { - h.Miner.AssertTxInBlock(blocks[0], txid) - } - - // Make sure the mempool has been updated. - for _, txid := range txids { - h.Miner.AssertTxNotInMempool(*txid) - } - - // Finally, make sure all the active nodes are synced. - bestBlock := blocks[len(blocks)-1] - h.AssertActiveNodesSyncedTo(bestBlock) - - return blocks -} - -// cleanMempool mines blocks till the mempool is empty and asserts all active -// nodes have synced to the chain. -func (h *HarnessTest) cleanMempool() { - _, startHeight := h.Miner.GetBestBlock() - - // Mining the blocks slow to give `lnd` more time to sync. - var bestBlock *wire.MsgBlock - err := wait.NoError(func() error { - // If mempool is empty, exit. - mem := h.Miner.GetRawMempool() - if len(mem) == 0 { - _, height := h.Miner.GetBestBlock() - h.Logf("Mined %d blocks when cleanup the mempool", - height-startHeight) - - return nil - } - - // Otherwise mine a block. - blocks := h.Miner.MineBlocksSlow(1) - bestBlock = blocks[len(blocks)-1] - - // Make sure all the active nodes are synced. - h.AssertActiveNodesSyncedTo(bestBlock) - - return fmt.Errorf("still have %d txes in mempool", len(mem)) - }, wait.MinerMempoolTimeout) - require.NoError(h, err, "timeout cleaning up mempool") -} - // CleanShutDown is used to quickly end a test by shutting down all non-standby // nodes and mining blocks to empty the mempool. // @@ -1840,21 +1722,6 @@ func (h *HarnessTest) CleanShutDown() { h.cleanMempool() } -// MineEmptyBlocks mines a given number of empty blocks. -// -// NOTE: this differs from miner's `MineEmptyBlocks` as it requires the nodes -// to be synced. -func (h *HarnessTest) MineEmptyBlocks(num int) []*wire.MsgBlock { - require.Less(h, num, maxBlocksAllowed, "too many blocks to mine") - - blocks := h.Miner.MineEmptyBlocks(num) - - // Finally, make sure all the active nodes are synced. - h.AssertActiveNodesSynced() - - return blocks -} - // QueryChannelByChanPoint tries to find a channel matching the channel point // and asserts. It returns the channel found. func (h *HarnessTest) QueryChannelByChanPoint(hn *node.HarnessNode, @@ -2035,7 +1902,7 @@ func (h *HarnessTest) CalculateTxFee(tx *wire.MsgTx) btcutil.Amount { var balance btcutil.Amount for _, in := range tx.TxIn { parentHash := in.PreviousOutPoint.Hash - rawTx := h.Miner.GetRawTransaction(&parentHash) + rawTx := h.miner.GetRawTransaction(&parentHash) parent := rawTx.MsgTx() value := parent.TxOut[in.PreviousOutPoint.Index].Value @@ -2147,19 +2014,6 @@ func findSweepInDetails(ht *HarnessTest, sweepTxid string, return false } -// ConnectMiner connects the miner with the chain backend in the network. -func (h *HarnessTest) ConnectMiner() { - err := h.manager.chainBackend.ConnectMiner() - require.NoError(h, err, "failed to connect miner") -} - -// DisconnectMiner removes the connection between the miner and the chain -// backend in the network. -func (h *HarnessTest) DisconnectMiner() { - err := h.manager.chainBackend.DisconnectMiner() - require.NoError(h, err, "failed to disconnect miner") -} - // QueryRoutesAndRetry attempts to keep querying a route until timeout is // reached. // @@ -2266,12 +2120,12 @@ func (h *HarnessTest) ReceiveChannelEvent( func (h *HarnessTest) GetOutputIndex(txid *chainhash.Hash, addr string) int { // We'll then extract the raw transaction from the mempool in order to // determine the index of the p2tr output. - tx := h.Miner.GetRawTransaction(txid) + tx := h.miner.GetRawTransaction(txid) p2trOutputIndex := -1 for i, txOut := range tx.MsgTx().TxOut { _, addrs, _, err := txscript.ExtractPkScriptAddrs( - txOut.PkScript, h.Miner.ActiveNet, + txOut.PkScript, h.miner.ActiveNet, ) require.NoError(h, err) @@ -2303,7 +2157,7 @@ func (h *HarnessTest) SendCoins(a, b *node.HarnessNode, TargetConf: 6, } a.RPC.SendCoins(sendReq) - tx := h.Miner.GetNumTxsFromMempool(1)[0] + tx := h.GetNumTxsFromMempool(1)[0] return tx } diff --git a/lntest/harness_assertion.go b/lntest/harness_assertion.go index 9ee9bc4e45..4a5d04274e 100644 --- a/lntest/harness_assertion.go +++ b/lntest/harness_assertion.go @@ -23,6 +23,7 @@ import ( "github.com/lightningnetwork/lnd/lnrpc/invoicesrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" + "github.com/lightningnetwork/lnd/lntest/miner" "github.com/lightningnetwork/lnd/lntest/node" "github.com/lightningnetwork/lnd/lntest/rpc" "github.com/lightningnetwork/lnd/lntest/wait" @@ -655,7 +656,7 @@ func (h *HarnessTest) AssertStreamChannelCoopClosed(hn *node.HarnessNode, // Consume one close event and assert the closing txid can be found in // the block. closingTxid := h.WaitForChannelCloseEvent(stream) - h.Miner.AssertTxInBlock(block, closingTxid) + h.AssertTxInBlock(block, closingTxid) // We should see zero waiting close channels now. h.AssertNumWaitingClose(hn, 0) @@ -699,7 +700,7 @@ func (h *HarnessTest) AssertStreamChannelForceClosed(hn *node.HarnessNode, // Consume one close event and assert the closing txid can be found in // the block. closingTxid := h.WaitForChannelCloseEvent(stream) - h.Miner.AssertTxInBlock(block, closingTxid) + h.AssertTxInBlock(block, closingTxid) // We should see zero waiting close channels and 1 pending force close // channels now. @@ -784,8 +785,13 @@ func (h *HarnessTest) AssertNumUTXOsWithConf(hn *node.HarnessNode, return nil } + desc := "has UTXOs:\n" + for _, utxo := range resp.Utxos { + desc += fmt.Sprintf("%v\n", utxo) + } + return errNumNotMatched(hn.Name(), "num of UTXOs", - expectedUtxos, total-old, total, old) + expectedUtxos, total-old, total, old, desc) }, DefaultTimeout) require.NoError(h, err, "timeout waiting for UTXOs") @@ -937,7 +943,7 @@ func (h *HarnessTest) RandomPreimage() lntypes.Preimage { // DecodeAddress decodes a given address and asserts there's no error. func (h *HarnessTest) DecodeAddress(addr string) btcutil.Address { - resp, err := btcutil.DecodeAddress(addr, harnessNetParams) + resp, err := btcutil.DecodeAddress(addr, miner.HarnessNetParams) require.NoError(h, err, "DecodeAddress failed") return resp @@ -2015,6 +2021,7 @@ func (h *HarnessTest) CreateBurnAddr(addrType lnrpc.AddressType) ([]byte, require.NoError(h, err) randomKeyBytes := randomPrivKey.PubKey().SerializeCompressed() + harnessNetParams := miner.HarnessNetParams var addr btcutil.Address switch addrType { @@ -2562,11 +2569,11 @@ func (h *HarnessTest) AssertClosingTxInMempool(cp *lnrpc.ChannelPoint, } // Wait for the expected txes to be found in the mempool. - h.Miner.AssertNumTxsInMempool(expectedTxes) + h.AssertNumTxsInMempool(expectedTxes) // Get the closing tx from the mempool. op := h.OutPointFromChannelPoint(cp) - closeTx := h.Miner.AssertOutpointInMempool(op) + closeTx := h.AssertOutpointInMempool(op) return closeTx } @@ -2576,11 +2583,11 @@ func (h *HarnessTest) AssertClosingTxInMempool(cp *lnrpc.ChannelPoint, // will assert the anchor sweep tx is also in the mempool. func (h *HarnessTest) MineClosingTx(cp *lnrpc.ChannelPoint) *wire.MsgTx { // Wait for the expected txes to be found in the mempool. - h.Miner.AssertNumTxsInMempool(1) + h.AssertNumTxsInMempool(1) // Get the closing tx from the mempool. op := h.OutPointFromChannelPoint(cp) - closeTx := h.Miner.AssertOutpointInMempool(op) + closeTx := h.AssertOutpointInMempool(op) // Mine a block to confirm the closing transaction and potential anchor // sweep. diff --git a/lntest/harness_miner.go b/lntest/harness_miner.go index f6348c0783..65994d254f 100644 --- a/lntest/harness_miner.go +++ b/lntest/harness_miner.go @@ -1,602 +1,332 @@ package lntest import ( - "bytes" - "context" "fmt" - "os" - "path/filepath" - "strings" - "testing" - "time" - "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/blockchain" "github.com/btcsuite/btcd/btcutil" - "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/integration/rpctest" - "github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/lntest/miner" "github.com/lightningnetwork/lnd/lntest/node" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/stretchr/testify/require" ) -const ( - // minerLogFilename is the default log filename for the miner node. - minerLogFilename = "output_btcd_miner.log" - - // minerLogDir is the default log dir for the miner node. - minerLogDir = ".minerlogs" - - // slowMineDelay defines a wait period between mining new blocks. - slowMineDelay = 100 * time.Millisecond -) - -var ( - harnessNetParams = &chaincfg.RegressionNetParams - - // temp is used to signal we want to establish a temporary connection - // using the btcd Node API. - // - // NOTE: Cannot be const, since the node API expects a reference. - temp = "temp" -) - -type HarnessMiner struct { - *testing.T - *rpctest.Harness - - // runCtx is a context with cancel method. It's used to signal when the - // node needs to quit, and used as the parent context when spawning - // children contexts for RPC requests. - runCtx context.Context //nolint:containedctx - cancel context.CancelFunc - - // logPath is the directory path of the miner's logs. - logPath string - - // logFilename is the saved log filename of the miner node. - logFilename string -} - -// NewMiner creates a new miner using btcd backend with the default log file -// dir and name. -func NewMiner(ctxt context.Context, t *testing.T) *HarnessMiner { - t.Helper() - return newMiner(ctxt, t, minerLogDir, minerLogFilename) -} - -// NewTempMiner creates a new miner using btcd backend with the specified log -// file dir and name. -func NewTempMiner(ctxt context.Context, t *testing.T, - tempDir, tempLogFilename string) *HarnessMiner { - - t.Helper() - - return newMiner(ctxt, t, tempDir, tempLogFilename) -} - -// newMiner creates a new miner using btcd's rpctest. -func newMiner(ctxb context.Context, t *testing.T, minerDirName, - logFilename string) *HarnessMiner { - - t.Helper() - - handler := &rpcclient.NotificationHandlers{} - btcdBinary := node.GetBtcdBinary() - baseLogPath := fmt.Sprintf("%s/%s", node.GetLogDir(), minerDirName) - - args := []string{ - "--rejectnonstd", - "--txindex", - "--nowinservice", - "--nobanning", - "--debuglevel=debug", - "--logdir=" + baseLogPath, - "--trickleinterval=100ms", - // Don't disconnect if a reply takes too long. - "--nostalldetect", - } - - miner, err := rpctest.New(harnessNetParams, handler, args, btcdBinary) - require.NoError(t, err, "unable to create mining node") - - ctxt, cancel := context.WithCancel(ctxb) - - return &HarnessMiner{ - T: t, - Harness: miner, - runCtx: ctxt, - cancel: cancel, - logPath: baseLogPath, - logFilename: logFilename, - } -} - -// saveLogs copies the node logs and save it to the file specified by -// h.logFilename. -func (h *HarnessMiner) saveLogs() { - // After shutting down the miner, we'll make a copy of the log files - // before deleting the temporary log dir. - path := fmt.Sprintf("%s/%s", h.logPath, harnessNetParams.Name) - files, err := os.ReadDir(path) - require.NoError(h, err, "unable to read log directory") - - for _, file := range files { - newFilename := strings.Replace( - file.Name(), "btcd.log", h.logFilename, 1, - ) - copyPath := fmt.Sprintf("%s/../%s", h.logPath, newFilename) - - logFile := fmt.Sprintf("%s/%s", path, file.Name()) - err := CopyFile(filepath.Clean(copyPath), logFile) - require.NoError(h, err, "unable to copy file") - } - - err = os.RemoveAll(h.logPath) - require.NoErrorf(h, err, "cannot remove dir %s", h.logPath) -} - -// Stop shuts down the miner and saves its logs. -func (h *HarnessMiner) Stop() { - h.cancel() - require.NoError(h, h.TearDown(), "tear down miner got error") - h.saveLogs() -} - -// GetBestBlock makes a RPC request to miner and asserts. -func (h *HarnessMiner) GetBestBlock() (*chainhash.Hash, int32) { - blockHash, height, err := h.Client.GetBestBlock() - require.NoError(h, err, "failed to GetBestBlock") - - return blockHash, height -} - -// GetRawMempool makes a RPC call to the miner's GetRawMempool and -// asserts. -func (h *HarnessMiner) GetRawMempool() []*chainhash.Hash { - mempool, err := h.Client.GetRawMempool() - require.NoError(h, err, "unable to get mempool") - - return mempool +// Miner returns the miner instance. +// +// NOTE: Caller should keep in mind that when using this private instance, +// certain states won't be managed by the HarnessTest anymore. For instance, +// when mining directly, the nodes managed by the HarnessTest can be out of +// sync, and the `HarnessTest.CurrentHeight()` won't be accurate. +func (h *HarnessTest) Miner() *miner.HarnessMiner { + return h.miner } -// GenerateBlocks mine 'num' of blocks and returns them. -func (h *HarnessMiner) GenerateBlocks(num uint32) []*chainhash.Hash { - blockHashes, err := h.Client.Generate(num) - require.NoError(h, err, "unable to generate blocks") - require.Len(h, blockHashes, int(num), "wrong num of blocks generated") - - return blockHashes -} +// MineBlocks mines blocks and asserts all active nodes have synced to the +// chain. It assumes no txns are expected in the blocks. +// +// NOTE: Use `MineBlocksAndAssertNumTxes` if you expect txns in the blocks. Use +// `MineEmptyBlocks` if you want to make sure that txns stay unconfirmed. +func (h *HarnessTest) MineBlocks(num int) { + require.Less(h, num, maxBlocksAllowed, "too many blocks to mine") -// GetBlock gets a block using its block hash. -func (h *HarnessMiner) GetBlock(blockHash *chainhash.Hash) *wire.MsgBlock { - block, err := h.Client.GetBlock(blockHash) - require.NoError(h, err, "unable to get block") + // Update the harness's current height. + defer h.updateCurrentHeight() - return block -} + // Mine num of blocks. + for i := 0; i < num; i++ { + block := h.miner.MineBlocks(1)[0] -// MineBlocks mine 'num' of blocks and check that blocks are present in -// node blockchain. -func (h *HarnessMiner) MineBlocks(num uint32) []*wire.MsgBlock { - blocks := make([]*wire.MsgBlock, num) + // Check the block doesn't have any txns except the coinbase. + if len(block.Transactions) <= 1 { + // Make sure all the active nodes are synced. + h.AssertActiveNodesSyncedTo(block) - blockHashes := h.GenerateBlocks(num) + // Mine the next block. + continue + } - for i, blockHash := range blockHashes { - block := h.GetBlock(blockHash) - blocks[i] = block - } + // Create a detailed description. + desc := fmt.Sprintf("block %v has %d txns:\n", + block.BlockHash(), len(block.Transactions)-1) - return blocks -} + // Print all the txns except the coinbase. + for _, tx := range block.Transactions { + if blockchain.IsCoinBaseTx(tx) { + continue + } -// AssertNumTxsInMempool polls until finding the desired number of transactions -// in the provided miner's mempool. It will asserrt if this number is not met -// after the given timeout. -func (h *HarnessMiner) AssertNumTxsInMempool(n int) []*chainhash.Hash { - var ( - mem []*chainhash.Hash - err error - ) - - err = wait.NoError(func() error { - // We require the RPC call to be succeeded and won't wait for - // it as it's an unexpected behavior. - mem = h.GetRawMempool() - if len(mem) == n { - return nil + desc += fmt.Sprintf("%v\n", tx.TxHash()) } - return fmt.Errorf("want %v, got %v in mempool: %v", - n, len(mem), mem) - }, wait.MinerMempoolTimeout) - require.NoError(h, err, "assert tx in mempool timeout") + desc += "Consider using `MineBlocksAndAssertNumTxes` if you " + + "expect txns, or `MineEmptyBlocks` if you want to " + + "keep the txns unconfirmed." - return mem + // Raise an error if the block has txns. + require.Fail(h, "MineBlocks", desc) + } } -// AssertTxInBlock asserts that a given txid can be found in the passed block. -func (h *HarnessMiner) AssertTxInBlock(block *wire.MsgBlock, - txid *chainhash.Hash) { +// MineEmptyBlocks mines a given number of empty blocks. +// +// NOTE: this differs from miner's `MineEmptyBlocks` as it requires the nodes +// to be synced. +func (h *HarnessTest) MineEmptyBlocks(num int) []*wire.MsgBlock { + require.Less(h, num, maxBlocksAllowed, "too many blocks to mine") - blockTxes := make([]chainhash.Hash, 0) + // Update the harness's current height. + defer h.updateCurrentHeight() - for _, tx := range block.Transactions { - sha := tx.TxHash() - blockTxes = append(blockTxes, sha) + blocks := h.miner.MineEmptyBlocks(num) - if bytes.Equal(txid[:], sha[:]) { - return - } - } + // Finally, make sure all the active nodes are synced. + h.AssertActiveNodesSynced() - require.Failf(h, "tx was not included in block", "tx:%v, block has:%v", - txid, blockTxes) + return blocks } -// MineBlocksAndAssertNumTxes mine 'num' of blocks and check that blocks are -// present in node blockchain. numTxs should be set to the number of -// transactions (excluding the coinbase) we expect to be included in the first -// mined block. -func (h *HarnessMiner) MineBlocksAndAssertNumTxes(num uint32, +// MineBlocksAndAssertNumTxes mines blocks and asserts the number of +// transactions are found in the first block. It also asserts all active nodes +// have synced to the chain. +// +// NOTE: this differs from miner's `MineBlocks` as it requires the nodes to be +// synced. +func (h *HarnessTest) MineBlocksAndAssertNumTxes(num uint32, numTxs int) []*wire.MsgBlock { + // Update the harness's current height. + defer h.updateCurrentHeight() + // If we expect transactions to be included in the blocks we'll mine, // we wait here until they are seen in the miner's mempool. txids := h.AssertNumTxsInMempool(numTxs) // Mine blocks. - blocks := h.MineBlocks(num) + blocks := h.miner.MineBlocks(num) + + // Assert that all the transactions were included in the first block. + for _, txid := range txids { + h.miner.AssertTxInBlock(blocks[0], txid) + } - // Finally, assert that all the transactions were included in the first - // block. + // Make sure the mempool has been updated. for _, txid := range txids { - h.AssertTxInBlock(blocks[0], txid) + h.miner.AssertTxNotInMempool(*txid) } + // Finally, make sure all the active nodes are synced. + bestBlock := blocks[len(blocks)-1] + h.AssertActiveNodesSyncedTo(bestBlock) + return blocks } -// GetRawTransaction makes a RPC call to the miner's GetRawTransaction and -// asserts. -func (h *HarnessMiner) GetRawTransaction(txid *chainhash.Hash) *btcutil.Tx { - tx, err := h.Client.GetRawTransaction(txid) - require.NoErrorf(h, err, "failed to get raw tx: %v", txid) - return tx +// ConnectMiner connects the miner with the chain backend in the network. +func (h *HarnessTest) ConnectMiner() { + err := h.manager.chainBackend.ConnectMiner() + require.NoError(h, err, "failed to connect miner") } -// GetRawTransactionVerbose makes a RPC call to the miner's -// GetRawTransactionVerbose and asserts. -func (h *HarnessMiner) GetRawTransactionVerbose( - txid *chainhash.Hash) *btcjson.TxRawResult { - - tx, err := h.Client.GetRawTransactionVerbose(txid) - require.NoErrorf(h, err, "failed to get raw tx verbose: %v", txid) - return tx +// DisconnectMiner removes the connection between the miner and the chain +// backend in the network. +func (h *HarnessTest) DisconnectMiner() { + err := h.manager.chainBackend.DisconnectMiner() + require.NoError(h, err, "failed to disconnect miner") } -// AssertTxInMempool asserts a given transaction can be found in the mempool. -func (h *HarnessMiner) AssertTxInMempool(txid *chainhash.Hash) *wire.MsgTx { - var msgTx *wire.MsgTx +// cleanMempool mines blocks till the mempool is empty and asserts all active +// nodes have synced to the chain. +func (h *HarnessTest) cleanMempool() { + _, startHeight := h.GetBestBlock() + // Mining the blocks slow to give `lnd` more time to sync. + var bestBlock *wire.MsgBlock err := wait.NoError(func() error { - // We require the RPC call to be succeeded and won't wait for - // it as it's an unexpected behavior. - mempool := h.GetRawMempool() - - if len(mempool) == 0 { - return fmt.Errorf("empty mempool") - } + // If mempool is empty, exit. + mem := h.miner.GetRawMempool() + if len(mem) == 0 { + _, height := h.GetBestBlock() + h.Logf("Mined %d blocks when cleanup the mempool", + height-startHeight) - for _, memTx := range mempool { - // Check the values are equal. - if *memTx == *txid { - return nil - } + return nil } - return fmt.Errorf("txid %v not found in mempool: %v", txid, - mempool) - }, wait.MinerMempoolTimeout) + // Otherwise mine a block. + blocks := h.miner.MineBlocksSlow(1) + bestBlock = blocks[len(blocks)-1] - require.NoError(h, err, "timeout checking mempool") + // Make sure all the active nodes are synced. + h.AssertActiveNodesSyncedTo(bestBlock) - return msgTx + return fmt.Errorf("still have %d txes in mempool", len(mem)) + }, wait.MinerMempoolTimeout) + require.NoError(h, err, "timeout cleaning up mempool") } -// AssertTxNotInMempool asserts a given transaction cannot be found in the -// mempool. It assumes the mempool is not empty. +// mineTillForceCloseResolved asserts that the number of pending close channels +// are zero. Each time it checks, a new block is mined using MineBlocksSlow to +// give the node some time to catch up the chain. // -// NOTE: this should be used after `AssertTxInMempool` to ensure the tx has -// entered the mempool before. Otherwise it might give false positive and the -// tx may enter the mempool after the check. -func (h *HarnessMiner) AssertTxNotInMempool(txid chainhash.Hash) *wire.MsgTx { - var msgTx *wire.MsgTx +// NOTE: this method is a workaround to make sure we have a clean mempool at +// the end of a channel force closure. We cannot directly mine blocks and +// assert channels being fully closed because the subsystems in lnd don't share +// the same block height. This is especially the case when blocks are produced +// too fast. +// TODO(yy): remove this workaround when syncing blocks are unified in all the +// subsystems. +func (h *HarnessTest) mineTillForceCloseResolved(hn *node.HarnessNode) { + _, startHeight := h.GetBestBlock() err := wait.NoError(func() error { - // We require the RPC call to be succeeded and won't wait for - // it as it's an unexpected behavior. - mempool := h.GetRawMempool() - - for _, memTx := range mempool { - // Check the values are equal. - if txid.IsEqual(memTx) { - return fmt.Errorf("expect txid %v to be NOT "+ - "found in mempool", txid) - } - } - - return nil - }, wait.MinerMempoolTimeout) - - require.NoError(h, err, "timeout checking tx not in mempool") + resp := hn.RPC.PendingChannels() + total := len(resp.PendingForceClosingChannels) + if total != 0 { + h.MineBlocks(1) - return msgTx -} + return fmt.Errorf("expected num of pending force " + + "close channel to be zero") + } -// SendOutputsWithoutChange uses the miner to send the given outputs using the -// specified fee rate and returns the txid. -func (h *HarnessMiner) SendOutputsWithoutChange(outputs []*wire.TxOut, - feeRate btcutil.Amount) *chainhash.Hash { + _, height := h.GetBestBlock() + h.Logf("Mined %d blocks while waiting for force closed "+ + "channel to be resolved", height-startHeight) - txid, err := h.Harness.SendOutputsWithoutChange( - outputs, feeRate, - ) - require.NoErrorf(h, err, "failed to send output") + return nil + }, DefaultTimeout) - return txid + require.NoErrorf(h, err, "assert force close resolved timeout") } -// CreateTransaction uses the miner to create a transaction using the given -// outputs using the specified fee rate and returns the transaction. -func (h *HarnessMiner) CreateTransaction(outputs []*wire.TxOut, - feeRate btcutil.Amount) *wire.MsgTx { - - tx, err := h.Harness.CreateTransaction(outputs, feeRate, false) - require.NoErrorf(h, err, "failed to create transaction") - - return tx +// AssertTxInMempool asserts a given transaction can be found in the mempool. +func (h *HarnessTest) AssertTxInMempool(txid *chainhash.Hash) *wire.MsgTx { + return h.miner.AssertTxInMempool(txid) } -// SendOutput creates, signs, and finally broadcasts a transaction spending -// the harness' available mature coinbase outputs to create the new output. -func (h *HarnessMiner) SendOutput(newOutput *wire.TxOut, - feeRate btcutil.Amount) *chainhash.Hash { - - hash, err := h.Harness.SendOutputs([]*wire.TxOut{newOutput}, feeRate) - require.NoErrorf(h, err, "failed to send outputs") - - return hash +// AssertTxNotInMempool asserts a given transaction cannot be found in the +// mempool. It assumes the mempool is not empty. +// +// NOTE: this should be used after `AssertTxInMempool` to ensure the tx has +// entered the mempool before. Otherwise it might give false positive and the +// tx may enter the mempool after the check. +func (h *HarnessTest) AssertTxNotInMempool(txid chainhash.Hash) *wire.MsgTx { + return h.miner.AssertTxNotInMempool(txid) } -// MineBlocksSlow mines 'num' of blocks. Between each mined block an artificial -// delay is introduced to give all network participants time to catch up. -func (h *HarnessMiner) MineBlocksSlow(num uint32) []*wire.MsgBlock { - blocks := make([]*wire.MsgBlock, num) - blockHashes := make([]*chainhash.Hash, 0, num) - - for i := uint32(0); i < num; i++ { - generatedHashes := h.GenerateBlocks(1) - blockHashes = append(blockHashes, generatedHashes...) - - time.Sleep(slowMineDelay) - } - - for i, blockHash := range blockHashes { - block, err := h.Client.GetBlock(blockHash) - require.NoError(h, err, "get blocks") - - blocks[i] = block - } - - return blocks +// AssertNumTxsInMempool polls until finding the desired number of transactions +// in the provided miner's mempool. It will asserrt if this number is not met +// after the given timeout. +func (h *HarnessTest) AssertNumTxsInMempool(n int) []*chainhash.Hash { + return h.miner.AssertNumTxsInMempool(n) } // AssertOutpointInMempool asserts a given outpoint can be found in the mempool. -func (h *HarnessMiner) AssertOutpointInMempool(op wire.OutPoint) *wire.MsgTx { - var msgTx *wire.MsgTx - - err := wait.NoError(func() error { - // We require the RPC call to be succeeded and won't wait for - // it as it's an unexpected behavior. - mempool := h.GetRawMempool() - - if len(mempool) == 0 { - return fmt.Errorf("empty mempool") - } - - for _, txid := range mempool { - // We don't use `ht.Miner.GetRawTransaction` which - // asserts a txid must be found. While iterating here, - // the actual mempool state might have been changed, - // causing a given txid being removed and cannot be - // found. For instance, the aggregation logic used in - // sweeping HTLC outputs will update the mempool by - // replacing the HTLC spending txes with a single one. - tx, err := h.Client.GetRawTransaction(txid) - if err != nil { - return err - } - - msgTx = tx.MsgTx() - for _, txIn := range msgTx.TxIn { - if txIn.PreviousOutPoint == op { - return nil - } - } - } - - return fmt.Errorf("outpoint %v not found in mempool", op) - }, wait.MinerMempoolTimeout) +func (h *HarnessTest) AssertOutpointInMempool(op wire.OutPoint) *wire.MsgTx { + return h.miner.AssertOutpointInMempool(op) +} - require.NoError(h, err, "timeout checking mempool") +// AssertTxInBlock asserts that a given txid can be found in the passed block. +func (h *HarnessTest) AssertTxInBlock(block *wire.MsgBlock, + txid *chainhash.Hash) { - return msgTx + h.miner.AssertTxInBlock(block, txid) } // GetNumTxsFromMempool polls until finding the desired number of transactions // in the miner's mempool and returns the full transactions to the caller. -func (h *HarnessMiner) GetNumTxsFromMempool(n int) []*wire.MsgTx { - txids := h.AssertNumTxsInMempool(n) - - var txes []*wire.MsgTx - for _, txid := range txids { - tx := h.GetRawTransaction(txid) - txes = append(txes, tx.MsgTx()) - } - - return txes +func (h *HarnessTest) GetNumTxsFromMempool(n int) []*wire.MsgTx { + return h.miner.GetNumTxsFromMempool(n) } -// NewMinerAddress creates a new address for the miner and asserts. -func (h *HarnessMiner) NewMinerAddress() btcutil.Address { - addr, err := h.NewAddress() - require.NoError(h, err, "failed to create new miner address") - return addr +// GetBestBlock makes a RPC request to miner and asserts. +func (h *HarnessTest) GetBestBlock() (*chainhash.Hash, int32) { + return h.miner.GetBestBlock() } -// MineBlocksWithTxes mines a single block to include the specifies -// transactions only. -func (h *HarnessMiner) MineBlockWithTxes(txes []*btcutil.Tx) *wire.MsgBlock { - var emptyTime time.Time - - // Generate a block. - b, err := h.GenerateAndSubmitBlock(txes, -1, emptyTime) - require.NoError(h, err, "unable to mine block") - - block, err := h.Client.GetBlock(b.Hash()) - require.NoError(h, err, "unable to get block") - - // Make sure the mempool has been updated. - for _, tx := range txes { - h.AssertTxNotInMempool(*tx.Hash()) - } - - return block +// MineBlockWithTx mines a single block to include the specifies tx only. +func (h *HarnessTest) MineBlockWithTx(tx *wire.MsgTx) *wire.MsgBlock { + return h.miner.MineBlockWithTx(tx) } -// MineBlocksWithTx mines a single block to include the specifies tx only. -func (h *HarnessMiner) MineBlockWithTx(tx *wire.MsgTx) *wire.MsgBlock { - var emptyTime time.Time - - txes := []*btcutil.Tx{btcutil.NewTx(tx)} - - // Generate a block. - b, err := h.GenerateAndSubmitBlock(txes, -1, emptyTime) - require.NoError(h, err, "unable to mine block") - - block, err := h.Client.GetBlock(b.Hash()) - require.NoError(h, err, "unable to get block") - - // Make sure the mempool has been updated. - h.AssertTxNotInMempool(tx.TxHash()) - - return block +// ConnectToMiner connects the miner to a temp miner. +func (h *HarnessTest) ConnectToMiner(tempMiner *miner.HarnessMiner) { + h.miner.ConnectMiner(tempMiner) } -// MineEmptyBlocks mines a given number of empty blocks. -func (h *HarnessMiner) MineEmptyBlocks(num int) []*wire.MsgBlock { - var emptyTime time.Time +// DisconnectFromMiner disconnects the miner from the temp miner. +func (h *HarnessTest) DisconnectFromMiner(tempMiner *miner.HarnessMiner) { + h.miner.DisconnectMiner(tempMiner) +} - blocks := make([]*wire.MsgBlock, num) - for i := 0; i < num; i++ { - // Generate an empty block. - b, err := h.GenerateAndSubmitBlock(nil, -1, emptyTime) - require.NoError(h, err, "unable to mine empty block") +// GetRawMempool makes a RPC call to the miner's GetRawMempool and +// asserts. +func (h *HarnessTest) GetRawMempool() []*chainhash.Hash { + return h.miner.GetRawMempool() +} - block := h.GetBlock(b.Hash()) - blocks[i] = block - } +// GetRawTransaction makes a RPC call to the miner's GetRawTransaction and +// asserts. +func (h *HarnessTest) GetRawTransaction(txid *chainhash.Hash) *btcutil.Tx { + return h.miner.GetRawTransaction(txid) +} - return blocks +// NewMinerAddress creates a new address for the miner and asserts. +func (h *HarnessTest) NewMinerAddress() btcutil.Address { + return h.miner.NewMinerAddress() } // SpawnTempMiner creates a temp miner and syncs it with the current miner. // Once miners are synced, the temp miner is disconnected from the original // miner and returned. -func (h *HarnessMiner) SpawnTempMiner() *HarnessMiner { - require := require.New(h.T) - - // Setup a temp miner. - tempLogDir := ".tempminerlogs" - logFilename := "output-temp_miner.log" - tempMiner := NewTempMiner(h.runCtx, h.T, tempLogDir, logFilename) - - // Make sure to clean the miner when the test ends. - h.T.Cleanup(tempMiner.Stop) +func (h *HarnessTest) SpawnTempMiner() *miner.HarnessMiner { + return h.miner.SpawnTempMiner() +} - // Setup the miner. - require.NoError(tempMiner.SetUp(false, 0), "unable to setup miner") +// CreateTransaction uses the miner to create a transaction using the given +// outputs using the specified fee rate and returns the transaction. +func (h *HarnessTest) CreateTransaction(outputs []*wire.TxOut, + feeRate btcutil.Amount) *wire.MsgTx { - // Connect the temp miner to the original miner. - err := h.Client.Node(btcjson.NConnect, tempMiner.P2PAddress(), &temp) - require.NoError(err, "unable to connect node") + return h.miner.CreateTransaction(outputs, feeRate) +} - // Sync the blocks. - nodeSlice := []*rpctest.Harness{h.Harness, tempMiner.Harness} - err = rpctest.JoinNodes(nodeSlice, rpctest.Blocks) - require.NoError(err, "unable to join node on blocks") +// SendOutputsWithoutChange uses the miner to send the given outputs using the +// specified fee rate and returns the txid. +func (h *HarnessTest) SendOutputsWithoutChange(outputs []*wire.TxOut, + feeRate btcutil.Amount) *chainhash.Hash { - // The two miners should be on the same block height. - h.AssertMinerBlockHeightDelta(tempMiner, 0) + return h.miner.SendOutputsWithoutChange(outputs, feeRate) +} - // Once synced, we now disconnect the temp miner so it'll be - // independent from the original miner. - err = h.Client.Node(btcjson.NDisconnect, tempMiner.P2PAddress(), &temp) - require.NoError(err, "unable to disconnect miners") +// AssertMinerBlockHeightDelta ensures that tempMiner is 'delta' blocks ahead +// of miner. +func (h *HarnessTest) AssertMinerBlockHeightDelta( + tempMiner *miner.HarnessMiner, delta int32) { - return tempMiner + h.miner.AssertMinerBlockHeightDelta(tempMiner, delta) } -// ConnectMiner connects the miner to a temp miner. -func (h *HarnessMiner) ConnectMiner(tempMiner *HarnessMiner) { - require := require.New(h.T) +// SendRawTransaction submits the encoded transaction to the server which will +// then relay it to the network. +func (h *HarnessTest) SendRawTransaction(tx *wire.MsgTx, + allowHighFees bool) (chainhash.Hash, error) { - // Connect the current miner to the temporary miner. - err := h.Client.Node(btcjson.NConnect, tempMiner.P2PAddress(), &temp) - require.NoError(err, "unable to connect temp miner") + txid, err := h.miner.Client.SendRawTransaction(tx, allowHighFees) + require.NoError(h, err) - nodes := []*rpctest.Harness{tempMiner.Harness, h.Harness} - err = rpctest.JoinNodes(nodes, rpctest.Blocks) - require.NoError(err, "unable to join node on blocks") + return *txid, nil } -// DisconnectMiner disconnects the miner from the temp miner. -func (h *HarnessMiner) DisconnectMiner(tempMiner *HarnessMiner) { - err := h.Client.Node(btcjson.NDisconnect, tempMiner.P2PAddress(), &temp) - require.NoError(h.T, err, "unable to disconnect temp miner") +// CurrentHeight returns the current block height. +func (h *HarnessTest) CurrentHeight() uint32 { + return h.currentHeight } -// AssertMinerBlockHeightDelta ensures that tempMiner is 'delta' blocks ahead -// of miner. -func (h *HarnessMiner) AssertMinerBlockHeightDelta(tempMiner *HarnessMiner, - delta int32) { - - // Ensure the chain lengths are what we expect. - err := wait.NoError(func() error { - _, tempMinerHeight, err := tempMiner.Client.GetBestBlock() - if err != nil { - return fmt.Errorf("unable to get current "+ - "blockheight %v", err) - } - - _, minerHeight, err := h.Client.GetBestBlock() - if err != nil { - return fmt.Errorf("unable to get current "+ - "blockheight %v", err) - } - - if tempMinerHeight != minerHeight+delta { - return fmt.Errorf("expected new miner(%d) to be %d "+ - "blocks ahead of original miner(%d)", - tempMinerHeight, delta, minerHeight) - } - - return nil - }, DefaultTimeout) - require.NoError(h.T, err, "failed to assert block height delta") +// updateCurrentHeight set the harness's current height to the best known +// height. +func (h *HarnessTest) updateCurrentHeight() { + _, height := h.GetBestBlock() + h.currentHeight = uint32(height) } diff --git a/lntest/harness_node_manager.go b/lntest/harness_node_manager.go index 3b0c412d97..90a74f75e2 100644 --- a/lntest/harness_node_manager.go +++ b/lntest/harness_node_manager.go @@ -8,6 +8,7 @@ import ( "testing" "github.com/lightningnetwork/lnd/lnrpc" + "github.com/lightningnetwork/lnd/lntest/miner" "github.com/lightningnetwork/lnd/lntest/node" "github.com/lightningnetwork/lnd/lntest/wait" ) @@ -88,7 +89,7 @@ func (nm *nodeManager) newNode(t *testing.T, name string, extraArgs []string, NativeSQL: nm.nativeSQL, NodeID: nm.nextNodeID(), LndBinary: nm.lndBinary, - NetParams: harnessNetParams, + NetParams: miner.HarnessNetParams, SkipUnlock: noAuth, } diff --git a/lntest/harness_setup.go b/lntest/harness_setup.go index 8aed3b880d..166880baec 100644 --- a/lntest/harness_setup.go +++ b/lntest/harness_setup.go @@ -6,6 +6,7 @@ import ( "testing" "github.com/btcsuite/btcd/integration/rpctest" + "github.com/lightningnetwork/lnd/lntest/miner" "github.com/lightningnetwork/lnd/lntest/node" "github.com/lightningnetwork/lnd/lntest/wait" "github.com/stretchr/testify/require" @@ -65,27 +66,27 @@ func SetupHarness(t *testing.T, binaryPath, dbBackendName string, // transactions on simnet to reject them. Transactions on the lightning network // should always be standard to get better guarantees of getting included in to // blocks. -func prepareMiner(ctxt context.Context, t *testing.T) *HarnessMiner { - miner := NewMiner(ctxt, t) +func prepareMiner(ctxt context.Context, t *testing.T) *miner.HarnessMiner { + m := miner.NewMiner(ctxt, t) // Before we start anything, we want to overwrite some of the // connection settings to make the tests more robust. We might need to // restart the miner while there are already blocks present, which will // take a bit longer than the 1 second the default settings amount to. // Doubling both values will give us retries up to 4 seconds. - miner.MaxConnRetries = rpctest.DefaultMaxConnectionRetries * 2 - miner.ConnectionRetryTimeout = rpctest.DefaultConnectionRetryTimeout * 2 + m.MaxConnRetries = rpctest.DefaultMaxConnectionRetries * 2 + m.ConnectionRetryTimeout = rpctest.DefaultConnectionRetryTimeout * 2 // Set up miner and connect chain backend to it. - require.NoError(t, miner.SetUp(true, 50)) - require.NoError(t, miner.Client.NotifyNewTransactions(false)) + require.NoError(t, m.SetUp(true, 50)) + require.NoError(t, m.Client.NotifyNewTransactions(false)) // Next mine enough blocks in order for segwit and the CSV package // soft-fork to activate on SimNet. - numBlocks := harnessNetParams.MinerConfirmationWindow * 2 - miner.GenerateBlocks(numBlocks) + numBlocks := miner.HarnessNetParams.MinerConfirmationWindow * 2 + m.GenerateBlocks(numBlocks) - return miner + return m } // prepareChainBackend creates a new chain backend. @@ -93,7 +94,7 @@ func prepareChainBackend(t *testing.T, minerAddr string) (node.BackendConfig, func()) { chainBackend, cleanUp, err := NewBackend( - minerAddr, harnessNetParams, + minerAddr, miner.HarnessNetParams, ) require.NoError(t, err, "new backend") diff --git a/lntest/miner/miner.go b/lntest/miner/miner.go new file mode 100644 index 0000000000..bc05f542fd --- /dev/null +++ b/lntest/miner/miner.go @@ -0,0 +1,602 @@ +package miner + +import ( + "bytes" + "context" + "fmt" + "os" + "path/filepath" + "strings" + "testing" + "time" + + "github.com/btcsuite/btcd/btcjson" + "github.com/btcsuite/btcd/btcutil" + "github.com/btcsuite/btcd/chaincfg" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/integration/rpctest" + "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/lntest/node" + "github.com/lightningnetwork/lnd/lntest/wait" + "github.com/stretchr/testify/require" +) + +const ( + // minerLogFilename is the default log filename for the miner node. + minerLogFilename = "output_btcd_miner.log" + + // minerLogDir is the default log dir for the miner node. + minerLogDir = ".minerlogs" + + // slowMineDelay defines a wait period between mining new blocks. + slowMineDelay = 100 * time.Millisecond +) + +var ( + HarnessNetParams = &chaincfg.RegressionNetParams + + // temp is used to signal we want to establish a temporary connection + // using the btcd Node API. + // + // NOTE: Cannot be const, since the node API expects a reference. + Temp = "temp" +) + +type HarnessMiner struct { + *testing.T + *rpctest.Harness + + // runCtx is a context with cancel method. It's used to signal when the + // node needs to quit, and used as the parent context when spawning + // children contexts for RPC requests. + runCtx context.Context //nolint:containedctx + cancel context.CancelFunc + + // logPath is the directory path of the miner's logs. + logPath string + + // logFilename is the saved log filename of the miner node. + logFilename string +} + +// NewMiner creates a new miner using btcd backend with the default log file +// dir and name. +func NewMiner(ctxt context.Context, t *testing.T) *HarnessMiner { + t.Helper() + return newMiner(ctxt, t, minerLogDir, minerLogFilename) +} + +// NewTempMiner creates a new miner using btcd backend with the specified log +// file dir and name. +func NewTempMiner(ctxt context.Context, t *testing.T, + tempDir, tempLogFilename string) *HarnessMiner { + + t.Helper() + + return newMiner(ctxt, t, tempDir, tempLogFilename) +} + +// newMiner creates a new miner using btcd's rpctest. +func newMiner(ctxb context.Context, t *testing.T, minerDirName, + logFilename string) *HarnessMiner { + + t.Helper() + + handler := &rpcclient.NotificationHandlers{} + btcdBinary := node.GetBtcdBinary() + baseLogPath := fmt.Sprintf("%s/%s", node.GetLogDir(), minerDirName) + + args := []string{ + "--rejectnonstd", + "--txindex", + "--nowinservice", + "--nobanning", + "--debuglevel=debug", + "--logdir=" + baseLogPath, + "--trickleinterval=100ms", + // Don't disconnect if a reply takes too long. + "--nostalldetect", + } + + miner, err := rpctest.New(HarnessNetParams, handler, args, btcdBinary) + require.NoError(t, err, "unable to create mining node") + + ctxt, cancel := context.WithCancel(ctxb) + + return &HarnessMiner{ + T: t, + Harness: miner, + runCtx: ctxt, + cancel: cancel, + logPath: baseLogPath, + logFilename: logFilename, + } +} + +// saveLogs copies the node logs and save it to the file specified by +// h.logFilename. +func (h *HarnessMiner) saveLogs() { + // After shutting down the miner, we'll make a copy of the log files + // before deleting the temporary log dir. + path := fmt.Sprintf("%s/%s", h.logPath, HarnessNetParams.Name) + files, err := os.ReadDir(path) + require.NoError(h, err, "unable to read log directory") + + for _, file := range files { + newFilename := strings.Replace( + file.Name(), "btcd.log", h.logFilename, 1, + ) + copyPath := fmt.Sprintf("%s/../%s", h.logPath, newFilename) + + logFile := fmt.Sprintf("%s/%s", path, file.Name()) + err := node.CopyFile(filepath.Clean(copyPath), logFile) + require.NoError(h, err, "unable to copy file") + } + + err = os.RemoveAll(h.logPath) + require.NoErrorf(h, err, "cannot remove dir %s", h.logPath) +} + +// Stop shuts down the miner and saves its logs. +func (h *HarnessMiner) Stop() { + h.cancel() + require.NoError(h, h.TearDown(), "tear down miner got error") + h.saveLogs() +} + +// GetBestBlock makes a RPC request to miner and asserts. +func (h *HarnessMiner) GetBestBlock() (*chainhash.Hash, int32) { + blockHash, height, err := h.Client.GetBestBlock() + require.NoError(h, err, "failed to GetBestBlock") + + return blockHash, height +} + +// GetRawMempool makes a RPC call to the miner's GetRawMempool and +// asserts. +func (h *HarnessMiner) GetRawMempool() []*chainhash.Hash { + mempool, err := h.Client.GetRawMempool() + require.NoError(h, err, "unable to get mempool") + + return mempool +} + +// GenerateBlocks mine 'num' of blocks and returns them. +func (h *HarnessMiner) GenerateBlocks(num uint32) []*chainhash.Hash { + blockHashes, err := h.Client.Generate(num) + require.NoError(h, err, "unable to generate blocks") + require.Len(h, blockHashes, int(num), "wrong num of blocks generated") + + return blockHashes +} + +// GetBlock gets a block using its block hash. +func (h *HarnessMiner) GetBlock(blockHash *chainhash.Hash) *wire.MsgBlock { + block, err := h.Client.GetBlock(blockHash) + require.NoError(h, err, "unable to get block") + + return block +} + +// MineBlocks mine 'num' of blocks and check that blocks are present in +// node blockchain. +func (h *HarnessMiner) MineBlocks(num uint32) []*wire.MsgBlock { + blocks := make([]*wire.MsgBlock, num) + + blockHashes := h.GenerateBlocks(num) + + for i, blockHash := range blockHashes { + block := h.GetBlock(blockHash) + blocks[i] = block + } + + return blocks +} + +// AssertNumTxsInMempool polls until finding the desired number of transactions +// in the provided miner's mempool. It will asserrt if this number is not met +// after the given timeout. +func (h *HarnessMiner) AssertNumTxsInMempool(n int) []*chainhash.Hash { + var ( + mem []*chainhash.Hash + err error + ) + + err = wait.NoError(func() error { + // We require the RPC call to be succeeded and won't wait for + // it as it's an unexpected behavior. + mem = h.GetRawMempool() + if len(mem) == n { + return nil + } + + return fmt.Errorf("want %v, got %v in mempool: %v", + n, len(mem), mem) + }, wait.MinerMempoolTimeout) + require.NoError(h, err, "assert tx in mempool timeout") + + return mem +} + +// AssertTxInBlock asserts that a given txid can be found in the passed block. +func (h *HarnessMiner) AssertTxInBlock(block *wire.MsgBlock, + txid *chainhash.Hash) { + + blockTxes := make([]chainhash.Hash, 0) + + for _, tx := range block.Transactions { + sha := tx.TxHash() + blockTxes = append(blockTxes, sha) + + if bytes.Equal(txid[:], sha[:]) { + return + } + } + + require.Failf(h, "tx was not included in block", "tx:%v, block has:%v", + txid, blockTxes) +} + +// MineBlocksAndAssertNumTxes mine 'num' of blocks and check that blocks are +// present in node blockchain. numTxs should be set to the number of +// transactions (excluding the coinbase) we expect to be included in the first +// mined block. +func (h *HarnessMiner) MineBlocksAndAssertNumTxes(num uint32, + numTxs int) []*wire.MsgBlock { + + // If we expect transactions to be included in the blocks we'll mine, + // we wait here until they are seen in the miner's mempool. + txids := h.AssertNumTxsInMempool(numTxs) + + // Mine blocks. + blocks := h.MineBlocks(num) + + // Finally, assert that all the transactions were included in the first + // block. + for _, txid := range txids { + h.AssertTxInBlock(blocks[0], txid) + } + + return blocks +} + +// GetRawTransaction makes a RPC call to the miner's GetRawTransaction and +// asserts. +func (h *HarnessMiner) GetRawTransaction(txid *chainhash.Hash) *btcutil.Tx { + tx, err := h.Client.GetRawTransaction(txid) + require.NoErrorf(h, err, "failed to get raw tx: %v", txid) + return tx +} + +// GetRawTransactionVerbose makes a RPC call to the miner's +// GetRawTransactionVerbose and asserts. +func (h *HarnessMiner) GetRawTransactionVerbose( + txid *chainhash.Hash) *btcjson.TxRawResult { + + tx, err := h.Client.GetRawTransactionVerbose(txid) + require.NoErrorf(h, err, "failed to get raw tx verbose: %v", txid) + return tx +} + +// AssertTxInMempool asserts a given transaction can be found in the mempool. +func (h *HarnessMiner) AssertTxInMempool(txid *chainhash.Hash) *wire.MsgTx { + var msgTx *wire.MsgTx + + err := wait.NoError(func() error { + // We require the RPC call to be succeeded and won't wait for + // it as it's an unexpected behavior. + mempool := h.GetRawMempool() + + if len(mempool) == 0 { + return fmt.Errorf("empty mempool") + } + + for _, memTx := range mempool { + // Check the values are equal. + if *memTx == *txid { + return nil + } + } + + return fmt.Errorf("txid %v not found in mempool: %v", txid, + mempool) + }, wait.MinerMempoolTimeout) + + require.NoError(h, err, "timeout checking mempool") + + return msgTx +} + +// AssertTxNotInMempool asserts a given transaction cannot be found in the +// mempool. It assumes the mempool is not empty. +// +// NOTE: this should be used after `AssertTxInMempool` to ensure the tx has +// entered the mempool before. Otherwise it might give false positive and the +// tx may enter the mempool after the check. +func (h *HarnessMiner) AssertTxNotInMempool(txid chainhash.Hash) *wire.MsgTx { + var msgTx *wire.MsgTx + + err := wait.NoError(func() error { + // We require the RPC call to be succeeded and won't wait for + // it as it's an unexpected behavior. + mempool := h.GetRawMempool() + + for _, memTx := range mempool { + // Check the values are equal. + if txid.IsEqual(memTx) { + return fmt.Errorf("expect txid %v to be NOT "+ + "found in mempool", txid) + } + } + + return nil + }, wait.MinerMempoolTimeout) + + require.NoError(h, err, "timeout checking tx not in mempool") + + return msgTx +} + +// SendOutputsWithoutChange uses the miner to send the given outputs using the +// specified fee rate and returns the txid. +func (h *HarnessMiner) SendOutputsWithoutChange(outputs []*wire.TxOut, + feeRate btcutil.Amount) *chainhash.Hash { + + txid, err := h.Harness.SendOutputsWithoutChange( + outputs, feeRate, + ) + require.NoErrorf(h, err, "failed to send output") + + return txid +} + +// CreateTransaction uses the miner to create a transaction using the given +// outputs using the specified fee rate and returns the transaction. +func (h *HarnessMiner) CreateTransaction(outputs []*wire.TxOut, + feeRate btcutil.Amount) *wire.MsgTx { + + tx, err := h.Harness.CreateTransaction(outputs, feeRate, false) + require.NoErrorf(h, err, "failed to create transaction") + + return tx +} + +// SendOutput creates, signs, and finally broadcasts a transaction spending +// the harness' available mature coinbase outputs to create the new output. +func (h *HarnessMiner) SendOutput(newOutput *wire.TxOut, + feeRate btcutil.Amount) *chainhash.Hash { + + hash, err := h.Harness.SendOutputs([]*wire.TxOut{newOutput}, feeRate) + require.NoErrorf(h, err, "failed to send outputs") + + return hash +} + +// MineBlocksSlow mines 'num' of blocks. Between each mined block an artificial +// delay is introduced to give all network participants time to catch up. +func (h *HarnessMiner) MineBlocksSlow(num uint32) []*wire.MsgBlock { + blocks := make([]*wire.MsgBlock, num) + blockHashes := make([]*chainhash.Hash, 0, num) + + for i := uint32(0); i < num; i++ { + generatedHashes := h.GenerateBlocks(1) + blockHashes = append(blockHashes, generatedHashes...) + + time.Sleep(slowMineDelay) + } + + for i, blockHash := range blockHashes { + block, err := h.Client.GetBlock(blockHash) + require.NoError(h, err, "get blocks") + + blocks[i] = block + } + + return blocks +} + +// AssertOutpointInMempool asserts a given outpoint can be found in the mempool. +func (h *HarnessMiner) AssertOutpointInMempool(op wire.OutPoint) *wire.MsgTx { + var msgTx *wire.MsgTx + + err := wait.NoError(func() error { + // We require the RPC call to be succeeded and won't wait for + // it as it's an unexpected behavior. + mempool := h.GetRawMempool() + + if len(mempool) == 0 { + return fmt.Errorf("empty mempool") + } + + for _, txid := range mempool { + // We don't use `ht.GetRawTransaction` which + // asserts a txid must be found. While iterating here, + // the actual mempool state might have been changed, + // causing a given txid being removed and cannot be + // found. For instance, the aggregation logic used in + // sweeping HTLC outputs will update the mempool by + // replacing the HTLC spending txes with a single one. + tx, err := h.Client.GetRawTransaction(txid) + if err != nil { + return err + } + + msgTx = tx.MsgTx() + for _, txIn := range msgTx.TxIn { + if txIn.PreviousOutPoint == op { + return nil + } + } + } + + return fmt.Errorf("outpoint %v not found in mempool", op) + }, wait.MinerMempoolTimeout) + + require.NoError(h, err, "timeout checking mempool") + + return msgTx +} + +// GetNumTxsFromMempool polls until finding the desired number of transactions +// in the miner's mempool and returns the full transactions to the caller. +func (h *HarnessMiner) GetNumTxsFromMempool(n int) []*wire.MsgTx { + txids := h.AssertNumTxsInMempool(n) + + var txes []*wire.MsgTx + for _, txid := range txids { + tx := h.GetRawTransaction(txid) + txes = append(txes, tx.MsgTx()) + } + + return txes +} + +// NewMinerAddress creates a new address for the miner and asserts. +func (h *HarnessMiner) NewMinerAddress() btcutil.Address { + addr, err := h.NewAddress() + require.NoError(h, err, "failed to create new miner address") + return addr +} + +// MineBlocksWithTxes mines a single block to include the specifies +// transactions only. +func (h *HarnessMiner) MineBlockWithTxes(txes []*btcutil.Tx) *wire.MsgBlock { + var emptyTime time.Time + + // Generate a block. + b, err := h.GenerateAndSubmitBlock(txes, -1, emptyTime) + require.NoError(h, err, "unable to mine block") + + block, err := h.Client.GetBlock(b.Hash()) + require.NoError(h, err, "unable to get block") + + // Make sure the mempool has been updated. + for _, tx := range txes { + h.AssertTxNotInMempool(*tx.Hash()) + } + + return block +} + +// MineBlocksWithTx mines a single block to include the specifies tx only. +func (h *HarnessMiner) MineBlockWithTx(tx *wire.MsgTx) *wire.MsgBlock { + var emptyTime time.Time + + txes := []*btcutil.Tx{btcutil.NewTx(tx)} + + // Generate a block. + b, err := h.GenerateAndSubmitBlock(txes, -1, emptyTime) + require.NoError(h, err, "unable to mine block") + + block, err := h.Client.GetBlock(b.Hash()) + require.NoError(h, err, "unable to get block") + + // Make sure the mempool has been updated. + h.AssertTxNotInMempool(tx.TxHash()) + + return block +} + +// MineEmptyBlocks mines a given number of empty blocks. +func (h *HarnessMiner) MineEmptyBlocks(num int) []*wire.MsgBlock { + var emptyTime time.Time + + blocks := make([]*wire.MsgBlock, num) + for i := 0; i < num; i++ { + // Generate an empty block. + b, err := h.GenerateAndSubmitBlock(nil, -1, emptyTime) + require.NoError(h, err, "unable to mine empty block") + + block := h.GetBlock(b.Hash()) + blocks[i] = block + } + + return blocks +} + +// SpawnTempMiner creates a temp miner and syncs it with the current miner. +// Once miners are synced, the temp miner is disconnected from the original +// miner and returned. +func (h *HarnessMiner) SpawnTempMiner() *HarnessMiner { + require := require.New(h.T) + + // Setup a temp miner. + tempLogDir := ".tempminerlogs" + logFilename := "output-temp_miner.log" + tempMiner := NewTempMiner(h.runCtx, h.T, tempLogDir, logFilename) + + // Make sure to clean the miner when the test ends. + h.T.Cleanup(tempMiner.Stop) + + // Setup the miner. + require.NoError(tempMiner.SetUp(false, 0), "unable to setup miner") + + // Connect the temp miner to the original miner. + err := h.Client.Node(btcjson.NConnect, tempMiner.P2PAddress(), &Temp) + require.NoError(err, "unable to connect node") + + // Sync the blocks. + nodeSlice := []*rpctest.Harness{h.Harness, tempMiner.Harness} + err = rpctest.JoinNodes(nodeSlice, rpctest.Blocks) + require.NoError(err, "unable to join node on blocks") + + // The two miners should be on the same block height. + h.AssertMinerBlockHeightDelta(tempMiner, 0) + + // Once synced, we now disconnect the temp miner so it'll be + // independent from the original miner. + err = h.Client.Node(btcjson.NDisconnect, tempMiner.P2PAddress(), &Temp) + require.NoError(err, "unable to disconnect miners") + + return tempMiner +} + +// ConnectMiner connects the miner to a temp miner. +func (h *HarnessMiner) ConnectMiner(tempMiner *HarnessMiner) { + require := require.New(h.T) + + // Connect the current miner to the temporary miner. + err := h.Client.Node(btcjson.NConnect, tempMiner.P2PAddress(), &Temp) + require.NoError(err, "unable to connect temp miner") + + nodes := []*rpctest.Harness{tempMiner.Harness, h.Harness} + err = rpctest.JoinNodes(nodes, rpctest.Blocks) + require.NoError(err, "unable to join node on blocks") +} + +// DisconnectMiner disconnects the miner from the temp miner. +func (h *HarnessMiner) DisconnectMiner(tempMiner *HarnessMiner) { + err := h.Client.Node(btcjson.NDisconnect, tempMiner.P2PAddress(), &Temp) + require.NoError(h.T, err, "unable to disconnect temp miner") +} + +// AssertMinerBlockHeightDelta ensures that tempMiner is 'delta' blocks ahead +// of miner. +func (h *HarnessMiner) AssertMinerBlockHeightDelta(tempMiner *HarnessMiner, + delta int32) { + + // Ensure the chain lengths are what we expect. + err := wait.NoError(func() error { + _, tempMinerHeight, err := tempMiner.Client.GetBestBlock() + if err != nil { + return fmt.Errorf("unable to get current "+ + "blockheight %v", err) + } + + _, minerHeight, err := h.Client.GetBestBlock() + if err != nil { + return fmt.Errorf("unable to get current "+ + "blockheight %v", err) + } + + if tempMinerHeight != minerHeight+delta { + return fmt.Errorf("expected new miner(%d) to be %d "+ + "blocks ahead of original miner(%d)", + tempMinerHeight, delta, minerHeight) + } + + return nil + }, wait.DefaultTimeout) + require.NoError(h.T, err, "failed to assert block height delta") +} diff --git a/lntest/utils.go b/lntest/utils.go index d230b6b611..d4ca705c31 100644 --- a/lntest/utils.go +++ b/lntest/utils.go @@ -53,10 +53,16 @@ func CopyFile(dest, src string) error { // errNumNotMatched is a helper method to return a nicely formatted error. func errNumNotMatched(name string, subject string, - want, got, total, old int) error { + want, got, total, old int, desc ...any) error { - return fmt.Errorf("%s: assert %s failed: want %d, got: %d, total: "+ + err := fmt.Errorf("%s: assert %s failed: want %d, got: %d, total: "+ "%d, previously had: %d", name, subject, want, got, total, old) + + if len(desc) > 0 { + err = fmt.Errorf("%w, desc: %v", err, desc) + } + + return err } // parseDerivationPath parses a path in the form of m/x'/y'/z'/a/b into a slice diff --git a/routing/chainview/bitcoind.go b/routing/chainview/bitcoind.go index 337f18262a..56e30c24a6 100644 --- a/routing/chainview/bitcoind.go +++ b/routing/chainview/bitcoind.go @@ -125,6 +125,9 @@ func (b *BitcoindFilteredChainView) Start() error { // // NOTE: This is part of the FilteredChainView interface. func (b *BitcoindFilteredChainView) Stop() error { + log.Debug("BitcoindFilteredChainView stopping") + defer log.Debug("BitcoindFilteredChainView stopped") + // Already shutting down? if atomic.AddInt32(&b.stopped, 1) != 1 { return nil @@ -136,8 +139,6 @@ func (b *BitcoindFilteredChainView) Stop() error { b.blockQueue.Stop() - log.Infof("FilteredChainView stopping") - close(b.quit) b.wg.Wait() diff --git a/routing/chainview/btcd.go b/routing/chainview/btcd.go index 876940693d..54c2ee4db1 100644 --- a/routing/chainview/btcd.go +++ b/routing/chainview/btcd.go @@ -135,6 +135,9 @@ func (b *BtcdFilteredChainView) Start() error { // // NOTE: This is part of the FilteredChainView interface. func (b *BtcdFilteredChainView) Stop() error { + log.Debug("BtcdFilteredChainView stopping") + defer log.Debug("BtcdFilteredChainView stopped") + // Already shutting down? if atomic.AddInt32(&b.stopped, 1) != 1 { return nil @@ -146,8 +149,6 @@ func (b *BtcdFilteredChainView) Stop() error { b.blockQueue.Stop() - log.Infof("FilteredChainView stopping") - close(b.quit) b.wg.Wait() diff --git a/routing/chainview/neutrino.go b/routing/chainview/neutrino.go index 6134cf991e..21f04ae95b 100644 --- a/routing/chainview/neutrino.go +++ b/routing/chainview/neutrino.go @@ -135,13 +135,14 @@ func (c *CfFilteredChainView) Start() error { // // NOTE: This is part of the FilteredChainView interface. func (c *CfFilteredChainView) Stop() error { + log.Debug("CfFilteredChainView stopping") + defer log.Debug("CfFilteredChainView stopped") + // Already shutting down? if atomic.AddInt32(&c.stopped, 1) != 1 { return nil } - log.Infof("FilteredChainView stopping") - close(c.quit) c.blockQueue.Stop() c.wg.Wait() diff --git a/routing/missioncontrol_store.go b/routing/missioncontrol_store.go index e149e85458..e07a46136e 100644 --- a/routing/missioncontrol_store.go +++ b/routing/missioncontrol_store.go @@ -303,7 +303,11 @@ func (b *missionControlStore) run() { // channel needs to be drained appropriately. This could happen // if the flushInterval is very small (e.g. 1 nanosecond). if !timer.Stop() { - <-timer.C + select { + case <-timer.C: + case <-b.done: + log.Debugf("Stopping mission control store") + } } for { @@ -335,7 +339,12 @@ func (b *missionControlStore) run() { case <-b.done: // Release the timer's resources. if !timer.Stop() { - <-timer.C + select { + case <-timer.C: + case <-b.done: + log.Debugf("Mission control " + + "store stopped") + } } return }