Merge pull request #8892 from lightningnetwork/yy-itest-miner

Beat [0/4]: improve itest miner
This commit is contained in:
Oliver Gugger 2024-07-23 12:12:36 -06:00 committed by GitHub
commit f27f9f2799
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
43 changed files with 1274 additions and 1018 deletions

View file

@ -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()

View file

@ -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

View file

@ -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
}

View file

@ -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.

View file

@ -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.

View file

@ -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{

View file

@ -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)

View file

@ -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)

View file

@ -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()
}

View file

@ -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)

View file

@ -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)

View file

@ -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,

View file

@ -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 {

View file

@ -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)
ht.AssertOutpointInMempool(htlcOutpoint)
// Mine a block to confirm Carol's direct spend tx.
ht.MineBlocks(1)
// 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

View file

@ -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))

View file

@ -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)

View file

@ -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)
}

View file

@ -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)
}

View file

@ -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.

View file

@ -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

View file

@ -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(

View file

@ -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.

View file

@ -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

View file

@ -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)

View file

@ -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{

View file

@ -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.

View file

@ -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

View file

@ -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)
}

View file

@ -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(

View file

@ -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",

View file

@ -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()

View file

@ -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.

View file

@ -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")
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 && !h.IsNeutrinoBackend() {
expectedBalance := btcutil.Amount(
initialBalance.UnconfirmedBalance,
) + amt
h.WaitForBalanceUnconfirmed(target, expectedBalance)
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
}

View file

@ -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.

View file

@ -1,311 +1,208 @@
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
// 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
}
// 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)
}
// 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")
// 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 {
// Update the harness's current height.
defer h.updateCurrentHeight()
t.Helper()
// Mine num of blocks.
for i := 0; i < num; i++ {
block := h.miner.MineBlocks(1)[0]
return newMiner(ctxt, t, tempDir, tempLogFilename)
}
// 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)
// newMiner creates a new miner using btcd's rpctest.
func newMiner(ctxb context.Context, t *testing.T, minerDirName,
logFilename string) *HarnessMiner {
// Mine the next block.
continue
}
t.Helper()
// Create a detailed description.
desc := fmt.Sprintf("block %v has %d txns:\n",
block.BlockHash(), len(block.Transactions)-1)
handler := &rpcclient.NotificationHandlers{}
btcdBinary := node.GetBtcdBinary()
baseLogPath := fmt.Sprintf("%s/%s", node.GetLogDir(), minerDirName)
// Print all the txns except the coinbase.
for _, tx := range block.Transactions {
if blockchain.IsCoinBaseTx(tx) {
continue
}
args := []string{
"--rejectnonstd",
"--txindex",
"--nowinservice",
"--nobanning",
"--debuglevel=debug",
"--logdir=" + baseLogPath,
"--trickleinterval=100ms",
// Don't disconnect if a reply takes too long.
"--nostalldetect",
}
desc += fmt.Sprintf("%v\n", tx.TxHash())
}
miner, err := rpctest.New(harnessNetParams, handler, args, btcdBinary)
require.NoError(t, err, "unable to create mining node")
desc += "Consider using `MineBlocksAndAssertNumTxes` if you " +
"expect txns, or `MineEmptyBlocks` if you want to " +
"keep the txns unconfirmed."
ctxt, cancel := context.WithCancel(ctxb)
return &HarnessMiner{
T: t,
Harness: miner,
runCtx: ctxt,
cancel: cancel,
logPath: baseLogPath,
logFilename: logFilename,
// Raise an error if the block has txns.
require.Fail(h, "MineBlocks", desc)
}
}
// 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")
// 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")
for _, file := range files {
newFilename := strings.Replace(
file.Name(), "btcd.log", h.logFilename, 1,
)
copyPath := fmt.Sprintf("%s/../%s", h.logPath, newFilename)
// Update the harness's current height.
defer h.updateCurrentHeight()
logFile := fmt.Sprintf("%s/%s", path, file.Name())
err := CopyFile(filepath.Clean(copyPath), logFile)
require.NoError(h, err, "unable to copy file")
}
blocks := h.miner.MineEmptyBlocks(num)
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
}
// Finally, make sure all the active nodes are synced.
h.AssertActiveNodesSynced()
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,
// 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)
// Finally, assert that all the transactions were included in the first
// block.
// Assert that all the transactions were included in the first block.
for _, txid := range txids {
h.AssertTxInBlock(blocks[0], txid)
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
}
// 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 {
// 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")
}
tx, err := h.Client.GetRawTransactionVerbose(txid)
require.NoErrorf(h, err, "failed to get raw tx verbose: %v", txid)
return tx
// 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 {
// 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)
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")
}
// 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.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.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")
}
// 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
func (h *HarnessTest) AssertTxInMempool(txid *chainhash.Hash) *wire.MsgTx {
return h.miner.AssertTxInMempool(txid)
}
// AssertTxNotInMempool asserts a given transaction cannot be found in the
@ -314,289 +211,122 @@ func (h *HarnessMiner) AssertTxInMempool(txid *chainhash.Hash) *wire.MsgTx {
// 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
func (h *HarnessTest) AssertTxNotInMempool(txid chainhash.Hash) *wire.MsgTx {
return h.miner.AssertTxNotInMempool(txid)
}
// 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
// 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
func (h *HarnessTest) AssertOutpointInMempool(op wire.OutPoint) *wire.MsgTx {
return h.miner.AssertOutpointInMempool(op)
}
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()
// AssertTxInBlock asserts that a given txid can be found in the passed block.
func (h *HarnessTest) AssertTxInBlock(block *wire.MsgBlock,
txid *chainhash.Hash) {
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)
require.NoError(h, err, "timeout checking mempool")
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)
func (h *HarnessTest) GetNumTxsFromMempool(n int) []*wire.MsgTx {
return h.miner.GetNumTxsFromMempool(n)
}
var txes []*wire.MsgTx
for _, txid := range txids {
tx := h.GetRawTransaction(txid)
txes = append(txes, tx.MsgTx())
}
// GetBestBlock makes a RPC request to miner and asserts.
func (h *HarnessTest) GetBestBlock() (*chainhash.Hash, int32) {
return h.miner.GetBestBlock()
}
return txes
// 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)
}
// ConnectToMiner connects the miner to a temp miner.
func (h *HarnessTest) ConnectToMiner(tempMiner *miner.HarnessMiner) {
h.miner.ConnectMiner(tempMiner)
}
// DisconnectFromMiner disconnects the miner from the temp miner.
func (h *HarnessTest) DisconnectFromMiner(tempMiner *miner.HarnessMiner) {
h.miner.DisconnectMiner(tempMiner)
}
// GetRawMempool makes a RPC call to the miner's GetRawMempool and
// asserts.
func (h *HarnessTest) GetRawMempool() []*chainhash.Hash {
return h.miner.GetRawMempool()
}
// 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)
}
// 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
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)
// 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
func (h *HarnessTest) SpawnTempMiner() *miner.HarnessMiner {
return h.miner.SpawnTempMiner()
}
// ConnectMiner connects the miner to a temp miner.
func (h *HarnessMiner) ConnectMiner(tempMiner *HarnessMiner) {
require := require.New(h.T)
// 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 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")
return h.miner.CreateTransaction(outputs, feeRate)
}
// 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")
// 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 {
return h.miner.SendOutputsWithoutChange(outputs, feeRate)
}
// AssertMinerBlockHeightDelta ensures that tempMiner is 'delta' blocks ahead
// of miner.
func (h *HarnessMiner) AssertMinerBlockHeightDelta(tempMiner *HarnessMiner,
delta int32) {
func (h *HarnessTest) AssertMinerBlockHeightDelta(
tempMiner *miner.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")
h.miner.AssertMinerBlockHeightDelta(tempMiner, delta)
}
// 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) {
txid, err := h.miner.Client.SendRawTransaction(tx, allowHighFees)
require.NoError(h, err)
return *txid, nil
}
// CurrentHeight returns the current block height.
func (h *HarnessTest) CurrentHeight() uint32 {
return h.currentHeight
}
// updateCurrentHeight set the harness's current height to the best known
// height.
func (h *HarnessTest) updateCurrentHeight() {
_, height := h.GetBestBlock()
h.currentHeight = uint32(height)
}

View file

@ -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,
}

View file

@ -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")

602
lntest/miner/miner.go Normal file
View file

@ -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")
}

View file

@ -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

View file

@ -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()

View file

@ -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()

View file

@ -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()

View file

@ -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
}