lntest: allow the main test files to be buildable w/o the rpctest build tag
In this commit, we modify our build tag set up to allow the main test files to be buildable w/o the current rpctest tag. We do this so that those of us that use extensions which will compile live files like vim-go can once again fix compile errors as we go in our editors. In order to do this, we now make an external `testsCases` variable, and have two variants: one that's empty (no build tag), and one that's fully populated with all our tests (build tag active). As a result, the main file will now always build regardless of if the build tag is active or not, but we'll only actually execute tests if the `testCases` variable has been populated. As sample run w/ the tag off: ``` === RUN TestLightningNetworkDaemon --- PASS: TestLightningNetworkDaemon (0.00s) PASS ok github.com/lightningnetwork/lnd/lntest/itest 0.051s ```
This commit is contained in:
parent
acd615aca4
commit
c769247198
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@ -24,7 +22,6 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/blockchain"
|
"github.com/btcsuite/btcd/blockchain"
|
||||||
"github.com/btcsuite/btcd/btcjson"
|
"github.com/btcsuite/btcd/btcjson"
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/integration/rpctest"
|
"github.com/btcsuite/btcd/integration/rpctest"
|
||||||
"github.com/btcsuite/btcd/rpcclient"
|
"github.com/btcsuite/btcd/rpcclient"
|
||||||
@ -55,66 +52,6 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
harnessNetParams = &chaincfg.RegressionNetParams
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
testFeeBase = 1e+6
|
|
||||||
defaultCSV = lntest.DefaultCSV
|
|
||||||
defaultTimeout = lntest.DefaultTimeout
|
|
||||||
minerMempoolTimeout = lntest.MinerMempoolTimeout
|
|
||||||
channelOpenTimeout = lntest.ChannelOpenTimeout
|
|
||||||
channelCloseTimeout = lntest.ChannelCloseTimeout
|
|
||||||
itestLndBinary = "../../lnd-itest"
|
|
||||||
anchorSize = 330
|
|
||||||
noFeeLimitMsat = math.MaxInt64
|
|
||||||
)
|
|
||||||
|
|
||||||
func assertTxInBlock(t *harnessTest, block *wire.MsgBlock, txid *chainhash.Hash) {
|
|
||||||
for _, tx := range block.Transactions {
|
|
||||||
sha := tx.TxHash()
|
|
||||||
if bytes.Equal(txid[:], sha[:]) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Fatalf("tx was not included in block")
|
|
||||||
}
|
|
||||||
|
|
||||||
func assertWalletUnspent(t *harnessTest, node *lntest.HarnessNode, out *lnrpc.OutPoint) {
|
|
||||||
t.t.Helper()
|
|
||||||
|
|
||||||
err := wait.NoError(func() error {
|
|
||||||
ctxt, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
|
||||||
defer cancel()
|
|
||||||
unspent, err := node.ListUnspent(ctxt, &lnrpc.ListUnspentRequest{})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
err = errors.New("tx with wanted txhash never found")
|
|
||||||
for _, utxo := range unspent.Utxos {
|
|
||||||
if !bytes.Equal(utxo.Outpoint.TxidBytes, out.TxidBytes) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
err = errors.New("wanted output is not a wallet utxo")
|
|
||||||
if utxo.Outpoint.OutputIndex != out.OutputIndex {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return err
|
|
||||||
}, defaultTimeout)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("outpoint %s not unspent by %s's wallet: %v", out,
|
|
||||||
node.Name(), err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func rpcPointToWirePoint(t *harnessTest, chanPoint *lnrpc.ChannelPoint) wire.OutPoint {
|
func rpcPointToWirePoint(t *harnessTest, chanPoint *lnrpc.ChannelPoint) wire.OutPoint {
|
||||||
txid, err := lnd.GetChanPointFundingTxid(chanPoint)
|
txid, err := lnd.GetChanPointFundingTxid(chanPoint)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -127,50 +64,6 @@ func rpcPointToWirePoint(t *harnessTest, chanPoint *lnrpc.ChannelPoint) wire.Out
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mineBlocks 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 mineBlocks(t *harnessTest, net *lntest.NetworkHarness,
|
|
||||||
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.
|
|
||||||
var txids []*chainhash.Hash
|
|
||||||
var err error
|
|
||||||
if numTxs > 0 {
|
|
||||||
txids, err = waitForNTxsInMempool(
|
|
||||||
net.Miner.Node, numTxs, minerMempoolTimeout,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to find txns in mempool: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
blocks := make([]*wire.MsgBlock, num)
|
|
||||||
|
|
||||||
blockHashes, err := net.Miner.Node.Generate(num)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to generate blocks: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, blockHash := range blockHashes {
|
|
||||||
block, err := net.Miner.Node.GetBlock(blockHash)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to get block: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
blocks[i] = block
|
|
||||||
}
|
|
||||||
|
|
||||||
// Finally, assert that all the transactions were included in the first
|
|
||||||
// block.
|
|
||||||
for _, txid := range txids {
|
|
||||||
assertTxInBlock(t, blocks[0], txid)
|
|
||||||
}
|
|
||||||
|
|
||||||
return blocks
|
|
||||||
}
|
|
||||||
|
|
||||||
// openChannelStream blocks until an OpenChannel request for a channel funding
|
// openChannelStream blocks until an OpenChannel request for a channel funding
|
||||||
// by alice succeeds. If it does, a stream client is returned to receive events
|
// by alice succeeds. If it does, a stream client is returned to receive events
|
||||||
// about the opening channel.
|
// about the opening channel.
|
||||||
@ -774,11 +667,6 @@ func getChanInfo(ctx context.Context, node *lntest.HarnessNode) (
|
|||||||
return channelInfo.Channels[0], nil
|
return channelInfo.Channels[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
AddrTypeWitnessPubkeyHash = lnrpc.AddressType_WITNESS_PUBKEY_HASH
|
|
||||||
AddrTypeNestedPubkeyHash = lnrpc.AddressType_NESTED_PUBKEY_HASH
|
|
||||||
)
|
|
||||||
|
|
||||||
// testGetRecoveryInfo checks whether lnd gives the right information about
|
// testGetRecoveryInfo checks whether lnd gives the right information about
|
||||||
// the wallet recovery process.
|
// the wallet recovery process.
|
||||||
func testGetRecoveryInfo(net *lntest.NetworkHarness, t *harnessTest) {
|
func testGetRecoveryInfo(net *lntest.NetworkHarness, t *harnessTest) {
|
||||||
@ -7460,50 +7348,6 @@ func testMaxPendingChannels(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// waitForTxInMempool polls until finding one transaction in the provided
|
|
||||||
// miner's mempool. An error is returned if *one* transaction isn't found within
|
|
||||||
// the given timeout.
|
|
||||||
func waitForTxInMempool(miner *rpcclient.Client,
|
|
||||||
timeout time.Duration) (*chainhash.Hash, error) {
|
|
||||||
|
|
||||||
txs, err := waitForNTxsInMempool(miner, 1, timeout)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return txs[0], err
|
|
||||||
}
|
|
||||||
|
|
||||||
// waitForNTxsInMempool polls until finding the desired number of transactions
|
|
||||||
// in the provided miner's mempool. An error is returned if this number is not
|
|
||||||
// met after the given timeout.
|
|
||||||
func waitForNTxsInMempool(miner *rpcclient.Client, n int,
|
|
||||||
timeout time.Duration) ([]*chainhash.Hash, error) {
|
|
||||||
|
|
||||||
breakTimeout := time.After(timeout)
|
|
||||||
ticker := time.NewTicker(50 * time.Millisecond)
|
|
||||||
defer ticker.Stop()
|
|
||||||
|
|
||||||
var err error
|
|
||||||
var mempool []*chainhash.Hash
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-breakTimeout:
|
|
||||||
return nil, fmt.Errorf("wanted %v, found %v txs "+
|
|
||||||
"in mempool: %v", n, len(mempool), mempool)
|
|
||||||
case <-ticker.C:
|
|
||||||
mempool, err = miner.GetRawMempool()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(mempool) == n {
|
|
||||||
return mempool, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// getNTxsFromMempool polls until finding the desired number of transactions in
|
// getNTxsFromMempool polls until finding the desired number of transactions in
|
||||||
// the provided miner's mempool and returns the full transactions to the caller.
|
// the provided miner's mempool and returns the full transactions to the caller.
|
||||||
func getNTxsFromMempool(miner *rpcclient.Client, n int,
|
func getNTxsFromMempool(miner *rpcclient.Client, n int,
|
||||||
@ -14078,296 +13922,14 @@ func getPaymentResult(stream routerrpc.Router_SendPaymentV2Client) (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type testCase struct {
|
|
||||||
name string
|
|
||||||
test func(net *lntest.NetworkHarness, t *harnessTest)
|
|
||||||
}
|
|
||||||
|
|
||||||
var testsCases = []*testCase{
|
|
||||||
{
|
|
||||||
name: "sweep coins",
|
|
||||||
test: testSweepAllCoins,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "recovery info",
|
|
||||||
test: testGetRecoveryInfo,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "onchain fund recovery",
|
|
||||||
test: testOnchainFundRecovery,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "basic funding flow",
|
|
||||||
test: testBasicChannelFunding,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "unconfirmed channel funding",
|
|
||||||
test: testUnconfirmedChannelFunding,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "update channel policy",
|
|
||||||
test: testUpdateChannelPolicy,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "open channel reorg test",
|
|
||||||
test: testOpenChannelAfterReorg,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "disconnecting target peer",
|
|
||||||
test: testDisconnectingTargetPeer,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "graph topology notifications",
|
|
||||||
test: testGraphTopologyNotifications,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "funding flow persistence",
|
|
||||||
test: testChannelFundingPersistence,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "channel force closure",
|
|
||||||
test: testChannelForceClosure,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "channel balance",
|
|
||||||
test: testChannelBalance,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "channel unsettled balance",
|
|
||||||
test: testChannelUnsettledBalance,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "single hop invoice",
|
|
||||||
test: testSingleHopInvoice,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "sphinx replay persistence",
|
|
||||||
test: testSphinxReplayPersistence,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list channels",
|
|
||||||
test: testListChannels,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "list outgoing payments",
|
|
||||||
test: testListPayments,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "max pending channel",
|
|
||||||
test: testMaxPendingChannels,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "multi-hop payments",
|
|
||||||
test: testMultiHopPayments,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "single-hop send to route",
|
|
||||||
test: testSingleHopSendToRoute,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "multi-hop send to route",
|
|
||||||
test: testMultiHopSendToRoute,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "send to route error propagation",
|
|
||||||
test: testSendToRouteErrorPropagation,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "unannounced channels",
|
|
||||||
test: testUnannouncedChannels,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "private channels",
|
|
||||||
test: testPrivateChannels,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invoice routing hints",
|
|
||||||
test: testInvoiceRoutingHints,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "multi-hop payments over private channels",
|
|
||||||
test: testMultiHopOverPrivateChannels,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "multiple channel creation and update subscription",
|
|
||||||
test: testBasicChannelCreationAndUpdates,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "invoice update subscription",
|
|
||||||
test: testInvoiceSubscriptions,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "multi-hop htlc error propagation",
|
|
||||||
test: testHtlcErrorPropagation,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "reject onward htlc",
|
|
||||||
test: testRejectHTLC,
|
|
||||||
},
|
|
||||||
// TODO(roasbeef): multi-path integration test
|
|
||||||
{
|
|
||||||
name: "node announcement",
|
|
||||||
test: testNodeAnnouncement,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "node sign verify",
|
|
||||||
test: testNodeSignVerify,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "derive shared key",
|
|
||||||
test: testDeriveSharedKey,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "async payments benchmark",
|
|
||||||
test: testAsyncPayments,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "async bidirectional payments",
|
|
||||||
test: testBidirectionalAsyncPayments,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "test multi-hop htlc",
|
|
||||||
test: testMultiHopHtlcClaims,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "switch circuit persistence",
|
|
||||||
test: testSwitchCircuitPersistence,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "switch offline delivery",
|
|
||||||
test: testSwitchOfflineDelivery,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "switch offline delivery persistence",
|
|
||||||
test: testSwitchOfflineDeliveryPersistence,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "switch offline delivery outgoing offline",
|
|
||||||
test: testSwitchOfflineDeliveryOutgoingOffline,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
// TODO(roasbeef): test always needs to be last as Bob's state
|
|
||||||
// is borked since we trick him into attempting to cheat Alice?
|
|
||||||
name: "revoked uncooperative close retribution",
|
|
||||||
test: testRevokedCloseRetribution,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "failing link",
|
|
||||||
test: testFailingChannel,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "garbage collect link nodes",
|
|
||||||
test: testGarbageCollectLinkNodes,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "abandonchannel",
|
|
||||||
test: testAbandonChannel,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "revoked uncooperative close retribution zero value remote output",
|
|
||||||
test: testRevokedCloseRetributionZeroValueRemoteOutput,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "revoked uncooperative close retribution remote hodl",
|
|
||||||
test: testRevokedCloseRetributionRemoteHodl,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "revoked uncooperative close retribution altruist watchtower",
|
|
||||||
test: testRevokedCloseRetributionAltruistWatchtower,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "data loss protection",
|
|
||||||
test: testDataLossProtection,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "query routes",
|
|
||||||
test: testQueryRoutes,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "route fee cutoff",
|
|
||||||
test: testRouteFeeCutoff,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "send update disable channel",
|
|
||||||
test: testSendUpdateDisableChannel,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "streaming channel backup update",
|
|
||||||
test: testChannelBackupUpdates,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "export channel backup",
|
|
||||||
test: testExportChannelBackup,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "channel backup restore",
|
|
||||||
test: testChannelBackupRestore,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "hold invoice sender persistence",
|
|
||||||
test: testHoldInvoicePersistence,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "cpfp",
|
|
||||||
test: testCPFP,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "macaroon authentication",
|
|
||||||
test: testMacaroonAuthentication,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "bake macaroon",
|
|
||||||
test: testBakeMacaroon,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "delete macaroon id",
|
|
||||||
test: testDeleteMacaroonID,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "immediate payment after channel opened",
|
|
||||||
test: testPaymentFollowingChannelOpen,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "external channel funding",
|
|
||||||
test: testExternalFundingChanPoint,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "psbt channel funding",
|
|
||||||
test: testPsbtChanFunding,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "sendtoroute multi path payment",
|
|
||||||
test: testSendToRouteMultiPath,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "send multi path payment",
|
|
||||||
test: testSendMultiPathPayment,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "REST API",
|
|
||||||
test: testRestApi,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "intercept forwarded htlc packets",
|
|
||||||
test: testForwardInterceptor,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "wumbo channels",
|
|
||||||
test: testWumboChannels,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "maximum channel size",
|
|
||||||
test: testMaxChannelSize,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "connection timeout",
|
|
||||||
test: testNetworkConnectionTimeout,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// TestLightningNetworkDaemon performs a series of integration tests amongst a
|
// TestLightningNetworkDaemon performs a series of integration tests amongst a
|
||||||
// programmatically driven network of lnd nodes.
|
// programmatically driven network of lnd nodes.
|
||||||
func TestLightningNetworkDaemon(t *testing.T) {
|
func TestLightningNetworkDaemon(t *testing.T) {
|
||||||
|
// If no tests are regsitered, then we can exit early.
|
||||||
|
if len(testsCases) == 0 {
|
||||||
|
t.Skip("integration tests not selected with flag 'rpctest'")
|
||||||
|
}
|
||||||
|
|
||||||
ht := newHarnessTest(t, nil)
|
ht := newHarnessTest(t, nil)
|
||||||
|
|
||||||
// Declare the network harness here to gain access to its
|
// Declare the network harness here to gain access to its
|
||||||
|
5
lntest/itest/lnd_test_list_off_test.go
Normal file
5
lntest/itest/lnd_test_list_off_test.go
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
// +build !rpctest
|
||||||
|
|
||||||
|
package itest
|
||||||
|
|
||||||
|
var testsCases = []*testCase{}
|
285
lntest/itest/lnd_test_list_on_test.go
Normal file
285
lntest/itest/lnd_test_list_on_test.go
Normal file
@ -0,0 +1,285 @@
|
|||||||
|
// +build rpctest
|
||||||
|
|
||||||
|
package itest
|
||||||
|
|
||||||
|
var testsCases = []*testCase{
|
||||||
|
{
|
||||||
|
name: "sweep coins",
|
||||||
|
test: testSweepAllCoins,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "recovery info",
|
||||||
|
test: testGetRecoveryInfo,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "onchain fund recovery",
|
||||||
|
test: testOnchainFundRecovery,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "basic funding flow",
|
||||||
|
test: testBasicChannelFunding,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unconfirmed channel funding",
|
||||||
|
test: testUnconfirmedChannelFunding,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "update channel policy",
|
||||||
|
test: testUpdateChannelPolicy,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "open channel reorg test",
|
||||||
|
test: testOpenChannelAfterReorg,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "disconnecting target peer",
|
||||||
|
test: testDisconnectingTargetPeer,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "graph topology notifications",
|
||||||
|
test: testGraphTopologyNotifications,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "funding flow persistence",
|
||||||
|
test: testChannelFundingPersistence,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "channel force closure",
|
||||||
|
test: testChannelForceClosure,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "channel balance",
|
||||||
|
test: testChannelBalance,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "channel unsettled balance",
|
||||||
|
test: testChannelUnsettledBalance,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "single hop invoice",
|
||||||
|
test: testSingleHopInvoice,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "sphinx replay persistence",
|
||||||
|
test: testSphinxReplayPersistence,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "list channels",
|
||||||
|
test: testListChannels,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "list outgoing payments",
|
||||||
|
test: testListPayments,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "max pending channel",
|
||||||
|
test: testMaxPendingChannels,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multi-hop payments",
|
||||||
|
test: testMultiHopPayments,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "single-hop send to route",
|
||||||
|
test: testSingleHopSendToRoute,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multi-hop send to route",
|
||||||
|
test: testMultiHopSendToRoute,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "send to route error propagation",
|
||||||
|
test: testSendToRouteErrorPropagation,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "unannounced channels",
|
||||||
|
test: testUnannouncedChannels,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "private channels",
|
||||||
|
test: testPrivateChannels,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invoice routing hints",
|
||||||
|
test: testInvoiceRoutingHints,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multi-hop payments over private channels",
|
||||||
|
test: testMultiHopOverPrivateChannels,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multiple channel creation and update subscription",
|
||||||
|
test: testBasicChannelCreationAndUpdates,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "invoice update subscription",
|
||||||
|
test: testInvoiceSubscriptions,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "multi-hop htlc error propagation",
|
||||||
|
test: testHtlcErrorPropagation,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "reject onward htlc",
|
||||||
|
test: testRejectHTLC,
|
||||||
|
},
|
||||||
|
// TODO(roasbeef): multi-path integration test
|
||||||
|
{
|
||||||
|
name: "node announcement",
|
||||||
|
test: testNodeAnnouncement,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "node sign verify",
|
||||||
|
test: testNodeSignVerify,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "derive shared key",
|
||||||
|
test: testDeriveSharedKey,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "async payments benchmark",
|
||||||
|
test: testAsyncPayments,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "async bidirectional payments",
|
||||||
|
test: testBidirectionalAsyncPayments,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "test multi-hop htlc",
|
||||||
|
test: testMultiHopHtlcClaims,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "switch circuit persistence",
|
||||||
|
test: testSwitchCircuitPersistence,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "switch offline delivery",
|
||||||
|
test: testSwitchOfflineDelivery,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "switch offline delivery persistence",
|
||||||
|
test: testSwitchOfflineDeliveryPersistence,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "switch offline delivery outgoing offline",
|
||||||
|
test: testSwitchOfflineDeliveryOutgoingOffline,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// TODO(roasbeef): test always needs to be last as Bob's state
|
||||||
|
// is borked since we trick him into attempting to cheat Alice?
|
||||||
|
name: "revoked uncooperative close retribution",
|
||||||
|
test: testRevokedCloseRetribution,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "failing link",
|
||||||
|
test: testFailingChannel,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "garbage collect link nodes",
|
||||||
|
test: testGarbageCollectLinkNodes,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "abandonchannel",
|
||||||
|
test: testAbandonChannel,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "revoked uncooperative close retribution zero value remote output",
|
||||||
|
test: testRevokedCloseRetributionZeroValueRemoteOutput,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "revoked uncooperative close retribution remote hodl",
|
||||||
|
test: testRevokedCloseRetributionRemoteHodl,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "revoked uncooperative close retribution altruist watchtower",
|
||||||
|
test: testRevokedCloseRetributionAltruistWatchtower,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "data loss protection",
|
||||||
|
test: testDataLossProtection,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "query routes",
|
||||||
|
test: testQueryRoutes,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "route fee cutoff",
|
||||||
|
test: testRouteFeeCutoff,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "send update disable channel",
|
||||||
|
test: testSendUpdateDisableChannel,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "streaming channel backup update",
|
||||||
|
test: testChannelBackupUpdates,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "export channel backup",
|
||||||
|
test: testExportChannelBackup,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "channel backup restore",
|
||||||
|
test: testChannelBackupRestore,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "hold invoice sender persistence",
|
||||||
|
test: testHoldInvoicePersistence,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "cpfp",
|
||||||
|
test: testCPFP,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "macaroon authentication",
|
||||||
|
test: testMacaroonAuthentication,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "bake macaroon",
|
||||||
|
test: testBakeMacaroon,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "delete macaroon id",
|
||||||
|
test: testDeleteMacaroonID,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "immediate payment after channel opened",
|
||||||
|
test: testPaymentFollowingChannelOpen,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "external channel funding",
|
||||||
|
test: testExternalFundingChanPoint,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "psbt channel funding",
|
||||||
|
test: testPsbtChanFunding,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "sendtoroute multi path payment",
|
||||||
|
test: testSendToRouteMultiPath,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "send multi path payment",
|
||||||
|
test: testSendMultiPathPayment,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "REST API",
|
||||||
|
test: testRestApi,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "intercept forwarded htlc packets",
|
||||||
|
test: testForwardInterceptor,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "wumbo channels",
|
||||||
|
test: testWumboChannels,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "maximum channel size",
|
||||||
|
test: testMaxChannelSize,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "connection timeout",
|
||||||
|
test: testNetworkConnectionTimeout,
|
||||||
|
},
|
||||||
|
}
|
@ -1,5 +1,3 @@
|
|||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -1,11 +1,40 @@
|
|||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
|
"github.com/btcsuite/btcd/rpcclient"
|
||||||
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/go-errors/errors"
|
"github.com/go-errors/errors"
|
||||||
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
harnessNetParams = &chaincfg.RegressionNetParams
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
testFeeBase = 1e+6
|
||||||
|
defaultCSV = lntest.DefaultCSV
|
||||||
|
defaultTimeout = lntest.DefaultTimeout
|
||||||
|
minerMempoolTimeout = lntest.MinerMempoolTimeout
|
||||||
|
channelOpenTimeout = lntest.ChannelOpenTimeout
|
||||||
|
channelCloseTimeout = lntest.ChannelCloseTimeout
|
||||||
|
itestLndBinary = "../../lnd-itest"
|
||||||
|
anchorSize = 330
|
||||||
|
noFeeLimitMsat = math.MaxInt64
|
||||||
|
|
||||||
|
AddrTypeWitnessPubkeyHash = lnrpc.AddressType_WITNESS_PUBKEY_HASH
|
||||||
|
AddrTypeNestedPubkeyHash = lnrpc.AddressType_NESTED_PUBKEY_HASH
|
||||||
)
|
)
|
||||||
|
|
||||||
// harnessTest wraps a regular testing.T providing enhanced error detection
|
// harnessTest wraps a regular testing.T providing enhanced error detection
|
||||||
@ -88,3 +117,135 @@ type testCase struct {
|
|||||||
name string
|
name string
|
||||||
test func(net *lntest.NetworkHarness, t *harnessTest)
|
test func(net *lntest.NetworkHarness, t *harnessTest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// waitForTxInMempool polls until finding one transaction in the provided
|
||||||
|
// miner's mempool. An error is returned if *one* transaction isn't found within
|
||||||
|
// the given timeout.
|
||||||
|
func waitForTxInMempool(miner *rpcclient.Client,
|
||||||
|
timeout time.Duration) (*chainhash.Hash, error) {
|
||||||
|
|
||||||
|
txs, err := waitForNTxsInMempool(miner, 1, timeout)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return txs[0], err
|
||||||
|
}
|
||||||
|
|
||||||
|
// waitForNTxsInMempool polls until finding the desired number of transactions
|
||||||
|
// in the provided miner's mempool. An error is returned if this number is not
|
||||||
|
// met after the given timeout.
|
||||||
|
func waitForNTxsInMempool(miner *rpcclient.Client, n int,
|
||||||
|
timeout time.Duration) ([]*chainhash.Hash, error) {
|
||||||
|
|
||||||
|
breakTimeout := time.After(timeout)
|
||||||
|
ticker := time.NewTicker(50 * time.Millisecond)
|
||||||
|
defer ticker.Stop()
|
||||||
|
|
||||||
|
var err error
|
||||||
|
var mempool []*chainhash.Hash
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-breakTimeout:
|
||||||
|
return nil, fmt.Errorf("wanted %v, found %v txs "+
|
||||||
|
"in mempool: %v", n, len(mempool), mempool)
|
||||||
|
case <-ticker.C:
|
||||||
|
mempool, err = miner.GetRawMempool()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(mempool) == n {
|
||||||
|
return mempool, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// mineBlocks 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 mineBlocks(t *harnessTest, net *lntest.NetworkHarness,
|
||||||
|
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.
|
||||||
|
var txids []*chainhash.Hash
|
||||||
|
var err error
|
||||||
|
if numTxs > 0 {
|
||||||
|
txids, err = waitForNTxsInMempool(
|
||||||
|
net.Miner.Node, numTxs, minerMempoolTimeout,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to find txns in mempool: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks := make([]*wire.MsgBlock, num)
|
||||||
|
|
||||||
|
blockHashes, err := net.Miner.Node.Generate(num)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to generate blocks: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, blockHash := range blockHashes {
|
||||||
|
block, err := net.Miner.Node.GetBlock(blockHash)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unable to get block: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
blocks[i] = block
|
||||||
|
}
|
||||||
|
|
||||||
|
// Finally, assert that all the transactions were included in the first
|
||||||
|
// block.
|
||||||
|
for _, txid := range txids {
|
||||||
|
assertTxInBlock(t, blocks[0], txid)
|
||||||
|
}
|
||||||
|
|
||||||
|
return blocks
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertTxInBlock(t *harnessTest, block *wire.MsgBlock, txid *chainhash.Hash) {
|
||||||
|
for _, tx := range block.Transactions {
|
||||||
|
sha := tx.TxHash()
|
||||||
|
if bytes.Equal(txid[:], sha[:]) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Fatalf("tx was not included in block")
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertWalletUnspent(t *harnessTest, node *lntest.HarnessNode, out *lnrpc.OutPoint) {
|
||||||
|
t.t.Helper()
|
||||||
|
|
||||||
|
err := wait.NoError(func() error {
|
||||||
|
ctxt, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
||||||
|
defer cancel()
|
||||||
|
unspent, err := node.ListUnspent(ctxt, &lnrpc.ListUnspentRequest{})
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = errors.New("tx with wanted txhash never found")
|
||||||
|
for _, utxo := range unspent.Utxos {
|
||||||
|
if !bytes.Equal(utxo.Outpoint.TxidBytes, out.TxidBytes) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
err = errors.New("wanted output is not a wallet utxo")
|
||||||
|
if utxo.Outpoint.OutputIndex != out.OutputIndex {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}, defaultTimeout)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("outpoint %s not unspent by %s's wallet: %v", out,
|
||||||
|
node.Name(), err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user