Merge pull request #6825 from yyforyongyu/6-new-itest

itest: fix previously known test flakes
This commit is contained in:
Olaoluwa Osuntokun 2023-02-23 15:35:45 -08:00 committed by GitHub
commit cfc19a9ac4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
134 changed files with 2162 additions and 8844 deletions

View file

@ -186,10 +186,10 @@ jobs:
parallel: true
########################
# run integration tests
# run ubuntu integration tests
########################
integration-test:
name: run itests
ubuntu-integration-test:
name: run ubuntu itests
runs-on: ubuntu-latest
if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')'
strategy:
@ -230,17 +230,18 @@ jobs:
- name: Zip log files on failure
if: ${{ failure() }}
timeout-minutes: 1 # timeout after 1 minute
run: 7z a logs-itest-${{ matrix.name }}.zip lntest/itest/**/*.log
timeout-minutes: 5 # timeout after 5 minute
run: 7z a logs-itest-${{ matrix.name }}.zip itest/**/*.log
- name: Upload log files on failure
uses: actions/upload-artifact@v2.2.4
uses: actions/upload-artifact@v3
if: ${{ failure() }}
with:
name: logs-itest-${{ matrix.name }}
path: logs-itest-${{ matrix.name }}.zip
retention-days: 5
########################
# run windows integration test
########################
@ -258,102 +259,15 @@ jobs:
go-version: '${{ env.GO_VERSION }}'
- name: run itest
run: make itest-parallel windows=1 tranches=2 parallel=2
run: make itest-parallel windows=1
- name: Zip log files on failure
if: ${{ failure() }}
run: 7z a logs-itest-windows.zip lntest/itest/**/*.log
timeout-minutes: 5 # timeout after 5 minute
run: 7z a logs-itest-windows.zip itest/**/*.log
- name: Upload log files on failure
uses: actions/upload-artifact@v2
if: ${{ failure() }}
with:
name: logs-itest-windows
path: logs-itest-windows.zip
retention-days: 5
########################
# run new integration tests
########################
new-integration-test:
name: run new itests
runs-on: ubuntu-latest
if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')'
strategy:
# Allow other tests in the matrix to continue if one fails.
fail-fast: false
matrix:
include:
- name: btcd
args: backend=btcd
- name: bitcoind
args: backend=bitcoind
- name: bitcoind-notxindex
args: backend="bitcoind notxindex"
- name: bitcoind-rpcpolling
args: backend="bitcoind rpcpolling"
- name: bitcoind-etcd
args: backend=bitcoind dbbackend=etcd
- name: bitcoind-postgres
args: backend=bitcoind dbbackend=postgres
- name: bitcoind-sqlite
args: backend=bitcoind dbbackend=sqlite
- name: neutrino
args: backend=neutrino
steps:
- name: git checkout
uses: actions/checkout@v3
- name: setup go ${{ env.GO_VERSION }}
uses: ./.github/actions/setup-go
with:
go-version: '${{ env.GO_VERSION }}'
- name: install bitcoind
run: ./scripts/install_bitcoind.sh
- name: run new ${{ matrix.name }}
run: make itest-parallel temptest=true ${{ matrix.args }}
- name: Zip log files on failure
if: ${{ failure() }}
timeout-minutes: 1 # timeout after 1 minute
run: 7z a logs-itest-${{ matrix.name }}.zip lntest/itest/**/*.log
- name: Upload log files on failure
uses: actions/upload-artifact@v2.2.4
if: ${{ failure() }}
with:
name: logs-itest-${{ matrix.name }}
path: logs-itest-${{ matrix.name }}.zip
retention-days: 5
########################
# run new windows integration test
########################
new-windows-integration-test:
name: run new windows itest
runs-on: windows-latest
if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')'
steps:
- name: git checkout
uses: actions/checkout@v3
- name: setup go ${{ env.GO_VERSION }}
uses: ./.github/actions/setup-go
with:
go-version: '${{ env.GO_VERSION }}'
- name: run new itest
run: make itest-parallel temptest=true windows=1 tranches=2 parallel=2
- name: Zip log files on failure
if: ${{ failure() }}
timeout-minutes: 1 # timeout after 1 minute
run: 7z a logs-itest-windows.zip lntest/itest/**/*.log
- name: Upload log files on failure
uses: actions/upload-artifact@v2
uses: actions/upload-artifact@v3
if: ${{ failure() }}
with:
name: logs-itest-windows

12
.gitignore vendored
View file

@ -32,12 +32,12 @@ _testmain.go
/lncli-itest
# Integration test log files
lntest/itest/*.log
lntest/itest/.backendlogs
lntest/itest/.minerlogs
lntest/itest/lnd-itest
lntest/itest/btcd-itest
lntest/itest/.logs-*
itest/*.log
itest/.backendlogs
itest/.minerlogs
itest/lnd-itest
itest/btcd-itest
itest/.logs-*
cmd/cmd
*.key

View file

@ -27,6 +27,7 @@ run:
- kvdb_etcd
- kvdb_postgres
- kvdb_sqlite
- integration
linters-settings:
govet:
@ -96,6 +97,7 @@ linters-settings:
ignored-functions:
- 'math.*'
- 'strconv.ParseInt'
- 'errors.Wrap'
linters:
@ -237,14 +239,9 @@ issues:
linters:
- forbidigo
# Fix false positives because of build flags in itest directory.
- path: lntest/itest/.*
- path: itest/.*
linters:
- unused
- unparam
- govet
# itest case can be very long so we disable long function check.
- funlen
- paralleltest
- path: lnmock/*
linters:

View file

@ -32,31 +32,15 @@ sudo: required
jobs:
include:
- stage: Sanity Check
name: Lint and compile
script:
# Step 1: Make sure no diff is produced when compiling with the correct
# version.
- make rpc-check
# Step 2: Make sure the unit tests compile, but don't run them. They run
# in a GitHub Workflow.
- make unit pkg=... case=_NONE_
# Step 3: Lint go code. Invoke GC more often to reduce memory usage.
- GOGC=30 make lint
- stage: Integration Test
name: Bitcoind Integration ARM
script:
- bash ./scripts/install_bitcoind.sh
- GOARM=7 GOARCH=arm GOOS=linux make itest-parallel backend=bitcoind tranches=3 parallel=3
- GOMEMLIMIT=500MiB GOARM=7 GOARCH=arm GOOS=linux travis_wait 30 make itest-parallel backend=bitcoind
arch: arm64
services:
- docker
after_failure:
- |-
LOG_FILES=$(find ./lntest/itest -name '*.log')
LOG_FILES=$(find ./itest -name '*.log')
echo "Uploading to termbin.com..." && for f in $LOG_FILES; do echo -n $f; cat $f | nc termbin.com 9999 | xargs -r0 printf ' uploaded to %s'; done
echo "Uploading to file.io..." && tar -zcvO $LOG_FILES | curl -s -F 'file=@-;filename=logs.tar.gz' https://file.io | xargs -r0 printf 'logs.tar.gz uploaded to %s\n'

View file

@ -93,19 +93,19 @@ build:
build-itest:
@$(call print, "Building itest btcd and lnd.")
CGO_ENABLED=0 $(GOBUILD) -tags="rpctest" -o lntest/itest/btcd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(BTCD_PKG)
CGO_ENABLED=0 $(GOBUILD) -tags="$(ITEST_TAGS)" -o lntest/itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd
CGO_ENABLED=0 $(GOBUILD) -tags="integration" -o itest/btcd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(BTCD_PKG)
CGO_ENABLED=0 $(GOBUILD) -tags="$(ITEST_TAGS)" -o itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd
@$(call print, "Building itest binary for ${backend} backend.")
CGO_ENABLED=0 $(GOTEST) -v ./lntest/itest -tags="$(DEV_TAGS) $(RPC_TAGS) rpctest $(backend)" -c -o lntest/itest/itest.test$(EXEC_SUFFIX)
CGO_ENABLED=0 $(GOTEST) -v ./itest -tags="$(DEV_TAGS) $(RPC_TAGS) integration $(backend)" -c -o itest/itest.test$(EXEC_SUFFIX)
build-itest-race:
@$(call print, "Building itest btcd and lnd with race detector.")
CGO_ENABLED=0 $(GOBUILD) -tags="rpctest" -o lntest/itest/btcd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(BTCD_PKG)
CGO_ENABLED=1 $(GOBUILD) -race -tags="$(ITEST_TAGS)" -o lntest/itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd
CGO_ENABLED=0 $(GOBUILD) -tags="integration" -o itest/btcd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(BTCD_PKG)
CGO_ENABLED=1 $(GOBUILD) -race -tags="$(ITEST_TAGS)" -o itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd
@$(call print, "Building itest binary for ${backend} backend.")
CGO_ENABLED=0 $(GOTEST) -v ./lntest/itest -tags="$(DEV_TAGS) $(RPC_TAGS) rpctest $(backend)" -c -o lntest/itest/itest.test$(EXEC_SUFFIX)
CGO_ENABLED=0 $(GOTEST) -v ./itest -tags="$(DEV_TAGS) $(RPC_TAGS) integration $(backend)" -c -o itest/itest.test$(EXEC_SUFFIX)
install:
@$(call print, "Installing lnd and lncli.")
@ -164,7 +164,7 @@ endif
itest-only: db-instance
@$(call print, "Running integration tests with ${backend} backend.")
rm -rf lntest/itest/*.log lntest/itest/.logs-*; date
rm -rf itest/*.log itest/.logs-*; date
EXEC_SUFFIX=$(EXEC_SUFFIX) scripts/itest_part.sh 0 1 $(TEST_FLAGS) $(ITEST_FLAGS)
itest: build-itest itest-only
@ -173,7 +173,7 @@ itest-race: build-itest-race itest-only
itest-parallel: build-itest db-instance
@$(call print, "Running tests")
rm -rf lntest/itest/*.log lntest/itest/.logs-*; date
rm -rf itest/*.log itest/.logs-*; date
EXEC_SUFFIX=$(EXEC_SUFFIX) echo "$$(seq 0 $$(expr $(ITEST_PARALLELISM) - 1))" | xargs -P $(ITEST_PARALLELISM) -n 1 -I {} scripts/itest_part.sh {} $(NUM_ITEST_TRANCHES) $(TEST_FLAGS) $(ITEST_FLAGS)
itest-clean:

View file

@ -1,5 +1,4 @@
//go:build rpctest
// +build rpctest
//go:build integration
package aezeed

View file

@ -1,6 +1,3 @@
//go:build !rpctest
// +build !rpctest
package contractcourt
import (

View file

@ -497,10 +497,10 @@ func newChainSet(chanState *channeldb.OpenChannel) (*chainSet, error) {
"chan_point=%v", chanState.FundingOutpoint)
}
log.Debugf("ChannelPoint(%v): local_commit_type=%v, local_commit=%v",
log.Tracef("ChannelPoint(%v): local_commit_type=%v, local_commit=%v",
chanState.FundingOutpoint, chanState.ChanType,
spew.Sdump(localCommit))
log.Debugf("ChannelPoint(%v): remote_commit_type=%v, remote_commit=%v",
log.Tracef("ChannelPoint(%v): remote_commit_type=%v, remote_commit=%v",
chanState.FundingOutpoint, chanState.ChanType,
spew.Sdump(remoteCommit))
@ -527,7 +527,7 @@ func newChainSet(chanState *channeldb.OpenChannel) (*chainSet, error) {
var remotePendingCommit *channeldb.ChannelCommitment
if remoteChainTip != nil {
remotePendingCommit = &remoteChainTip.Commitment
log.Debugf("ChannelPoint(%v): remote_pending_commit_type=%v, "+
log.Tracef("ChannelPoint(%v): remote_pending_commit_type=%v, "+
"remote_pending_commit=%v", chanState.FundingOutpoint,
chanState.ChanType,
spew.Sdump(remoteChainTip.Commitment))

View file

@ -1,6 +1,3 @@
//go:build !rpctest
// +build !rpctest
package contractcourt
import (

View file

@ -1,6 +1,3 @@
//go:build !rpctest
// +build !rpctest
package contractcourt
import (

View file

@ -316,6 +316,11 @@ type Config struct {
// ChannelID. This is used to sign updates for them if the channel has
// no AuthProof and the option-scid-alias feature bit was negotiated.
GetAlias func(lnwire.ChannelID) (lnwire.ShortChannelID, error)
// FindChannel allows the gossiper to find a channel that we're party
// to without iterating over the entire set of open channels.
FindChannel func(node *btcec.PublicKey, chanID lnwire.ChannelID) (
*channeldb.OpenChannel, error)
}
// processedNetworkMsg is a wrapper around networkMsg and a boolean. It is
@ -3016,6 +3021,16 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
ann.ShortChannelID,
)
if err != nil {
_, err = d.cfg.FindChannel(nMsg.source, ann.ChannelID)
if err != nil {
err := fmt.Errorf("unable to store the proof for "+
"short_chan_id=%v: %v", shortChanID, err)
log.Error(err)
nMsg.err <- err
return nil, false
}
proof := channeldb.NewWaitingProof(nMsg.isRemote, ann)
err := d.cfg.WaitingProofStore.Add(proof)
if err != nil {

View file

@ -697,6 +697,12 @@ func createChannelAnnouncement(blockHeight uint32, key1, key2 *btcec.PrivateKey,
return a, nil
}
func mockFindChannel(node *btcec.PublicKey, chanID lnwire.ChannelID) (
*channeldb.OpenChannel, error) {
return nil, nil
}
type testCtx struct {
gossiper *AuthenticatedGossiper
router *mockGraphSource
@ -792,6 +798,7 @@ func createTestCtx(t *testing.T, startHeight uint32) (*testCtx, error) {
SignAliasUpdate: signAliasUpdate,
FindBaseByAlias: findBaseByAlias,
GetAlias: getAlias,
FindChannel: mockFindChannel,
}, selfKeyDesc)
if err := gossiper.Start(); err != nil {

View file

@ -155,7 +155,7 @@ A quick summary of test practices follows:
or RPC's will need to be accompanied by integration tests which use the
[`networkHarness`framework](https://github.com/lightningnetwork/lnd/blob/master/lntest/harness.go)
contained within `lnd`. For example integration tests, see
[`lnd_test.go`](https://github.com/lightningnetwork/lnd/blob/master/lntest/itest/lnd_test.go).
[`lnd_test.go`](https://github.com/lightningnetwork/lnd/blob/master/itest/lnd_test.go).
- The itest log files are automatically scanned for `[ERR]` lines. There
shouldn't be any of those in the logs, see [Use of Log Levels](#use-of-log-levels).

View file

@ -44,7 +44,7 @@ to test the RPCs and to showcase the different use cases.
### 3-of-3 Taproot key spend path (BIP-0086)
See `testTaprootMuSig2KeySpendBip86` in
[`lntest/itest/lnd_taproot_test.go`](../lntest/itest/lnd_taproot_test.go) to see
[`itest/lnd_taproot_test.go`](../itest/lnd_taproot_test.go) to see
the full code.
This example uses combines the public keys of 3 participants into a shared
@ -73,7 +73,7 @@ the `MuSig2CreateSession` RPC call:
### 3-of-3 Taproot key spend path with root hash commitment
See `testTaprootMuSig2KeySpendRootHash` in
[`lntest/itest/lnd_taproot_test.go`](../lntest/itest/lnd_taproot_test.go) to see
[`itest/lnd_taproot_test.go`](../itest/lnd_taproot_test.go) to see
the full code.
This is very similar to the above example but with the main difference that the
@ -101,7 +101,7 @@ the `MuSig2CreateSession` RPC call:
### 3-of-3 `OP_CHECKSIG` in Taproot script spend path
See `testTaprootMuSig2CombinedLeafKeySpend` in
[`lntest/itest/lnd_taproot_test.go`](../lntest/itest/lnd_taproot_test.go) to see
[`itest/lnd_taproot_test.go`](../itest/lnd_taproot_test.go) to see
the full code.
This example is definitely the most involved one. To be able to use a MuSig2

View file

@ -487,7 +487,8 @@ PRs([6776](https://github.com/lightningnetwork/lnd/pull/6776),
[7242](https://github.com/lightningnetwork/lnd/pull/7242),
[7245](https://github.com/lightningnetwork/lnd/pull/7245)),
[6823](https://github.com/lightningnetwork/lnd/pull/6823),
[6824](https://github.com/lightningnetwork/lnd/pull/6824),) have been made to
[6824](https://github.com/lightningnetwork/lnd/pull/6824),
[6825](https://github.com/lightningnetwork/lnd/pull/6825)) have been made to
refactor the itest for code health and maintenance.
# Contributors (Alphabetical Order)

View file

@ -1,4 +1,4 @@
//go:build rpctest
//go:build integration
package funding

View file

@ -108,6 +108,11 @@ const (
// for the funding transaction to be confirmed before forgetting
// channels that aren't initiated by us. 2016 blocks is ~2 weeks.
maxWaitNumBlocksFundingConf = 2016
// pendingChansLimit is the maximum number of pending channels that we
// can have. After this point, pending channel opens will start to be
// rejected.
pendingChansLimit = 1_000
)
var (
@ -1320,6 +1325,25 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer,
return
}
// Ensure that the pendingChansLimit is respected.
pendingChans, err := f.cfg.Wallet.Cfg.Database.FetchPendingChannels()
if err != nil {
f.failFundingFlow(
peer, msg.PendingChannelID, err,
)
return
}
if len(pendingChans) > pendingChansLimit {
f.failFundingFlow(
peer, msg.PendingChannelID,
lnwire.ErrMaxPendingChannels,
)
return
}
// We'll also reject any requests to create channels until we're fully
// synced to the network as we won't be able to properly validate the
// confirmation of the funding transaction.

View file

@ -1,6 +1,3 @@
//go:build !rpctest
// +build !rpctest
package funding
import (

View file

@ -2743,6 +2743,15 @@ func (l *channelLink) handleSwitchPacket(pkt *htlcPacket) error {
//
// NOTE: Part of the ChannelLink interface.
func (l *channelLink) HandleChannelUpdate(message lnwire.Message) {
select {
case <-l.quit:
// Return early if the link is already in the process of
// quitting. It doesn't make sense to hand the message to the
// mailbox here.
return
default:
}
l.mailBox.AddMessage(message)
}

106
itest/README.md Normal file
View file

@ -0,0 +1,106 @@
# Integration Test
`itest` is a package that houses the integration tests made for `lnd`. This
package builds test cases using the test framework `lntest`.
## Add New Tests
To add a new test case, create a `TestFunc` and add it in `list_on_test.go`.
Ideally, the `Name` should just be the snake case of the name used in
`TestFunc` without the leading `test` and underscores. For instance, to test
`lnd`'s exporting channel backup, we have,
```go
{
Name: "export channel backup",
TestFunc: testExportChannelBackup,
}
```
The place to put the code of the `TestFunc` is case-specific. `itest` package
has loosely defined a list of files to test different functionalities of `lnd`.
The new test needs to be put into one of these files, otherwise, a new file
needs to be created.
## Run Tests
#### Run a single test case
To run a single test case, use `make itest icase=$case`, where `case` is the
name defined in `list_on_test.go`, with spaces replaced with underscores(`_`).
```shell
# Run `testListChannels`.
make itest icase=list_channels
```
#### Run multiple test cases
There are two ways to run multiple test cases. One way is to use `make itest
icase=$cases`, where `cases` has the format `cases='(case|case|...)'`. The
`case` is the name defined in `list_on_test.go`, with spaces replaced with
underscores(`_`).
```shell
# Run `testListChannels` and `testListAddresses` together.
make itest icase='(list_channels|list_addresses)'
```
Another way to run multiple cases is similar to how Go runs its tests - by
simple regex matching. For instance, the following command will run three cases
since they all start with the word `list`,
```shell
# Run `testListChannels`, `testListAddresses`, and `testListPayments` together.
make itest icase=list
```
#### Run all tests
To run all tests, use `make itest` without `icase` flag.
```shell
# Run all test cases.
make itest
```
#### Run tests in parallel
To run tests in parallel, use `make itest-parallel`. This command takes two
special arguments,
- `tranches`, specifies the number of parts the test cases will be split into.
- `parallel`, specifies the number of threads to run in parallel. This value
must be smaller than or equal to `tranches`.
```shell
# Split the tests into 4 parts, and run them using 2 threads.
make itest-parallel tranches=4 parallel=2
```
By default, `itest-parallel` splits the tests into 4 parts and uses 4 threads
to run each of them.
#### Additional arguments
For both `make itest` and `make itest-parallel`, the following arguments are
allowed,
- `timeout`, specifies the timeout value used in testing.
- `dbbackend`, specifies the database backend. Must be `bbolt`, `etcd`, or
`postgres`, default to `bbolt`.
- `backend`, specifies the chain backend to be used. Must be one of,
- `btcd`, the default value.
- `neutrino`
- `bitcoind`
- `bitcoind notxindex`
- `bitcoind rpcpolling`
```shell
# Run a single test case using bitcoind as the chain backend and etcd as the
# database backend, with a timeout of 5 minutes.
make itest icase=list_channels backend=bitcoind dbbackend=etcd timeout=5m
# Run all test cases in parallel, using bitcoind notxindex as the chain backend
# and etcd as the database backend, with a timeout of 60 minutes for each
# parallel.
make itest-parallel backend="bitcoind notxindex" dbbackend=etcd timeout=60m
```

7
itest/list_off_test.go Normal file
View file

@ -0,0 +1,7 @@
//go:build !integration
package itest
import "github.com/lightningnetwork/lnd/lntest"
var allTestCases = []*lntest.TestCase{}

View file

@ -1,12 +1,10 @@
//go:build rpctest
// +build rpctest
//go:build integration
package itest
import "github.com/lightningnetwork/lnd/lntemp"
import "github.com/lightningnetwork/lnd/lntest"
// TODO(yy): remove the temp.
var allTestCasesTemp = []*lntemp.TestCase{
var allTestCases = []*lntest.TestCase{
{
Name: "update channel status",
TestFunc: testUpdateChanStatus,
@ -509,4 +507,8 @@ var allTestCasesTemp = []*lntemp.TestCase{
Name: "zero conf reorg edge existence",
TestFunc: testZeroConfReorg,
},
{
Name: "async bidirectional payments",
TestFunc: testBidirectionalAsyncPayments,
},
}

View file

@ -11,15 +11,15 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/stretchr/testify/require"
)
// testSendPaymentAMPInvoice tests that we can send an AMP payment to a
// specified AMP invoice using SendPaymentV2.
func testSendPaymentAMPInvoice(ht *lntemp.HarnessTest) {
func testSendPaymentAMPInvoice(ht *lntest.HarnessTest) {
succeed := ht.Run("native payaddr", func(t *testing.T) {
tt := ht.Subtest(t)
testSendPaymentAMPInvoiceCase(tt, false)
@ -36,7 +36,7 @@ func testSendPaymentAMPInvoice(ht *lntemp.HarnessTest) {
})
}
func testSendPaymentAMPInvoiceCase(ht *lntemp.HarnessTest,
func testSendPaymentAMPInvoiceCase(ht *lntest.HarnessTest,
useExternalPayAddr bool) {
mts := newMppTestScenario(ht)
@ -196,7 +196,7 @@ func testSendPaymentAMPInvoiceCase(ht *lntemp.HarnessTest,
// testSendPaymentAMPInvoiceRepeat tests that it's possible to pay an AMP
// invoice multiple times by having the client generate a new setID each time.
func testSendPaymentAMPInvoiceRepeat(ht *lntemp.HarnessTest) {
func testSendPaymentAMPInvoiceRepeat(ht *lntest.HarnessTest) {
// In this basic test, we'll only need two nodes as we want to
// primarily test the recurring payment feature. So we'll re-use the
carol := ht.NewNode("Carol", nil)
@ -218,7 +218,7 @@ func testSendPaymentAMPInvoiceRepeat(ht *lntemp.HarnessTest) {
// Establish a channel between Carol and Dave.
chanAmt := btcutil.Amount(100_000)
ht.OpenChannel(
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
carol, dave, lntest.OpenChannelParams{Amt: chanAmt},
)
// Create an AMP invoice of a trivial amount, that we'll pay repeatedly
@ -353,7 +353,7 @@ func testSendPaymentAMPInvoiceRepeat(ht *lntemp.HarnessTest) {
// testSendPaymentAMP tests that we can send an AMP payment to a specified
// destination using SendPaymentV2.
func testSendPaymentAMP(ht *lntemp.HarnessTest) {
func testSendPaymentAMP(ht *lntest.HarnessTest) {
mts := newMppTestScenario(ht)
const paymentAmt = btcutil.Amount(300000)
@ -460,7 +460,7 @@ func testSendPaymentAMP(ht *lntemp.HarnessTest) {
mts.closeChannels()
}
func testSendToRouteAMP(ht *lntemp.HarnessTest) {
func testSendToRouteAMP(ht *lntest.HarnessTest) {
mts := newMppTestScenario(ht)
const (
paymentAmt = btcutil.Amount(300000)

View file

@ -18,8 +18,8 @@ import (
"github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/stretchr/testify/require"
)
@ -34,7 +34,7 @@ type (
// that'll return the same node, but with its state restored via a
// custom method. We use this to abstract away _how_ a node is restored
// from our assertions once the node has been fully restored itself.
restoreMethodType func(ht *lntemp.HarnessTest,
restoreMethodType func(ht *lntest.HarnessTest,
oldNode *node.HarnessNode, backupFilePath string,
password []byte, mnemonic []string) nodeRestorer
)
@ -50,12 +50,12 @@ type chanRestoreScenario struct {
dave *node.HarnessNode
password []byte
mnemonic []string
params lntemp.OpenChannelParams
params lntest.OpenChannelParams
}
// newChanRestoreScenario creates a new scenario that has two nodes, Carol and
// Dave, connected and funded.
func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
func newChanRestoreScenario(ht *lntest.HarnessTest, ct lnrpc.CommitmentType,
zeroConf bool) *chanRestoreScenario {
const (
@ -70,7 +70,7 @@ func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
}
if ct != lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE {
args := nodeArgsForCommitType(ct)
args := lntest.NodeArgsForCommitType(ct)
nodeArgs = append(nodeArgs, args...)
}
@ -99,7 +99,7 @@ func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
// For the anchor output case we need two UTXOs for Carol so she can
// sweep both the local and remote anchor.
if commitTypeHasAnchors(ct) {
if lntest.CommitTypeHasAnchors(ct) {
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
}
@ -112,7 +112,7 @@ func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
dave: dave,
mnemonic: mnemonic,
password: password,
params: lntemp.OpenChannelParams{
params: lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
ZeroConf: zeroConf,
@ -123,7 +123,7 @@ func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
// restoreDave will call the `nodeRestorer` and asserts Dave is restored by
// checking his wallet balance against zero.
func (c *chanRestoreScenario) restoreDave(ht *lntemp.HarnessTest,
func (c *chanRestoreScenario) restoreDave(ht *lntest.HarnessTest,
restoredNodeFunc nodeRestorer) *node.HarnessNode {
// Next, we'll make a new Dave and start the bulk of our recovery
@ -154,7 +154,7 @@ func (c *chanRestoreScenario) restoreDave(ht *lntemp.HarnessTest,
// 4. validate pending channel state and check we cannot force close it.
// 5. validate Carol's UTXOs.
// 6. assert DLP is executed.
func (c *chanRestoreScenario) testScenario(ht *lntemp.HarnessTest,
func (c *chanRestoreScenario) testScenario(ht *lntest.HarnessTest,
restoredNodeFunc nodeRestorer) {
carol, dave := c.carol, c.dave
@ -212,7 +212,7 @@ func (c *chanRestoreScenario) testScenario(ht *lntemp.HarnessTest,
// let's start up Carol again.
require.NoError(ht, restartCarol(), "restart carol failed")
if commitTypeHasAnchors(c.params.CommitmentType) {
if lntest.CommitTypeHasAnchors(c.params.CommitmentType) {
ht.AssertNumUTXOs(carol, 2)
} else {
ht.AssertNumUTXOs(carol, 1)
@ -232,7 +232,7 @@ func (c *chanRestoreScenario) testScenario(ht *lntemp.HarnessTest,
// restoring from initial wallet creation. We'll also alternate between
// restoring form the on disk file, and restoring from the exported RPC command
// as well.
func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
func testChannelBackupRestoreBasic(ht *lntest.HarnessTest) {
var testCases = []struct {
name string
restoreMethod restoreMethodType
@ -241,7 +241,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
// was the initiator, of the non-advertised channel.
{
name: "restore from RPC backup",
restoreMethod: func(st *lntemp.HarnessTest,
restoreMethod: func(st *lntest.HarnessTest,
oldNode *node.HarnessNode,
backupFilePath string,
password []byte,
@ -269,7 +269,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
// interface.
{
name: "restore from backup file",
restoreMethod: func(st *lntemp.HarnessTest,
restoreMethod: func(st *lntest.HarnessTest,
oldNode *node.HarnessNode,
backupFilePath string,
password []byte,
@ -293,7 +293,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
// prior mnemonic and new backup seed.
{
name: "restore during creation",
restoreMethod: func(st *lntemp.HarnessTest,
restoreMethod: func(st *lntest.HarnessTest,
oldNode *node.HarnessNode,
backupFilePath string,
password []byte,
@ -325,7 +325,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
// re-created, using the Unlock call.
{
name: "restore during unlock",
restoreMethod: func(st *lntemp.HarnessTest,
restoreMethod: func(st *lntest.HarnessTest,
oldNode *node.HarnessNode,
backupFilePath string,
password []byte,
@ -362,7 +362,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
// make sure imports can be canceled and later resumed.
{
name: "restore from backup file twice",
restoreMethod: func(st *lntemp.HarnessTest,
restoreMethod: func(st *lntest.HarnessTest,
oldNode *node.HarnessNode,
backupFilePath string,
password []byte,
@ -376,6 +376,8 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
// Now that we have Dave's backup file, we'll
// create a new nodeRestorer that will restore
// using the on-disk channel.backup.
//
//nolint:lll
backup := &lnrpc.RestoreChanBackupRequest_MultiChanBackup{
MultiChanBackup: multi,
}
@ -420,7 +422,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
// ensuring that after Dave restores his channel state according to the
// testCase, the DLP protocol is executed properly and both nodes are made
// whole.
func runChanRestoreScenarioBasic(ht *lntemp.HarnessTest,
func runChanRestoreScenarioBasic(ht *lntest.HarnessTest,
restoreMethod restoreMethodType) {
// Create a new retore scenario.
@ -445,7 +447,7 @@ func runChanRestoreScenarioBasic(ht *lntemp.HarnessTest,
// testChannelBackupRestoreUnconfirmed tests that we're able to restore from
// disk file and the exported RPC command for unconfirmed channel.
func testChannelBackupRestoreUnconfirmed(ht *lntemp.HarnessTest) {
func testChannelBackupRestoreUnconfirmed(ht *lntest.HarnessTest) {
// Use the channel backup file that contains an unconfirmed channel and
// make sure recovery works as well.
ht.Run("restore unconfirmed channel file", func(t *testing.T) {
@ -463,7 +465,7 @@ func testChannelBackupRestoreUnconfirmed(ht *lntemp.HarnessTest) {
// runChanRestoreScenarioUnConfirmed checks that Dave is able to restore for an
// unconfirmed channel.
func runChanRestoreScenarioUnConfirmed(ht *lntemp.HarnessTest, useFile bool) {
func runChanRestoreScenarioUnConfirmed(ht *lntest.HarnessTest, useFile bool) {
// Create a new retore scenario.
crs := newChanRestoreScenario(
ht, lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE, false,
@ -527,7 +529,7 @@ func runChanRestoreScenarioUnConfirmed(ht *lntemp.HarnessTest, useFile bool) {
// testChannelBackupRestoreCommitTypes tests that we're able to recover from,
// and initiate the DLP protocol for different channel commitment types and
// zero-conf channel.
func testChannelBackupRestoreCommitTypes(ht *lntemp.HarnessTest) {
func testChannelBackupRestoreCommitTypes(ht *lntest.HarnessTest) {
var testCases = []struct {
name string
ct lnrpc.CommitmentType
@ -584,7 +586,7 @@ func testChannelBackupRestoreCommitTypes(ht *lntemp.HarnessTest) {
// runChanRestoreScenarioCommitTypes tests that the DLP is applied for
// different channel commitment types and zero-conf channel.
func runChanRestoreScenarioCommitTypes(ht *lntemp.HarnessTest,
func runChanRestoreScenarioCommitTypes(ht *lntest.HarnessTest,
ct lnrpc.CommitmentType, zeroConf bool) {
// Create a new retore scenario.
@ -606,7 +608,7 @@ func runChanRestoreScenarioCommitTypes(ht *lntemp.HarnessTest,
_, minerHeight := ht.Miner.GetBestBlock()
thawHeight := uint32(minerHeight + thawHeightDelta)
fundingShim, _, _ = deriveFundingShim(
fundingShim, _ = deriveFundingShim(
ht, dave, carol, crs.params.Amt, thawHeight, true,
)
crs.params.FundingShim = fundingShim
@ -639,7 +641,7 @@ func runChanRestoreScenarioCommitTypes(ht *lntemp.HarnessTest,
// testChannelBackupRestoreLegacy checks a channel with the legacy revocation
// producer format and makes sure old SCBs can still be recovered.
func testChannelBackupRestoreLegacy(ht *lntemp.HarnessTest) {
func testChannelBackupRestoreLegacy(ht *lntest.HarnessTest) {
// Create a new retore scenario.
crs := newChanRestoreScenario(
ht, lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE, false,
@ -668,7 +670,7 @@ func testChannelBackupRestoreLegacy(ht *lntemp.HarnessTest) {
// testChannelBackupRestoreForceClose checks that Dave can restore from force
// closed channels.
func testChannelBackupRestoreForceClose(ht *lntemp.HarnessTest) {
func testChannelBackupRestoreForceClose(ht *lntest.HarnessTest) {
// Restore a channel that was force closed by dave just before going
// offline.
success := ht.Run("from backup file anchors", func(t *testing.T) {
@ -691,7 +693,7 @@ func testChannelBackupRestoreForceClose(ht *lntemp.HarnessTest) {
// runChanRestoreScenarioForceClose creates anchor-enabled force close channels
// and checks that Dave is able to restore from them.
func runChanRestoreScenarioForceClose(ht *lntemp.HarnessTest, zeroConf bool) {
func runChanRestoreScenarioForceClose(ht *lntest.HarnessTest, zeroConf bool) {
crs := newChanRestoreScenario(
ht, lnrpc.CommitmentType_ANCHORS, zeroConf,
)
@ -792,7 +794,7 @@ func runChanRestoreScenarioForceClose(ht *lntemp.HarnessTest, zeroConf bool) {
// testChannelBackupUpdates tests that both the streaming channel update RPC,
// and the on-disk channel.backup are updated each time a channel is
// opened/closed.
func testChannelBackupUpdates(ht *lntemp.HarnessTest) {
func testChannelBackupUpdates(ht *lntest.HarnessTest) {
alice := ht.Alice
// First, we'll make a temp directory that we'll use to store our
@ -850,7 +852,7 @@ func testChannelBackupUpdates(ht *lntemp.HarnessTest) {
chanAmt := btcutil.Amount(1000000)
for i := 0; i < numChans; i++ {
chanPoint := ht.OpenChannel(
alice, carol, lntemp.OpenChannelParams{Amt: chanAmt},
alice, carol, lntest.OpenChannelParams{Amt: chanAmt},
)
chanPoints = append(chanPoints, chanPoint)
}
@ -962,7 +964,7 @@ func testChannelBackupUpdates(ht *lntemp.HarnessTest) {
// testExportChannelBackup tests that we're able to properly export either a
// targeted channel's backup, or export backups of all the currents open
// channels.
func testExportChannelBackup(ht *lntemp.HarnessTest) {
func testExportChannelBackup(ht *lntest.HarnessTest) {
// First, we'll create our primary test node: Carol. We'll use Carol to
// open channels and also export backups that we'll examine throughout
// the test.
@ -979,7 +981,7 @@ func testExportChannelBackup(ht *lntemp.HarnessTest) {
chanAmt := btcutil.Amount(1000000)
for i := 0; i < numChans; i++ {
chanPoint := ht.OpenChannel(
alice, carol, lntemp.OpenChannelParams{Amt: chanAmt},
alice, carol, lntest.OpenChannelParams{Amt: chanAmt},
)
chanPoints = append(chanPoints, chanPoint)
}
@ -1022,17 +1024,20 @@ func testExportChannelBackup(ht *lntemp.HarnessTest) {
require.NoError(ht, err, "timeout checking num single backup")
}
assertMultiBackupFound := func() func(bool, map[wire.OutPoint]struct{}) {
assertMultiBackupFound := func() func(bool,
map[wire.OutPoint]struct{}) {
chanSnapshot := carol.RPC.ExportAllChanBackups()
return func(found bool, chanPoints map[wire.OutPoint]struct{}) {
num := len(chanSnapshot.MultiChanBackup.MultiChanBackup)
switch {
case found && chanSnapshot.MultiChanBackup == nil:
require.Fail(ht, "multi-backup not present")
case !found && chanSnapshot.MultiChanBackup != nil &&
(len(chanSnapshot.MultiChanBackup.MultiChanBackup) !=
chanbackup.NilMultiSizePacked):
num != chanbackup.NilMultiSizePacked:
require.Fail(ht, "found multi-backup when "+
"non should be found")
@ -1086,7 +1091,7 @@ func testExportChannelBackup(ht *lntemp.HarnessTest) {
// relationship lost state, they will detect this during channel sync, and the
// up-to-date party will force close the channel, giving the outdated party the
// opportunity to sweep its output.
func testDataLossProtection(ht *lntemp.HarnessTest) {
func testDataLossProtection(ht *lntest.HarnessTest) {
const (
chanAmt = funding.MaxBtcFundingAmount
paymentAmt = 10000
@ -1107,22 +1112,20 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
// directly from the miner.
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
// timeTravel is a method that will make Carol open a channel to the
// passed node, settle a series of payments, then reset the node back
// to the state before the payments happened. When this method returns
// the node will be unaware of the new state updates. The returned
// function can be used to restart the node in this state.
timeTravel := func(node *node.HarnessNode) (func() error,
*lnrpc.ChannelPoint, int64) {
// timeTravelDave is a method that will make Carol open a channel to
// Dave, settle a series of payments, then Dave back to the state
// before the payments happened. When this method returns Dave will
// be unaware of the new state updates. The returned function can be
// used to restart Dave in this state.
timeTravelDave := func() (func() error, *lnrpc.ChannelPoint, int64) {
// We must let the node communicate with Carol before they are
// able to open channel, so we connect them.
ht.EnsureConnected(carol, node)
ht.EnsureConnected(carol, dave)
// We'll first open up a channel between them with a 0.5 BTC
// value.
chanPoint := ht.OpenChannel(
carol, node, lntemp.OpenChannelParams{
carol, dave, lntest.OpenChannelParams{
Amt: chanAmt,
},
)
@ -1132,17 +1135,17 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
// the channel.
// TODO(halseth): have dangling HTLCs on the commitment, able to
// retrieve funds?
payReqs, _, _ := ht.CreatePayReqs(node, paymentAmt, numInvoices)
payReqs, _, _ := ht.CreatePayReqs(dave, paymentAmt, numInvoices)
// Send payments from Carol using 3 of the payment hashes
// generated above.
ht.CompletePaymentRequests(carol, payReqs[:numInvoices/2])
// Next query for the node's channel state, as we sent 3
// payments of 10k satoshis each, it should now see his balance
// as being 30k satoshis.
// Next query for Dave's channel state, as we sent 3 payments
// of 10k satoshis each, it should now see his balance as being
// 30k satoshis.
nodeChan := ht.AssertChannelLocalBalance(
node, chanPoint, 30_000,
dave, chanPoint, 30_000,
)
// Grab the current commitment height (update number), we'll
@ -1153,39 +1156,46 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
// With the temporary file created, copy the current state into
// the temporary file we created above. Later after more
// updates, we'll restore this state.
ht.BackupDB(node)
ht.BackupDB(dave)
// Reconnect the peers after the restart that was needed for
// the db backup.
ht.EnsureConnected(carol, node)
ht.EnsureConnected(carol, dave)
// Finally, send more payments from , using the remaining
// Finally, send more payments from Carol, using the remaining
// payment hashes.
ht.CompletePaymentRequests(carol, payReqs[numInvoices/2:])
// Now we shutdown the node, copying over the its temporary
// TODO(yy): remove the sleep once the following bug is fixed.
//
// While the payment is reported as settled, the commitment
// dance may not be finished, which leaves several HTLCs in the
// commitment. Later on, when Carol force closes this channel,
// she would have HTLCs there and the test won't pass.
time.Sleep(2 * time.Second)
// Now we shutdown Dave, copying over the its temporary
// database state which has the *prior* channel state over his
// current most up to date state. With this, we essentially
// force the node to travel back in time within the channel's
// force Dave to travel back in time within the channel's
// history.
ht.RestartNodeAndRestoreDB(node)
ht.RestartNodeAndRestoreDB(dave)
// Make sure the channel is still there from the PoV of the
// node.
ht.AssertNodeNumChannels(node, 1)
// Make sure the channel is still there from the PoV of Dave.
ht.AssertNodeNumChannels(dave, 1)
// Now query for the channel state, it should show that it's at
// a state number in the past, not the *latest* state.
ht.AssertChannelNumUpdates(node, stateNumPreCopy, chanPoint)
ht.AssertChannelNumUpdates(dave, stateNumPreCopy, chanPoint)
balResp := node.RPC.WalletBalance()
restart := ht.SuspendNode(node)
balResp := dave.RPC.WalletBalance()
restart := ht.SuspendNode(dave)
return restart, chanPoint, balResp.ConfirmedBalance
}
// Reset Dave to a state where he has an outdated channel state.
restartDave, _, daveStartingBalance := timeTravel(dave)
restartDave, _, daveStartingBalance := timeTravelDave()
// We make a note of the nodes' current on-chain balances, to make sure
// they are able to retrieve the channel funds eventually,
@ -1209,7 +1219,7 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
// closed channel, such that Dave can retrieve his funds.
//
// We start by letting Dave time travel back to an outdated state.
restartDave, chanPoint2, daveStartingBalance := timeTravel(dave)
restartDave, chanPoint2, daveStartingBalance := timeTravelDave()
carolBalResp = carol.RPC.WalletBalance()
carolStartingBalance = carolBalResp.ConfirmedBalance
@ -1255,7 +1265,7 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
// createLegacyRevocationChannel creates a single channel using the legacy
// revocation producer format by using PSBT to signal a special pending channel
// ID.
func createLegacyRevocationChannel(ht *lntemp.HarnessTest,
func createLegacyRevocationChannel(ht *lntest.HarnessTest,
chanAmt, pushAmt btcutil.Amount, from, to *node.HarnessNode) {
// We'll signal to the wallet that we also want to create a channel
@ -1277,7 +1287,7 @@ func createLegacyRevocationChannel(ht *lntemp.HarnessTest,
},
},
}
openChannelReq := lntemp.OpenChannelParams{
openChannelReq := lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
FundingShim: shim,
@ -1295,8 +1305,9 @@ func createLegacyRevocationChannel(ht *lntemp.HarnessTest,
}
fundResp := from.RPC.FundPsbt(fundReq)
// We have a PSBT that has no witness data yet, which is exactly what we
// need for the next step of verifying the PSBT with the funding intents.
// We have a PSBT that has no witness data yet, which is exactly what
// we need for the next step of verifying the PSBT with the funding
// intents.
msg := &lnrpc.FundingTransitionMsg{
Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{
PsbtVerify: &lnrpc.FundingPsbtVerify{
@ -1345,7 +1356,7 @@ func createLegacyRevocationChannel(ht *lntemp.HarnessTest,
// chanRestoreViaRPC is a helper test method that returns a nodeRestorer
// instance which will restore the target node from a password+seed, then
// trigger a SCB restore using the RPC interface.
func chanRestoreViaRPC(ht *lntemp.HarnessTest, password []byte,
func chanRestoreViaRPC(ht *lntest.HarnessTest, password []byte,
mnemonic []string, multi []byte,
oldNode *node.HarnessNode) nodeRestorer {
@ -1382,7 +1393,7 @@ func copyPorts(oldNode *node.HarnessNode) node.Option {
//
// Note: this function is only used in this test file and has been made
// specifically for testChanRestoreScenario.
func assertTimeLockSwept(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode,
func assertTimeLockSwept(ht *lntest.HarnessTest, carol, dave *node.HarnessNode,
carolStartingBalance, daveStartingBalance int64) {
// We expect Carol to sweep her funds and also the anchor tx.
@ -1450,11 +1461,13 @@ func assertTimeLockSwept(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode,
// funds immediately, and Carol sweeping her fund after her CSV delay is up. If
// the blankSlate value is true, then this means that Dave won't need to sweep
// on chain as he has no funds in the channel.
func assertDLPExecuted(ht *lntemp.HarnessTest,
func assertDLPExecuted(ht *lntest.HarnessTest,
carol *node.HarnessNode, carolStartingBalance int64,
dave *node.HarnessNode, daveStartingBalance int64,
commitType lnrpc.CommitmentType) {
ht.Helper()
// Increase the fee estimate so that the following force close tx will
// be cpfp'ed.
ht.SetFeeEstimate(30000)
@ -1467,7 +1480,7 @@ func assertDLPExecuted(ht *lntemp.HarnessTest,
// Upon reconnection, the nodes should detect that Dave is out of sync.
// Carol should force close the channel using her latest commitment.
expectedTxes := 1
if commitTypeHasAnchors(commitType) {
if lntest.CommitTypeHasAnchors(commitType) {
expectedTxes = 2
}
ht.Miner.AssertNumTxsInMempool(expectedTxes)

View file

@ -7,8 +7,8 @@ import (
"github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/stretchr/testify/require"
@ -16,7 +16,7 @@ import (
// testChannelBalance creates a new channel between Alice and Bob, then checks
// channel balance to be equal amount specified while creation of channel.
func testChannelBalance(ht *lntemp.HarnessTest) {
func testChannelBalance(ht *lntest.HarnessTest) {
// Open a channel with 0.16 BTC between Alice and Bob, ensuring the
// channel has been opened properly.
amount := funding.MaxBtcFundingAmount
@ -52,16 +52,16 @@ func testChannelBalance(ht *lntemp.HarnessTest) {
ht.EnsureConnected(alice, bob)
chanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: amount},
alice, bob, lntest.OpenChannelParams{Amt: amount},
)
cType := ht.GetChannelCommitType(alice, chanPoint)
// As this is a single funder channel, Alice's balance should be
// exactly 0.5 BTC since now state transitions have taken place yet.
checkChannelBalance(alice, amount-calcStaticFee(cType, 0), 0)
checkChannelBalance(alice, amount-lntest.CalcStaticFee(cType, 0), 0)
// Ensure Bob currently has no available balance within the channel.
checkChannelBalance(bob, 0, amount-calcStaticFee(cType, 0))
checkChannelBalance(bob, 0, amount-lntest.CalcStaticFee(cType, 0))
// Finally close the channel between Alice and Bob, asserting that the
// channel has been properly closed on-chain.
@ -73,7 +73,7 @@ func testChannelBalance(ht *lntemp.HarnessTest) {
// Alice will send Htlcs to Carol while she is in hodl mode. This will result
// in a build of pending Htlcs. We expect the channels unsettled balance to
// equal the sum of all the Pending Htlcs.
func testChannelUnsettledBalance(ht *lntemp.HarnessTest) {
func testChannelUnsettledBalance(ht *lntest.HarnessTest) {
const chanAmt = btcutil.Amount(1000000)
// Creates a helper closure to be used below which asserts the proper
@ -123,17 +123,21 @@ func testChannelUnsettledBalance(ht *lntemp.HarnessTest) {
// Open a channel between Alice and Carol.
chanPointAlice := ht.OpenChannel(
alice, carol, lntemp.OpenChannelParams{Amt: chanAmt},
alice, carol, lntest.OpenChannelParams{Amt: chanAmt},
)
cType := ht.GetChannelCommitType(alice, chanPointAlice)
// Check alice's channel balance, which should have zero remote and zero
// pending balance.
checkChannelBalance(alice, chanAmt-calcStaticFee(cType, 0), 0, 0, 0)
checkChannelBalance(
alice, chanAmt-lntest.CalcStaticFee(cType, 0), 0, 0, 0,
)
// Check carol's channel balance, which should have zero local and zero
// pending balance.
checkChannelBalance(carol, 0, chanAmt-calcStaticFee(cType, 0), 0, 0)
checkChannelBalance(
carol, 0, chanAmt-lntest.CalcStaticFee(cType, 0), 0, 0,
)
// Channel should be ready for payments.
const (
@ -195,7 +199,8 @@ func testChannelUnsettledBalance(ht *lntemp.HarnessTest) {
// Check alice's channel balance, which should have a remote unsettled
// balance that equals to the amount of invoices * payAmt. The remote
// balance remains zero.
aliceLocal := chanAmt - calcStaticFee(cType, 0) - numInvoices*payAmt
fee := lntest.CalcStaticFee(cType, 0)
aliceLocal := chanAmt - fee - numInvoices*payAmt
checkChannelBalance(alice, aliceLocal, 0, 0, numInvoices*payAmt)
// Check carol's channel balance, which should have a local unsettled

View file

@ -13,8 +13,8 @@ import (
"github.com/lightningnetwork/lnd/chainreg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
@ -30,7 +30,7 @@ import (
//
// Note that whether the deadline is used or not is implicitly checked by its
// corresponding fee rates.
func testCommitmentTransactionDeadline(ht *lntemp.HarnessTest) {
func testCommitmentTransactionDeadline(ht *lntest.HarnessTest) {
// Get the default max fee rate used in sweeping the commitment
// transaction.
defaultMax := lnwallet.DefaultAnchorsCommitMaxFeeRateSatPerVByte
@ -72,7 +72,7 @@ func testCommitmentTransactionDeadline(ht *lntemp.HarnessTest) {
setupNode := func(name string) *node.HarnessNode {
// Create the node.
args := []string{"--hodl.exit-settle"}
args = append(args, nodeArgsForCommitType(
args = append(args, lntest.NodeArgsForCommitType(
lnrpc.CommitmentType_ANCHORS)...,
)
node := ht.NewNode(name, args)
@ -104,7 +104,7 @@ func testCommitmentTransactionDeadline(ht *lntemp.HarnessTest) {
// Open a channel between Alice and Bob.
chanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: 10e6,
PushAmt: 5e6,
},
@ -194,7 +194,7 @@ func testCommitmentTransactionDeadline(ht *lntemp.HarnessTest) {
// process.
//
// TODO(roasbeef): also add an unsettled HTLC before force closing.
func testChannelForceClosure(ht *lntemp.HarnessTest) {
func testChannelForceClosure(ht *lntest.HarnessTest) {
// We'll test the scenario for some of the commitment types, to ensure
// outputs can be swept.
commitTypes := []lnrpc.CommitmentType{
@ -209,7 +209,7 @@ func testChannelForceClosure(ht *lntemp.HarnessTest) {
success := ht.Run(testName, func(t *testing.T) {
st := ht.Subtest(t)
args := nodeArgsForCommitType(channelType)
args := lntest.NodeArgsForCommitType(channelType)
alice := st.NewNode("Alice", args)
defer st.Shutdown(alice)
@ -237,7 +237,7 @@ func testChannelForceClosure(ht *lntemp.HarnessTest) {
}
}
func channelForceClosureTest(ht *lntemp.HarnessTest,
func channelForceClosureTest(ht *lntest.HarnessTest,
alice, carol *node.HarnessNode, channelType lnrpc.CommitmentType) {
const (
@ -268,7 +268,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
carolStartingBalance := carolBalResp.ConfirmedBalance
chanPoint := ht.OpenChannel(
alice, carol, lntemp.OpenChannelParams{
alice, carol, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
},
@ -600,6 +600,20 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
// Update current height
_, curHeight = ht.Miner.GetBestBlock()
// checkForceClosedChannelNumHtlcs verifies that a force closed channel
// has the proper number of htlcs.
checkPendingChannelNumHtlcs := func(
forceClose lntest.PendingForceClose) error {
if len(forceClose.PendingHtlcs) != numInvoices {
return fmt.Errorf("expected force closed channel to "+
"have %d pending htlcs, found %d instead",
numInvoices, len(forceClose.PendingHtlcs))
}
return nil
}
err = wait.NoError(func() error {
// Now that the commit output has been fully swept, check to
// see that the channel remains open for the pending htlc
@ -611,7 +625,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
// The commitment funds will have been recovered after the
// commit txn was included in the last block. The htlc funds
// will be shown in limbo.
err := checkPendingChannelNumHtlcs(forceClose, numInvoices)
err := checkPendingChannelNumHtlcs(forceClose)
if err != nil {
return err
}
@ -659,7 +673,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
// We should now be at the block just before the utxo nursery
// will attempt to broadcast the htlc timeout transactions.
err = checkPendingChannelNumHtlcs(forceClose, numInvoices)
err = checkPendingChannelNumHtlcs(forceClose)
if err != nil {
return err
}
@ -702,9 +716,9 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
// Retrieve each htlc timeout txn from the mempool, and ensure it is
// well-formed. This entails verifying that each only spends from
// output, and that that output is from the commitment txn. In case
// this is an anchor channel, the transactions are aggregated by the
// sweeper into one.
// output, and that output is from the commitment txn. In case this is
// an anchor channel, the transactions are aggregated by the sweeper
// into one.
numInputs := 1
if channelType == lnrpc.CommitmentType_ANCHORS {
numInputs = numInvoices + 1
@ -796,7 +810,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
// We record the htlc amount less fees here, so that we know
// what value to expect for the second stage of our htlc
// htlc resolution.
// resolution.
htlcLessFees = uint64(outputs[0].Value)
}
@ -838,7 +852,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
return fmt.Errorf("htlc funds should still be in limbo")
}
return checkPendingChannelNumHtlcs(forceClose, numInvoices)
return checkPendingChannelNumHtlcs(forceClose)
}, defaultTimeout)
require.NoError(ht, err, "timeout while checking force closed channel")
@ -913,7 +927,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
forceClose := ht.AssertChannelPendingForceClose(
alice, chanPoint,
)
err := checkPendingChannelNumHtlcs(forceClose, numInvoices)
err := checkPendingChannelNumHtlcs(forceClose)
if err != nil {
return err
}
@ -986,7 +1000,7 @@ func padCLTV(cltv uint32) uint32 {
// testFailingChannel tests that we will fail the channel by force closing it
// in the case where a counterparty tries to settle an HTLC with the wrong
// preimage.
func testFailingChannel(ht *lntemp.HarnessTest) {
func testFailingChannel(ht *lntest.HarnessTest) {
const paymentAmt = 10000
chanAmt := lnd.MaxFundingAmount
@ -999,7 +1013,7 @@ func testFailingChannel(ht *lntemp.HarnessTest) {
ht.ConnectNodes(alice, carol)
// Let Alice connect and open a channel to Carol,
ht.OpenChannel(alice, carol, lntemp.OpenChannelParams{Amt: chanAmt})
ht.OpenChannel(alice, carol, lntest.OpenChannelParams{Amt: chanAmt})
// With the channel open, we'll create a invoice for Carol that Alice
// will attempt to pay.
@ -1058,7 +1072,7 @@ func testFailingChannel(ht *lntemp.HarnessTest) {
// type matches a set of expected resolutions.
//
// NOTE: only used in current test file.
func assertReports(ht *lntemp.HarnessTest, hn *node.HarnessNode,
func assertReports(ht *lntest.HarnessTest, hn *node.HarnessNode,
chanPoint *lnrpc.ChannelPoint, expected map[string]*lnrpc.Resolution) {
op := ht.OutPointFromChannelPoint(chanPoint)
@ -1087,3 +1101,54 @@ func assertReports(ht *lntemp.HarnessTest, hn *node.HarnessNode,
require.Equal(ht, expected, res)
}
}
// checkCommitmentMaturity checks that both the maturity height and blocks
// maturity height are as expected.
//
// NOTE: only used in current test file.
func checkCommitmentMaturity(forceClose lntest.PendingForceClose,
maturityHeight uint32, blocksTilMaturity int32) error {
if forceClose.MaturityHeight != maturityHeight {
return fmt.Errorf("expected commitment maturity height to be "+
"%d, found %d instead", maturityHeight,
forceClose.MaturityHeight)
}
if forceClose.BlocksTilMaturity != blocksTilMaturity {
return fmt.Errorf("expected commitment blocks til maturity to "+
"be %d, found %d instead", blocksTilMaturity,
forceClose.BlocksTilMaturity)
}
return nil
}
// checkPendingHtlcStageAndMaturity uniformly tests all pending htlc's belonging
// to a force closed channel, testing for the expected stage number, blocks till
// maturity, and the maturity height.
//
// NOTE: only used in current test file.
func checkPendingHtlcStageAndMaturity(
forceClose *lnrpc.PendingChannelsResponse_ForceClosedChannel,
stage, maturityHeight uint32, blocksTillMaturity int32) error {
for _, pendingHtlc := range forceClose.PendingHtlcs {
if pendingHtlc.Stage != stage {
return fmt.Errorf("expected pending htlc to be stage "+
"%d, found %d", stage, pendingHtlc.Stage)
}
if pendingHtlc.MaturityHeight != maturityHeight {
return fmt.Errorf("expected pending htlc maturity "+
"height to be %d, instead has %d",
maturityHeight, pendingHtlc.MaturityHeight)
}
if pendingHtlc.BlocksTilMaturity != blocksTillMaturity {
return fmt.Errorf("expected pending htlc blocks til "+
"maturity to be %d, instead has %d",
blocksTillMaturity,
pendingHtlc.BlocksTilMaturity)
}
}
return nil
}

View file

@ -11,8 +11,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/peersrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/stretchr/testify/require"
)
@ -40,7 +40,7 @@ import (
// take more than 5 seconds to finish, the channel will be marked as disabled,
// thus a following operation will fail if it relies on the channel being
// enabled.
func testUpdateChanStatus(ht *lntemp.HarnessTest) {
func testUpdateChanStatus(ht *lntest.HarnessTest) {
// Create two fresh nodes and open a channel between them.
alice, bob := ht.Alice, ht.Bob
args := []string{
@ -57,7 +57,7 @@ func testUpdateChanStatus(ht *lntemp.HarnessTest) {
// being the sole funder of the channel.
chanAmt := btcutil.Amount(100000)
chanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
)
defer ht.CloseChannel(alice, chanPoint)
@ -141,7 +141,7 @@ func testUpdateChanStatus(ht *lntemp.HarnessTest) {
FeeRateMilliMsat: int64(chainreg.DefaultBitcoinFeeRate),
TimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta,
MinHtlc: 1000, // default value
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
}
// Manually disable the channel and ensure that a "Disabled = true"
@ -217,14 +217,14 @@ func testUpdateChanStatus(ht *lntemp.HarnessTest) {
// testUnannouncedChannels checks unannounced channels are not returned by
// describeGraph RPC request unless explicitly asked for.
func testUnannouncedChannels(ht *lntemp.HarnessTest) {
func testUnannouncedChannels(ht *lntest.HarnessTest) {
amount := funding.MaxBtcFundingAmount
alice, bob := ht.Alice, ht.Bob
// Open a channel between Alice and Bob, ensuring the
// channel has been opened properly.
chanOpenUpdate := ht.OpenChannelAssertStream(
alice, bob, lntemp.OpenChannelParams{Amt: amount},
alice, bob, lntest.OpenChannelParams{Amt: amount},
)
// Mine 2 blocks, and check that the channel is opened but not yet
@ -252,7 +252,7 @@ func testUnannouncedChannels(ht *lntemp.HarnessTest) {
ht.CloseChannel(alice, fundingChanPoint)
}
func testGraphTopologyNotifications(ht *lntemp.HarnessTest) {
func testGraphTopologyNotifications(ht *lntest.HarnessTest) {
ht.Run("pinned", func(t *testing.T) {
subT := ht.Subtest(t)
testGraphTopologyNtfns(subT, true)
@ -263,7 +263,7 @@ func testGraphTopologyNotifications(ht *lntemp.HarnessTest) {
})
}
func testGraphTopologyNtfns(ht *lntemp.HarnessTest, pinned bool) {
func testGraphTopologyNtfns(ht *lntest.HarnessTest, pinned bool) {
const chanAmt = funding.MaxBtcFundingAmount
// Spin up Bob first, since we will need to grab his pubkey when
@ -305,7 +305,7 @@ func testGraphTopologyNtfns(ht *lntemp.HarnessTest, pinned bool) {
// Open a new channel between Alice and Bob.
chanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
)
// The channel opening above should have triggered a few notifications
@ -335,17 +335,30 @@ func testGraphTopologyNtfns(ht *lntemp.HarnessTest, pinned bool) {
// For the final portion of the test, we'll ensure that once a new node
// appears in the network, the proper notification is dispatched. Note
// that a node that does not have any channels open is ignored, so first
// we disconnect Alice and Bob, open a channel between Bob and Carol,
// and finally connect Alice to Bob again.
ht.DisconnectNodes(alice, bob)
// that a node that does not have any channels open is ignored, so
// first we disconnect Alice and Bob, open a channel between Bob and
// Carol, and finally connect Alice to Bob again.
ht.DisconnectNodes(bob, alice)
// Since Alice and Bob has a permanent connection, the above
// disconnection won't be enough as Alice will try to reconnect to Bob
// again. Atm, it seems nothing is stopping the reconnection. So we
// need to shutdown Alice here.
//
// TODO(yy): clearly define what `disconnectpeer` rpc is responsible
// for and its effect. If we disconnect a peer, we shouldn't allow the
// peer to connect to us again.
restartAlice := ht.SuspendNode(alice)
carol := ht.NewNode("Carol", nil)
ht.ConnectNodes(bob, carol)
chanPoint = ht.OpenChannel(
bob, carol, lntemp.OpenChannelParams{Amt: chanAmt},
bob, carol, lntest.OpenChannelParams{Amt: chanAmt},
)
// Restart Alice so she can receive the channel updates from Bob.
require.NoError(ht, restartAlice(), "failed to restart Alice")
// Reconnect Alice and Bob. This should result in the nodes syncing up
// their respective graph state, with the new addition being the
// existence of Carol in the graph, and also the channel between Bob
@ -366,7 +379,7 @@ func testGraphTopologyNtfns(ht *lntemp.HarnessTest, pinned bool) {
// testNodeAnnouncement ensures that when a node is started with one or more
// external IP addresses specified on the command line, that those addresses
// announced to the network and reported in the network graph.
func testNodeAnnouncement(ht *lntemp.HarnessTest) {
func testNodeAnnouncement(ht *lntest.HarnessTest) {
alice, bob := ht.Alice, ht.Bob
advertisedAddrs := []string{
@ -392,7 +405,7 @@ func testNodeAnnouncement(ht *lntemp.HarnessTest) {
// ensures that Alice receives the node announcement from Bob as part of
// the announcement broadcast.
chanPoint := ht.OpenChannel(
bob, dave, lntemp.OpenChannelParams{Amt: 1000000},
bob, dave, lntest.OpenChannelParams{Amt: 1000000},
)
assertAddrs := func(addrsFound []string, targetAddrs ...string) {
@ -421,7 +434,7 @@ func testNodeAnnouncement(ht *lntemp.HarnessTest) {
// testUpdateNodeAnnouncement ensures that the RPC endpoint validates
// the requests correctly and that the new node announcement is brodcasted
// with the right information after updating our node.
func testUpdateNodeAnnouncement(ht *lntemp.HarnessTest) {
func testUpdateNodeAnnouncement(ht *lntest.HarnessTest) {
alice, bob := ht.Alice, ht.Bob
var lndArgs []string
@ -500,7 +513,7 @@ func testUpdateNodeAnnouncement(ht *lntemp.HarnessTest) {
// ensures that Alice receives the node announcement from Bob as part of
// the announcement broadcast.
chanPoint := ht.OpenChannel(
bob, dave, lntemp.OpenChannelParams{
bob, dave, lntest.OpenChannelParams{
Amt: 1000000,
},
)
@ -637,7 +650,7 @@ func testUpdateNodeAnnouncement(ht *lntemp.HarnessTest) {
// assertSyncType asserts that the peer has an expected syncType.
//
// NOTE: only made for tests in this file.
func assertSyncType(ht *lntemp.HarnessTest, hn *node.HarnessNode,
func assertSyncType(ht *lntest.HarnessTest, hn *node.HarnessNode,
peer string, syncType lnrpc.Peer_SyncType) {
resp := hn.RPC.ListPeers()
@ -693,7 +706,7 @@ func compareNodeAnns(n1, n2 *lnrpc.NodeUpdate) error {
// the response expected values.
//
// NOTE: only used for tests in this file.
func assertUpdateNodeAnnouncementResponse(ht *lntemp.HarnessTest,
func assertUpdateNodeAnnouncementResponse(ht *lntest.HarnessTest,
response *peersrpc.NodeAnnouncementUpdateResponse,
expectedOps map[string]int) {

View file

@ -10,37 +10,22 @@ import (
"github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/stretchr/testify/require"
)
// assertPolicyUpdate checks that a given policy update has been received by a
// list of given nodes.
// TODO(yy): delete.
func assertPolicyUpdate(t *harnessTest, nodes []*lntest.HarnessNode,
advertisingNode string, policy *lnrpc.RoutingPolicy,
chanPoint *lnrpc.ChannelPoint) {
for _, node := range nodes {
assertChannelPolicyUpdate(
t.t, node, advertisingNode, policy, chanPoint, false,
)
}
}
// testUpdateChannelPolicy tests that policy updates made to a channel
// gets propagated to other nodes in the network.
func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
func testUpdateChannelPolicy(ht *lntest.HarnessTest) {
const (
defaultFeeBase = 1000
defaultFeeRate = 1
defaultTimeLockDelta = chainreg.DefaultBitcoinTimeLockDelta
defaultMinHtlc = 1000
)
defaultMaxHtlc := calculateMaxHtlc(funding.MaxBtcFundingAmount)
defaultMaxHtlc := lntest.CalculateMaxHtlc(funding.MaxBtcFundingAmount)
chanAmt := funding.MaxBtcFundingAmount
pushAmt := chanAmt / 2
@ -49,7 +34,7 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
// Create a channel Alice->Bob.
chanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
},
@ -102,7 +87,7 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
// part of his ChannelUpdate.
const customMinHtlc = 5000
chanPoint2 := ht.OpenChannel(
carol, bob, lntemp.OpenChannelParams{
carol, bob, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
MinHtlc: customMinHtlc,
@ -182,9 +167,9 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
payAmt = btcutil.Amount(4)
amtSat := int64(payAmt)
amtMSat := int64(lnwire.NewMSatFromSatoshis(payAmt))
routes.Routes[0].Hops[0].AmtToForward = amtSat // nolint:staticcheck
routes.Routes[0].Hops[0].AmtToForward = amtSat
routes.Routes[0].Hops[0].AmtToForwardMsat = amtMSat
routes.Routes[0].Hops[1].AmtToForward = amtSat // nolint:staticcheck
routes.Routes[0].Hops[1].AmtToForward = amtSat
routes.Routes[0].Hops[1].AmtToForwardMsat = amtMSat
// Send the payment with the modified value.
@ -215,9 +200,9 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
payAmt = btcutil.Amount(5)
amtSat = int64(payAmt)
amtMSat = int64(lnwire.NewMSatFromSatoshis(payAmt))
routes.Routes[0].Hops[0].AmtToForward = amtSat // nolint:staticcheck
routes.Routes[0].Hops[0].AmtToForward = amtSat
routes.Routes[0].Hops[0].AmtToForwardMsat = amtMSat
routes.Routes[0].Hops[1].AmtToForward = amtSat // nolint:staticcheck
routes.Routes[0].Hops[1].AmtToForward = amtSat
routes.Routes[0].Hops[1].AmtToForwardMsat = amtMSat
// Manually set the MPP payload a new for each payment since
@ -298,7 +283,7 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
// We'll now open a channel from Alice directly to Carol.
ht.ConnectNodes(alice, carol)
chanPoint3 := ht.OpenChannel(
alice, carol, lntemp.OpenChannelParams{
alice, carol, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
},
@ -439,7 +424,7 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
// chan-disable-timeout flags here. For instance, if some operations take more
// than 6 seconds to finish, the channel will be marked as disabled, thus a
// following operation will fail if it relies on the channel being enabled.
func testSendUpdateDisableChannel(ht *lntemp.HarnessTest) {
func testSendUpdateDisableChannel(ht *lntest.HarnessTest) {
const chanAmt = 100000
alice, bob := ht.Alice, ht.Bob
@ -482,8 +467,8 @@ func testSendUpdateDisableChannel(ht *lntemp.HarnessTest) {
// We now proceed to open channels: Alice=>Bob, Alice=>Carol and
// Eve=>Carol.
p := lntemp.OpenChannelParams{Amt: chanAmt}
reqs := []*lntemp.OpenChannelRequest{
p := lntest.OpenChannelParams{Amt: chanAmt}
reqs := []*lntest.OpenChannelRequest{
{Local: alice, Remote: bob, Param: p},
{Local: alice, Remote: carol, Param: p},
{Local: eve, Remote: carol, Param: p},
@ -528,7 +513,7 @@ func testSendUpdateDisableChannel(ht *lntemp.HarnessTest) {
FeeRateMilliMsat: int64(chainreg.DefaultBitcoinFeeRate),
TimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta,
MinHtlc: 1000, // default value
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
Disabled: true,
}
@ -670,7 +655,7 @@ func testSendUpdateDisableChannel(ht *lntemp.HarnessTest) {
// Bob will update the base fee via UpdateChannelPolicy, we will test that
// Alice will not fail the payment and send it using the updated channel
// policy.
func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
func testUpdateChannelPolicyForPrivateChannel(ht *lntest.HarnessTest) {
const (
chanAmt = btcutil.Amount(100000)
paymentAmt = 20000
@ -683,7 +668,7 @@ func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
// Open a channel with 100k satoshis between Alice and Bob.
chanPointAliceBob := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: chanAmt,
},
)
@ -696,7 +681,7 @@ func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
// Open a channel with 100k satoshis between Bob and Carol.
chanPointBobCarol := ht.OpenChannel(
bob, carol, lntemp.OpenChannelParams{
bob, carol, lntest.OpenChannelParams{
Amt: chanAmt,
Private: true,
},
@ -729,6 +714,19 @@ func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
// Alice pays the invoices. She will use the updated baseFeeMSat in the
// payment
//
// TODO(yy): we may get a flake saying the timeout checking the
// payment's state, which is due to slow round of HTLC settlement. An
// example log is shown below, where Alice sent RevokeAndAck to Bob,
// but it took Bob 7 seconds to reply back the final UpdateFulfillHTLC.
//
// 2022-11-14 06:23:59.774 PEER: Peer(Bob): Sending UpdateAddHTLC
// 2022-11-14 06:24:00.635 PEER: Peer(Bob): Sending CommitSig
// 2022-11-14 06:24:01.784 PEER: Peer(Bob): Sending RevokeAndAck
// 2022-11-14 06:24:08.464 PEER: Peer(Bob): Received UpdateFulfillHTLC
//
// 7 seconds is too long for a local test and this needs more
// investigation.
payReqs := []string{resp.PaymentRequest}
ht.CompletePaymentRequests(alice, payReqs)
@ -770,14 +768,14 @@ func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
// testUpdateChannelPolicyFeeRateAccuracy tests that updating the channel policy
// rounds fee rate values correctly as well as setting fee rate with ppm works
// as expected.
func testUpdateChannelPolicyFeeRateAccuracy(ht *lntemp.HarnessTest) {
func testUpdateChannelPolicyFeeRateAccuracy(ht *lntest.HarnessTest) {
chanAmt := funding.MaxBtcFundingAmount
pushAmt := chanAmt / 2
// Create a channel Alice -> Bob.
alice, bob := ht.Alice, ht.Bob
chanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
},
@ -841,7 +839,7 @@ func testUpdateChannelPolicyFeeRateAccuracy(ht *lntemp.HarnessTest) {
// assertNodesPolicyUpdate checks that a given policy update has been received
// by a list of given nodes.
func assertNodesPolicyUpdate(ht *lntemp.HarnessTest, nodes []*node.HarnessNode,
func assertNodesPolicyUpdate(ht *lntest.HarnessTest, nodes []*node.HarnessNode,
advertisingNode *node.HarnessNode, policy *lnrpc.RoutingPolicy,
chanPoint *lnrpc.ChannelPoint) {

View file

@ -5,7 +5,7 @@ import (
"time"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/stretchr/testify/require"
)
@ -13,7 +13,7 @@ import (
// testCustomMessage tests sending and receiving of overridden custom message
// types (within the message type range usually reserved for protocol messages)
// via the send and subscribe custom message APIs.
func testCustomMessage(ht *lntemp.HarnessTest) {
func testCustomMessage(ht *lntest.HarnessTest) {
alice, bob := ht.Alice, ht.Bob
var (
@ -82,7 +82,7 @@ func testCustomMessage(ht *lntemp.HarnessTest) {
require.Equal(ht, bob.PubKey[:], msg.Peer, "first msg "+
"peer wrong")
case <-time.After(defaultTimeout):
case <-time.After(lntest.DefaultTimeout):
ht.Fatalf("alice did not receive first custom message: %v",
msgType)
}
@ -151,7 +151,7 @@ func testCustomMessage(ht *lntemp.HarnessTest) {
require.Equal(ht, bob.PubKey[:], msg.Peer, "second "+
"message peer")
case <-time.After(defaultTimeout):
case <-time.After(lntest.DefaultTimeout):
ht.Fatalf("alice did not receive second custom message")
}
}

View file

@ -12,12 +12,12 @@ import (
"github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lncfg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/stretchr/testify/require"
)
func assertLeader(ht *lntemp.HarnessTest, observer cluster.LeaderElector,
func assertLeader(ht *lntest.HarnessTest, observer cluster.LeaderElector,
expected string) {
leader, err := observer.Leader(ht.Context())
@ -29,7 +29,7 @@ func assertLeader(ht *lntemp.HarnessTest, observer cluster.LeaderElector,
// testEtcdFailover tests that in a cluster setup where two LND nodes form a
// single cluster (sharing the same identity) one can hand over the leader role
// to the other (failing over after graceful shutdown or forceful abort).
func testEtcdFailover(ht *lntemp.HarnessTest) {
func testEtcdFailover(ht *lntest.HarnessTest) {
testCases := []struct {
name string
kill bool
@ -54,10 +54,10 @@ func testEtcdFailover(ht *lntemp.HarnessTest) {
}
}
func testEtcdFailoverCase(ht *lntemp.HarnessTest, kill bool) {
func testEtcdFailoverCase(ht *lntest.HarnessTest, kill bool) {
etcdCfg, cleanup, err := kvdb.StartEtcdTestBackend(
ht.T.TempDir(), uint16(lntest.NextAvailablePort()),
uint16(lntest.NextAvailablePort()), "",
ht.T.TempDir(), uint16(node.NextAvailablePort()),
uint16(node.NextAvailablePort()), "",
)
require.NoError(ht, err, "Failed to start etcd instance")
defer cleanup()
@ -91,7 +91,7 @@ func testEtcdFailoverCase(ht *lntemp.HarnessTest, kill bool) {
// Open a channel with 100k satoshis between Carol and Alice with Alice
// being the sole funder of the channel.
chanAmt := btcutil.Amount(100_000)
ht.OpenChannel(alice, carol1, lntemp.OpenChannelParams{Amt: chanAmt})
ht.OpenChannel(alice, carol1, lntest.OpenChannelParams{Amt: chanAmt})
// At this point Carol-1 is the elected leader, while Carol-2 will wait
// to become the leader when Carol-1 stops.

View file

@ -9,8 +9,8 @@ import (
"github.com/lightningnetwork/lnd/chainreg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/routing/route"
@ -34,7 +34,7 @@ type interceptorTestCase struct {
// testForwardInterceptorDedupHtlc tests that upon reconnection, duplicate
// HTLCs aren't re-notified using the HTLC interceptor API.
func testForwardInterceptorDedupHtlc(ht *lntemp.HarnessTest) {
func testForwardInterceptorDedupHtlc(ht *lntest.HarnessTest) {
// Initialize the test context with 3 connected nodes.
ts := newInterceptorTestScenario(ht)
@ -42,8 +42,8 @@ func testForwardInterceptorDedupHtlc(ht *lntemp.HarnessTest) {
// Open and wait for channels.
const chanAmt = btcutil.Amount(300000)
p := lntemp.OpenChannelParams{Amt: chanAmt}
reqs := []*lntemp.OpenChannelRequest{
p := lntest.OpenChannelParams{Amt: chanAmt}
reqs := []*lntest.OpenChannelRequest{
{Local: alice, Remote: bob, Param: p},
{Local: bob, Remote: carol, Param: p},
}
@ -106,6 +106,7 @@ func testForwardInterceptorDedupHtlc(ht *lntemp.HarnessTest) {
ht.EnsureConnected(bob, alice)
// Here we wait for the channel to be active again.
ht.AssertChannelExists(alice, cpAB)
ht.AssertChannelExists(bob, cpAB)
// Now that the channel is active we make sure the test passes as
@ -185,15 +186,15 @@ func testForwardInterceptorDedupHtlc(ht *lntemp.HarnessTest) {
// 3. Intercepted held htlcs result in no payment (invoice is not settled).
// 4. When Interceptor disconnects it resumes all held htlcs, which result in
// valid payment (invoice is settled).
func testForwardInterceptorBasic(ht *lntemp.HarnessTest) {
func testForwardInterceptorBasic(ht *lntest.HarnessTest) {
ts := newInterceptorTestScenario(ht)
alice, bob, carol := ts.alice, ts.bob, ts.carol
// Open and wait for channels.
const chanAmt = btcutil.Amount(300000)
p := lntemp.OpenChannelParams{Amt: chanAmt}
reqs := []*lntemp.OpenChannelRequest{
p := lntest.OpenChannelParams{Amt: chanAmt}
reqs := []*lntest.OpenChannelRequest{
{Local: alice, Remote: bob, Param: p},
{Local: bob, Remote: carol, Param: p},
}
@ -296,7 +297,8 @@ func testForwardInterceptorBasic(ht *lntemp.HarnessTest) {
restartAlice := ht.SuspendNode(alice)
require.NoError(ht, restartAlice(), "failed to restart alice")
// Make sure the channel is active from Bob's PoV.
// Make sure the channel is active from both Alice and Bob's PoV.
ht.AssertChannelExists(alice, cpAB)
ht.AssertChannelExists(bob, cpAB)
// Create a new interceptor as the old one has quit.
@ -345,7 +347,7 @@ func testForwardInterceptorBasic(ht *lntemp.HarnessTest) {
// interceptorTestScenario is a helper struct to hold the test context and
// provide the needed functionality.
type interceptorTestScenario struct {
ht *lntemp.HarnessTest
ht *lntest.HarnessTest
alice, bob, carol *node.HarnessNode
}
@ -356,7 +358,7 @@ type interceptorTestScenario struct {
//
// Among them, Alice and Bob are standby nodes and Carol is a new node.
func newInterceptorTestScenario(
ht *lntemp.HarnessTest) *interceptorTestScenario {
ht *lntest.HarnessTest) *interceptorTestScenario {
alice, bob := ht.Alice, ht.Bob
carol := ht.NewNode("carol", nil)
@ -416,6 +418,7 @@ func (c *interceptorTestScenario) prepareTestCases() []*interceptorTestCase {
t.invoice = invoice
t.payAddr = payReq.PaymentAddr
}
return cases
}

View file

@ -13,8 +13,8 @@ import (
"github.com/lightningnetwork/lnd/labels"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/stretchr/testify/require"
)
@ -24,7 +24,7 @@ import (
// Bob, then immediately closes the channel after asserting some expected post
// conditions. Finally, the chain itself is checked to ensure the closing
// transaction was mined.
func testBasicChannelFunding(ht *lntemp.HarnessTest) {
func testBasicChannelFunding(ht *lntest.HarnessTest) {
// Run through the test with combinations of all the different
// commitment types.
allTypes := []lnrpc.CommitmentType{
@ -35,20 +35,20 @@ func testBasicChannelFunding(ht *lntemp.HarnessTest) {
// testFunding is a function closure that takes Carol and Dave's
// commitment types and test the funding flow.
testFunding := func(ht *lntemp.HarnessTest, carolCommitType,
testFunding := func(ht *lntest.HarnessTest, carolCommitType,
daveCommitType lnrpc.CommitmentType) {
// Based on the current tweak variable for Carol, we'll
// preferentially signal the legacy commitment format. We do
// the same for Dave shortly below.
carolArgs := nodeArgsForCommitType(carolCommitType)
carolArgs := lntest.NodeArgsForCommitType(carolCommitType)
carol := ht.NewNode("Carol", carolArgs)
// Each time, we'll send Carol a new set of coins in order to
// fund the channel.
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
daveArgs := nodeArgsForCommitType(daveCommitType)
daveArgs := lntest.NodeArgsForCommitType(daveCommitType)
dave := ht.NewNode("Dave", daveArgs)
// Before we start the test, we'll ensure both sides are
@ -140,7 +140,7 @@ test:
// test. Given two nodes: Alice and Bob, it'll assert proper channel creation,
// then return a function closure that should be called to assert proper
// channel closure.
func basicChannelFundingTest(ht *lntemp.HarnessTest,
func basicChannelFundingTest(ht *lntest.HarnessTest,
alice, bob *node.HarnessNode,
fundingShim *lnrpc.FundingShim) (*lnrpc.Channel,
*lnrpc.Channel, func()) {
@ -181,7 +181,7 @@ func basicChannelFundingTest(ht *lntemp.HarnessTest,
// assertions will be executed to ensure the funding process completed
// successfully.
chanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
FundingShim: fundingShim,
@ -193,7 +193,7 @@ func basicChannelFundingTest(ht *lntemp.HarnessTest,
// With the channel open, ensure that the amount specified above has
// properly been pushed to Bob.
aliceLocalBalance := chanAmt - pushAmt - calcStaticFee(cType, 0)
aliceLocalBalance := chanAmt - pushAmt - lntest.CalcStaticFee(cType, 0)
checkChannelBalance(
alice, aliceChannelBalance, aliceLocalBalance, pushAmt,
)
@ -216,7 +216,7 @@ func basicChannelFundingTest(ht *lntemp.HarnessTest,
// testUnconfirmedChannelFunding tests that our unconfirmed change outputs can
// be used to fund channels.
func testUnconfirmedChannelFunding(ht *lntemp.HarnessTest) {
func testUnconfirmedChannelFunding(ht *lntest.HarnessTest) {
const (
chanAmt = funding.MaxBtcFundingAmount
pushAmt = btcutil.Amount(100000)
@ -236,7 +236,7 @@ func testUnconfirmedChannelFunding(ht *lntemp.HarnessTest) {
ht.ConnectNodes(carol, alice)
chanOpenUpdate := ht.OpenChannelAssertStream(
carol, alice, lntemp.OpenChannelParams{
carol, alice, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
SpendUnconfirmed: true,
@ -289,7 +289,7 @@ func testUnconfirmedChannelFunding(ht *lntemp.HarnessTest) {
// Note that atm we haven't obtained the chanPoint yet, so we use the
// type directly.
cType := lnrpc.CommitmentType_STATIC_REMOTE_KEY
carolLocalBalance := chanAmt - pushAmt - calcStaticFee(cType, 0)
carolLocalBalance := chanAmt - pushAmt - lntest.CalcStaticFee(cType, 0)
checkChannelBalance(carol, 0, 0, carolLocalBalance, pushAmt)
// For Alice, her local/remote balances should be zero, and the
@ -329,7 +329,12 @@ func testUnconfirmedChannelFunding(ht *lntemp.HarnessTest) {
// testChannelFundingInputTypes tests that any type of supported input type can
// be used to fund channels.
func testChannelFundingInputTypes(ht *lntemp.HarnessTest) {
func testChannelFundingInputTypes(ht *lntest.HarnessTest) {
const (
chanAmt = funding.MaxBtcFundingAmount
burnAddr = "bcrt1qxsnqpdc842lu8c0xlllgvejt6rhy49u6fmpgyz"
)
// We'll start off by creating a node for Carol.
carol := ht.NewNode("Carol", nil)
@ -342,7 +347,7 @@ func testChannelFundingInputTypes(ht *lntemp.HarnessTest) {
// runChannelFundingInputTypes tests that any type of supported input type can
// be used to fund channels.
func runChannelFundingInputTypes(ht *lntemp.HarnessTest, alice,
func runChannelFundingInputTypes(ht *lntest.HarnessTest, alice,
carol *node.HarnessNode) {
const (
@ -411,7 +416,7 @@ func runChannelFundingInputTypes(ht *lntemp.HarnessTest, alice,
funder((chanAmt*11)/10, carol)
chanOpenUpdate := ht.OpenChannelAssertStream(
carol, alice, lntemp.OpenChannelParams{
carol, alice, lntest.OpenChannelParams{
Amt: chanAmt,
},
)
@ -423,7 +428,7 @@ func runChannelFundingInputTypes(ht *lntemp.HarnessTest, alice,
// Note that atm we haven't obtained the chanPoint yet, so we
// use the type directly.
cType := lnrpc.CommitmentType_STATIC_REMOTE_KEY
carolLocalBalance := chanAmt - calcStaticFee(cType, 0)
carolLocalBalance := chanAmt - lntest.CalcStaticFee(cType, 0)
checkChannelBalance(carol, 0, 0, carolLocalBalance, 0)
// For Alice, her local/remote balances should be zero, and the
@ -463,7 +468,7 @@ func runChannelFundingInputTypes(ht *lntemp.HarnessTest, alice,
// sendAllCoinsConfirm sends all coins of the node's wallet to the given address
// and awaits one confirmation.
func sendAllCoinsConfirm(ht *lntemp.HarnessTest, node *node.HarnessNode,
func sendAllCoinsConfirm(ht *lntest.HarnessTest, node *node.HarnessNode,
addr string) {
sweepReq := &lnrpc.SendCoinsRequest{
@ -477,7 +482,7 @@ func sendAllCoinsConfirm(ht *lntemp.HarnessTest, node *node.HarnessNode,
// testExternalFundingChanPoint tests that we're able to carry out a normal
// channel funding workflow given a channel point that was constructed outside
// the main daemon.
func testExternalFundingChanPoint(ht *lntemp.HarnessTest) {
func testExternalFundingChanPoint(ht *lntest.HarnessTest) {
// First, we'll create two new nodes that we'll use to open channel
// between for this test.
carol := ht.NewNode("carol", nil)
@ -496,11 +501,11 @@ func testExternalFundingChanPoint(ht *lntemp.HarnessTest) {
// a transaction that will never be published.
const thawHeight uint32 = 10
const chanSize = funding.MaxBtcFundingAmount
fundingShim1, chanPoint1, _ := deriveFundingShim(
fundingShim1, chanPoint1 := deriveFundingShim(
ht, carol, dave, chanSize, thawHeight, false,
)
ht.OpenChannelAssertPending(
carol, dave, lntemp.OpenChannelParams{
carol, dave, lntest.OpenChannelParams{
Amt: chanSize,
FundingShim: fundingShim1,
},
@ -512,7 +517,7 @@ func testExternalFundingChanPoint(ht *lntemp.HarnessTest) {
// externally funded, we should still be able to open another one. Let's
// do exactly that now. For this one we publish the transaction so we
// can mine it later.
fundingShim2, chanPoint2, _ := deriveFundingShim(
fundingShim2, chanPoint2 := deriveFundingShim(
ht, carol, dave, chanSize, thawHeight, true,
)
@ -591,7 +596,7 @@ func testExternalFundingChanPoint(ht *lntemp.HarnessTest) {
// representation of channels if the system is restarted or disconnected.
// testFundingPersistence mirrors testBasicChannelFunding, but adds restarts
// and checks for the state of channels with unconfirmed funding transactions.
func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
func testChannelFundingPersistence(ht *lntest.HarnessTest) {
chanAmt := funding.MaxBtcFundingAmount
pushAmt := btcutil.Amount(0)
@ -609,7 +614,7 @@ func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
// Create a new channel that requires 5 confs before it's considered
// open, then broadcast the funding transaction
param := lntemp.OpenChannelParams{
param := lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
}
@ -676,7 +681,7 @@ func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
// The channel should be listed in the peer information returned by
// both peers.
chanPoint := lntemp.ChanPointFromPendingUpdate(update)
chanPoint := lntest.ChanPointFromPendingUpdate(update)
// Re-lookup our transaction in the block that it confirmed in.
tx = ht.AssertTxAtHeight(alice, height, fundingTxID)
@ -685,6 +690,11 @@ func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
chanAlice := ht.AssertChannelExists(alice, chanPoint)
ht.AssertChannelExists(carol, chanPoint)
// Make sure Alice and Carol have seen the channel in their network
// topology.
ht.AssertTopologyChannelOpen(alice, chanPoint)
ht.AssertTopologyChannelOpen(carol, chanPoint)
// Create an additional check for our channel assertion that will
// check that our label is as expected.
shortChanID := lnwire.NewShortChanIDFromInt(chanAlice.ChanId)
@ -699,7 +709,7 @@ func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
// testBatchChanFunding makes sure multiple channels can be opened in one batch
// transaction in an atomic way.
func testBatchChanFunding(ht *lntemp.HarnessTest) {
func testBatchChanFunding(ht *lntest.HarnessTest) {
// First, we'll create two new nodes that we'll use to open channels
// to during this test. Carol has a high minimum funding amount that
// we'll use to trigger an error during the batch channel open.
@ -793,10 +803,10 @@ func testBatchChanFunding(ht *lntemp.HarnessTest) {
// deriveFundingShim creates a channel funding shim by deriving the necessary
// keys on both sides.
func deriveFundingShim(ht *lntemp.HarnessTest,
func deriveFundingShim(ht *lntest.HarnessTest,
carol, dave *node.HarnessNode, chanSize btcutil.Amount,
thawHeight uint32, publish bool) (*lnrpc.FundingShim,
*lnrpc.ChannelPoint, *chainhash.Hash) {
*lnrpc.ChannelPoint) {
keyLoc := &signrpc.KeyLocator{KeyFamily: 9999}
carolFundingKey := carol.RPC.DeriveKey(keyLoc)
@ -882,5 +892,5 @@ func deriveFundingShim(ht *lntemp.HarnessTest,
}
fundingShim.GetChanPointShim().RemoteKey = daveFundingKey.RawKeyBytes
return fundingShim, chanPoint, txid
return fundingShim, chanPoint
}

View file

@ -7,7 +7,7 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/stretchr/testify/require"
@ -15,11 +15,11 @@ import (
// testHoldInvoiceForceClose tests cancellation of accepted hold invoices which
// would otherwise trigger force closes when they expire.
func testHoldInvoiceForceClose(ht *lntemp.HarnessTest) {
func testHoldInvoiceForceClose(ht *lntest.HarnessTest) {
// Open a channel between alice and bob.
alice, bob := ht.Alice, ht.Bob
chanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: 300000},
alice, bob, lntest.OpenChannelParams{Amt: 300000},
)
// Create a non-dust hold invoice for bob.

View file

@ -7,8 +7,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/rpc"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/rpc"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/stretchr/testify/require"
@ -17,7 +17,7 @@ import (
// testHoldInvoicePersistence tests that a sender to a hold-invoice, can be
// restarted before the payment gets settled, and still be able to receive the
// preimage.
func testHoldInvoicePersistence(ht *lntemp.HarnessTest) {
func testHoldInvoicePersistence(ht *lntest.HarnessTest) {
const (
chanAmt = btcutil.Amount(1000000)
numPayments = 10
@ -34,7 +34,7 @@ func testHoldInvoicePersistence(ht *lntemp.HarnessTest) {
// Open a channel between Alice and Carol which is private so that we
// cover the addition of hop hints for hold invoices.
chanPointAlice := ht.OpenChannel(
alice, carol, lntemp.OpenChannelParams{
alice, carol, lntest.OpenChannelParams{
Amt: chanAmt,
Private: true,
},
@ -45,7 +45,7 @@ func testHoldInvoicePersistence(ht *lntemp.HarnessTest) {
// has at least one public channel in the graph. We open a public
// channel from Alice -> Bob and wait for Carol to see it.
chanPointBob := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: chanAmt,
},
)

View file

@ -11,8 +11,8 @@ import (
"github.com/golang/protobuf/proto"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/macaroons"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
@ -23,7 +23,7 @@ import (
// enabled on the gRPC interface, no requests with missing or invalid
// macaroons are allowed. Further, the specific access rights (read/write,
// entity based) and first-party caveats are tested as well.
func testMacaroonAuthentication(ht *lntemp.HarnessTest) {
func testMacaroonAuthentication(ht *lntest.HarnessTest) {
var (
infoReq = &lnrpc.GetInfoRequest{}
newAddrReq = &lnrpc.NewAddressRequest{
@ -294,7 +294,7 @@ func testMacaroonAuthentication(ht *lntemp.HarnessTest) {
// testBakeMacaroon checks that when creating macaroons, the permissions param
// in the request must be set correctly, and the baked macaroon has the intended
// permissions.
func testBakeMacaroon(ht *lntemp.HarnessTest) {
func testBakeMacaroon(ht *lntest.HarnessTest) {
var testNode = ht.Alice
testCases := []struct {
@ -518,7 +518,7 @@ func testBakeMacaroon(ht *lntemp.HarnessTest) {
// specified ID and invalidates all macaroons derived from the key with that ID.
// Also, it checks deleting the reserved marcaroon ID, DefaultRootKeyID or is
// forbidden.
func testDeleteMacaroonID(ht *lntemp.HarnessTest) {
func testDeleteMacaroonID(ht *lntest.HarnessTest) {
var (
ctxb = ht.Context()
testNode = ht.Alice
@ -610,7 +610,7 @@ func testDeleteMacaroonID(ht *lntemp.HarnessTest) {
// does not write any macaroon files to the daemon's file system and returns
// the admin macaroon in the response. It then checks that the password
// change of the wallet can also happen stateless.
func testStatelessInit(ht *lntemp.HarnessTest) {
func testStatelessInit(ht *lntest.HarnessTest) {
var (
initPw = []byte("stateless")
newPw = []byte("stateless-new")

View file

@ -1,6 +1,3 @@
//go:build rpctest
// +build rpctest
package itest
import (
@ -8,14 +5,14 @@ import (
"github.com/btcsuite/btcd/btcutil"
"github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lnwallet"
)
// testMaxChannelSize tests that lnd handles --maxchansize parameter correctly.
// Wumbo nodes should enforce a default soft limit of 10 BTC by default. This
// limit can be adjusted with --maxchansize config option.
func testMaxChannelSize(ht *lntemp.HarnessTest) {
func testMaxChannelSize(ht *lntest.HarnessTest) {
// We'll make two new nodes, both wumbo but with the default limit on
// maximum channel size (10 BTC)
wumboNode := ht.NewNode(
@ -42,7 +39,7 @@ func testMaxChannelSize(ht *lntemp.HarnessTest) {
)
ht.OpenChannelAssertErr(
wumboNode, wumboNode2,
lntemp.OpenChannelParams{Amt: chanAmt}, expectedErr,
lntest.OpenChannelParams{Amt: chanAmt}, expectedErr,
)
// We'll now make another wumbo node with appropriate maximum channel
@ -60,7 +57,7 @@ func testMaxChannelSize(ht *lntemp.HarnessTest) {
// Creating a wumbo channel between these two nodes should succeed.
ht.EnsureConnected(wumboNode, wumboNode3)
chanPoint := ht.OpenChannel(
wumboNode, wumboNode3, lntemp.OpenChannelParams{Amt: chanAmt},
wumboNode, wumboNode3, lntest.OpenChannelParams{Amt: chanAmt},
)
ht.CloseChannel(wumboNode, chanPoint)

View file

@ -4,8 +4,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/stretchr/testify/require"
)
@ -14,14 +14,14 @@ import (
// channel where we have already reached the limit of the number of htlcs that
// we may add to the remote party's commitment. This test asserts that we do
// not attempt to use the full channel at all in our pathfinding.
func testMaxHtlcPathfind(ht *lntemp.HarnessTest) {
func testMaxHtlcPathfind(ht *lntest.HarnessTest) {
// Setup a channel between Alice and Bob where Alice will only allow
// Bob to add a maximum of 5 htlcs to her commitment.
maxHtlcs := 5
alice, bob := ht.Alice, ht.Bob
chanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: 1000000,
PushAmt: 800000,
RemoteMaxHtlcs: uint16(maxHtlcs),
@ -84,7 +84,7 @@ type holdSubscription struct {
// cancel updates a hold invoice to cancel from the recipient and consumes
// updates from the payer until it has reached a final, failed state.
func (h *holdSubscription) cancel(ht *lntemp.HarnessTest) {
func (h *holdSubscription) cancel(ht *lntest.HarnessTest) {
h.recipient.RPC.CancelInvoice(h.hash[:])
invUpdate := ht.ReceiveSingleInvoice(h.invSubscription)
@ -110,7 +110,7 @@ func (h *holdSubscription) cancel(ht *lntemp.HarnessTest) {
// acceptHoldInvoice adds a hold invoice to the recipient node, pays it from
// the sender and asserts that we have reached the accepted state where htlcs
// are locked in for the payment.
func acceptHoldInvoice(ht *lntemp.HarnessTest, idx int, sender,
func acceptHoldInvoice(ht *lntest.HarnessTest, idx int, sender,
receiver *node.HarnessNode) *holdSubscription {
hash := [lntypes.HashSize]byte{byte(idx + 1)}

View file

@ -15,8 +15,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
@ -28,7 +28,7 @@ import (
// disconnect at any point.
//
// TODO(yy): move to lnd_network_test.
func testDisconnectingTargetPeer(ht *lntemp.HarnessTest) {
func testDisconnectingTargetPeer(ht *lntest.HarnessTest) {
// We'll start both nodes with a high backoff so that they don't
// reconnect automatically during our test.
args := []string{
@ -49,7 +49,7 @@ func testDisconnectingTargetPeer(ht *lntemp.HarnessTest) {
// Create a new channel that requires 1 confs before it's considered
// open, then broadcast the funding transaction
const numConfs = 1
p := lntemp.OpenChannelParams{
p := lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
}
@ -119,7 +119,7 @@ func testDisconnectingTargetPeer(ht *lntemp.HarnessTest) {
// configuration arguments to force Carol to replay the same sphinx packet
// after reconnecting to Dave, and compare the returned failure message with
// what we expect for replayed onion packets.
func testSphinxReplayPersistence(ht *lntemp.HarnessTest) {
func testSphinxReplayPersistence(ht *lntest.HarnessTest) {
// Open a channel with 100k satoshis between Carol and Dave with Carol
// being the sole funder of the channel.
chanAmt := btcutil.Amount(100000)
@ -135,7 +135,7 @@ func testSphinxReplayPersistence(ht *lntemp.HarnessTest) {
ht.ConnectNodes(carol, dave)
chanPoint := ht.OpenChannel(
carol, dave, lntemp.OpenChannelParams{
carol, dave, lntest.OpenChannelParams{
Amt: chanAmt,
},
)
@ -150,7 +150,7 @@ func testSphinxReplayPersistence(ht *lntemp.HarnessTest) {
ht.ConnectNodes(fred, carol)
chanPointFC := ht.OpenChannel(
fred, carol, lntemp.OpenChannelParams{
fred, carol, lntest.OpenChannelParams{
Amt: chanAmt,
},
)
@ -232,7 +232,7 @@ func testSphinxReplayPersistence(ht *lntemp.HarnessTest) {
// tests the values in all ChannelConstraints are returned as expected. Once
// ListChannels becomes mature, a test against all fields in ListChannels
// should be performed.
func testListChannels(ht *lntemp.HarnessTest) {
func testListChannels(ht *lntest.HarnessTest) {
const aliceRemoteMaxHtlcs = 50
const bobRemoteMaxHtlcs = 100
@ -255,7 +255,7 @@ func testListChannels(ht *lntemp.HarnessTest) {
chanAmt := btcutil.Amount(100000)
pushAmt := btcutil.Amount(1000)
p := lntemp.OpenChannelParams{
p := lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
MinHtlc: customizedMinHtlc,
@ -337,7 +337,7 @@ func testListChannels(ht *lntemp.HarnessTest) {
// testMaxPendingChannels checks that error is returned from remote peer if
// max pending channel number was exceeded and that '--maxpendingchannels' flag
// exists and works properly.
func testMaxPendingChannels(ht *lntemp.HarnessTest) {
func testMaxPendingChannels(ht *lntest.HarnessTest) {
maxPendingChannels := lncfg.DefaultMaxPendingChannels + 1
amount := funding.MaxBtcFundingAmount
@ -362,7 +362,7 @@ func testMaxPendingChannels(ht *lntemp.HarnessTest) {
)
for i := 0; i < maxPendingChannels; i++ {
stream := ht.OpenChannelAssertStream(
alice, carol, lntemp.OpenChannelParams{
alice, carol, lntest.OpenChannelParams{
Amt: amount,
},
)
@ -372,7 +372,7 @@ func testMaxPendingChannels(ht *lntemp.HarnessTest) {
// Carol exhausted available amount of pending channels, next open
// channel request should cause ErrorGeneric to be sent back to Alice.
ht.OpenChannelAssertErr(
alice, carol, lntemp.OpenChannelParams{
alice, carol, lntest.OpenChannelParams{
Amt: amount,
}, lnwire.ErrMaxPendingChannels,
)
@ -415,7 +415,7 @@ func testMaxPendingChannels(ht *lntemp.HarnessTest) {
// testGarbageCollectLinkNodes tests that we properly garbage collect link
// nodes from the database and the set of persistent connections within the
// server.
func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
func testGarbageCollectLinkNodes(ht *lntest.HarnessTest) {
const chanAmt = 1000000
alice, bob := ht.Alice, ht.Bob
@ -423,7 +423,7 @@ func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
// Open a channel between Alice and Bob which will later be
// cooperatively closed.
coopChanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: chanAmt,
},
)
@ -435,7 +435,7 @@ func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
// Open a channel between Alice and Carol which will later be force
// closed.
forceCloseChanPoint := ht.OpenChannel(
alice, carol, lntemp.OpenChannelParams{
alice, carol, lntest.OpenChannelParams{
Amt: chanAmt,
},
)
@ -447,7 +447,7 @@ func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
ht.ConnectNodes(alice, dave)
persistentChanPoint := ht.OpenChannel(
alice, dave, lntemp.OpenChannelParams{
alice, dave, lntest.OpenChannelParams{
Amt: chanAmt,
},
)
@ -527,7 +527,7 @@ func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
// testRejectHTLC tests that a node can be created with the flag --rejecthtlc.
// This means that the node will reject all forwarded HTLCs but can still
// accept direct HTLCs as well as send HTLCs.
func testRejectHTLC(ht *lntemp.HarnessTest) {
func testRejectHTLC(ht *lntest.HarnessTest) {
// RejectHTLC
// Alice ------> Carol ------> Bob
//
@ -548,14 +548,14 @@ func testRejectHTLC(ht *lntemp.HarnessTest) {
// Open a channel between Alice and Carol.
chanPointAlice := ht.OpenChannel(
alice, carol, lntemp.OpenChannelParams{
alice, carol, lntest.OpenChannelParams{
Amt: chanAmt,
},
)
// Open a channel between Carol and Bob.
chanPointCarol := ht.OpenChannel(
carol, bob, lntemp.OpenChannelParams{
carol, bob, lntest.OpenChannelParams{
Amt: chanAmt,
},
)
@ -623,14 +623,14 @@ func testRejectHTLC(ht *lntemp.HarnessTest) {
// testNodeSignVerify checks that only connected nodes are allowed to perform
// signing and verifying messages.
func testNodeSignVerify(ht *lntemp.HarnessTest) {
func testNodeSignVerify(ht *lntest.HarnessTest) {
chanAmt := funding.MaxBtcFundingAmount
pushAmt := btcutil.Amount(100000)
alice, bob := ht.Alice, ht.Bob
// Create a channel between alice and bob.
aliceBobCh := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
},
@ -670,11 +670,11 @@ func testNodeSignVerify(ht *lntemp.HarnessTest) {
// testAbandonChannel abandons a channel and asserts that it is no longer open
// and not in one of the pending closure states. It also verifies that the
// abandoned channel is reported as closed with close type 'abandoned'.
func testAbandonChannel(ht *lntemp.HarnessTest) {
func testAbandonChannel(ht *lntest.HarnessTest) {
alice, bob := ht.Alice, ht.Bob
// First establish a channel between Alice and Bob.
channelParam := lntemp.OpenChannelParams{
channelParam := lntest.OpenChannelParams{
Amt: funding.MaxBtcFundingAmount,
PushAmt: btcutil.Amount(100000),
}
@ -741,7 +741,7 @@ func testAbandonChannel(ht *lntemp.HarnessTest) {
// wallet into a single target address at the specified fee rate.
//
// TODO(yy): expand this test to also use P2TR.
func testSweepAllCoins(ht *lntemp.HarnessTest) {
func testSweepAllCoins(ht *lntest.HarnessTest) {
// First, we'll make a new node, ainz who'll we'll use to test wallet
// sweeping.
//
@ -917,7 +917,7 @@ func testSweepAllCoins(ht *lntemp.HarnessTest) {
// testListAddresses tests that we get all the addresses and their
// corresponding balance correctly.
func testListAddresses(ht *lntemp.HarnessTest) {
func testListAddresses(ht *lntest.HarnessTest) {
// First, we'll make a new node - Alice, which will be generating
// new addresses.
alice := ht.NewNode("Alice", nil)
@ -964,7 +964,8 @@ func testListAddresses(ht *lntemp.HarnessTest) {
})
generatedAddr[resp.Address] = addressDetails{
Balance: 400_000,
Type: walletrpc.AddressType_HYBRID_NESTED_WITNESS_PUBKEY_HASH,
Type: walletrpc.
AddressType_HYBRID_NESTED_WITNESS_PUBKEY_HASH,
}
for addr, addressDetail := range generatedAddr {
@ -985,7 +986,7 @@ func testListAddresses(ht *lntemp.HarnessTest) {
foundAddresses := 0
for _, addressList := range addressLists.AccountWithAddresses {
addresses := addressList.Addresses
derivationPath, err := lntemp.ParseDerivationPath(
derivationPath, err := lntest.ParseDerivationPath(
addressList.DerivationPath,
)
require.NoError(ht, err)
@ -1023,7 +1024,7 @@ func testListAddresses(ht *lntemp.HarnessTest) {
for _, addressList := range addressLists.AccountWithAddresses {
addresses := addressList.Addresses
derivationPath, err := lntemp.ParseDerivationPath(
derivationPath, err := lntest.ParseDerivationPath(
addressList.DerivationPath,
)
require.NoError(ht, err)
@ -1053,7 +1054,7 @@ func testListAddresses(ht *lntemp.HarnessTest) {
require.Equal(ht, len(generatedAddr), foundAddresses)
}
func assertChannelConstraintsEqual(ht *lntemp.HarnessTest,
func assertChannelConstraintsEqual(ht *lntest.HarnessTest,
want, got *lnrpc.ChannelConstraints) {
require.Equal(ht, want.CsvDelay, got.CsvDelay, "CsvDelay mismatched")
@ -1076,7 +1077,7 @@ func assertChannelConstraintsEqual(ht *lntemp.HarnessTest,
// testSignVerifyMessageWithAddr tests signing and also verifying a signature
// on a message with a provided address.
func testSignVerifyMessageWithAddr(ht *lntemp.HarnessTest) {
func testSignVerifyMessageWithAddr(ht *lntest.HarnessTest) {
// Using different nodes to sign the message and verify the signature.
alice, bob := ht.Alice, ht.Bob

View file

@ -7,8 +7,8 @@ import (
"github.com/lightningnetwork/lnd/chainreg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/stretchr/testify/require"
@ -16,7 +16,7 @@ import (
// testSendToRouteMultiPath tests that we are able to successfully route a
// payment using multiple shards across different paths, by using SendToRoute.
func testSendToRouteMultiPath(ht *lntemp.HarnessTest) {
func testSendToRouteMultiPath(ht *lntest.HarnessTest) {
mts := newMppTestScenario(ht)
// To ensure the payment goes through separate paths, we'll set a
@ -162,7 +162,7 @@ func testSendToRouteMultiPath(ht *lntemp.HarnessTest) {
// It has two standby nodes, alice and bob, and three new nodes, carol, dave,
// and eve.
type mppTestScenario struct {
ht *lntemp.HarnessTest
ht *lntest.HarnessTest
alice, bob, carol, dave, eve *node.HarnessNode
nodes []*node.HarnessNode
@ -179,7 +179,7 @@ type mppTestScenario struct {
// Alice -- Carol ---- Bob
// \ /
// \__ Dave ____/
func newMppTestScenario(ht *lntemp.HarnessTest) *mppTestScenario {
func newMppTestScenario(ht *lntest.HarnessTest) *mppTestScenario {
alice, bob := ht.Alice, ht.Bob
ht.RestartNodeWithExtraArgs(bob, []string{
"--maxpendingchannels=2",
@ -256,36 +256,36 @@ type mppOpenChannelRequest struct {
//
// NOTE: all the channels are open together to save blocks mined.
func (m *mppTestScenario) openChannels(r *mppOpenChannelRequest) {
reqs := []*lntemp.OpenChannelRequest{
reqs := []*lntest.OpenChannelRequest{
{
Local: m.alice,
Remote: m.carol,
Param: lntemp.OpenChannelParams{Amt: r.amtAliceCarol},
Param: lntest.OpenChannelParams{Amt: r.amtAliceCarol},
},
{
Local: m.alice,
Remote: m.dave,
Param: lntemp.OpenChannelParams{Amt: r.amtAliceDave},
Param: lntest.OpenChannelParams{Amt: r.amtAliceDave},
},
{
Local: m.carol,
Remote: m.bob,
Param: lntemp.OpenChannelParams{Amt: r.amtCarolBob},
Param: lntest.OpenChannelParams{Amt: r.amtCarolBob},
},
{
Local: m.carol,
Remote: m.eve,
Param: lntemp.OpenChannelParams{Amt: r.amtCarolEve},
Param: lntest.OpenChannelParams{Amt: r.amtCarolEve},
},
{
Local: m.dave,
Remote: m.bob,
Param: lntemp.OpenChannelParams{Amt: r.amtDaveBob},
Param: lntest.OpenChannelParams{Amt: r.amtDaveBob},
},
{
Local: m.eve,
Remote: m.bob,
Param: lntemp.OpenChannelParams{Amt: r.amtEveBob},
Param: lntest.OpenChannelParams{Amt: r.amtEveBob},
},
}
@ -313,7 +313,7 @@ func (m *mppTestScenario) closeChannels() {
// active htlcs` or `link failed to shutdown` if we close the channel.
// We need to investigate the order of settling the payments and
// updating commitments to understand and fix .
time.Sleep(2 * time.Second)
time.Sleep(5 * time.Second)
// Close all channels without mining the closing transactions.
m.ht.CloseChannelAssertPending(m.alice, m.channelPoints[0], false)

View file

@ -6,12 +6,12 @@ import (
"github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/stretchr/testify/require"
)
func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
func testHtlcErrorPropagation(ht *lntest.HarnessTest) {
// In this test we wish to exercise the daemon's correct parsing,
// handling, and propagation of errors that occur while processing a
// multi-hop payment.
@ -39,23 +39,22 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
// and Bob.
chanPointAlice := ht.OpenChannel(
alice, bob,
lntemp.OpenChannelParams{Amt: chanAmt},
lntest.OpenChannelParams{Amt: chanAmt},
)
// Next, we'll create a connection from Bob to Carol, and open a
// channel between them so we have the topology: Alice -> Bob -> Carol.
// The channel created will be of lower capacity that the one created
// above.
const bobChanAmt = funding.MaxBtcFundingAmount
chanPointBob := ht.OpenChannel(
bob, carol, lntemp.OpenChannelParams{Amt: chanAmt},
bob, carol, lntest.OpenChannelParams{Amt: chanAmt},
)
// Ensure that Alice has Carol in her routing table before proceeding.
ht.AssertTopologyChannelOpen(alice, chanPointBob)
cType := ht.GetChannelCommitType(alice, chanPointAlice)
commitFee := calcStaticFee(cType, 0)
commitFee := lntest.CalcStaticFee(cType, 0)
assertBaseBalance := func() {
// Alice has opened a channel with Bob with zero push amount,
@ -153,24 +152,24 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
assertAliceAndBob := func() {
ht.AssertHtlcEventTypes(
aliceEvents, routerrpc.HtlcEvent_SEND,
lntemp.HtlcEventForward,
lntest.HtlcEventForward,
)
ht.AssertHtlcEventTypes(
aliceEvents, routerrpc.HtlcEvent_SEND,
lntemp.HtlcEventForwardFail,
lntest.HtlcEventForwardFail,
)
ht.AssertHtlcEventTypes(
bobEvents, routerrpc.HtlcEvent_FORWARD,
lntemp.HtlcEventForward,
lntest.HtlcEventForward,
)
ht.AssertHtlcEventTypes(
bobEvents, routerrpc.HtlcEvent_FORWARD,
lntemp.HtlcEventForwardFail,
lntest.HtlcEventForwardFail,
)
ht.AssertHtlcEventTypes(
bobEvents, routerrpc.HtlcEvent_UNKNOWN,
lntemp.HtlcEventFinal,
lntest.HtlcEventFinal,
)
}
@ -188,7 +187,7 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
// There's also a final htlc event that gives the final outcome of the
// htlc.
ht.AssertHtlcEventTypes(
carolEvents, routerrpc.HtlcEvent_UNKNOWN, lntemp.HtlcEventFinal,
carolEvents, routerrpc.HtlcEvent_UNKNOWN, lntest.HtlcEventFinal,
)
// The balances of all parties should be the same as initially since
@ -228,7 +227,7 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
// There's also a final htlc event that gives the final outcome of the
// htlc.
ht.AssertHtlcEventTypes(
carolEvents, routerrpc.HtlcEvent_UNKNOWN, lntemp.HtlcEventFinal,
carolEvents, routerrpc.HtlcEvent_UNKNOWN, lntest.HtlcEventFinal,
)
// The balances of all parties should be the same as initially since
@ -273,19 +272,19 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
// settle event and a final htlc event for her receive.
ht.AssertHtlcEventTypes(
bobEvents, routerrpc.HtlcEvent_SEND,
lntemp.HtlcEventForward,
lntest.HtlcEventForward,
)
ht.AssertHtlcEventTypes(
bobEvents, routerrpc.HtlcEvent_SEND,
lntemp.HtlcEventSettle,
lntest.HtlcEventSettle,
)
ht.AssertHtlcEventTypes(
carolEvents, routerrpc.HtlcEvent_RECEIVE,
lntemp.HtlcEventSettle,
lntest.HtlcEventSettle,
)
ht.AssertHtlcEventTypes(
carolEvents, routerrpc.HtlcEvent_UNKNOWN,
lntemp.HtlcEventFinal,
lntest.HtlcEventFinal,
)
amtSent += toSend
@ -316,11 +315,11 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
// Alice should have a forwarding event and a forwarding failure.
ht.AssertHtlcEventTypes(
aliceEvents, routerrpc.HtlcEvent_SEND,
lntemp.HtlcEventForward,
lntest.HtlcEventForward,
)
ht.AssertHtlcEventTypes(
aliceEvents, routerrpc.HtlcEvent_SEND,
lntemp.HtlcEventForwardFail,
lntest.HtlcEventForwardFail,
)
// Bob should have a link failure because the htlc failed on his
@ -331,7 +330,7 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
// There's also a final htlc event that gives the final outcome of the
// htlc.
ht.AssertHtlcEventTypes(
bobEvents, routerrpc.HtlcEvent_UNKNOWN, lntemp.HtlcEventFinal,
bobEvents, routerrpc.HtlcEvent_UNKNOWN, lntest.HtlcEventFinal,
)
// Generate new invoice to not pay same invoice twice.
@ -362,11 +361,11 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
// Alice should have a forwarding event and subsequent fail.
ht.AssertHtlcEventTypes(
aliceEvents, routerrpc.HtlcEvent_SEND,
lntemp.HtlcEventForward,
lntest.HtlcEventForward,
)
ht.AssertHtlcEventTypes(
aliceEvents, routerrpc.HtlcEvent_SEND,
lntemp.HtlcEventForwardFail,
lntest.HtlcEventForwardFail,
)
// Bob should have a link failure because he could not find the next
@ -377,7 +376,7 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
// There's also a final htlc event that gives the final outcome of the
// htlc.
ht.AssertHtlcEventTypes(
bobEvents, routerrpc.HtlcEvent_UNKNOWN, lntemp.HtlcEventFinal,
bobEvents, routerrpc.HtlcEvent_UNKNOWN, lntest.HtlcEventFinal,
)
// Finally, immediately close the channel. This function will also

View file

@ -5,12 +5,12 @@ import (
"github.com/lightningnetwork/lnd/chainreg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/stretchr/testify/require"
)
func testMultiHopPayments(ht *lntemp.HarnessTest) {
func testMultiHopPayments(ht *lntest.HarnessTest) {
const chanAmt = btcutil.Amount(100000)
// As preliminary setup, we'll create two new nodes: Carol and Dave,
@ -43,21 +43,21 @@ func testMultiHopPayments(ht *lntemp.HarnessTest) {
// Open a channel with 100k satoshis between Alice and Bob with Alice
// being the sole funder of the channel.
chanPointAlice := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
)
// We'll create Dave and establish a channel to Alice. Dave will be
// running an older node that requires the legacy onion payload.
ht.FundCoins(btcutil.SatoshiPerBitcoin, dave)
chanPointDave := ht.OpenChannel(
dave, alice, lntemp.OpenChannelParams{Amt: chanAmt},
dave, alice, lntest.OpenChannelParams{Amt: chanAmt},
)
// Next, we'll create Carol and establish a channel to from her to
// Dave.
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
chanPointCarol := ht.OpenChannel(
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
carol, dave, lntest.OpenChannelParams{Amt: chanAmt},
)
// Create 5 invoices for Bob, which expect a payment from Carol for 1k
@ -69,7 +69,7 @@ func testMultiHopPayments(ht *lntemp.HarnessTest) {
// Set the fee policies of the Alice -> Bob and the Dave -> Alice
// channel edges to relatively large non default values. This makes it
// possible to pick up more subtle fee calculation errors.
maxHtlc := calculateMaxHtlc(chanAmt)
maxHtlc := lntest.CalculateMaxHtlc(chanAmt)
const aliceBaseFeeSat = 1
const aliceFeeRatePPM = 100000
updateChannelPolicy(
@ -222,7 +222,7 @@ func testMultiHopPayments(ht *lntemp.HarnessTest) {
// policy update.
//
// NOTE: only used in current test.
func updateChannelPolicy(ht *lntemp.HarnessTest, hn *node.HarnessNode,
func updateChannelPolicy(ht *lntest.HarnessTest, hn *node.HarnessNode,
chanPoint *lnrpc.ChannelPoint, baseFee int64,
feeRate int64, timeLockDelta uint32,
maxHtlc uint64, listenerNode *node.HarnessNode) {

View file

@ -12,10 +12,9 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntemp/rpc"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/rpc"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/routing"
"github.com/stretchr/testify/require"
@ -52,109 +51,13 @@ var commitWithZeroConf = []struct {
},
}
// waitForInvoiceAccepted waits until the specified invoice moved to the
// accepted state by the node.
func waitForInvoiceAccepted(t *harnessTest, node *lntest.HarnessNode,
payHash lntypes.Hash) {
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
defer cancel()
invoiceUpdates, err := node.SubscribeSingleInvoice(ctx,
&invoicesrpc.SubscribeSingleInvoiceRequest{
RHash: payHash[:],
},
)
if err != nil {
t.Fatalf("subscribe single invoice: %v", err)
}
for {
update, err := invoiceUpdates.Recv()
if err != nil {
t.Fatalf("invoice update err: %v", err)
}
if update.State == lnrpc.Invoice_ACCEPTED {
break
}
}
}
// checkPaymentStatus asserts that the given node list a payment with the given
// preimage has the expected status.
func checkPaymentStatus(node *lntest.HarnessNode, preimage lntypes.Preimage,
status lnrpc.Payment_PaymentStatus) error {
ctxb := context.Background()
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
req := &lnrpc.ListPaymentsRequest{
IncludeIncomplete: true,
}
paymentsResp, err := node.ListPayments(ctxt, req)
if err != nil {
return fmt.Errorf("error when obtaining Alice payments: %v",
err)
}
payHash := preimage.Hash()
var found bool
for _, p := range paymentsResp.Payments {
if p.PaymentHash != payHash.String() {
continue
}
found = true
if p.Status != status {
return fmt.Errorf("expected payment status "+
"%v, got %v", status, p.Status)
}
switch status {
// If this expected status is SUCCEEDED, we expect the final preimage.
case lnrpc.Payment_SUCCEEDED:
if p.PaymentPreimage != preimage.String() {
return fmt.Errorf("preimage doesn't match: %v vs %v",
p.PaymentPreimage, preimage.String())
}
// Otherwise we expect an all-zero preimage.
default:
if p.PaymentPreimage != (lntypes.Preimage{}).String() {
return fmt.Errorf("expected zero preimage, got %v",
p.PaymentPreimage)
}
}
}
if !found {
return fmt.Errorf("payment with payment hash %v not found "+
"in response", payHash)
}
return nil
}
// assertAllTxesSpendFrom asserts that all txes in the list spend from the given
// tx.
func assertAllTxesSpendFrom(t *harnessTest, txes []*wire.MsgTx,
prevTxid chainhash.Hash) {
for _, tx := range txes {
if tx.TxIn[0].PreviousOutPoint.Hash != prevTxid {
t.Fatalf("tx %v did not spend from %v",
tx.TxHash(), prevTxid)
}
}
}
// caseRunner defines a single test case runner.
type caseRunner func(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode,
type caseRunner func(ht *lntest.HarnessTest, alice, bob *node.HarnessNode,
c lnrpc.CommitmentType, zeroConf bool)
// runMultiHopHtlcClaimTest is a helper method to build test cases based on
// different commitment types and zero-conf config and run them.
func runMultiHopHtlcClaimTest(ht *lntemp.HarnessTest, tester caseRunner) {
func runMultiHopHtlcClaimTest(ht *lntest.HarnessTest, tester caseRunner) {
for _, typeAndConf := range commitWithZeroConf {
typeAndConf := typeAndConf
name := fmt.Sprintf("zeroconf=%v/committype=%v",
@ -162,7 +65,7 @@ func runMultiHopHtlcClaimTest(ht *lntemp.HarnessTest, tester caseRunner) {
// Create the nodes here so that separate logs will be created
// for Alice and Bob.
args := nodeArgsForCommitType(typeAndConf.commitType)
args := lntest.NodeArgsForCommitType(typeAndConf.commitType)
if typeAndConf.zeroConf {
args = append(
args, "--protocol.option-scid-alias",
@ -200,11 +103,11 @@ func runMultiHopHtlcClaimTest(ht *lntemp.HarnessTest, tester caseRunner) {
// it using the HTLC timeout transaction. Any dust HTLC's should be immediately
// canceled backwards. Once the timeout has been reached, then we should sweep
// it on-chain, and cancel the HTLC backwards.
func testMultiHopHtlcLocalTimeout(ht *lntemp.HarnessTest) {
func testMultiHopHtlcLocalTimeout(ht *lntest.HarnessTest) {
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcLocalTimeout)
}
func runMultiHopHtlcLocalTimeout(ht *lntemp.HarnessTest,
func runMultiHopHtlcLocalTimeout(ht *lntest.HarnessTest,
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
@ -268,7 +171,7 @@ func runMultiHopHtlcLocalTimeout(ht *lntemp.HarnessTest,
// Bob's force close transaction should now be found in the mempool. If
// there are anchors, we also expect Bob's anchor sweep.
expectedTxes := 1
hasAnchors := commitTypeHasAnchors(c)
hasAnchors := lntest.CommitTypeHasAnchors(c)
if hasAnchors {
expectedTxes = 2
}
@ -369,11 +272,11 @@ func runMultiHopHtlcLocalTimeout(ht *lntemp.HarnessTest,
// transaction. In this scenario, the node that sent the outgoing HTLC should
// extract the preimage from the sweep transaction, and finish settling the
// HTLC backwards into the route.
func testMultiHopReceiverChainClaim(ht *lntemp.HarnessTest) {
func testMultiHopReceiverChainClaim(ht *lntest.HarnessTest) {
runMultiHopHtlcClaimTest(ht, runMultiHopReceiverChainClaim)
}
func runMultiHopReceiverChainClaim(ht *lntemp.HarnessTest,
func runMultiHopReceiverChainClaim(ht *lntest.HarnessTest,
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
@ -445,7 +348,7 @@ func runMultiHopReceiverChainClaim(ht *lntemp.HarnessTest,
// transaction in order to go to the chain and sweep her HTLC. If there
// are anchors, Carol also sweeps hers.
expectedTxes := 1
hasAnchors := commitTypeHasAnchors(c)
hasAnchors := lntest.CommitTypeHasAnchors(c)
if hasAnchors {
expectedTxes = 2
}
@ -567,13 +470,13 @@ func runMultiHopReceiverChainClaim(ht *lntemp.HarnessTest,
// commitment on-chain early, then it eventually recognizes this HTLC as one
// that's timed out. At this point, the node should timeout the HTLC using the
// HTLC timeout transaction, then cancel it backwards as normal.
func testMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest) {
func testMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest) {
runMultiHopHtlcClaimTest(
ht, runMultiHopLocalForceCloseOnChainHtlcTimeout,
)
}
func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest,
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
@ -614,7 +517,7 @@ func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
// Now that all parties have the HTLC locked in, we'll immediately
// force close the Bob -> Carol channel. This should trigger contract
// resolution mode for both of them.
hasAnchors := commitTypeHasAnchors(c)
hasAnchors := lntest.CommitTypeHasAnchors(c)
stream, _ := ht.CloseChannelAssertPending(bob, bobChanPoint, true)
closeTx := ht.AssertStreamChannelForceClosed(
bob, bobChanPoint, hasAnchors, stream,
@ -723,13 +626,13 @@ func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
// channel, then we properly timeout the HTLC directly on *their* commitment
// transaction once the timeout has expired. Once we sweep the transaction, we
// should also cancel back the initial HTLC.
func testMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest) {
func testMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest) {
runMultiHopHtlcClaimTest(
ht, runMultiHopRemoteForceCloseOnChainHtlcTimeout,
)
}
func runMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
func runMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest,
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
@ -779,7 +682,7 @@ func runMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
// transaction. This will let us exercise that Bob is able to sweep the
// expired HTLC on Carol's version of the commitment transaction. If
// Carol has an anchor, it will be swept too.
hasAnchors := commitTypeHasAnchors(c)
hasAnchors := lntest.CommitTypeHasAnchors(c)
closeStream, _ := ht.CloseChannelAssertPending(
carol, bobChanPoint, true,
)
@ -879,11 +782,11 @@ func runMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
// we force close a channel with an incoming HTLC, and later find out the
// preimage via the witness beacon, we properly settle the HTLC on-chain using
// the HTLC success transaction in order to ensure we don't lose any funds.
func testMultiHopHtlcLocalChainClaim(ht *lntemp.HarnessTest) {
func testMultiHopHtlcLocalChainClaim(ht *lntest.HarnessTest) {
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcLocalChainClaim)
}
func runMultiHopHtlcLocalChainClaim(ht *lntemp.HarnessTest,
func runMultiHopHtlcLocalChainClaim(ht *lntest.HarnessTest,
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
@ -937,7 +840,7 @@ func runMultiHopHtlcLocalChainClaim(ht *lntemp.HarnessTest,
// At this point, Bob decides that he wants to exit the channel
// immediately, so he force closes his commitment transaction.
hasAnchors := commitTypeHasAnchors(c)
hasAnchors := lntest.CommitTypeHasAnchors(c)
closeStream, _ := ht.CloseChannelAssertPending(
bob, aliceChanPoint, true,
)
@ -985,7 +888,7 @@ func runMultiHopHtlcLocalChainClaim(ht *lntemp.HarnessTest,
// Carol's commitment transaction should now be in the mempool. If
// there is an anchor, Carol will sweep that too.
if commitTypeHasAnchors(c) {
if lntest.CommitTypeHasAnchors(c) {
expectedTxes = 2
}
ht.Miner.AssertNumTxsInMempool(expectedTxes)
@ -1173,11 +1076,11 @@ func runMultiHopHtlcLocalChainClaim(ht *lntemp.HarnessTest,
// we found out the preimage via the witness beacon, we properly settle the
// HTLC directly on-chain using the preimage in order to ensure that we don't
// lose any funds.
func testMultiHopHtlcRemoteChainClaim(ht *lntemp.HarnessTest) {
func testMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest) {
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcRemoteChainClaim)
}
func runMultiHopHtlcRemoteChainClaim(ht *lntemp.HarnessTest,
func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest,
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
@ -1232,7 +1135,7 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntemp.HarnessTest,
// Next, Alice decides that she wants to exit the channel, so she'll
// immediately force close the channel by broadcast her commitment
// transaction.
hasAnchors := commitTypeHasAnchors(c)
hasAnchors := lntest.CommitTypeHasAnchors(c)
closeStream, _ := ht.CloseChannelAssertPending(
alice, aliceChanPoint, true,
)
@ -1443,11 +1346,11 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntemp.HarnessTest,
// resolve them using the second level timeout and success transactions. In
// case of anchor channels, the second-level spends can also be aggregated and
// properly feebumped, so we'll check that as well.
func testMultiHopHtlcAggregation(ht *lntemp.HarnessTest) {
func testMultiHopHtlcAggregation(ht *lntest.HarnessTest) {
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcAggregation)
}
func runMultiHopHtlcAggregation(ht *lntemp.HarnessTest,
func runMultiHopHtlcAggregation(ht *lntest.HarnessTest,
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
// First, we'll create a three hop network: Alice -> Bob -> Carol.
@ -1586,7 +1489,7 @@ func runMultiHopHtlcAggregation(ht *lntemp.HarnessTest,
// Bob's force close transaction should now be found in the mempool. If
// there are anchors, we also expect Bob's anchor sweep.
hasAnchors := commitTypeHasAnchors(c)
hasAnchors := lntest.CommitTypeHasAnchors(c)
expectedTxes := 1
if hasAnchors {
expectedTxes = 2
@ -1825,7 +1728,7 @@ func runMultiHopHtlcAggregation(ht *lntemp.HarnessTest,
}
// createThreeHopNetwork creates a topology of `Alice -> Bob -> Carol`.
func createThreeHopNetwork(ht *lntemp.HarnessTest,
func createThreeHopNetwork(ht *lntest.HarnessTest,
alice, bob *node.HarnessNode, carolHodl bool, c lnrpc.CommitmentType,
zeroConf bool) (*lnrpc.ChannelPoint,
*lnrpc.ChannelPoint, *node.HarnessNode) {
@ -1835,7 +1738,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
// We'll create a new node "carol" and have Bob connect to her.
// If the carolHodl flag is set, we'll make carol always hold onto the
// HTLC, this way it'll force Bob to go to chain to resolve the HTLC.
carolFlags := nodeArgsForCommitType(c)
carolFlags := lntest.NodeArgsForCommitType(c)
if carolHodl {
carolFlags = append(carolFlags, "--hodl.exit-settle")
}
@ -1871,7 +1774,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
if c == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE {
_, minerHeight := ht.Miner.GetBestBlock()
thawHeight = uint32(minerHeight + thawHeightDelta)
aliceFundingShim, _, _ = deriveFundingShim(
aliceFundingShim, _ = deriveFundingShim(
ht, alice, bob, chanAmt, thawHeight, true,
)
}
@ -1887,7 +1790,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
go acceptChannel(ht.T, true, acceptStream)
}
aliceParams := lntemp.OpenChannelParams{
aliceParams := lntest.OpenChannelParams{
Amt: chanAmt,
CommitmentType: c,
FundingShim: aliceFundingShim,
@ -1904,7 +1807,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
// open, our topology looks like: A -> B -> C.
var bobFundingShim *lnrpc.FundingShim
if c == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE {
bobFundingShim, _, _ = deriveFundingShim(
bobFundingShim, _ = deriveFundingShim(
ht, bob, carol, chanAmt, thawHeight, true,
)
}
@ -1916,7 +1819,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
go acceptChannel(ht.T, true, acceptStream)
}
bobParams := lntemp.OpenChannelParams{
bobParams := lntest.OpenChannelParams{
Amt: chanAmt,
CommitmentType: c,
FundingShim: bobFundingShim,

View file

@ -3,12 +3,12 @@ package itest
import (
"fmt"
"net"
"time"
"github.com/lightningnetwork/lnd/lncfg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/stretchr/testify/require"
)
@ -16,7 +16,7 @@ import (
// testNetworkConnectionTimeout checks that the connectiontimeout is taking
// effect. It creates a node with a small connection timeout value, and
// connects it to a non-routable IP address.
func testNetworkConnectionTimeout(ht *lntemp.HarnessTest) {
func testNetworkConnectionTimeout(ht *lntest.HarnessTest) {
var (
// testPub is a random public key for testing only.
testPub = "0332bda7da70fefe4b6ab92f53b3c4f4ee7999" +
@ -75,7 +75,7 @@ func testNetworkConnectionTimeout(ht *lntemp.HarnessTest) {
// testReconnectAfterIPChange verifies that if a persistent inbound node changes
// its listening address then it's peer will still be able to reconnect to it.
func testReconnectAfterIPChange(ht *lntemp.HarnessTest) {
func testReconnectAfterIPChange(ht *lntest.HarnessTest) {
// In this test, the following network will be set up. A single
// dash line represents a peer connection and a double dash line
// represents a channel.
@ -105,7 +105,7 @@ func testReconnectAfterIPChange(ht *lntemp.HarnessTest) {
// We derive an extra port for Dave, and we initialise his node with
// the port advertised as `--externalip` arguments.
ip2 := lntest.NextAvailablePort()
ip2 := node.NextAvailablePort()
// Create a new node, Dave, which will initialize a P2P port for him.
daveArgs := []string{fmt.Sprintf("--externalip=127.0.0.1:%d", ip2)}
@ -127,7 +127,7 @@ func testReconnectAfterIPChange(ht *lntemp.HarnessTest) {
// ensures that Charlie receives the node announcement from Alice as
// part of the announcement broadcast.
chanPoint := ht.OpenChannel(
alice, dave, lntemp.OpenChannelParams{Amt: 1000000},
alice, dave, lntest.OpenChannelParams{Amt: 1000000},
)
// waitForNodeAnnouncement is a closure used to wait on the given graph
@ -184,7 +184,7 @@ func testReconnectAfterIPChange(ht *lntemp.HarnessTest) {
// address.
// Change Dave's listening port and restart.
dave.Cfg.P2PPort = lntest.NextAvailablePort()
dave.Cfg.P2PPort = node.NextAvailablePort()
dave.Cfg.ExtraArgs = []string{
fmt.Sprintf(
"--externalip=127.0.0.1:%d", dave.Cfg.P2PPort,
@ -210,7 +210,7 @@ func testReconnectAfterIPChange(ht *lntemp.HarnessTest) {
// testAddPeerConfig tests that the "--addpeer" config flag successfully adds
// a new peer.
func testAddPeerConfig(ht *lntemp.HarnessTest) {
func testAddPeerConfig(ht *lntest.HarnessTest) {
alice := ht.Alice
info := alice.RPC.GetInfo()
@ -220,6 +220,9 @@ func testAddPeerConfig(ht *lntemp.HarnessTest) {
args := []string{fmt.Sprintf("--addpeer=%v", alicePeerAddress)}
carol := ht.NewNode("Carol", args)
// TODO(yy): remove this once the peer conn race is fixed.
time.Sleep(1 * time.Second)
ht.EnsureConnected(alice, carol)
// If we list Carol's peers, Alice should already be

View file

@ -2,15 +2,14 @@ package itest
import (
"github.com/lightningnetwork/lnd/lnrpc/neutrinorpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/stretchr/testify/require"
)
// testNeutrino checks that the neutrino sub-server can fetch compact
// block filters, server status and connect to a connected peer.
func testNeutrino(ht *lntemp.HarnessTest) {
if ht.ChainBackendName() != lntest.NeutrinoBackendName {
func testNeutrino(ht *lntest.HarnessTest) {
if !ht.IsNeutrinoBackend() {
ht.Skipf("skipping test for non neutrino backends")
}

View file

@ -3,8 +3,8 @@
package itest
import "github.com/lightningnetwork/lnd/lntemp"
import "github.com/lightningnetwork/lnd/lntest"
// testEtcdFailover is an empty itest when LND is not compiled with etcd
// support.
func testEtcdFailover(ht *lntemp.HarnessTest) {}
func testEtcdFailover(ht *lntest.HarnessTest) {}

View file

@ -5,11 +5,11 @@ import (
"github.com/btcsuite/btcd/btcutil"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/stretchr/testify/require"
)
func testNonstdSweep(ht *lntemp.HarnessTest) {
func testNonstdSweep(ht *lntest.HarnessTest) {
p2shAddr, err := btcutil.NewAddressScriptHash(
make([]byte, 1), harnessNetParams,
)
@ -74,7 +74,7 @@ func testNonstdSweep(ht *lntemp.HarnessTest) {
}
}
func testNonStdSweepInner(ht *lntemp.HarnessTest, address string) {
func testNonStdSweepInner(ht *lntest.HarnessTest, address string) {
carol := ht.NewNode("carol", nil)
// Give Carol a UTXO so SendCoins will behave as expected.

View file

@ -11,8 +11,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/sweep"
@ -20,7 +20,7 @@ import (
)
// testChainKit tests ChainKit RPC endpoints.
func testChainKit(ht *lntemp.HarnessTest) {
func testChainKit(ht *lntest.HarnessTest) {
// Test functions registered as test cases spin up separate nodes
// during execution. By calling sub-test functions as seen below we
// avoid the need to start separate nodes.
@ -30,7 +30,7 @@ func testChainKit(ht *lntemp.HarnessTest) {
// testChainKitGetBlock ensures that given a block hash, the RPC endpoint
// returns the correct target block.
func testChainKitGetBlock(ht *lntemp.HarnessTest) {
func testChainKitGetBlock(ht *lntest.HarnessTest) {
// Get best block hash.
bestBlockRes := ht.Alice.RPC.GetBestBlock(nil)
@ -58,7 +58,7 @@ func testChainKitGetBlock(ht *lntemp.HarnessTest) {
// testChainKitGetBlockHash ensures that given a block height, the RPC endpoint
// returns the correct target block hash.
func testChainKitGetBlockHash(ht *lntemp.HarnessTest) {
func testChainKitGetBlockHash(ht *lntest.HarnessTest) {
// Get best block hash.
bestBlockRes := ht.Alice.RPC.GetBestBlock(nil)
@ -78,13 +78,13 @@ func testChainKitGetBlockHash(ht *lntemp.HarnessTest) {
// rate by broadcasting a Child-Pays-For-Parent (CPFP) transaction.
//
// TODO(wilmer): Add RBF case once btcd supports it.
func testCPFP(ht *lntemp.HarnessTest) {
func testCPFP(ht *lntest.HarnessTest) {
runCPFP(ht, ht.Alice, ht.Bob)
}
// runCPFP ensures that the daemon can bump an unconfirmed transaction's fee
// rate by broadcasting a Child-Pays-For-Parent (CPFP) transaction.
func runCPFP(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
func runCPFP(ht *lntest.HarnessTest, alice, bob *node.HarnessNode) {
// Skip this test for neutrino, as it's not aware of mempool
// transactions.
if ht.IsNeutrinoBackend() {
@ -172,6 +172,7 @@ func runCPFP(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
return fmt.Errorf("expected 0 pending sweeps, found %d",
len(resp.PendingSweeps))
}
return nil
}, defaultTimeout)
require.NoError(ht, err, "timeout checking bob's pending sweeps")
@ -180,9 +181,9 @@ func runCPFP(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
// testAnchorReservedValue tests that we won't allow sending transactions when
// that would take the value we reserve for anchor fee bumping out of our
// wallet.
func testAnchorReservedValue(ht *lntemp.HarnessTest) {
func testAnchorReservedValue(ht *lntest.HarnessTest) {
// Start two nodes supporting anchor channels.
args := nodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
args := lntest.NodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
// NOTE: we cannot reuse the standby node here as the test requires the
// node to start with no UTXOs.
@ -203,7 +204,7 @@ func testAnchorReservedValue(ht *lntemp.HarnessTest) {
// wallet, without a change output. This should not be allowed.
ht.OpenChannelAssertErr(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: chanAmt,
}, lnwallet.ErrReservedValueInvalidated,
)
@ -211,13 +212,13 @@ func testAnchorReservedValue(ht *lntemp.HarnessTest) {
// Alice opens a smaller channel. This works since it will have a
// change output.
chanPoint1 := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt / 4},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt / 4},
)
// If Alice tries to open another anchor channel to Bob, Bob should not
// reject it as he is not contributing any funds.
chanPoint2 := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt / 4},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt / 4},
)
// Similarly, if Alice tries to open a legacy channel to Bob, Bob
@ -229,7 +230,7 @@ func testAnchorReservedValue(ht *lntemp.HarnessTest) {
ht.EnsureConnected(alice, bob)
chanPoint3 := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt / 4},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt / 4},
)
chanPoints := []*lnrpc.ChannelPoint{chanPoint1, chanPoint2, chanPoint3}
@ -276,6 +277,7 @@ func testAnchorReservedValue(ht *lntemp.HarnessTest) {
}
balance = resp.TotalBalance
return nil
}, defaultTimeout)
require.NoError(ht, err, "timeout checking alice's balance")
@ -347,18 +349,15 @@ func testAnchorReservedValue(ht *lntemp.HarnessTest) {
// testAnchorThirdPartySpend tests that if we force close a channel, but then
// don't sweep the anchor in time and a 3rd party spends it, that we remove any
// transactions that are a descendent of that sweep.
func testAnchorThirdPartySpend(ht *lntemp.HarnessTest) {
func testAnchorThirdPartySpend(ht *lntest.HarnessTest) {
// First, we'll create two new nodes that both default to anchor
// channels.
//
// NOTE: The itests differ here as anchors is default off vs the normal
// lnd binary.
args := nodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
args := lntest.NodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
alice := ht.NewNode("Alice", args)
defer ht.Shutdown(alice)
bob := ht.NewNode("Bob", args)
defer ht.Shutdown(bob)
ht.EnsureConnected(alice, bob)
@ -374,7 +373,7 @@ func testAnchorThirdPartySpend(ht *lntemp.HarnessTest) {
// Open the channel between the two nodes and wait for it to confirm
// fully.
aliceChanPoint1 := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: firstChanSize,
},
)
@ -493,7 +492,7 @@ func testAnchorThirdPartySpend(ht *lntemp.HarnessTest) {
// assertAnchorOutputLost asserts that the anchor output for the given channel
// has the state of being lost.
func assertAnchorOutputLost(ht *lntemp.HarnessTest, hn *node.HarnessNode,
func assertAnchorOutputLost(ht *lntest.HarnessTest, hn *node.HarnessNode,
chanPoint *lnrpc.ChannelPoint) {
cp := ht.OutPointFromChannelPoint(chanPoint)
@ -527,8 +526,8 @@ func assertAnchorOutputLost(ht *lntemp.HarnessTest, hn *node.HarnessNode,
// genAnchorSweep generates a "3rd party" anchor sweeping from an existing one.
// In practice, we just re-use the existing witness, and track on our own
// output producing a 1-in-1-out transaction.
func genAnchorSweep(ht *lntemp.HarnessTest,
aliceAnchor *lntemp.SweptOutput, anchorCsv uint32) *btcutil.Tx {
func genAnchorSweep(ht *lntest.HarnessTest,
aliceAnchor *lntest.SweptOutput, anchorCsv uint32) *btcutil.Tx {
// At this point, we have the transaction that Alice used to try to
// sweep her anchor. As this is actually just something anyone can

View file

@ -10,9 +10,9 @@ import (
"github.com/lightningnetwork/lnd/chainreg"
"github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntemp/rpc"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/rpc"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/stretchr/testify/require"
)
@ -20,7 +20,7 @@ import (
// testOpenChannelAfterReorg tests that in the case where we have an open
// channel where the funding tx gets reorged out, the channel will no
// longer be present in the node's routing table.
func testOpenChannelAfterReorg(ht *lntemp.HarnessTest) {
func testOpenChannelAfterReorg(ht *lntest.HarnessTest) {
// Skip test for neutrino, as we cannot disconnect the miner at will.
// TODO(halseth): remove when either can disconnect at will, or restart
// node with connection to new miner.
@ -33,7 +33,7 @@ func testOpenChannelAfterReorg(ht *lntemp.HarnessTest) {
// Set up a new miner that we can use to cause a reorg.
tempLogDir := ".tempminerlogs"
logFilename := "output-open_channel_reorg-temp_miner.log"
tempMiner := lntemp.NewTempMiner(
tempMiner := lntest.NewTempMiner(
ht.Context(), ht.T, tempLogDir, logFilename,
)
defer tempMiner.Stop()
@ -68,7 +68,7 @@ func testOpenChannelAfterReorg(ht *lntemp.HarnessTest) {
// Create a new channel that requires 1 confs before it's considered
// open, then broadcast the funding transaction
params := lntemp.OpenChannelParams{
params := lntest.OpenChannelParams{
Amt: funding.MaxBtcFundingAmount,
Private: true,
}
@ -172,7 +172,7 @@ func testOpenChannelAfterReorg(ht *lntemp.HarnessTest) {
// ChannelUpdate --> defaultBaseFee, provided FeeRate
// 4.) baseFee and feeRate provided to OpenChannelRequest
// ChannelUpdate --> provided baseFee, provided feeRate.
func testOpenChannelUpdateFeePolicy(ht *lntemp.HarnessTest) {
func testOpenChannelUpdateFeePolicy(ht *lntest.HarnessTest) {
const (
defaultBaseFee = 1000
defaultFeeRate = 1
@ -182,12 +182,12 @@ func testOpenChannelUpdateFeePolicy(ht *lntemp.HarnessTest) {
optionalFeeRate = 1337
)
defaultMaxHtlc := calculateMaxHtlc(funding.MaxBtcFundingAmount)
defaultMaxHtlc := lntest.CalculateMaxHtlc(funding.MaxBtcFundingAmount)
chanAmt := funding.MaxBtcFundingAmount
pushAmt := chanAmt / 2
feeScenarios := []lntemp.OpenChannelParams{
feeScenarios := []lntest.OpenChannelParams{
{
Amt: chanAmt,
PushAmt: pushAmt,
@ -259,8 +259,8 @@ func testOpenChannelUpdateFeePolicy(ht *lntemp.HarnessTest) {
alice, bob := ht.Alice, ht.Bob
runTestCase := func(ht *lntemp.HarnessTest,
fs lntemp.OpenChannelParams,
runTestCase := func(ht *lntest.HarnessTest,
fs lntest.OpenChannelParams,
alicePolicy, bobPolicy *lnrpc.RoutingPolicy) {
// Create a channel Alice->Bob.
@ -305,14 +305,14 @@ func testOpenChannelUpdateFeePolicy(ht *lntemp.HarnessTest) {
// testBasicChannelCreationAndUpdates tests multiple channel opening and
// closing, and ensures that if a node is subscribed to channel updates they
// will be received correctly for both cooperative and force closed channels.
func testBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest) {
func testBasicChannelCreationAndUpdates(ht *lntest.HarnessTest) {
runBasicChannelCreationAndUpdates(ht, ht.Alice, ht.Bob)
}
// runBasicChannelCreationAndUpdates tests multiple channel opening and closing,
// and ensures that if a node is subscribed to channel updates they will be
// received correctly for both cooperative and force closed channels.
func runBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest,
func runBasicChannelCreationAndUpdates(ht *lntest.HarnessTest,
alice, bob *node.HarnessNode) {
const (
@ -329,7 +329,7 @@ func runBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest,
chanPoints := make([]*lnrpc.ChannelPoint, numChannels)
for i := 0; i < numChannels; i++ {
chanPoints[i] = ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: amount,
},
)
@ -458,8 +458,8 @@ func runBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest,
// assertMinerBlockHeightDelta ensures that tempMiner is 'delta' blocks ahead
// of miner.
func assertMinerBlockHeightDelta(ht *lntemp.HarnessTest,
miner, tempMiner *lntemp.HarnessMiner, delta int32) {
func assertMinerBlockHeightDelta(ht *lntest.HarnessTest,
miner, tempMiner *lntest.HarnessMiner, delta int32) {
// Ensure the chain lengths are what we expect.
err := wait.NoError(func() error {

View file

@ -1,7 +1,6 @@
package itest
import (
"context"
"crypto/sha256"
"encoding/hex"
"fmt"
@ -11,14 +10,13 @@ import (
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/stretchr/testify/require"
)
func testListPayments(ht *lntemp.HarnessTest) {
func testListPayments(ht *lntest.HarnessTest) {
alice, bob := ht.Alice, ht.Bob
// Check that there are no payments before test.
@ -28,7 +26,7 @@ func testListPayments(ht *lntemp.HarnessTest) {
// being the sole funder of the channel.
chanAmt := btcutil.Amount(100000)
chanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
)
// Get the number of invoices Bob already has.
@ -171,13 +169,13 @@ func testListPayments(ht *lntemp.HarnessTest) {
// subsystems trying to update the channel state in the db. We follow this
// transition with a payment that updates the commitment state and verify that
// the pending state is up to date.
func testPaymentFollowingChannelOpen(ht *lntemp.HarnessTest) {
func testPaymentFollowingChannelOpen(ht *lntest.HarnessTest) {
const paymentAmt = btcutil.Amount(100)
channelCapacity := paymentAmt * 1000
// We first establish a channel between Alice and Bob.
alice, bob := ht.Alice, ht.Bob
p := lntemp.OpenChannelParams{
p := lntest.OpenChannelParams{
Amt: channelCapacity,
}
pendingUpdate := ht.OpenChannelAssertPending(alice, bob, p)
@ -198,7 +196,7 @@ func testPaymentFollowingChannelOpen(ht *lntemp.HarnessTest) {
ht.MineBlocksAndAssertNumTxes(6, 1)
// We verify that the channel is open from both nodes point of view.
chanPoint := lntemp.ChanPointFromPendingUpdate(pendingUpdate)
chanPoint := lntest.ChanPointFromPendingUpdate(pendingUpdate)
ht.AssertNodesNumPendingOpenChannels(alice, bob, 0)
ht.AssertChannelExists(alice, chanPoint)
ht.AssertChannelExists(bob, chanPoint)
@ -226,7 +224,7 @@ func testPaymentFollowingChannelOpen(ht *lntemp.HarnessTest) {
}
// testAsyncPayments tests the performance of the async payments.
func testAsyncPayments(ht *lntemp.HarnessTest) {
func testAsyncPayments(ht *lntest.HarnessTest) {
// We use new nodes here as the benchmark test creates lots of data
// which can be costly to be carried on.
alice := ht.NewNode("Alice", []string{"--pending-commit-interval=3m"})
@ -239,7 +237,7 @@ func testAsyncPayments(ht *lntemp.HarnessTest) {
}
// runAsyncPayments tests the performance of the async payments.
func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
func runAsyncPayments(ht *lntest.HarnessTest, alice, bob *node.HarnessNode) {
const paymentAmt = 100
// First establish a channel with a capacity equals to the overall
@ -247,7 +245,7 @@ func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
// Alice should send all money from her side to Bob.
channelCapacity := btcutil.Amount(paymentAmt * 2000)
chanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: channelCapacity},
alice, bob, lntest.OpenChannelParams{Amt: channelCapacity},
)
info := ht.QueryChannelByChanPoint(alice, chanPoint)
@ -273,7 +271,7 @@ func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
settled := make(chan struct{})
defer close(settled)
timeout := lntest.AsyncBenchmarkTimeout * 2
timeout := wait.AsyncBenchmarkTimeout
for i := 0; i < numInvoices; i++ {
payReq := bobPayReqs[i]
go func() {
@ -304,46 +302,13 @@ func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
// All payments have been sent, mark the finish time.
timeTaken := time.Since(now)
// assertChannelState asserts the channel state by checking the values
// in fields, LocalBalance, RemoteBalance and num of PendingHtlcs.
assertChannelState := func(hn *node.HarnessNode, cp *lnrpc.ChannelPoint,
localBalance, remoteBalance int64, numPendingHtlcs int) {
// Get the funding point.
err := wait.NoError(func() error {
// Find the target channel first.
target := ht.GetChannelByChanPoint(hn, cp)
if len(target.PendingHtlcs) != numPendingHtlcs {
return fmt.Errorf("pending htlcs is "+
"incorrect, got %v, expected %v",
len(target.PendingHtlcs), 0)
}
if target.LocalBalance != localBalance {
return fmt.Errorf("local balance is "+
"incorrect, got %v, expected %v",
target.LocalBalance, localBalance)
}
if target.RemoteBalance != remoteBalance {
return fmt.Errorf("remote balance is "+
"incorrect, got %v, expected %v",
target.RemoteBalance, remoteBalance)
}
return nil
}, lntemp.DefaultTimeout)
require.NoError(ht, err, "timeout while chekcing for balance")
}
// Wait for the revocation to be received so alice no longer has
// pending htlcs listed and has correct balances. This is needed due to
// the fact that we now pipeline the settles.
assertChannelState(alice, chanPoint, aliceAmt, bobAmt, 0)
assertChannelState(ht, alice, chanPoint, aliceAmt, bobAmt)
// Wait for Bob to receive revocation from Alice.
assertChannelState(bob, chanPoint, bobAmt, aliceAmt, 0)
assertChannelState(ht, bob, chanPoint, bobAmt, aliceAmt)
ht.Log("\tBenchmark info: Elapsed time: ", timeTaken)
ht.Log("\tBenchmark info: TPS: ",
@ -357,28 +322,41 @@ func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
// testBidirectionalAsyncPayments tests that nodes are able to send the
// payments to each other in async manner without blocking.
func testBidirectionalAsyncPayments(net *lntest.NetworkHarness, t *harnessTest) {
ctxb := context.Background()
func testBidirectionalAsyncPayments(ht *lntest.HarnessTest) {
const paymentAmt = 1000
const (
paymentAmt = 1000
)
// We use new nodes here as the benchmark test creates lots of data
// which can be costly to be carried on.
args := []string{
// Increase the dust threshold to avoid the payments fail due
// to threshold limit reached.
"--dust-threshold=5000000",
// Increase the pending commit interval since there are lots of
// commitment dances.
"--pending-commit-interval=5m",
// Increase the mailbox delivery timeout as there are lots of
// ADDs going on.
"--htlcswitch.mailboxdeliverytimeout=2m",
}
alice := ht.NewNode("Alice", args)
bob := ht.NewNode("Bob", args)
ht.EnsureConnected(alice, bob)
ht.FundCoins(btcutil.SatoshiPerBitcoin, alice)
// First establish a channel with a capacity equals to the overall
// amount of payments, between Alice and Bob, at the end of the test
// Alice should send all money from her side to Bob.
chanPoint := openChannelAndAssert(
t, net, net.Alice, net.Bob,
lntest.OpenChannelParams{
chanPoint := ht.OpenChannel(
alice, bob, lntest.OpenChannelParams{
Amt: paymentAmt * 2000,
PushAmt: paymentAmt * 1000,
},
)
info, err := getChanInfo(net.Alice)
if err != nil {
t.Fatalf("unable to get alice channel info: %v", err)
}
info := ht.QueryChannelByChanPoint(alice, chanPoint)
// We'll create a number of invoices equal the max number of HTLCs that
// can be carried in one direction. The number on the commitment will
@ -394,158 +372,67 @@ func testBidirectionalAsyncPayments(net *lntest.NetworkHarness, t *harnessTest)
// With the channel open, we'll create invoices for Bob that Alice
// will pay to in order to advance the state of the channel.
bobPayReqs, _, _, err := createPayReqs(
net.Bob, paymentAmt, numInvoices,
)
if err != nil {
t.Fatalf("unable to create pay reqs: %v", err)
}
bobPayReqs, _, _ := ht.CreatePayReqs(bob, paymentAmt, numInvoices)
// With the channel open, we'll create invoices for Alice that Bob
// will pay to in order to advance the state of the channel.
alicePayReqs, _, _, err := createPayReqs(
net.Alice, paymentAmt, numInvoices,
)
if err != nil {
t.Fatalf("unable to create pay reqs: %v", err)
}
// Wait for Alice to receive the channel edge from the funding manager.
if err = net.Alice.WaitForNetworkChannelOpen(chanPoint); err != nil {
t.Fatalf("alice didn't see the alice->bob channel before "+
"timeout: %v", err)
}
if err = net.Bob.WaitForNetworkChannelOpen(chanPoint); err != nil {
t.Fatalf("bob didn't see the bob->alice channel before "+
"timeout: %v", err)
}
alicePayReqs, _, _ := ht.CreatePayReqs(alice, paymentAmt, numInvoices)
// Reset mission control to prevent previous payment results from
// interfering with this test. A new channel has been opened, but
// mission control operates on node pairs.
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
_, err = net.Alice.RouterClient.ResetMissionControl(
ctxt, &routerrpc.ResetMissionControlRequest{},
)
if err != nil {
t.Fatalf("unable to reset mc for alice: %v", err)
}
alice.RPC.ResetMissionControl()
// Send payments from Alice to Bob and from Bob to Alice in async
// manner.
errChan := make(chan error)
statusChan := make(chan *lnrpc.Payment)
settled := make(chan struct{})
defer close(settled)
send := func(node *lntest.HarnessNode, payReq string) {
go func() {
ctxt, _ = context.WithTimeout(
ctxb, lntest.AsyncBenchmarkTimeout,
)
stream, err := node.RouterClient.SendPaymentV2(
ctxt,
&routerrpc.SendPaymentRequest{
PaymentRequest: payReq,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
},
)
if err != nil {
errChan <- err
}
result, err := getPaymentResult(stream)
if err != nil {
errChan <- err
}
timeout := wait.AsyncBenchmarkTimeout * 2
send := func(node *node.HarnessNode, payReq string) {
req := &routerrpc.SendPaymentRequest{
PaymentRequest: payReq,
TimeoutSeconds: int32(timeout.Seconds()),
FeeLimitMsat: noFeeLimitMsat,
}
// AssertPaymentStatusWithTimeout will assert that the
// payment is settled.
stream := node.RPC.SendPayment(req)
ht.AssertPaymentSucceedWithTimeout(stream, timeout)
statusChan <- result
}()
settled <- struct{}{}
}
for i := 0; i < numInvoices; i++ {
send(net.Bob, alicePayReqs[i])
send(net.Alice, bobPayReqs[i])
go send(bob, alicePayReqs[i])
go send(alice, bobPayReqs[i])
}
// Expect all payments to succeed.
timer := time.After(timeout)
for i := 0; i < 2*numInvoices; i++ {
select {
case result := <-statusChan:
if result.Status != lnrpc.Payment_SUCCEEDED {
t.Fatalf("payment error: %v", result.Status)
}
case err := <-errChan:
t.Fatalf("payment error: %v", err)
case <-settled:
case <-timer:
require.Fail(ht, "timeout", "wait payment failed")
}
}
// Wait for Alice and Bob to receive revocations messages, and update
// states, i.e. balance info.
err = wait.NoError(func() error {
aliceInfo, err := getChanInfo(net.Alice)
if err != nil {
t.Fatalf("unable to get alice's channel info: %v", err)
}
if aliceInfo.RemoteBalance != bobAmt {
return fmt.Errorf("alice's remote balance is incorrect, "+
"got %v, expected %v", aliceInfo.RemoteBalance,
bobAmt)
}
if aliceInfo.LocalBalance != aliceAmt {
return fmt.Errorf("alice's local balance is incorrect, "+
"got %v, expected %v", aliceInfo.LocalBalance,
aliceAmt)
}
if len(aliceInfo.PendingHtlcs) != 0 {
return fmt.Errorf("alice's pending htlcs is incorrect, "+
"got %v expected %v",
len(aliceInfo.PendingHtlcs), 0)
}
return nil
}, defaultTimeout)
require.NoError(t.t, err)
assertChannelState(ht, alice, chanPoint, aliceAmt, bobAmt)
// Next query for Bob's and Alice's channel states, in order to confirm
// that all payment have been successful transmitted.
err = wait.NoError(func() error {
bobInfo, err := getChanInfo(net.Bob)
if err != nil {
t.Fatalf("unable to get bob's channel info: %v", err)
}
if bobInfo.LocalBalance != bobAmt {
return fmt.Errorf("bob's local balance is incorrect, "+
"got %v, expected %v", bobInfo.LocalBalance,
bobAmt)
}
if bobInfo.RemoteBalance != aliceAmt {
return fmt.Errorf("bob's remote balance is incorrect, "+
"got %v, expected %v", bobInfo.RemoteBalance,
aliceAmt)
}
if len(bobInfo.PendingHtlcs) != 0 {
return fmt.Errorf("bob's pending htlcs is incorrect, "+
"got %v, expected %v",
len(bobInfo.PendingHtlcs), 0)
}
return nil
}, defaultTimeout)
require.NoError(t.t, err)
assertChannelState(ht, bob, chanPoint, bobAmt, aliceAmt)
// Finally, immediately close the channel. This function will also
// block until the channel is closed and will additionally assert the
// relevant channel closing post conditions.
closeChannelAndAssert(t, net, net.Alice, chanPoint, false)
ht.CloseChannel(alice, chanPoint)
}
func testInvoiceSubscriptions(ht *lntemp.HarnessTest) {
func testInvoiceSubscriptions(ht *lntest.HarnessTest) {
const chanAmt = btcutil.Amount(500000)
alice, bob := ht.Alice, ht.Bob
@ -558,7 +445,7 @@ func testInvoiceSubscriptions(ht *lntemp.HarnessTest) {
// Open a channel with 500k satoshis between Alice and Bob with Alice
// being the sole funder of the channel.
chanPoint := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
)
// Next create a new invoice for Bob requesting 1k satoshis.
@ -672,3 +559,36 @@ func testInvoiceSubscriptions(ht *lntemp.HarnessTest) {
ht.CloseChannel(alice, chanPoint)
}
// assertChannelState asserts the channel state by checking the values in
// fields, LocalBalance, RemoteBalance and num of PendingHtlcs.
func assertChannelState(ht *lntest.HarnessTest, hn *node.HarnessNode,
cp *lnrpc.ChannelPoint, localBalance, remoteBalance int64) {
// Get the funding point.
err := wait.NoError(func() error {
// Find the target channel first.
target := ht.GetChannelByChanPoint(hn, cp)
if len(target.PendingHtlcs) != 0 {
return fmt.Errorf("pending htlcs is "+
"incorrect, got %v, expected %v",
len(target.PendingHtlcs), 0)
}
if target.LocalBalance != localBalance {
return fmt.Errorf("local balance is "+
"incorrect, got %v, expected %v",
target.LocalBalance, localBalance)
}
if target.RemoteBalance != remoteBalance {
return fmt.Errorf("remote balance is "+
"incorrect, got %v, expected %v",
target.RemoteBalance, remoteBalance)
}
return nil
}, lntest.DefaultTimeout)
require.NoError(ht, err, "timeout while chekcing for balance")
}

View file

@ -2,8 +2,6 @@ package itest
import (
"bytes"
"context"
"fmt"
"time"
"github.com/btcsuite/btcd/btcec/v2"
@ -20,16 +18,15 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/stretchr/testify/require"
)
// testPsbtChanFunding makes sure a channel can be opened between carol and dave
// by using a Partially Signed Bitcoin Transaction that funds the channel
// multisig funding output.
func testPsbtChanFunding(ht *lntemp.HarnessTest) {
func testPsbtChanFunding(ht *lntest.HarnessTest) {
// First, we'll create two new nodes that we'll use to open channels
// between for this test. Dave gets some coins that will be used to
// fund the PSBT, just to make sure that Carol has an empty wallet.
@ -42,7 +39,7 @@ func testPsbtChanFunding(ht *lntemp.HarnessTest) {
// runPsbtChanFunding makes sure a channel can be opened between carol and dave
// by using a Partially Signed Bitcoin Transaction that funds the channel
// multisig funding output.
func runPsbtChanFunding(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode) {
func runPsbtChanFunding(ht *lntest.HarnessTest, carol, dave *node.HarnessNode) {
const chanSize = funding.MaxBtcFundingAmount
ht.FundCoins(btcutil.SatoshiPerBitcoin, dave)
@ -64,7 +61,7 @@ func runPsbtChanFunding(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode) {
// by specifying a PSBT shim. We use the NoPublish flag here to avoid
// publishing the whole batch TX too early.
chanUpdates, tempPsbt := ht.OpenChannelPsbt(
carol, dave, lntemp.OpenChannelParams{
carol, dave, lntest.OpenChannelParams{
Amt: chanSize,
FundingShim: &lnrpc.FundingShim{
Shim: &lnrpc.FundingShim_PsbtShim{
@ -81,7 +78,7 @@ func runPsbtChanFunding(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode) {
// Alice. We will publish the batch TX once this channel funding is
// complete.
chanUpdates2, psbtBytes2 := ht.OpenChannelPsbt(
carol, alice, lntemp.OpenChannelParams{
carol, alice, lntest.OpenChannelParams{
Amt: chanSize,
FundingShim: &lnrpc.FundingShim{
Shim: &lnrpc.FundingShim_PsbtShim{
@ -231,7 +228,7 @@ func runPsbtChanFunding(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode) {
// and dave by using a Partially Signed Bitcoin Transaction that funds the
// channel multisig funding output and is fully funded by an external third
// party.
func testPsbtChanFundingExternal(ht *lntemp.HarnessTest) {
func testPsbtChanFundingExternal(ht *lntest.HarnessTest) {
const chanSize = funding.MaxBtcFundingAmount
// First, we'll create two new nodes that we'll use to open channels
@ -258,7 +255,7 @@ func testPsbtChanFundingExternal(ht *lntemp.HarnessTest) {
// by specifying a PSBT shim. We use the NoPublish flag here to avoid
// publishing the whole batch TX too early.
chanUpdates, tempPsbt := ht.OpenChannelPsbt(
carol, dave, lntemp.OpenChannelParams{
carol, dave, lntest.OpenChannelParams{
Amt: chanSize,
FundingShim: &lnrpc.FundingShim{
Shim: &lnrpc.FundingShim_PsbtShim{
@ -275,7 +272,7 @@ func testPsbtChanFundingExternal(ht *lntemp.HarnessTest) {
// Alice. We will publish the batch TX once this channel funding is
// complete.
chanUpdates2, psbtBytes2 := ht.OpenChannelPsbt(
carol, alice, lntemp.OpenChannelParams{
carol, alice, lntest.OpenChannelParams{
Amt: chanSize,
FundingShim: &lnrpc.FundingShim{
Shim: &lnrpc.FundingShim_PsbtShim{
@ -413,19 +410,16 @@ func testPsbtChanFundingExternal(ht *lntemp.HarnessTest) {
// the wallet of both nodes are empty and one of them uses PSBT and an external
// wallet to fund the channel while creating reserve output in the same
// transaction.
func testPsbtChanFundingSingleStep(ht *lntemp.HarnessTest) {
func testPsbtChanFundingSingleStep(ht *lntest.HarnessTest) {
const chanSize = funding.MaxBtcFundingAmount
args := nodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
args := lntest.NodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
// First, we'll create two new nodes that we'll use to open channels
// between for this test. But in this case both nodes have an empty
// wallet.
carol := ht.NewNode("carol", args)
defer ht.Shutdown(carol)
dave := ht.NewNode("dave", args)
defer ht.Shutdown(dave)
alice := ht.Alice
ht.FundCoins(btcutil.SatoshiPerBitcoin, alice)
@ -454,7 +448,7 @@ func testPsbtChanFundingSingleStep(ht *lntemp.HarnessTest) {
// Now that we have the pending channel ID, Carol will open the channel
// by specifying a PSBT shim.
chanUpdates, tempPsbt := ht.OpenChannelPsbt(
carol, dave, lntemp.OpenChannelParams{
carol, dave, lntest.OpenChannelParams{
Amt: chanSize,
FundingShim: &lnrpc.FundingShim{
Shim: &lnrpc.FundingShim_PsbtShim{
@ -576,7 +570,7 @@ func testPsbtChanFundingSingleStep(ht *lntemp.HarnessTest) {
}
// testSignPsbt tests that the SignPsbt RPC works correctly.
func testSignPsbt(ht *lntemp.HarnessTest) {
func testSignPsbt(ht *lntest.HarnessTest) {
runSignPsbtSegWitV0P2WKH(ht, ht.Alice)
runSignPsbtSegWitV0NP2WKH(ht, ht.Alice)
runSignPsbtSegWitV1KeySpendBip86(ht, ht.Alice)
@ -591,7 +585,7 @@ func testSignPsbt(ht *lntemp.HarnessTest) {
// runSignPsbtSegWitV0P2WKH tests that the SignPsbt RPC works correctly for a
// SegWit v0 p2wkh input.
func runSignPsbtSegWitV0P2WKH(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
func runSignPsbtSegWitV0P2WKH(ht *lntest.HarnessTest, alice *node.HarnessNode) {
// We test that we can sign a PSBT that spends funds from an input that
// the wallet doesn't know about. To set up that test case, we first
// derive an address manually that the wallet won't be watching on
@ -670,7 +664,7 @@ func runSignPsbtSegWitV0P2WKH(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
// runSignPsbtSegWitV0NP2WKH tests that the SignPsbt RPC works correctly for a
// SegWit v0 np2wkh input.
func runSignPsbtSegWitV0NP2WKH(ht *lntemp.HarnessTest,
func runSignPsbtSegWitV0NP2WKH(ht *lntest.HarnessTest,
alice *node.HarnessNode) {
// We test that we can sign a PSBT that spends funds from an input that
@ -759,7 +753,7 @@ func runSignPsbtSegWitV0NP2WKH(ht *lntemp.HarnessTest,
// runSignPsbtSegWitV1KeySpendBip86 tests that the SignPsbt RPC works correctly
// for a SegWit v1 p2tr key spend BIP-0086 input.
func runSignPsbtSegWitV1KeySpendBip86(ht *lntemp.HarnessTest,
func runSignPsbtSegWitV1KeySpendBip86(ht *lntest.HarnessTest,
alice *node.HarnessNode) {
// Derive a key we can use for signing.
@ -803,7 +797,7 @@ func runSignPsbtSegWitV1KeySpendBip86(ht *lntemp.HarnessTest,
// runSignPsbtSegWitV1KeySpendRootHash tests that the SignPsbt RPC works
// correctly for a SegWit v1 p2tr key spend that also commits to a script tree
// root hash.
func runSignPsbtSegWitV1KeySpendRootHash(ht *lntemp.HarnessTest,
func runSignPsbtSegWitV1KeySpendRootHash(ht *lntest.HarnessTest,
alice *node.HarnessNode) {
// Derive a key we can use for signing.
@ -850,7 +844,7 @@ func runSignPsbtSegWitV1KeySpendRootHash(ht *lntemp.HarnessTest,
// runSignPsbtSegWitV1ScriptSpend tests that the SignPsbt RPC works correctly
// for a SegWit v1 p2tr script spend.
func runSignPsbtSegWitV1ScriptSpend(ht *lntemp.HarnessTest,
func runSignPsbtSegWitV1ScriptSpend(ht *lntest.HarnessTest,
alice *node.HarnessNode) {
// Derive a key we can use for signing.
@ -911,7 +905,7 @@ func runSignPsbtSegWitV1ScriptSpend(ht *lntemp.HarnessTest,
// runFundAndSignPsbt makes sure we can sign PSBTs that were funded by our
// internal wallet.
func runFundAndSignPsbt(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
func runFundAndSignPsbt(ht *lntest.HarnessTest, alice *node.HarnessNode) {
alice.AddToLogf("================ runFundAndSignPsbt ===============")
// We'll be using a "main" address where we send the funds to and from
@ -965,7 +959,7 @@ func runFundAndSignPsbt(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
// assertPsbtSpend creates an output with the given pkScript on chain and then
// attempts to create a sweep transaction that is signed using the SignPsbt RPC
// that spends that output again.
func assertPsbtSpend(ht *lntemp.HarnessTest, alice *node.HarnessNode,
func assertPsbtSpend(ht *lntest.HarnessTest, alice *node.HarnessNode,
pkScript []byte, decorateUnsigned func(*psbt.Packet),
verifySigned func(*psbt.Packet)) {
@ -1074,7 +1068,7 @@ func assertPsbtSpend(ht *lntemp.HarnessTest, alice *node.HarnessNode,
// assertPsbtFundSignSpend funds a PSBT from the internal wallet and then
// attempts to sign it by using the SignPsbt or FinalizePsbt method.
func assertPsbtFundSignSpend(ht *lntemp.HarnessTest, alice *node.HarnessNode,
func assertPsbtFundSignSpend(ht *lntest.HarnessTest, alice *node.HarnessNode,
fundOutputs map[string]uint64, changeType walletrpc.ChangeAddressType,
useFinalize bool) {
@ -1149,7 +1143,7 @@ func assertPsbtFundSignSpend(ht *lntemp.HarnessTest, alice *node.HarnessNode,
// assertChangeScriptType checks if the given script has the right type given
// the change address type we used in FundPsbt. By default, the script should
// be a P2WPKH one.
func assertChangeScriptType(ht *lntemp.HarnessTest, script []byte,
func assertChangeScriptType(ht *lntest.HarnessTest, script []byte,
fundChangeType walletrpc.ChangeAddressType) {
switch fundChangeType {
@ -1163,7 +1157,7 @@ func assertChangeScriptType(ht *lntemp.HarnessTest, script []byte,
// deriveInternalKey derives a signing key and returns its descriptor, full
// derivation path and parsed public key.
func deriveInternalKey(ht *lntemp.HarnessTest,
func deriveInternalKey(ht *lntest.HarnessTest,
alice *node.HarnessNode) (*signrpc.KeyDescriptor, *btcec.PublicKey,
[]uint32) {
@ -1187,96 +1181,9 @@ func deriveInternalKey(ht *lntemp.HarnessTest,
return keyDesc, parsedPubKey, fullDerivationPath
}
// openChannelPsbt attempts to open a channel between srcNode and destNode with
// the passed channel funding parameters. If the passed context has a timeout,
// then if the timeout is reached before the channel pending notification is
// received, an error is returned. An error is returned if the expected step
// of funding the PSBT is not received from the source node.
func openChannelPsbt(ctx context.Context, srcNode, destNode *lntest.HarnessNode,
p lntest.OpenChannelParams) (lnrpc.Lightning_OpenChannelClient, []byte,
error) {
// Wait until srcNode and destNode have the latest chain synced.
// Otherwise, we may run into a check within the funding manager that
// prevents any funding workflows from being kicked off if the chain
// isn't yet synced.
if err := srcNode.WaitForBlockchainSync(); err != nil {
return nil, nil, fmt.Errorf("unable to sync srcNode chain: %v",
err)
}
if err := destNode.WaitForBlockchainSync(); err != nil {
return nil, nil, fmt.Errorf("unable to sync destNode chain: %v",
err)
}
// Send the request to open a channel to the source node now. This will
// open a long-lived stream where we'll receive status updates about the
// progress of the channel.
respStream, err := srcNode.OpenChannel(ctx, &lnrpc.OpenChannelRequest{
NodePubkey: destNode.PubKey[:],
LocalFundingAmount: int64(p.Amt),
PushSat: int64(p.PushAmt),
Private: p.Private,
SpendUnconfirmed: p.SpendUnconfirmed,
MinHtlcMsat: int64(p.MinHtlc),
FundingShim: p.FundingShim,
})
if err != nil {
return nil, nil, fmt.Errorf("unable to open channel between "+
"source and dest: %v", err)
}
// Consume the "PSBT funding ready" update. This waits until the node
// notifies us that the PSBT can now be funded.
resp, err := receiveChanUpdate(ctx, respStream)
if err != nil {
return nil, nil, fmt.Errorf("unable to consume channel update "+
"message: %v", err)
}
upd, ok := resp.Update.(*lnrpc.OpenStatusUpdate_PsbtFund)
if !ok {
return nil, nil, fmt.Errorf("expected PSBT funding update, "+
"instead got %v", resp)
}
return respStream, upd.PsbtFund.Psbt, nil
}
// receiveChanUpdate waits until a message is received on the stream or the
// context is canceled. The context must have a timeout or must be canceled
// in case no message is received, otherwise this function will block forever.
func receiveChanUpdate(ctx context.Context,
stream lnrpc.Lightning_OpenChannelClient) (*lnrpc.OpenStatusUpdate,
error) {
chanMsg := make(chan *lnrpc.OpenStatusUpdate)
errChan := make(chan error)
go func() {
// Consume one message. This will block until the message is
// received.
resp, err := stream.Recv()
if err != nil {
errChan <- err
return
}
chanMsg <- resp
}()
select {
case <-ctx.Done():
return nil, fmt.Errorf("timeout reached before chan pending " +
"update sent")
case err := <-errChan:
return nil, err
case updateMsg := <-chanMsg:
return updateMsg, nil
}
}
// sendAllCoinsToAddrType sweeps all coins from the wallet and sends them to a
// new address of the given type.
func sendAllCoinsToAddrType(ht *lntemp.HarnessTest,
func sendAllCoinsToAddrType(ht *lntest.HarnessTest,
hn *node.HarnessNode, addrType lnrpc.AddressType) {
resp := hn.RPC.NewAddress(&lnrpc.NewAddressRequest{

View file

@ -15,8 +15,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/stretchr/testify/require"
@ -24,7 +24,7 @@ import (
// testGetRecoveryInfo checks whether lnd gives the right information about
// the wallet recovery process.
func testGetRecoveryInfo(ht *lntemp.HarnessTest) {
func testGetRecoveryInfo(ht *lntest.HarnessTest) {
// First, create a new node with strong passphrase and grab the mnemonic
// used for key derivation. This will bring up Carol with an empty
// wallet, and such that she is synced up.
@ -94,7 +94,7 @@ func testGetRecoveryInfo(ht *lntemp.HarnessTest) {
// when providing a valid aezeed that owns outputs on the chain. This test
// performs multiple restorations using the same seed and various recovery
// windows to ensure we detect funds properly.
func testOnchainFundRecovery(ht *lntemp.HarnessTest) {
func testOnchainFundRecovery(ht *lntest.HarnessTest) {
// First, create a new node with strong passphrase and grab the mnemonic
// used for key derivation. This will bring up Carol with an empty
// wallet, and such that she is synced up.
@ -321,7 +321,7 @@ func testOnchainFundRecovery(ht *lntemp.HarnessTest) {
// The fix in the wallet is simple: In step 6, don't detect addresses from
// internal scopes while re-scanning to be in line with the logic in other areas
// of the wallet code.
func testRescanAddressDetection(ht *lntemp.HarnessTest) {
func testRescanAddressDetection(ht *lntest.HarnessTest) {
// We start off by creating a new node with the wallet re-scan flag
// enabled. This won't have any effect on the first startup but will
// come into effect after we re-start the node.

View file

@ -11,8 +11,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/stretchr/testify/require"
)
@ -55,24 +55,24 @@ var (
// testRemoteSigner tests that a watch-only wallet can use a remote signing
// wallet to perform any signing or ECDH operations.
func testRemoteSigner(ht *lntemp.HarnessTest) {
func testRemoteSigner(ht *lntest.HarnessTest) {
type testCase struct {
name string
randomSeed bool
sendCoins bool
fn func(tt *lntemp.HarnessTest,
fn func(tt *lntest.HarnessTest,
wo, carol *node.HarnessNode)
}
subTests := []testCase{{
name: "random seed",
randomSeed: true,
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
// Nothing more to test here.
},
}, {
name: "account import",
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
runWalletImportAccountScenario(
tt, walletrpc.AddressType_WITNESS_PUBKEY_HASH,
carol, wo,
@ -81,36 +81,36 @@ func testRemoteSigner(ht *lntemp.HarnessTest) {
}, {
name: "basic channel open close",
sendCoins: true,
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
runBasicChannelCreationAndUpdates(tt, wo, carol)
},
}, {
name: "channel funding input types",
sendCoins: false,
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
runChannelFundingInputTypes(tt, carol, wo)
},
}, {
name: "async payments",
sendCoins: true,
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
runAsyncPayments(tt, wo, carol)
},
}, {
name: "shared key",
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
runDeriveSharedKey(tt, wo)
},
}, {
name: "cpfp",
sendCoins: true,
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
runCPFP(tt, wo, carol)
},
}, {
name: "psbt",
randomSeed: true,
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
runPsbtChanFunding(tt, carol, wo)
runSignPsbtSegWitV0P2WKH(tt, wo)
runSignPsbtSegWitV1KeySpendBip86(tt, wo)
@ -125,20 +125,20 @@ func testRemoteSigner(ht *lntemp.HarnessTest) {
}, {
name: "sign output raw",
sendCoins: true,
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
runSignOutputRaw(tt, wo)
},
}, {
name: "sign verify msg",
sendCoins: true,
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
runSignVerifyMessage(tt, wo)
},
}, {
name: "taproot",
sendCoins: true,
randomSeed: true,
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
testTaprootSendCoinsKeySpendBip86(tt, wo)
testTaprootComputeInputScriptKeySpendBip86(tt, wo)
testTaprootSignOutputRawScriptSpend(tt, wo)
@ -162,7 +162,7 @@ func testRemoteSigner(ht *lntemp.HarnessTest) {
},
}}
prepareTest := func(st *lntemp.HarnessTest,
prepareTest := func(st *lntest.HarnessTest,
subTest testCase) (*node.HarnessNode,
*node.HarnessNode, *node.HarnessNode) {

View file

@ -5,13 +5,13 @@ import (
"github.com/btcsuite/btcd/btcutil"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/stretchr/testify/require"
)
// testResHandoff tests that the contractcourt is able to properly hand-off
// resolution messages to the switch.
func testResHandoff(ht *lntemp.HarnessTest) {
func testResHandoff(ht *lntest.HarnessTest) {
const (
chanAmt = btcutil.Amount(1000000)
paymentAmt = 50000
@ -22,14 +22,13 @@ func testResHandoff(ht *lntemp.HarnessTest) {
// First we'll create a channel between Alice and Bob.
ht.EnsureConnected(alice, bob)
params := lntemp.OpenChannelParams{Amt: chanAmt}
params := lntest.OpenChannelParams{Amt: chanAmt}
chanPointAlice := ht.OpenChannel(alice, bob, params)
// Create a new node Carol that will be in hodl mode. This is used to
// trigger the behavior of checkRemoteDanglingActions in the
// contractcourt. This will cause Bob to fail the HTLC back to Alice.
carol := ht.NewNode("Carol", []string{"--hodl.commit"})
defer ht.Shutdown(carol)
// Connect Bob to Carol.
ht.ConnectNodes(bob, carol)

View file

@ -23,8 +23,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnrpc/verrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/stretchr/testify/require"
)
@ -56,7 +56,7 @@ var (
// testRestAPI tests that the most important features of the REST API work
// correctly.
func testRestAPI(ht *lntemp.HarnessTest) {
func testRestAPI(ht *lntest.HarnessTest) {
testCases := []struct {
name string
run func(*testing.T, *node.HarnessNode, *node.HarnessNode)
@ -201,7 +201,7 @@ func testRestAPI(ht *lntemp.HarnessTest) {
}}
wsTestCases := []struct {
name string
run func(ht *lntemp.HarnessTest)
run func(ht *lntest.HarnessTest)
}{{
name: "websocket subscription",
run: wsTestCaseSubscription,
@ -243,7 +243,7 @@ func testRestAPI(ht *lntemp.HarnessTest) {
}
}
func wsTestCaseSubscription(ht *lntemp.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()
@ -317,7 +317,7 @@ func wsTestCaseSubscription(ht *lntemp.HarnessTest) {
}
}
func wsTestCaseSubscriptionMacaroon(ht *lntemp.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()
@ -407,7 +407,7 @@ func wsTestCaseSubscriptionMacaroon(ht *lntemp.HarnessTest) {
}
}
func wsTestCaseBiDirectionalSubscription(ht *lntemp.HarnessTest) {
func wsTestCaseBiDirectionalSubscription(ht *lntest.HarnessTest) {
initialRequest := &lnrpc.ChannelAcceptResponse{}
url := "/v1/channels/acceptor"
@ -530,7 +530,7 @@ func wsTestCaseBiDirectionalSubscription(ht *lntemp.HarnessTest) {
const numChannels = 3
for i := 0; i < numChannels; i++ {
chanPoint := ht.OpenChannel(
bob, alice, lntemp.OpenChannelParams{Amt: 500000},
bob, alice, lntest.OpenChannelParams{Amt: 500000},
)
defer ht.CloseChannel(bob, chanPoint)
@ -545,7 +545,7 @@ func wsTestCaseBiDirectionalSubscription(ht *lntemp.HarnessTest) {
}
}
func wsTestPingPongTimeout(ht *lntemp.HarnessTest) {
func wsTestPingPongTimeout(ht *lntest.HarnessTest) {
initialRequest := &lnrpc.InvoiceSubscription{
AddIndex: 1, SettleIndex: 1,
}

View file

@ -12,7 +12,6 @@ import (
"github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/stretchr/testify/require"
@ -21,7 +20,7 @@ import (
// testRevokedCloseRetribution tests that Carol is able carry out
// retribution in the event that she fails immediately after detecting Bob's
// breach txn in the mempool.
func testRevokedCloseRetribution(ht *lntemp.HarnessTest) {
func testRevokedCloseRetribution(ht *lntest.HarnessTest) {
const (
chanAmt = funding.MaxBtcFundingAmount
paymentAmt = 10000
@ -51,7 +50,7 @@ func testRevokedCloseRetribution(ht *lntemp.HarnessTest) {
// closure by Bob, we'll first open up a channel between them with a
// 0.5 BTC value.
chanPoint := ht.OpenChannel(
carol, bob, lntemp.OpenChannelParams{Amt: chanAmt},
carol, bob, lntest.OpenChannelParams{Amt: chanAmt},
)
// With the channel open, we'll create a few invoices for Bob that
@ -158,7 +157,7 @@ func testRevokedCloseRetribution(ht *lntemp.HarnessTest) {
// tx's confHeight+CSV-1 blocks and since we've already mined one that
// included the justice tx we only need to mine extra DefaultCSV-2
// blocks to unlock it.
ht.MineBlocks(lntest.DefaultCSV - 2)
ht.MineBlocks(defaultCSV - 2)
ht.AssertNumPendingForceClose(bob, 0)
}
@ -166,7 +165,7 @@ func testRevokedCloseRetribution(ht *lntemp.HarnessTest) {
// testRevokedCloseRetributionZeroValueRemoteOutput tests that Dave is able
// carry out retribution in the event that he fails in state where the remote
// commitment output has zero-value.
func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntemp.HarnessTest) {
func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntest.HarnessTest) {
const (
chanAmt = funding.MaxBtcFundingAmount
paymentAmt = 10000
@ -199,7 +198,7 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntemp.HarnessTest) {
// closure by Carol, we'll first open up a channel between them with a
// 0.5 BTC value.
chanPoint := ht.OpenChannel(
dave, carol, lntemp.OpenChannelParams{Amt: chanAmt},
dave, carol, lntest.OpenChannelParams{Amt: chanAmt},
)
// With the channel open, we'll create a few invoices for Carol that
@ -224,6 +223,9 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntemp.HarnessTest) {
// backup.
ht.EnsureConnected(dave, carol)
// Once connected, give Dave some time to enable the channel again.
ht.AssertTopologyChannelOpen(dave, chanPoint)
// Finally, send payments from Dave to Carol, consuming Carol's
// remaining payment hashes.
ht.CompletePaymentRequestsNoWait(dave, carolPayReqs, chanPoint)
@ -298,7 +300,7 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntemp.HarnessTest) {
// testRevokedCloseRetributionRemoteHodl tests that Dave properly responds to a
// channel breach made by the remote party, specifically in the case that the
// remote party breaches before settling extended HTLCs.
func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
func testRevokedCloseRetributionRemoteHodl(ht *lntest.HarnessTest) {
const (
chanAmt = funding.MaxBtcFundingAmount
pushAmt = 200000
@ -333,7 +335,7 @@ func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
// by Carol, we'll first open up a channel between them with a
// funding.MaxBtcFundingAmount (2^24) satoshis value.
chanPoint := ht.OpenChannel(
dave, carol, lntemp.OpenChannelParams{
dave, carol, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
},
@ -401,6 +403,9 @@ func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
// backup.
ht.EnsureConnected(dave, carol)
// Once connected, give Dave some time to enable the channel again.
ht.AssertTopologyChannelOpen(dave, chanPoint)
// Finally, send payments from Dave to Carol, consuming Carol's
// remaining payment hashes.
ht.CompletePaymentRequestsNoWait(
@ -472,7 +477,14 @@ func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
for _, txid := range mempool {
// Check that the justice tx has the appropriate number
// of inputs.
tx := ht.Miner.GetRawTransaction(txid)
//
// NOTE: We don't use `ht.Miner.GetRawTransaction`
// which asserts a txid must be found as the HTLC
// spending txes might be aggregated.
tx, err := ht.Miner.Client.GetRawTransaction(txid)
if err != nil {
return nil, err
}
exNumInputs := 2 + numInvoices
if len(tx.MsgTx().TxIn) == exNumInputs {
@ -578,7 +590,7 @@ func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
// trigger a breach. Carol is kept offline throughout the process and the test
// asserts that Willy responds by broadcasting the justice transaction on
// Carol's behalf sweeping her funds without a reward.
func testRevokedCloseRetributionAltruistWatchtower(ht *lntemp.HarnessTest) {
func testRevokedCloseRetributionAltruistWatchtower(ht *lntest.HarnessTest) {
testCases := []struct {
name string
anchors bool
@ -592,7 +604,7 @@ func testRevokedCloseRetributionAltruistWatchtower(ht *lntemp.HarnessTest) {
for _, tc := range testCases {
tc := tc
testFunc := func(ht *lntemp.HarnessTest) {
testFunc := func(ht *lntest.HarnessTest) {
testRevokedCloseRetributionAltruistWatchtowerCase(
ht, tc.anchors,
)
@ -601,7 +613,7 @@ func testRevokedCloseRetributionAltruistWatchtower(ht *lntemp.HarnessTest) {
success := ht.Run(tc.name, func(tt *testing.T) {
st := ht.Subtest(tt)
st.RunTestCase(&lntemp.TestCase{
st.RunTestCase(&lntest.TestCase{
Name: tc.name,
TestFunc: testFunc,
})
@ -619,7 +631,7 @@ func testRevokedCloseRetributionAltruistWatchtower(ht *lntemp.HarnessTest) {
}
}
func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntemp.HarnessTest,
func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest,
anchors bool) {
const (
@ -696,7 +708,7 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntemp.HarnessTest,
// In order to test Dave's response to an uncooperative channel
// closure by Carol, we'll first open up a channel between them with a
// 0.5 BTC value.
params := lntemp.OpenChannelParams{
params := lntest.OpenChannelParams{
Amt: 3 * (chanAmt / 4),
PushAmt: chanAmt / 4,
}
@ -727,6 +739,9 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntemp.HarnessTest,
// backup.
ht.EnsureConnected(dave, carol)
// Once connected, give Dave some time to enable the channel again.
ht.AssertTopologyChannelOpen(dave, chanPoint)
// Finally, send payments from Dave to Carol, consuming Carol's
// remaining payment hashes.
ht.CompletePaymentRequestsNoWait(dave, carolPayReqs, chanPoint)

View file

@ -10,8 +10,8 @@ import (
"github.com/lightningnetwork/lnd/chainreg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/stretchr/testify/require"
@ -65,7 +65,7 @@ var singleHopSendToRouteCases = []singleHopSendToRouteCase{
// by feeding the route back into the various SendToRoute RPC methods. Here we
// test all three SendToRoute endpoints, forcing each to perform both a regular
// payment and an MPP payment.
func testSingleHopSendToRoute(ht *lntemp.HarnessTest) {
func testSingleHopSendToRoute(ht *lntest.HarnessTest) {
for _, test := range singleHopSendToRouteCases {
test := test
@ -76,7 +76,7 @@ func testSingleHopSendToRoute(ht *lntemp.HarnessTest) {
}
}
func testSingleHopSendToRouteCase(ht *lntemp.HarnessTest,
func testSingleHopSendToRouteCase(ht *lntest.HarnessTest,
test singleHopSendToRouteCase) {
const chanAmt = btcutil.Amount(100000)
@ -97,7 +97,7 @@ func testSingleHopSendToRouteCase(ht *lntemp.HarnessTest,
// Open a channel with 100k satoshis between Carol and Dave with Carol
// being the sole funder of the channel.
chanPointCarol := ht.OpenChannel(
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
carol, dave, lntest.OpenChannelParams{Amt: chanAmt},
)
defer ht.CloseChannel(carol, chanPointCarol)
@ -289,7 +289,7 @@ func testSingleHopSendToRouteCase(ht *lntemp.HarnessTest,
//
// We'll query the daemon for routes from Alice to Carol and then
// send payments through the routes.
func testMultiHopSendToRoute(ht *lntemp.HarnessTest) {
func testMultiHopSendToRoute(ht *lntest.HarnessTest) {
ht.Run("with cache", func(tt *testing.T) {
st := ht.Subtest(tt)
runMultiHopSendToRoute(st, true)
@ -309,7 +309,7 @@ func testMultiHopSendToRoute(ht *lntemp.HarnessTest) {
//
// We'll query the daemon for routes from Alice to Carol and then
// send payments through the routes.
func runMultiHopSendToRoute(ht *lntemp.HarnessTest, useGraphCache bool) {
func runMultiHopSendToRoute(ht *lntest.HarnessTest, useGraphCache bool) {
var opts []string
if !useGraphCache {
opts = append(opts, "--db.no-graph-cache")
@ -325,7 +325,7 @@ func runMultiHopSendToRoute(ht *lntemp.HarnessTest, useGraphCache bool) {
// Open a channel with 100k satoshis between Alice and Bob with Alice
// being the sole funder of the channel.
chanPointAlice := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
)
defer ht.CloseChannel(alice, chanPointAlice)
@ -337,10 +337,13 @@ func runMultiHopSendToRoute(ht *lntemp.HarnessTest, useGraphCache bool) {
ht.ConnectNodes(carol, bob)
chanPointBob := ht.OpenChannel(
bob, carol, lntemp.OpenChannelParams{Amt: chanAmt},
bob, carol, lntest.OpenChannelParams{Amt: chanAmt},
)
defer ht.CloseChannel(carol, chanPointBob)
// Make sure Alice knows the channel between Bob and Carol.
ht.AssertTopologyChannelOpen(alice, chanPointBob)
// Create 5 invoices for Carol, which expect a payment from Alice for
// 1k satoshis with a different preimage each time.
const (
@ -407,14 +410,14 @@ func runMultiHopSendToRoute(ht *lntemp.HarnessTest, useGraphCache bool) {
// testSendToRouteErrorPropagation tests propagation of errors that occur
// while processing a multi-hop payment through an unknown route.
func testSendToRouteErrorPropagation(ht *lntemp.HarnessTest) {
func testSendToRouteErrorPropagation(ht *lntest.HarnessTest) {
const chanAmt = btcutil.Amount(100000)
// Open a channel with 100k satoshis between Alice and Bob with Alice
// being the sole funder of the channel.
alice, bob := ht.Alice, ht.Bob
chanPointAlice := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
)
// Create a new nodes (Carol and Charlie), load her with some funds,
@ -432,7 +435,7 @@ func testSendToRouteErrorPropagation(ht *lntemp.HarnessTest) {
ht.FundCoins(btcutil.SatoshiPerBitcoin, charlie)
ht.ConnectNodes(carol, charlie)
ht.OpenChannel(carol, charlie, lntemp.OpenChannelParams{Amt: chanAmt})
ht.OpenChannel(carol, charlie, lntest.OpenChannelParams{Amt: chanAmt})
// Query routes from Carol to Charlie which will be an invalid route
// for Alice -> Bob.
@ -476,7 +479,9 @@ func testSendToRouteErrorPropagation(ht *lntemp.HarnessTest) {
// testPrivateChannels tests that a private channel can be used for
// routing by the two endpoints of the channel, but is not known by
// the rest of the nodes in the graph.
func testPrivateChannels(ht *lntemp.HarnessTest) {
//
//nolint:dupword
func testPrivateChannels(ht *lntest.HarnessTest) {
const chanAmt = btcutil.Amount(100000)
// We create the following topology:
@ -493,7 +498,7 @@ func testPrivateChannels(ht *lntemp.HarnessTest) {
// Open a channel with 200k satoshis between Alice and Bob.
alice, bob := ht.Alice, ht.Bob
chanPointAlice := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt * 2},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt * 2},
)
// Create Dave, and a channel to Alice of 100k.
@ -502,7 +507,7 @@ func testPrivateChannels(ht *lntemp.HarnessTest) {
ht.FundCoins(btcutil.SatoshiPerBitcoin, dave)
chanPointDave := ht.OpenChannel(
dave, alice, lntemp.OpenChannelParams{Amt: chanAmt},
dave, alice, lntest.OpenChannelParams{Amt: chanAmt},
)
// Next, we'll create Carol and establish a channel from her to
@ -512,14 +517,14 @@ func testPrivateChannels(ht *lntemp.HarnessTest) {
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
chanPointCarol := ht.OpenChannel(
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
carol, dave, lntest.OpenChannelParams{Amt: chanAmt},
)
// Now create a _private_ channel directly between Carol and
// Alice of 100k.
ht.ConnectNodes(carol, alice)
chanPointPrivate := ht.OpenChannel(
carol, alice, lntemp.OpenChannelParams{
carol, alice, lntest.OpenChannelParams{
Amt: chanAmt,
Private: true,
},
@ -602,7 +607,7 @@ func testPrivateChannels(ht *lntemp.HarnessTest) {
// testInvoiceRoutingHints tests that the routing hints for an invoice are
// created properly.
func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
func testInvoiceRoutingHints(ht *lntest.HarnessTest) {
const chanAmt = btcutil.Amount(100000)
// Throughout this test, we'll be opening a channel between Alice and
@ -615,7 +620,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
// invoice's payment.
alice, bob := ht.Alice, ht.Bob
chanPointBob := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: chanAmt / 2,
Private: true,
@ -629,7 +634,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
ht.ConnectNodes(alice, carol)
chanPointCarol := ht.OpenChannel(
alice, carol, lntemp.OpenChannelParams{
alice, carol, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: chanAmt / 2,
},
@ -642,7 +647,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
// that wish to stay unadvertised.
ht.ConnectNodes(bob, carol)
chanPointBobCarol := ht.OpenChannel(
bob, carol, lntemp.OpenChannelParams{
bob, carol, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: chanAmt / 2,
},
@ -656,7 +661,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
ht.ConnectNodes(alice, dave)
chanPointDave := ht.OpenChannel(
alice, dave, lntemp.OpenChannelParams{
alice, dave, lntest.OpenChannelParams{
Amt: chanAmt,
Private: true,
},
@ -669,7 +674,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
eve := ht.NewNode("Eve", nil)
ht.ConnectNodes(alice, eve)
chanPointEve := ht.OpenChannel(
alice, eve, lntemp.OpenChannelParams{
alice, eve, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: chanAmt / 2,
Private: true,
@ -744,7 +749,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
// testMultiHopOverPrivateChannels tests that private channels can be used as
// intermediate hops in a route for payments.
func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
func testMultiHopOverPrivateChannels(ht *lntest.HarnessTest) {
// We'll test that multi-hop payments over private channels work as
// intended. To do so, we'll create the following topology:
// private public private
@ -755,7 +760,7 @@ func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
// being the funder.
alice, bob := ht.Alice, ht.Bob
chanPointAlice := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: chanAmt,
Private: true,
},
@ -766,7 +771,7 @@ func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
carol := ht.NewNode("Carol", nil)
ht.ConnectNodes(bob, carol)
chanPointBob := ht.OpenChannel(
bob, carol, lntemp.OpenChannelParams{
bob, carol, lntest.OpenChannelParams{
Amt: chanAmt,
},
)
@ -781,7 +786,7 @@ func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
chanPointCarol := ht.OpenChannel(
carol, dave, lntemp.OpenChannelParams{
carol, dave, lntest.OpenChannelParams{
Amt: chanAmt,
Private: true,
},
@ -851,7 +856,7 @@ func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
// Alice --> Bob --> Carol --> Dave
//
// and query the daemon for routes from Alice to Dave.
func testQueryRoutes(ht *lntemp.HarnessTest) {
func testQueryRoutes(ht *lntest.HarnessTest) {
const chanAmt = btcutil.Amount(100000)
// Grab Alice and Bob from the standby nodes.
@ -869,8 +874,8 @@ func testQueryRoutes(ht *lntemp.HarnessTest) {
// We now proceed to open channels:
// Alice=>Bob, Bob=>Carol and Carol=>Dave.
p := lntemp.OpenChannelParams{Amt: chanAmt}
reqs := []*lntemp.OpenChannelRequest{
p := lntest.OpenChannelParams{Amt: chanAmt}
reqs := []*lntest.OpenChannelRequest{
{Local: alice, Remote: bob, Param: p},
{Local: bob, Remote: carol, Param: p},
{Local: carol, Remote: dave, Param: p},
@ -1086,7 +1091,7 @@ func testMissionControlCfg(t *testing.T, hn *node.HarnessNode) {
// testMissionControlImport tests import of mission control results from an
// external source.
func testMissionControlImport(ht *lntemp.HarnessTest, hn *node.HarnessNode,
func testMissionControlImport(ht *lntest.HarnessTest, hn *node.HarnessNode,
fromNode, toNode []byte) {
// Reset mission control so that our query will return the default
@ -1138,7 +1143,7 @@ func testMissionControlImport(ht *lntemp.HarnessTest, hn *node.HarnessNode,
// testRouteFeeCutoff tests that we are able to prevent querying routes and
// sending payments that incur a fee higher than the fee limit.
func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
func testRouteFeeCutoff(ht *lntest.HarnessTest) {
// For this test, we'll create the following topology:
//
// --- Bob ---
@ -1155,7 +1160,7 @@ func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
// Open a channel between Alice and Bob.
alice, bob := ht.Alice, ht.Bob
chanPointAliceBob := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
)
// Create Carol's node and open a channel between her and Alice with
@ -1165,7 +1170,7 @@ func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
chanPointAliceCarol := ht.OpenChannel(
alice, carol, lntemp.OpenChannelParams{Amt: chanAmt},
alice, carol, lntest.OpenChannelParams{Amt: chanAmt},
)
// Create Dave's node and open a channel between him and Bob with Bob
@ -1173,13 +1178,13 @@ func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
dave := ht.NewNode("Dave", nil)
ht.ConnectNodes(dave, bob)
chanPointBobDave := ht.OpenChannel(
bob, dave, lntemp.OpenChannelParams{Amt: chanAmt},
bob, dave, lntest.OpenChannelParams{Amt: chanAmt},
)
// Open a channel between Carol and Dave.
ht.ConnectNodes(carol, dave)
chanPointCarolDave := ht.OpenChannel(
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
carol, dave, lntest.OpenChannelParams{Amt: chanAmt},
)
// Now that all the channels were set up, we'll wait for all the nodes
@ -1203,7 +1208,7 @@ func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
baseFee := int64(10000)
feeRate := int64(5)
timeLockDelta := uint32(chainreg.DefaultBitcoinTimeLockDelta)
maxHtlc := calculateMaxHtlc(chanAmt)
maxHtlc := lntest.CalculateMaxHtlc(chanAmt)
expectedPolicy := &lnrpc.RoutingPolicy{
FeeBaseMsat: baseFee,
@ -1285,7 +1290,8 @@ func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
case *lnrpc.FeeLimit_Fixed:
sendReq.FeeLimitMsat = 1000 * limit.Fixed
case *lnrpc.FeeLimit_Percent:
sendReq.FeeLimitMsat = 1000 * paymentAmt * limit.Percent / 100
sendReq.FeeLimitMsat = 1000 * paymentAmt *
limit.Percent / 100
}
result := ht.SendPaymentAssertSettled(alice, sendReq)

View file

@ -8,8 +8,8 @@ import (
"github.com/btcsuite/btcd/btcutil"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/macaroons"
"github.com/lightningnetwork/lnd/zpay32"
"github.com/stretchr/testify/require"
@ -19,7 +19,7 @@ import (
// testRPCMiddlewareInterceptor tests that the RPC middleware interceptor can
// be used correctly and in a safe way.
func testRPCMiddlewareInterceptor(ht *lntemp.HarnessTest) {
func testRPCMiddlewareInterceptor(ht *lntest.HarnessTest) {
// Let's first enable the middleware interceptor.
//
// NOTE: we cannot use standby nodes here as the test messes with
@ -32,7 +32,7 @@ func testRPCMiddlewareInterceptor(ht *lntemp.HarnessTest) {
// data to inspect when doing RPC calls to Alice later.
ht.EnsureConnected(alice, bob)
ht.FundCoins(btcutil.SatoshiPerBitcoin, alice)
ht.OpenChannel(alice, bob, lntemp.OpenChannelParams{Amt: 1_234_567})
ht.OpenChannel(alice, bob, lntest.OpenChannelParams{Amt: 1_234_567})
// Load or bake the macaroons that the simulated users will use to
// access the RPC.
@ -545,7 +545,7 @@ func middlewareRequestManipulationTest(t *testing.T, node *node.HarnessNode,
// middlewareMandatoryTest tests that all RPC requests are blocked if there is
// a mandatory middleware declared that's currently not registered.
func middlewareMandatoryTest(ht *lntemp.HarnessTest, node *node.HarnessNode) {
func middlewareMandatoryTest(ht *lntest.HarnessTest, node *node.HarnessNode) {
// Let's declare our itest interceptor as mandatory but don't register
// it just yet. That should cause all RPC requests to fail, except for
// the registration itself.

View file

@ -6,13 +6,13 @@ import (
"github.com/btcsuite/btcd/btcutil"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/stretchr/testify/require"
)
// testSendMultiPathPayment tests that we are able to successfully route a
// payment using multiple shards across different paths.
func testSendMultiPathPayment(ht *lntemp.HarnessTest) {
func testSendMultiPathPayment(ht *lntest.HarnessTest) {
mts := newMppTestScenario(ht)
const paymentAmt = btcutil.Amount(300000)

View file

@ -13,8 +13,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/stretchr/testify/require"
)
@ -22,7 +22,7 @@ import (
// DeriveSharedKey. It creates an ephemeral private key, performing an ECDH with
// the node's pubkey and a customized public key to check the validity of the
// result.
func testDeriveSharedKey(ht *lntemp.HarnessTest) {
func testDeriveSharedKey(ht *lntest.HarnessTest) {
runDeriveSharedKey(ht, ht.Alice)
}
@ -30,7 +30,7 @@ func testDeriveSharedKey(ht *lntemp.HarnessTest) {
// DeriveSharedKey. It creates an ephemeral private key, performing an ECDH with
// the node's pubkey and a customized public key to check the validity of the
// result.
func runDeriveSharedKey(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
func runDeriveSharedKey(ht *lntest.HarnessTest, alice *node.HarnessNode) {
// Create an ephemeral key, extracts its public key, and make a
// PrivKeyECDH using the ephemeral key.
ephemeralPriv, err := btcec.NewPrivateKey()
@ -194,13 +194,13 @@ func runDeriveSharedKey(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
// testSignOutputRaw makes sure that the SignOutputRaw RPC can be used with all
// custom ways of specifying the signing key in the key descriptor/locator.
func testSignOutputRaw(ht *lntemp.HarnessTest) {
func testSignOutputRaw(ht *lntest.HarnessTest) {
runSignOutputRaw(ht, ht.Alice)
}
// runSignOutputRaw makes sure that the SignOutputRaw RPC can be used with all
// custom ways of specifying the signing key in the key descriptor/locator.
func runSignOutputRaw(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
func runSignOutputRaw(ht *lntest.HarnessTest, alice *node.HarnessNode) {
// For the next step, we need a public key. Let's use a special family
// for this. We want this to be an index of zero.
const testCustomKeyFamily = 44
@ -272,7 +272,7 @@ func runSignOutputRaw(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
// assertSignOutputRaw sends coins to a p2wkh address derived from the given
// target public key and then tries to spend that output again by invoking the
// SignOutputRaw RPC with the key descriptor provided.
func assertSignOutputRaw(ht *lntemp.HarnessTest,
func assertSignOutputRaw(ht *lntest.HarnessTest,
alice *node.HarnessNode, targetPubKey *btcec.PublicKey,
keyDesc *signrpc.KeyDescriptor,
sigHash txscript.SigHashType) {
@ -373,14 +373,14 @@ func assertSignOutputRaw(ht *lntemp.HarnessTest,
// testSignVerifyMessage makes sure that the SignMessage RPC can be used with
// all custom flags by verifying with VerifyMessage. Tests both ECDSA and
// Schnorr signatures.
func testSignVerifyMessage(ht *lntemp.HarnessTest) {
func testSignVerifyMessage(ht *lntest.HarnessTest) {
runSignVerifyMessage(ht, ht.Alice)
}
// runSignVerifyMessage makes sure that the SignMessage RPC can be used with
// all custom flags by verifying with VerifyMessage. Tests both ECDSA and
// Schnorr signatures.
func runSignVerifyMessage(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
func runSignVerifyMessage(ht *lntest.HarnessTest, alice *node.HarnessNode) {
aliceMsg := []byte("alice msg")
keyLoc := &signrpc.KeyLocator{
KeyFamily: int32(keychain.KeyFamilyNodeKey),

View file

@ -7,20 +7,20 @@ import (
"github.com/btcsuite/btcd/btcutil"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/record"
"github.com/stretchr/testify/require"
)
func testSingleHopInvoice(ht *lntemp.HarnessTest) {
func testSingleHopInvoice(ht *lntest.HarnessTest) {
// Open a channel with 100k satoshis between Alice and Bob with Alice
// being the sole funder of the channel.
chanAmt := btcutil.Amount(100000)
alice, bob := ht.Alice, ht.Bob
cp := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
)
// assertAmountPaid is a helper closure that asserts the amount paid by

View file

@ -3,8 +3,8 @@ package itest
import (
"github.com/btcsuite/btcd/btcutil"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/stretchr/testify/require"
)
@ -21,11 +21,11 @@ const (
//
// The general flow of this test:
// 1. Carol --> Dave --> Alice --> Bob forward payment
// 2. -------X X X Bob restart sender and intermediaries
// 2. X X X Bob restart sender and intermediaries
// 3. Carol <-- Dave <-- Alice <-- Bob expect settle to propagate
//
//nolint:dupword
func testSwitchCircuitPersistence(ht *lntemp.HarnessTest) {
func testSwitchCircuitPersistence(ht *lntest.HarnessTest) {
// Setup our test scenario. We should now have four nodes running with
// three channels.
s := setupScenarioFourNodes(ht)
@ -95,7 +95,7 @@ func testSwitchCircuitPersistence(ht *lntemp.HarnessTest) {
// 2. Carol --- Dave X Alice --- Bob disconnect intermediaries
// 3. Carol --- Dave X Alice <-- Bob settle last hop
// 4. Carol <-- Dave <-- Alice --- Bob reconnect, expect settle to propagate
func testSwitchOfflineDelivery(ht *lntemp.HarnessTest) {
func testSwitchOfflineDelivery(ht *lntest.HarnessTest) {
// Setup our test scenario. We should now have four nodes running with
// three channels.
s := setupScenarioFourNodes(ht)
@ -131,11 +131,6 @@ func testSwitchOfflineDelivery(ht *lntemp.HarnessTest) {
// Wait until all outstanding htlcs in the network have been settled.
s.assertHTLCs(ht, 0)
// When asserting the amount of satoshis moved, we'll factor in the
// default base fee, as we didn't modify the fee structure when
// creating the seed nodes in the network.
const baseFee = 1
// At this point all the channels within our proto network should be
// shifted by 5k satoshis in the direction of Carol, the sink within the
// payment flow generated above. The order of asserts corresponds to
@ -174,7 +169,9 @@ func testSwitchOfflineDelivery(ht *lntemp.HarnessTest) {
// 3. Carol --- Dave X Alice <-- Bob settle last hop
// 4. Carol --- Dave X X Bob restart Alice
// 5. Carol <-- Dave <-- Alice --- Bob expect settle to propagate
func testSwitchOfflineDeliveryPersistence(ht *lntemp.HarnessTest) {
//
//nolint:dupword
func testSwitchOfflineDeliveryPersistence(ht *lntest.HarnessTest) {
// Setup our test scenario. We should now have four nodes running with
// three channels.
s := setupScenarioFourNodes(ht)
@ -260,7 +257,9 @@ func testSwitchOfflineDeliveryPersistence(ht *lntemp.HarnessTest) {
// 3. Carol --- Dave X Alice <-- Bob settle last hop
// 4. Carol --- Dave X X shutdown Bob, restart Alice
// 5. Carol <-- Dave <-- Alice X expect settle to propagate
func testSwitchOfflineDeliveryOutgoingOffline(ht *lntemp.HarnessTest) {
//
//nolint:dupword
func testSwitchOfflineDeliveryOutgoingOffline(ht *lntest.HarnessTest) {
// Setup our test scenario. We should now have four nodes running with
// three channels. Note that we won't call the cleanUp function here as
// we will manually stop the node Carol and her channel.
@ -371,13 +370,13 @@ type scenarioFourNodes struct {
//
// NOTE: caller needs to call cleanUp to clean the nodes and channels created
// from this setup.
func setupScenarioFourNodes(ht *lntemp.HarnessTest) *scenarioFourNodes {
func setupScenarioFourNodes(ht *lntest.HarnessTest) *scenarioFourNodes {
const (
chanAmt = btcutil.Amount(1000000)
pushAmt = btcutil.Amount(900000)
)
params := lntemp.OpenChannelParams{
params := lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
}
@ -404,7 +403,7 @@ func setupScenarioFourNodes(ht *lntemp.HarnessTest) *scenarioFourNodes {
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
// Open channels in batch to save blocks mined.
reqs := []*lntemp.OpenChannelRequest{
reqs := []*lntest.OpenChannelRequest{
{Local: alice, Remote: bob, Param: params},
{Local: dave, Remote: alice, Param: params},
{Local: carol, Remote: dave, Param: params},
@ -456,7 +455,7 @@ func setupScenarioFourNodes(ht *lntemp.HarnessTest) *scenarioFourNodes {
// assertHTLCs is a helper function which asserts the desired num of
// HTLCs has been seen in the nodes.
func (s *scenarioFourNodes) assertHTLCs(ht *lntemp.HarnessTest, num int) {
func (s *scenarioFourNodes) assertHTLCs(ht *lntest.HarnessTest, num int) {
// Alice should have both the same number of outgoing and
// incoming HTLCs.
ht.AssertNumActiveHtlcs(s.alice, num*2)
@ -472,7 +471,7 @@ func (s *scenarioFourNodes) assertHTLCs(ht *lntemp.HarnessTest, num int) {
// assertAmoutPaid is a helper method which takes a given paid amount
// and number of payments and asserts the desired payments are made in
// the four nodes.
func (s *scenarioFourNodes) assertAmoutPaid(ht *lntemp.HarnessTest,
func (s *scenarioFourNodes) assertAmoutPaid(ht *lntest.HarnessTest,
amt int64, num int64) {
ht.AssertAmountPaid(

View file

@ -20,8 +20,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/stretchr/testify/require"
)
@ -47,7 +47,7 @@ var (
// testTaproot ensures that the daemon can send to and spend from taproot (p2tr)
// outputs.
func testTaproot(ht *lntemp.HarnessTest) {
func testTaproot(ht *lntest.HarnessTest) {
testTaprootSendCoinsKeySpendBip86(ht, ht.Alice)
testTaprootComputeInputScriptKeySpendBip86(ht, ht.Alice)
testTaprootSignOutputRawScriptSpend(ht, ht.Alice)
@ -81,7 +81,7 @@ func testTaproot(ht *lntemp.HarnessTest) {
// testTaprootSendCoinsKeySpendBip86 tests sending to and spending from
// p2tr key spend only (BIP-0086) addresses through the SendCoins RPC which
// internally uses the ComputeInputScript method for signing.
func testTaprootSendCoinsKeySpendBip86(ht *lntemp.HarnessTest,
func testTaprootSendCoinsKeySpendBip86(ht *lntest.HarnessTest,
alice *node.HarnessNode) {
// We'll start the test by sending Alice some coins, which she'll use to
@ -137,7 +137,7 @@ func testTaprootSendCoinsKeySpendBip86(ht *lntemp.HarnessTest,
// testTaprootComputeInputScriptKeySpendBip86 tests sending to and spending from
// p2tr key spend only (BIP-0086) addresses through the SendCoins RPC which
// internally uses the ComputeInputScript method for signing.
func testTaprootComputeInputScriptKeySpendBip86(ht *lntemp.HarnessTest,
func testTaprootComputeInputScriptKeySpendBip86(ht *lntest.HarnessTest,
alice *node.HarnessNode) {
// We'll start the test by sending Alice some coins, which she'll use
@ -234,7 +234,7 @@ func testTaprootComputeInputScriptKeySpendBip86(ht *lntemp.HarnessTest,
// testTaprootSignOutputRawScriptSpend tests sending to and spending from p2tr
// script addresses using the script path with the SignOutputRaw RPC.
func testTaprootSignOutputRawScriptSpend(ht *lntemp.HarnessTest,
func testTaprootSignOutputRawScriptSpend(ht *lntest.HarnessTest,
alice *node.HarnessNode, sigHashType ...txscript.SigHashType) {
// For the next step, we need a public key. Let's use a special family
@ -260,9 +260,7 @@ func testTaprootSignOutputRawScriptSpend(ht *lntemp.HarnessTest,
require.NoError(ht, err)
// Send some coins to the generated tapscript address.
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
ht, alice, taprootKey, testAmount,
)
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
// Spend the output again, this time back to a p2wkh address.
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
@ -392,7 +390,7 @@ func testTaprootSignOutputRawScriptSpend(ht *lntemp.HarnessTest,
// testTaprootSignOutputRawKeySpendBip86 tests that a tapscript address can
// also be spent using the key spend path through the SignOutputRaw RPC using a
// BIP0086 key spend only commitment.
func testTaprootSignOutputRawKeySpendBip86(ht *lntemp.HarnessTest,
func testTaprootSignOutputRawKeySpendBip86(ht *lntest.HarnessTest,
alice *node.HarnessNode, sigHashType ...txscript.SigHashType) {
// For the next step, we need a public key. Let's use a special family
@ -413,9 +411,7 @@ func testTaprootSignOutputRawKeySpendBip86(ht *lntemp.HarnessTest,
taprootKey := txscript.ComputeTaprootKeyNoScript(internalKey)
// Send some coins to the generated tapscript address.
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
ht, alice, taprootKey, testAmount,
)
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
// Spend the output again, this time back to a p2wkh address.
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
@ -490,7 +486,7 @@ func testTaprootSignOutputRawKeySpendBip86(ht *lntemp.HarnessTest,
// testTaprootSignOutputRawKeySpendRootHash tests that a tapscript address can
// also be spent using the key spend path through the SignOutputRaw RPC using a
// tapscript root hash.
func testTaprootSignOutputRawKeySpendRootHash(ht *lntemp.HarnessTest,
func testTaprootSignOutputRawKeySpendRootHash(ht *lntest.HarnessTest,
alice *node.HarnessNode) {
// For the next step, we need a public key. Let's use a special family
@ -514,9 +510,7 @@ func testTaprootSignOutputRawKeySpendRootHash(ht *lntemp.HarnessTest,
taprootKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash[:])
// Send some coins to the generated tapscript address.
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
ht, alice, taprootKey, testAmount,
)
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
// Spend the output again, this time back to a p2wkh address.
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
@ -583,7 +577,7 @@ func testTaprootSignOutputRawKeySpendRootHash(ht *lntemp.HarnessTest,
// testTaprootMuSig2KeySpendBip86 tests that a combined MuSig2 key can also be
// used as a BIP-0086 key spend only key.
func testTaprootMuSig2KeySpendBip86(ht *lntemp.HarnessTest,
func testTaprootMuSig2KeySpendBip86(ht *lntest.HarnessTest,
alice *node.HarnessNode, version signrpc.MuSig2Version) {
// We're not going to commit to a script. So our taproot tweak will be
@ -601,9 +595,7 @@ func testTaprootMuSig2KeySpendBip86(ht *lntemp.HarnessTest,
)
// Send some coins to the generated tapscript address.
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
ht, alice, taprootKey, testAmount,
)
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
// Spend the output again, this time back to a p2wkh address.
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
@ -711,7 +703,7 @@ func testTaprootMuSig2KeySpendBip86(ht *lntemp.HarnessTest,
// testTaprootMuSig2KeySpendRootHash tests that a tapscript address can also be
// spent using a MuSig2 combined key.
func testTaprootMuSig2KeySpendRootHash(ht *lntemp.HarnessTest,
func testTaprootMuSig2KeySpendRootHash(ht *lntest.HarnessTest,
alice *node.HarnessNode, version signrpc.MuSig2Version) {
// We're going to commit to a script as well. This is a hash lock with a
@ -733,9 +725,7 @@ func testTaprootMuSig2KeySpendRootHash(ht *lntemp.HarnessTest,
)
// Send some coins to the generated tapscript address.
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
ht, alice, taprootKey, testAmount,
)
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
// Spend the output again, this time back to a p2wkh address.
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
@ -843,7 +833,7 @@ func testTaprootMuSig2KeySpendRootHash(ht *lntemp.HarnessTest,
// testTaprootMuSig2ScriptSpend tests that a tapscript address with an internal
// key that is a MuSig2 combined key can also be spent using the script path.
func testTaprootMuSig2ScriptSpend(ht *lntemp.HarnessTest,
func testTaprootMuSig2ScriptSpend(ht *lntest.HarnessTest,
alice *node.HarnessNode, version signrpc.MuSig2Version) {
// We're going to commit to a script and spend the output using the
@ -870,9 +860,7 @@ func testTaprootMuSig2ScriptSpend(ht *lntemp.HarnessTest,
tapscript := input.TapscriptFullTree(internalKey, leaf1)
// Send some coins to the generated tapscript address.
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
ht, alice, taprootKey, testAmount,
)
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
// Spend the output again, this time back to a p2wkh address.
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
@ -926,7 +914,7 @@ func testTaprootMuSig2ScriptSpend(ht *lntemp.HarnessTest,
// testTaprootMuSig2CombinedLeafKeySpend tests that a MuSig2 combined key can be
// used for an OP_CHECKSIG inside a tap script leaf spend.
func testTaprootMuSig2CombinedLeafKeySpend(ht *lntemp.HarnessTest,
func testTaprootMuSig2CombinedLeafKeySpend(ht *lntest.HarnessTest,
alice *node.HarnessNode, version signrpc.MuSig2Version) {
// We're using the combined MuSig2 key in a script leaf. So we need to
@ -951,9 +939,7 @@ func testTaprootMuSig2CombinedLeafKeySpend(ht *lntemp.HarnessTest,
require.NoError(ht, err)
// Send some coins to the generated tapscript address.
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
ht, alice, taprootKey, testAmount,
)
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
// Spend the output again, this time back to a p2wkh address.
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
@ -1102,7 +1088,7 @@ func testTaprootMuSig2CombinedLeafKeySpend(ht *lntemp.HarnessTest,
// testTaprootImportTapscriptScriptSpend tests importing p2tr script addresses
// using the script path with the full tree known.
func testTaprootImportTapscriptFullTree(ht *lntemp.HarnessTest,
func testTaprootImportTapscriptFullTree(ht *lntest.HarnessTest,
alice *node.HarnessNode) {
// For the next step, we need a public key. Let's use a special family
@ -1151,9 +1137,7 @@ func testTaprootImportTapscriptFullTree(ht *lntemp.HarnessTest,
require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
// Send some coins to the generated tapscript address.
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
ht, alice, taprootKey, testAmount,
)
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
p2trOutputRPC := &lnrpc.OutPoint{
TxidBytes: p2trOutpoint.Hash[:],
OutputIndex: p2trOutpoint.Index,
@ -1176,7 +1160,7 @@ func testTaprootImportTapscriptFullTree(ht *lntemp.HarnessTest,
// testTaprootImportTapscriptPartialReveal tests importing p2tr script addresses
// for which we only know part of the tree.
func testTaprootImportTapscriptPartialReveal(ht *lntemp.HarnessTest,
func testTaprootImportTapscriptPartialReveal(ht *lntest.HarnessTest,
alice *node.HarnessNode) {
// For the next step, we need a public key. Let's use a special family
@ -1221,9 +1205,7 @@ func testTaprootImportTapscriptPartialReveal(ht *lntemp.HarnessTest,
require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
// Send some coins to the generated tapscript address.
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
ht, alice, taprootKey, testAmount,
)
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
p2trOutputRPC := &lnrpc.OutPoint{
TxidBytes: p2trOutpoint.Hash[:],
@ -1247,7 +1229,7 @@ func testTaprootImportTapscriptPartialReveal(ht *lntemp.HarnessTest,
// testTaprootImportTapscriptRootHashOnly tests importing p2tr script addresses
// for which we only know the root hash.
func testTaprootImportTapscriptRootHashOnly(ht *lntemp.HarnessTest,
func testTaprootImportTapscriptRootHashOnly(ht *lntest.HarnessTest,
alice *node.HarnessNode) {
// For the next step, we need a public key. Let's use a special family
@ -1280,9 +1262,7 @@ func testTaprootImportTapscriptRootHashOnly(ht *lntemp.HarnessTest,
require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
// Send some coins to the generated tapscript address.
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
ht, alice, taprootKey, testAmount,
)
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
p2trOutputRPC := &lnrpc.OutPoint{
TxidBytes: p2trOutpoint.Hash[:],
@ -1306,7 +1286,7 @@ func testTaprootImportTapscriptRootHashOnly(ht *lntemp.HarnessTest,
// testTaprootImportTapscriptFullKey tests importing p2tr script addresses for
// which we only know the full Taproot key.
func testTaprootImportTapscriptFullKey(ht *lntemp.HarnessTest,
func testTaprootImportTapscriptFullKey(ht *lntest.HarnessTest,
alice *node.HarnessNode) {
// For the next step, we need a public key. Let's use a special family
@ -1339,9 +1319,7 @@ func testTaprootImportTapscriptFullKey(ht *lntemp.HarnessTest,
require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
// Send some coins to the generated tapscript address.
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
ht, alice, taprootKey, testAmount,
)
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
p2trOutputRPC := &lnrpc.OutPoint{
TxidBytes: p2trOutpoint.Hash[:],
@ -1365,7 +1343,7 @@ func testTaprootImportTapscriptFullKey(ht *lntemp.HarnessTest,
// clearWalletImportedTapscriptBalance manually assembles and then attempts to
// sign a TX to sweep funds from an imported tapscript address.
func clearWalletImportedTapscriptBalance(ht *lntemp.HarnessTest,
func clearWalletImportedTapscriptBalance(ht *lntest.HarnessTest,
hn *node.HarnessNode, utxo *wire.TxOut, outPoint wire.OutPoint,
internalKey *btcec.PublicKey, derivationPath []uint32,
rootHash []byte) {
@ -1460,7 +1438,7 @@ func testScriptSchnorrSig(t *testing.T,
}
// newAddrWithScript returns a new address and its pkScript.
func newAddrWithScript(ht *lntemp.HarnessTest, node *node.HarnessNode,
func newAddrWithScript(ht *lntest.HarnessTest, node *node.HarnessNode,
addrType lnrpc.AddressType) (btcutil.Address, []byte) {
p2wkhResp := node.RPC.NewAddress(&lnrpc.NewAddressRequest{
@ -1479,8 +1457,8 @@ func newAddrWithScript(ht *lntemp.HarnessTest, node *node.HarnessNode,
// sendToTaprootOutput sends coins to a p2tr output of the given taproot key and
// mines a block to confirm the coins.
func sendToTaprootOutput(ht *lntemp.HarnessTest, hn *node.HarnessNode,
taprootKey *btcec.PublicKey, amt int64) (wire.OutPoint, []byte) {
func sendToTaprootOutput(ht *lntest.HarnessTest, hn *node.HarnessNode,
taprootKey *btcec.PublicKey) (wire.OutPoint, []byte) {
tapScriptAddr, err := btcutil.NewAddressTaproot(
schnorr.SerializePubKey(taprootKey), harnessNetParams,
@ -1492,7 +1470,7 @@ func sendToTaprootOutput(ht *lntemp.HarnessTest, hn *node.HarnessNode,
// Send some coins to the generated tapscript address.
req := &lnrpc.SendCoinsRequest{
Addr: tapScriptAddr.String(),
Amount: amt,
Amount: testAmount,
}
hn.RPC.SendCoins(req)
@ -1542,7 +1520,7 @@ func sendToTaprootOutput(ht *lntemp.HarnessTest, hn *node.HarnessNode,
// after checking its weight against an estimate. After asserting the given
// spend request, the given sweep address' balance is verified to be seen as
// funds belonging to the wallet.
func publishTxAndConfirmSweep(ht *lntemp.HarnessTest, node *node.HarnessNode,
func publishTxAndConfirmSweep(ht *lntest.HarnessTest, node *node.HarnessNode,
tx *wire.MsgTx, estimatedWeight int64,
spendRequest *chainrpc.SpendRequest, sweepAddr string) {
@ -1604,7 +1582,7 @@ func publishTxAndConfirmSweep(ht *lntemp.HarnessTest, node *node.HarnessNode,
// confirmAddress makes sure that a transaction in the mempool spends funds to
// the given address. It also checks that a confirmation notification for the
// address is triggered when the transaction is mined.
func confirmAddress(ht *lntemp.HarnessTest, hn *node.HarnessNode,
func confirmAddress(ht *lntest.HarnessTest, hn *node.HarnessNode,
addrString string) {
// Wait until the tx that sends to the address is found.
@ -1654,7 +1632,7 @@ func confirmAddress(ht *lntemp.HarnessTest, hn *node.HarnessNode,
// deriveSigningKeys derives three signing keys and returns their descriptors,
// as well as the public keys in the Schnorr serialized format.
func deriveSigningKeys(ht *lntemp.HarnessTest, node *node.HarnessNode,
func deriveSigningKeys(ht *lntest.HarnessTest, node *node.HarnessNode,
version signrpc.MuSig2Version) (*signrpc.KeyDescriptor,
*signrpc.KeyDescriptor, *signrpc.KeyDescriptor, [][]byte) {
@ -1700,7 +1678,7 @@ func deriveSigningKeys(ht *lntemp.HarnessTest, node *node.HarnessNode,
// combined into a single key. The same node is used for the three signing
// participants but a separate key is generated for each session. So the result
// should be the same as if it were three different nodes.
func createMuSigSessions(ht *lntemp.HarnessTest, node *node.HarnessNode,
func createMuSigSessions(ht *lntest.HarnessTest, node *node.HarnessNode,
taprootTweak *signrpc.TaprootTweakDesc,
keyDesc1, keyDesc2, keyDesc3 *signrpc.KeyDescriptor,
allPubKeys [][]byte, version signrpc.MuSig2Version) (*btcec.PublicKey,
@ -1838,7 +1816,7 @@ func createMuSigSessions(ht *lntemp.HarnessTest, node *node.HarnessNode,
// testTaprootCoopClose asserts that if both peers signal ShutdownAnySegwit,
// then a taproot closing addr is used. Otherwise, we shouldn't expect one to
// be used.
func testTaprootCoopClose(ht *lntemp.HarnessTest) {
func testTaprootCoopClose(ht *lntest.HarnessTest) {
// We'll start by making two new nodes, and funding a channel between
// them.
carol := ht.NewNode("Carol", nil)
@ -1853,7 +1831,7 @@ func testTaprootCoopClose(ht *lntemp.HarnessTest) {
// We'll now open a channel between Carol and Dave.
chanPoint := ht.OpenChannel(
carol, dave, lntemp.OpenChannelParams{
carol, dave, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
SatPerVByte: satPerVbyte,
@ -1888,7 +1866,7 @@ func testTaprootCoopClose(ht *lntemp.HarnessTest) {
// We'll now open up a chanel again between Carol and Eve.
chanPoint = ht.OpenChannel(
carol, eve, lntemp.OpenChannelParams{
carol, eve, lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: pushAmt,
SatPerVByte: satPerVbyte,
@ -1904,7 +1882,7 @@ func testTaprootCoopClose(ht *lntemp.HarnessTest) {
// testMuSig2CombineKey makes sure that combining a key with MuSig2 returns the
// correct result according to the MuSig2 version specified.
func testMuSig2CombineKey(ht *lntemp.HarnessTest, alice *node.HarnessNode,
func testMuSig2CombineKey(ht *lntest.HarnessTest, alice *node.HarnessNode,
version signrpc.MuSig2Version) {
testVector040Key1 := hexDecode(

View file

@ -4,6 +4,7 @@ import (
"flag"
"fmt"
"io"
"math"
"os"
"path/filepath"
"runtime"
@ -11,9 +12,12 @@ import (
"testing"
"time"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/integration/rpctest"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/stretchr/testify/require"
"google.golang.org/grpc/grpclog"
)
@ -26,9 +30,25 @@ const (
// defaultRunTranche is the default index of the test cases tranche that
// we run.
defaultRunTranche uint = 0
defaultTimeout = wait.DefaultTimeout
itestLndBinary = "../lnd-itest"
// TODO(yy): remove the following defined constants and put them in the
// specific tests where they are used?
testFeeBase = 1e+6
anchorSize = 330
defaultCSV = node.DefaultCSV
noFeeLimitMsat = math.MaxInt64
AddrTypeWitnessPubkeyHash = lnrpc.AddressType_WITNESS_PUBKEY_HASH
AddrTypeNestedPubkeyHash = lnrpc.AddressType_NESTED_PUBKEY_HASH
AddrTypeTaprootPubkey = lnrpc.AddressType_TAPROOT_PUBKEY
)
var (
harnessNetParams = &chaincfg.RegressionNetParams
// testCasesSplitParts is the number of tranches the test cases should
// be split into. By default this is set to 1, so no splitting happens.
// If this value is increased, then the -runtranche flag must be
@ -49,31 +69,32 @@ var (
// dbBackendFlag specifies the backend to use.
dbBackendFlag = flag.String("dbbackend", "bbolt", "Database backend "+
"(bbolt, etcd, postgres, sqlite)")
"(bbolt, etcd, postgres)")
// lndExecutable is the full path to the lnd binary.
lndExecutable = flag.String(
"lndexec", itestLndBinary, "full path to lnd binary",
)
)
// TestLightningNetworkDaemonTemp performs a series of integration tests
// amongst a programmatically driven network of lnd nodes.
func TestLightningNetworkDaemonTemp(t *testing.T) {
if !*tempTest {
t.Skip("Running old tests, new tests are skipped")
}
// TestLightningNetworkDaemon performs a series of integration tests amongst a
// programmatically driven network of lnd nodes.
func TestLightningNetworkDaemon(t *testing.T) {
// If no tests are registered, then we can exit early.
if len(allTestCasesTemp) == 0 {
t.Skip("integration tests not selected with flag 'rpctest'")
if len(allTestCases) == 0 {
t.Skip("integration tests not selected with flag 'integration'")
}
// Get the test cases to be run in this tranche.
testCases, trancheIndex, trancheOffset := getTestCaseSplitTranche()
lntest.ApplyPortOffset(uint32(trancheIndex) * 1000)
node.ApplyPortOffset(uint32(trancheIndex) * 1000)
// Create a simple fee service.
feeService := lntemp.NewFeeService(t)
feeService := lntest.NewFeeService(t)
// Get the binary path and setup the harness test.
binary := getLndBinary(t)
harnessTest := lntemp.SetupHarness(
harnessTest := lntest.SetupHarness(
t, binary, *dbBackendFlag, feeService,
)
defer harnessTest.Stop()
@ -126,12 +147,16 @@ func TestLightningNetworkDaemonTemp(t *testing.T) {
break
}
}
_, height := harnessTest.Miner.GetBestBlock()
t.Logf("=========> tests finished for tranche: %v, tested %d "+
"cases, end height: %d\n", trancheIndex, len(testCases), height)
}
// getTestCaseSplitTranche returns the sub slice of the test cases that should
// be run as the current split tranche as well as the index and slice offset of
// the tranche.
func getTestCaseSplitTranche() ([]*lntemp.TestCase, uint, uint) {
func getTestCaseSplitTranche() ([]*lntest.TestCase, uint, uint) {
numTranches := defaultSplitTranches
if testCasesSplitTranches != nil {
numTranches = *testCasesSplitTranches
@ -150,7 +175,7 @@ func getTestCaseSplitTranche() ([]*lntemp.TestCase, uint, uint) {
runTranche = 0
}
numCases := uint(len(allTestCasesTemp))
numCases := uint(len(allTestCases))
testsPerTranche := numCases / numTranches
trancheOffset := runTranche * testsPerTranche
trancheEnd := trancheOffset + testsPerTranche
@ -158,7 +183,7 @@ func getTestCaseSplitTranche() ([]*lntemp.TestCase, uint, uint) {
trancheEnd = numCases
}
return allTestCasesTemp[trancheOffset:trancheEnd], threadID,
return allTestCases[trancheOffset:trancheEnd], threadID,
trancheOffset
}
@ -188,7 +213,7 @@ func init() {
// Before we start any node, we need to make sure that any btcd node
// that is started through the RPC harness uses a unique port as well
// to avoid any port collisions.
rpctest.ListenAddressGenerator = lntest.GenerateBtcdListenerAddresses
rpctest.ListenAddressGenerator = node.GenerateBtcdListenerAddresses
// Swap out grpc's default logger with out fake logger which drops the
// statements on the floor.

View file

@ -7,17 +7,17 @@ import (
"github.com/btcsuite/btcd/btcutil"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/stretchr/testify/require"
)
// testTrackPayments tests whether a client that calls the TrackPayments api
// receives payment updates.
func testTrackPayments(ht *lntemp.HarnessTest) {
func testTrackPayments(ht *lntest.HarnessTest) {
// Open a channel between alice and bob.
alice, bob := ht.Alice, ht.Bob
channel := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{
alice, bob, lntest.OpenChannelParams{
Amt: btcutil.Amount(300000),
},
)

View file

@ -16,8 +16,8 @@ import (
"github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/stretchr/testify/require"
)
@ -51,7 +51,7 @@ func walletToLNAddrType(t *testing.T,
// newExternalAddr generates a new external address of an imported account for a
// pair of nodes, where one acts as the funder and the other as the signer.
func newExternalAddr(ht *lntemp.HarnessTest, funder, signer *node.HarnessNode,
func newExternalAddr(ht *lntest.HarnessTest, funder, signer *node.HarnessNode,
importedAccount string, addrType walletrpc.AddressType) string {
// We'll generate a new address for Carol from Dave's node to receive
@ -125,7 +125,7 @@ func assertOutputScriptType(t *testing.T, expType txscript.ScriptClass,
// psbtSendFromImportedAccount attempts to fund a PSBT from the given imported
// account, originating from the source node to the destination.
func psbtSendFromImportedAccount(ht *lntemp.HarnessTest, srcNode, destNode,
func psbtSendFromImportedAccount(ht *lntest.HarnessTest, srcNode, destNode,
signer *node.HarnessNode, account string,
accountAddrType walletrpc.AddressType) {
@ -236,7 +236,7 @@ func psbtSendFromImportedAccount(ht *lntemp.HarnessTest, srcNode, destNode,
// node. To ensure the channel is operational before closing it, a test payment
// is made. Several balance assertions are made along the way for the sake of
// correctness.
func fundChanAndCloseFromImportedAccount(ht *lntemp.HarnessTest, srcNode,
func fundChanAndCloseFromImportedAccount(ht *lntest.HarnessTest, srcNode,
destNode, signer *node.HarnessNode, account string,
accountAddrType walletrpc.AddressType, utxoAmt, chanSize int64) {
@ -256,7 +256,7 @@ func fundChanAndCloseFromImportedAccount(ht *lntemp.HarnessTest, srcNode,
// The source node will then fund the channel through a PSBT shim.
pendingChanID := ht.Random32Bytes()
chanUpdates, rawPsbt := ht.OpenChannelPsbt(
srcNode, destNode, lntemp.OpenChannelParams{
srcNode, destNode, lntest.OpenChannelParams{
Amt: btcutil.Amount(chanSize),
FundingShim: &lnrpc.FundingShim{
Shim: &lnrpc.FundingShim_PsbtShim{
@ -463,7 +463,7 @@ func fundChanAndCloseFromImportedAccount(ht *lntemp.HarnessTest, srcNode,
// testWalletImportAccount tests that an imported account can fund transactions
// and channels through PSBTs, by having one node (the one with the imported
// account) craft the transactions and another node act as the signer.
func testWalletImportAccount(ht *lntemp.HarnessTest) {
func testWalletImportAccount(ht *lntest.HarnessTest) {
testCases := []struct {
name string
addrType walletrpc.AddressType
@ -491,7 +491,7 @@ func testWalletImportAccount(ht *lntemp.HarnessTest) {
for _, tc := range testCases {
tc := tc
success := ht.Run(tc.name, func(tt *testing.T) {
testFunc := func(ht *lntemp.HarnessTest) {
testFunc := func(ht *lntest.HarnessTest) {
testWalletImportAccountScenario(
ht, tc.addrType,
)
@ -499,7 +499,7 @@ func testWalletImportAccount(ht *lntemp.HarnessTest) {
st := ht.Subtest(tt)
st.RunTestCase(&lntemp.TestCase{
st.RunTestCase(&lntest.TestCase{
Name: tc.name,
TestFunc: testFunc,
})
@ -515,7 +515,7 @@ func testWalletImportAccount(ht *lntemp.HarnessTest) {
}
}
func testWalletImportAccountScenario(ht *lntemp.HarnessTest,
func testWalletImportAccountScenario(ht *lntest.HarnessTest,
addrType walletrpc.AddressType) {
// We'll start our test by having two nodes, Carol and Dave. Carol's
@ -529,7 +529,7 @@ func testWalletImportAccountScenario(ht *lntemp.HarnessTest,
runWalletImportAccountScenario(ht, addrType, carol, dave)
}
func runWalletImportAccountScenario(ht *lntemp.HarnessTest,
func runWalletImportAccountScenario(ht *lntest.HarnessTest,
addrType walletrpc.AddressType, carol, dave *node.HarnessNode) {
const utxoAmt int64 = btcutil.SatoshiPerBitcoin
@ -619,7 +619,7 @@ func runWalletImportAccountScenario(ht *lntemp.HarnessTest,
// testWalletImportPubKey tests that an imported public keys can fund
// transactions and channels through PSBTs, by having one node (the one with the
// imported account) craft the transactions and another node act as the signer.
func testWalletImportPubKey(ht *lntemp.HarnessTest) {
func testWalletImportPubKey(ht *lntest.HarnessTest) {
testCases := []struct {
name string
addrType walletrpc.AddressType
@ -642,7 +642,7 @@ func testWalletImportPubKey(ht *lntemp.HarnessTest) {
for _, tc := range testCases {
tc := tc
success := ht.Run(tc.name, func(tt *testing.T) {
testFunc := func(ht *lntemp.HarnessTest) {
testFunc := func(ht *lntest.HarnessTest) {
testWalletImportPubKeyScenario(
ht, tc.addrType,
)
@ -650,7 +650,7 @@ func testWalletImportPubKey(ht *lntemp.HarnessTest) {
st := ht.Subtest(tt)
st.RunTestCase(&lntemp.TestCase{
st.RunTestCase(&lntest.TestCase{
Name: tc.name,
TestFunc: testFunc,
})
@ -666,7 +666,7 @@ func testWalletImportPubKey(ht *lntemp.HarnessTest) {
}
}
func testWalletImportPubKeyScenario(ht *lntemp.HarnessTest,
func testWalletImportPubKeyScenario(ht *lntest.HarnessTest,
addrType walletrpc.AddressType) {
const utxoAmt int64 = btcutil.SatoshiPerBitcoin

View file

@ -5,12 +5,10 @@ import (
"github.com/lightningnetwork/lnd/chainreg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/stretchr/testify/require"
)
type pendingChan *lnrpc.PendingChannelsResponse_PendingChannel
// testWipeForwardingPackagesLocal tests that when a channel is closed, either
// through local force close, remote close, or coop close, all the forwarding
// packages of that particular channel are deleted. The test creates a
@ -21,7 +19,7 @@ type pendingChan *lnrpc.PendingChannelsResponse_PendingChannel
// packages are wiped.
// - Bob coop closes the channel Bob->Carol, and checks from both Bob PoVs
// that the forwarding packages are wiped.
func testWipeForwardingPackages(ht *lntemp.HarnessTest) {
func testWipeForwardingPackages(ht *lntest.HarnessTest) {
const (
chanAmt = 10e6
paymentAmt = 10e4
@ -41,12 +39,12 @@ func testWipeForwardingPackages(ht *lntemp.HarnessTest) {
// Open a channel between Alice and Bob.
chanPointAB := ht.OpenChannel(
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
)
// Open a channel between Bob and Carol.
chanPointBC := ht.OpenChannel(
bob, carol, lntemp.OpenChannelParams{Amt: chanAmt},
bob, carol, lntest.OpenChannelParams{Amt: chanAmt},
)
// Before we continue, make sure Alice has seen the channel between Bob

View file

@ -3,7 +3,7 @@ package itest
import (
"github.com/btcsuite/btcd/btcutil"
"github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lnwallet"
)
@ -11,7 +11,7 @@ import (
// acceptances will allow a wumbo channel to be created. Additionally, if a
// node is running with mini channels only enabled, then they should reject any
// inbound wumbo channel requests.
func testWumboChannels(ht *lntemp.HarnessTest) {
func testWumboChannels(ht *lntest.HarnessTest) {
// With all the channel types exercised, we'll now make sure the wumbo
// signalling support works properly.
//
@ -33,7 +33,7 @@ func testWumboChannels(ht *lntemp.HarnessTest) {
// The test should indicate a failure due to the channel being too
// large.
ht.OpenChannelAssertErr(
wumboNode, miniNode, lntemp.OpenChannelParams{Amt: chanAmt},
wumboNode, miniNode, lntest.OpenChannelParams{Amt: chanAmt},
lnwallet.ErrChanTooLarge(chanAmt, funding.MaxBtcFundingAmount),
)
@ -46,7 +46,7 @@ func testWumboChannels(ht *lntemp.HarnessTest) {
// Creating a wumbo channel between these two nodes should succeed.
ht.EnsureConnected(wumboNode, wumboNode2)
chanPoint := ht.OpenChannel(
wumboNode, wumboNode2, lntemp.OpenChannelParams{Amt: chanAmt},
wumboNode, wumboNode2, lntest.OpenChannelParams{Amt: chanAmt},
)
ht.CloseChannel(wumboNode, chanPoint)
}

View file

@ -1,7 +1,7 @@
package itest
import (
"context"
"fmt"
"testing"
"time"
@ -13,10 +13,9 @@ import (
"github.com/lightningnetwork/lnd/chainreg"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntemp/rpc"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/rpc"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/stretchr/testify/require"
@ -24,7 +23,7 @@ import (
// testZeroConfChannelOpen tests that opening a zero-conf channel works and
// sending payments also works.
func testZeroConfChannelOpen(ht *lntemp.HarnessTest) {
func testZeroConfChannelOpen(ht *lntest.HarnessTest) {
// Since option-scid-alias is opt-in, the provided harness nodes will
// not have the feature bit set. Also need to set anchors as those are
// default-off in itests.
@ -40,7 +39,7 @@ func testZeroConfChannelOpen(ht *lntemp.HarnessTest) {
// We'll open a regular public channel between Bob and Carol here.
chanAmt := btcutil.Amount(1_000_000)
p := lntemp.OpenChannelParams{
p := lntest.OpenChannelParams{
Amt: chanAmt,
}
chanPoint := ht.OpenChannel(bob, carol, p)
@ -59,7 +58,7 @@ func testZeroConfChannelOpen(ht *lntemp.HarnessTest) {
go acceptChannel(ht.T, true, acceptStream)
// Open a private zero-conf anchors channel of 1M satoshis.
params := lntemp.OpenChannelParams{
params := lntest.OpenChannelParams{
Amt: chanAmt,
Private: true,
CommitmentType: lnrpc.CommitmentType_ANCHORS,
@ -192,7 +191,7 @@ func testZeroConfChannelOpen(ht *lntemp.HarnessTest) {
// testOptionScidAlias checks that opening an option_scid_alias channel-type
// channel or w/o the channel-type works properly.
func testOptionScidAlias(ht *lntemp.HarnessTest) {
func testOptionScidAlias(ht *lntest.HarnessTest) {
type scidTestCase struct {
name string
@ -235,7 +234,7 @@ func testOptionScidAlias(ht *lntemp.HarnessTest) {
}
}
func optionScidAliasScenario(ht *lntemp.HarnessTest, chantype, private bool) {
func optionScidAliasScenario(ht *lntest.HarnessTest, chantype, private bool) {
// Option-scid-alias is opt-in, as is anchors.
scidAliasArgs := []string{
"--protocol.option-scid-alias",
@ -257,7 +256,7 @@ func optionScidAliasScenario(ht *lntemp.HarnessTest, chantype, private bool) {
chanAmt := btcutil.Amount(1_000_000)
params := lntemp.OpenChannelParams{
params := lntest.OpenChannelParams{
Amt: chanAmt,
Private: private,
CommitmentType: lnrpc.CommitmentType_ANCHORS,
@ -283,7 +282,7 @@ func optionScidAliasScenario(ht *lntemp.HarnessTest, chantype, private bool) {
// We'll now open a regular public channel between Bob and Carol and
// assert that Bob can pay Dave. We'll also assert that the invoice
// Dave issues has the startingAlias as a hop hint.
p := lntemp.OpenChannelParams{
p := lntest.OpenChannelParams{
Amt: chanAmt,
}
fundingPoint2 := ht.OpenChannel(bob, carol, p)
@ -313,6 +312,7 @@ func optionScidAliasScenario(ht *lntemp.HarnessTest, chantype, private bool) {
require.Len(ht, decodedReq.RouteHints, 0)
payReq := daveInvoiceResp2.PaymentRequest
ht.CompletePaymentRequests(bob, []string{payReq})
return
}
@ -410,7 +410,7 @@ func waitForZeroConfGraphChange(hn *node.HarnessNode,
// testUpdateChannelPolicyScidAlias checks that option-scid-alias, zero-conf
// channel-types, and option-scid-alias feature-bit-only channels have the
// expected graph and that payments work when updating the channel policy.
func testUpdateChannelPolicyScidAlias(ht *lntemp.HarnessTest) {
func testUpdateChannelPolicyScidAlias(ht *lntest.HarnessTest) {
tests := []struct {
name string
@ -462,7 +462,7 @@ func testUpdateChannelPolicyScidAlias(ht *lntemp.HarnessTest) {
}
}
func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
func testPrivateUpdateAlias(ht *lntest.HarnessTest,
zeroConf, scidAliasType, private bool) {
// We'll create a new node Eve that will not have option-scid-alias
@ -495,7 +495,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
chanAmt := btcutil.Amount(1_000_000)
p := lntemp.OpenChannelParams{
p := lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: chanAmt / 2,
}
@ -509,7 +509,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
go acceptChannel(ht.T, zeroConf, acceptStream)
// Open a private channel, optionally specifying a channel-type.
params := lntemp.OpenChannelParams{
params := lntest.OpenChannelParams{
Amt: chanAmt,
Private: private,
CommitmentType: lnrpc.CommitmentType_ANCHORS,
@ -542,7 +542,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
FeeRateMilliMsat: testFeeBase * feeRate,
TimeLockDelta: timeLockDelta,
MinHtlc: 1000, // default value
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
}
// Assert that Dave receives Carol's policy update.
@ -568,7 +568,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
FeeRateMilliMsat: testFeeBase * feeRate,
TimeLockDelta: timeLockDelta,
MinHtlc: 1000,
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
}
// Assert that Carol receives Dave's policy update.
@ -655,7 +655,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
FeeRateMilliMsat: testFeeBase * feeRate,
TimeLockDelta: timeLockDelta,
MinHtlc: 1000,
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
}
// Assert Dave receives Carol's policy update.
@ -744,7 +744,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
FeeRateMilliMsat: testFeeBase * feeRate,
TimeLockDelta: timeLockDelta,
MinHtlc: 1000,
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
}
// Assert Dave and optionally Eve receives Carol's update.
@ -764,7 +764,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
// testOptionScidUpgrade tests that toggling the option-scid-alias feature bit
// correctly upgrades existing channels.
func testOptionScidUpgrade(ht *lntemp.HarnessTest) {
func testOptionScidUpgrade(ht *lntest.HarnessTest) {
bob := ht.Bob
// Start carol with anchors only.
@ -788,7 +788,7 @@ func testOptionScidUpgrade(ht *lntemp.HarnessTest) {
chanAmt := btcutil.Amount(1_000_000)
p := lntemp.OpenChannelParams{
p := lntest.OpenChannelParams{
Amt: chanAmt,
PushAmt: chanAmt / 2,
Private: true,
@ -798,7 +798,7 @@ func testOptionScidUpgrade(ht *lntemp.HarnessTest) {
// Bob will open a channel to Carol now.
ht.EnsureConnected(bob, carol)
p = lntemp.OpenChannelParams{
p = lntest.OpenChannelParams{
Amt: chanAmt,
}
fundingPoint2 := ht.OpenChannel(bob, carol, p)
@ -822,25 +822,34 @@ func testOptionScidUpgrade(ht *lntemp.HarnessTest) {
var startingAlias lnwire.ShortChannelID
startingAlias.BlockHeight = 16_000_000
err := wait.Predicate(func() bool {
// TODO(yy): Carol and Dave will attempt to connect to each other
// during restart. However, due to the race condition in peer
// connection, they may both fail. Thus we need to ensure the
// connection here. Once the race is fixed, we can remove this line.
ht.EnsureConnected(dave, carol)
err := wait.NoError(func() error {
invoiceResp := dave.RPC.AddInvoice(daveParams)
decodedReq := dave.RPC.DecodePayReq(invoiceResp.PaymentRequest)
if len(decodedReq.RouteHints) != 1 {
return false
return fmt.Errorf("expected 1 route hint, got %v",
decodedReq.RouteHints)
}
if len(decodedReq.RouteHints[0].HopHints) != 1 {
return false
return fmt.Errorf("expected 1 hop hint, got %v",
len(decodedReq.RouteHints[0].HopHints))
}
hopHint := decodedReq.RouteHints[0].HopHints[0].ChanId
if startingAlias.ToUint64() == hopHint {
daveInvoice = invoiceResp
return true
return nil
}
return false
return fmt.Errorf("unmatched alias, expected %v, got %v",
startingAlias.ToUint64(), hopHint)
}, defaultTimeout)
require.NoError(ht, err)
@ -892,15 +901,12 @@ func acceptChannel(t *testing.T, zeroConf bool, stream rpc.AcceptorClient) {
// testZeroConfReorg tests that a reorg does not cause a zero-conf channel to
// be deleted from the channel graph. This was previously the case due to logic
// in the function DisconnectBlockAtHeight.
func testZeroConfReorg(ht *lntemp.HarnessTest) {
if ht.ChainBackendName() == lntest.NeutrinoBackendName {
func testZeroConfReorg(ht *lntest.HarnessTest) {
if ht.IsNeutrinoBackend() {
ht.Skipf("skipping zero-conf reorg test for neutrino backend")
}
var (
ctxb = context.Background()
temp = "temp"
)
var temp = "temp"
// Since zero-conf is opt in, the harness nodes provided won't be able
// to open zero-conf channels. In that case, we just spin up new nodes.
@ -926,7 +932,7 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
go acceptChannel(ht.T, true, acceptStream)
// Open a private zero-conf anchors channel of 1M satoshis.
params := lntemp.OpenChannelParams{
params := lntest.OpenChannelParams{
Amt: btcutil.Amount(1_000_000),
CommitmentType: lnrpc.CommitmentType_ANCHORS,
ZeroConf: true,
@ -949,10 +955,9 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
// We will now attempt to query for the alias SCID in Carol's graph.
// We will query for the starting alias, which is exported by the
// aliasmgr package.
_, err := carol.RPC.LN.GetChanInfo(ctxb, &lnrpc.ChanInfoRequest{
carol.RPC.GetChanInfo(&lnrpc.ChanInfoRequest{
ChanId: aliasmgr.StartingAlias.ToUint64(),
})
require.NoError(ht.T, err)
// Now we will trigger a reorg and we'll assert that the edge still
// exists in the graph.
@ -960,7 +965,7 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
// First, we'll setup a new miner that we can use to cause a reorg.
tempLogDir := ".tempminerlogs"
logFilename := "output-open_channel_reorg-temp_miner.log"
tempMiner := lntemp.NewTempMiner(
tempMiner := lntest.NewTempMiner(
ht.Context(), ht.T, tempLogDir, logFilename,
)
defer tempMiner.Stop()
@ -971,7 +976,7 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
// We start by connecting the new miner to our original miner, such
// that it will sync to our original chain.
err = ht.Miner.Client.Node(
err := ht.Miner.Client.Node(
btcjson.NConnect, tempMiner.P2PAddress(), &temp,
)
require.NoError(ht.T, err, "unable to connect node")
@ -991,18 +996,16 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
require.NoError(ht.T, err, "unable to remove node")
// We now cause a fork, by letting our original miner mine 1 block and
// our new miner will mine 2.
ht.MineBlocks(1)
_, err = tempMiner.Client.Generate(2)
require.NoError(ht.T, err, "unable to generate blocks")
// our new miner will mine 2. We also expect the funding transition to
// be mined.
ht.MineBlocksAndAssertNumTxes(1, 1)
tempMiner.MineEmptyBlocks(2)
// Ensure the temp miner is one block ahead.
assertMinerBlockHeightDelta(ht, ht.Miner, tempMiner, 1)
// Wait for Carol to sync to the original miner's chain.
_, minerHeight, err := ht.Miner.Client.GetBestBlock()
require.NoError(ht.T, err, "unable to get current blockheight")
_, minerHeight := ht.Miner.GetBestBlock()
ht.WaitForNodeBlockHeight(carol, minerHeight)
// Now we'll disconnect Carol's chain backend from the original miner
@ -1033,24 +1036,19 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
ht.ConnectMiner()
// This should have caused a reorg and Alice should sync to the new
// This should have caused a reorg and Carol should sync to the new
// chain.
_, tempMinerHeight, err := tempMiner.Client.GetBestBlock()
require.NoError(ht.T, err, "unable to get current blockheight")
_, tempMinerHeight := tempMiner.GetBestBlock()
ht.WaitForNodeBlockHeight(carol, tempMinerHeight)
err = wait.Predicate(func() bool {
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
// Make sure all active nodes are synced.
ht.AssertActiveNodesSynced()
_, err = carol.RPC.LN.GetChanInfo(ctxt, &lnrpc.ChanInfoRequest{
ChanId: aliasmgr.StartingAlias.ToUint64(),
})
return err == nil
}, defaultTimeout)
require.NoError(ht.T, err, "carol doesn't have zero-conf edge")
// Carol should have the channel once synced.
carol.RPC.GetChanInfo(&lnrpc.ChanInfoRequest{
ChanId: aliasmgr.StartingAlias.ToUint64(),
})
// Mine the zero-conf funding transaction so the test doesn't fail.
ht.MineBlocks(1)
ht.MineBlocksAndAssertNumTxes(1, 1)
}

View file

@ -1,6 +1,3 @@
//go:build !rpctest
// +build !rpctest
package lncfg
import (

View file

@ -1,5 +1,4 @@
//go:build !rpctest
// +build !rpctest
//go:build !integration
package lncfg

View file

@ -1,5 +1,4 @@
//go:build rpctest
// +build rpctest
//go:build integration
package lncfg
@ -7,6 +6,8 @@ package lncfg
// compatibility of protocol additions, while defaulting to the latest within
// lnd, or to enable experimental protocol changes.
//
// TODO(yy): delete this build flag to unify with `lncfg/protocol.go`.
//
//nolint:lll
type ProtocolOptions struct {
// LegacyProtocol is a sub-config that houses all the legacy protocol

View file

@ -1,140 +0,0 @@
package lntemp
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"sync"
"testing"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/stretchr/testify/require"
)
// WebFeeService defines an interface that's used to provide fee estimation
// service used in the integration tests. It must provide an URL so that a lnd
// node can be started with the flag `--feeurl` and uses the customized fee
// estimator.
type WebFeeService interface {
// Start starts the service.
Start() error
// Stop stops the service.
Stop() error
// URL returns the service's endpoint.
URL() string
// SetFeeRate sets the estimated fee rate for a given confirmation
// target.
SetFeeRate(feeRate chainfee.SatPerKWeight, conf uint32)
}
const (
// feeServiceTarget is the confirmation target for which a fee estimate
// is returned. Requests for higher confirmation targets will fall back
// to this.
feeServiceTarget = 1
// DefaultFeeRateSatPerKw specifies the default fee rate used in the
// tests.
DefaultFeeRateSatPerKw = 12500
)
// FeeService runs a web service that provides fee estimation information.
type FeeService struct {
*testing.T
feeRateMap map[uint32]uint32
url string
srv *http.Server
wg sync.WaitGroup
lock sync.Mutex
}
// Compile-time check for the WebFeeService interface.
var _ WebFeeService = (*FeeService)(nil)
// Start spins up a go-routine to serve fee estimates.
func NewFeeService(t *testing.T) *FeeService {
port := lntest.NextAvailablePort()
f := FeeService{
T: t,
url: fmt.Sprintf(
"http://localhost:%v/fee-estimates.json", port,
),
}
// Initialize default fee estimate.
f.feeRateMap = map[uint32]uint32{
feeServiceTarget: DefaultFeeRateSatPerKw,
}
listenAddr := fmt.Sprintf(":%v", port)
mux := http.NewServeMux()
mux.HandleFunc("/fee-estimates.json", f.handleRequest)
f.srv = &http.Server{
Addr: listenAddr,
Handler: mux,
}
return &f
}
// Start starts the web server.
func (f *FeeService) Start() error {
f.wg.Add(1)
go func() {
defer f.wg.Done()
if err := f.srv.ListenAndServe(); err != http.ErrServerClosed {
require.NoErrorf(f, err, "cannot start fee api")
}
}()
return nil
}
// handleRequest handles a client request for fee estimates.
func (f *FeeService) handleRequest(w http.ResponseWriter, r *http.Request) {
f.lock.Lock()
defer f.lock.Unlock()
bytes, err := json.Marshal(
struct {
Fees map[uint32]uint32 `json:"fee_by_block_target"`
}{
Fees: f.feeRateMap,
},
)
require.NoErrorf(f, err, "cannot serialize estimates")
_, err = io.WriteString(w, string(bytes))
require.NoError(f, err, "cannot send estimates")
}
// Stop stops the web server.
func (f *FeeService) Stop() error {
err := f.srv.Shutdown(context.Background())
require.NoError(f, err, "cannot stop fee api")
f.wg.Wait()
return nil
}
// SetFeeRate sets a fee for the given confirmation target.
func (f *FeeService) SetFeeRate(fee chainfee.SatPerKWeight, conf uint32) {
f.lock.Lock()
defer f.lock.Unlock()
f.feeRateMap[conf] = uint32(fee.FeePerKVByte())
}
// URL returns the service endpoint.
func (f *FeeService) URL() string {
return f.url
}

View file

@ -1,438 +0,0 @@
package lntemp
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"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"
"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
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
runCtx context.Context
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 {
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 {
handler := &rpcclient.NotificationHandlers{}
btcdBinary := lntest.GetBtcdBinary()
baseLogPath := fmt.Sprintf("%s/%s", lntest.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 := ioutil.ReadDir(path)
require.NoError(h, err, "unable to read log directory")
for _, file := range files {
newFilename := strings.Replace(
file.Name(), "btcd.log", h.logFilename, 1,
)
copyPath := fmt.Sprintf("%s/../%s", h.logPath, newFilename)
logFile := fmt.Sprintf("%s/%s", path, file.Name())
err := CopyFile(filepath.Clean(copyPath), logFile)
require.NoError(h, err, "unable to copy file")
}
err = os.RemoveAll(h.logPath)
require.NoErrorf(h, err, "cannot remove dir %s", h.logPath)
}
// Stop shuts down the miner and saves its logs.
func (h *HarnessMiner) Stop() {
h.cancel()
require.NoError(h, h.TearDown(), "tear down miner got error")
h.saveLogs()
}
// GetBestBlock makes a RPC request to miner and asserts.
func (h *HarnessMiner) GetBestBlock() (*chainhash.Hash, int32) {
blockHash, height, err := h.Client.GetBestBlock()
require.NoError(h, err, "failed to GetBestBlock")
return blockHash, height
}
// GetRawMempool makes a RPC call to the miner's GetRawMempool and
// asserts.
func (h *HarnessMiner) GetRawMempool() []*chainhash.Hash {
mempool, err := h.Client.GetRawMempool()
require.NoError(h, err, "unable to get mempool")
return mempool
}
// 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)
}, lntest.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)
}, lntest.MinerMempoolTimeout)
require.NoError(h, err, "timeout checking 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 require the RPC call to be succeeded and won't
// wait for it as it's an unexpected behavior.
tx := h.GetRawTransaction(txid)
msgTx = tx.MsgTx()
for _, txIn := range msgTx.TxIn {
if txIn.PreviousOutPoint == op {
return nil
}
}
}
return fmt.Errorf("outpoint %v not found in mempool", op)
}, lntest.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")
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
}

View file

@ -93,3 +93,24 @@ making a new test case using `Subtest`, theres a cleanup function which
further validates the current test case has no dangling uncleaned states, such
as transactions left in mempool, open channels, etc.
### Different Code Used in `lntest`
Since the miner in `lntest` uses regtest, it has a very fast block production
rate, which is the greatest difference between the conditions it simulates and
the real-world has. Aside from that, `lnd` has several places that use
different code, which is triggered by the build flag `integration`, to speed up
the tests. They are summarized as followings,
1. `funding.checkPeerFundingLockInterval`, which is used when we wait for the
peer to send us `FundingLocked`. This value is 1 second in `lnd`, and 10
milliseconds in `lntest`.
2. `lncfg.ProtocolOptions`, which is used to specify protocol flags. In `lnd`,
anchor and script enforced lease are enabled by default, while in `lntest`,
they are disabled by default.
3. Reduced scrypt parameters are used in `lntest`. In `lnd`, the parameters N,
R, and P are imported from `snacl`, while in `lntest` they are replaced with
`waddrmgr.FastScryptOptions`. Both `macaroon` and `aezeed` are affected.
4. The method, `nextRevocationProducer`, defined in `LightningWallet` is
slightly different. For `lnwallet`, it will check a special pre-defined
channel ID to test restoring channel backups created with the old revocation
root derivation method.

View file

@ -14,6 +14,7 @@ import (
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/rpcclient"
"github.com/lightningnetwork/lnd/lntest/node"
)
// logDirPattern is the pattern of the name of the temporary log directory.
@ -37,7 +38,7 @@ type BitcoindBackendConfig struct {
// A compile time assertion to ensure BitcoindBackendConfig meets the
// BackendConfig interface.
var _ BackendConfig = (*BitcoindBackendConfig)(nil)
var _ node.BackendConfig = (*BitcoindBackendConfig)(nil)
// GenArgs returns the arguments needed to be passed to LND at startup for
// using this node as a chain backend.
@ -89,7 +90,7 @@ func (b BitcoindBackendConfig) Name() string {
func newBackend(miner string, netParams *chaincfg.Params, extraArgs []string,
rpcPolling bool) (*BitcoindBackendConfig, func() error, error) {
baseLogDir := fmt.Sprintf(logDirPattern, GetLogDir())
baseLogDir := fmt.Sprintf(logDirPattern, node.GetLogDir())
if netParams != &chaincfg.RegressionNetParams {
return nil, nil, fmt.Errorf("only regtest supported")
}
@ -109,10 +110,12 @@ func newBackend(miner string, netParams *chaincfg.Params, extraArgs []string,
fmt.Errorf("unable to create temp directory: %v", err)
}
zmqBlockAddr := fmt.Sprintf("tcp://127.0.0.1:%d", NextAvailablePort())
zmqTxAddr := fmt.Sprintf("tcp://127.0.0.1:%d", NextAvailablePort())
rpcPort := NextAvailablePort()
p2pPort := NextAvailablePort()
zmqBlockAddr := fmt.Sprintf("tcp://127.0.0.1:%d",
node.NextAvailablePort())
zmqTxAddr := fmt.Sprintf("tcp://127.0.0.1:%d",
node.NextAvailablePort())
rpcPort := node.NextAvailablePort()
p2pPort := node.NextAvailablePort()
cmdArgs := []string{
"-datadir=" + tempBitcoindDir,
@ -146,9 +149,9 @@ func newBackend(miner string, netParams *chaincfg.Params, extraArgs []string,
// After shutting down the chain backend, we'll make a copy of
// the log file before deleting the temporary log dir.
logDestination := fmt.Sprintf(
"%s/output_bitcoind_chainbackend.log", GetLogDir(),
"%s/output_bitcoind_chainbackend.log", node.GetLogDir(),
)
err := CopyFile(logDestination, logFile)
err := node.CopyFile(logDestination, logFile)
if err != nil {
errStr += fmt.Sprintf("unable to copy file: %v\n", err)
}

View file

@ -15,6 +15,7 @@ import (
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/integration/rpctest"
"github.com/btcsuite/btcd/rpcclient"
"github.com/lightningnetwork/lnd/lntest/node"
)
// logDirPattern is the pattern of the name of the temporary log directory.
@ -41,7 +42,7 @@ type BtcdBackendConfig struct {
// A compile time assertion to ensure BtcdBackendConfig meets the BackendConfig
// interface.
var _ BackendConfig = (*BtcdBackendConfig)(nil)
var _ node.BackendConfig = (*BtcdBackendConfig)(nil)
// GenArgs returns the arguments needed to be passed to LND at startup for
// using this node as a chain backend.
@ -83,7 +84,7 @@ func (b BtcdBackendConfig) Name() string {
func NewBackend(miner string, netParams *chaincfg.Params) (
*BtcdBackendConfig, func() error, error) {
baseLogDir := fmt.Sprintf(logDirPattern, GetLogDir())
baseLogDir := fmt.Sprintf(logDirPattern, node.GetLogDir())
args := []string{
"--rejectnonstd",
"--txindex",
@ -98,9 +99,12 @@ func NewBackend(miner string, netParams *chaincfg.Params) (
// Don't disconnect if a reply takes too long.
"--nostalldetect",
}
chainBackend, err := rpctest.New(netParams, nil, args, GetBtcdBinary())
chainBackend, err := rpctest.New(
netParams, nil, args, node.GetBtcdBinary(),
)
if err != nil {
return nil, nil, fmt.Errorf("unable to create btcd node: %v", err)
return nil, nil, fmt.Errorf("unable to create btcd node: %w",
err)
}
// We want to overwrite some of the connection settings to make the
@ -108,11 +112,17 @@ func NewBackend(miner string, netParams *chaincfg.Params) (
// 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.
chainBackend.MaxConnRetries = rpctest.DefaultMaxConnectionRetries * 2
chainBackend.ConnectionRetryTimeout = rpctest.DefaultConnectionRetryTimeout * 2
const (
maxConnRetries = rpctest.DefaultMaxConnectionRetries * 2
connRetryTimeout = rpctest.DefaultConnectionRetryTimeout * 2
)
chainBackend.MaxConnRetries = maxConnRetries
chainBackend.ConnectionRetryTimeout = connRetryTimeout
if err := chainBackend.SetUp(false, 0); err != nil {
return nil, nil, fmt.Errorf("unable to set up btcd backend: %v", err)
return nil, nil, fmt.Errorf("unable to set up btcd backend: %w",
err)
}
bd := &BtcdBackendConfig{
@ -141,14 +151,16 @@ func NewBackend(miner string, netParams *chaincfg.Params) (
for _, file := range files {
logFile := fmt.Sprintf("%s/%s", logDir, file.Name())
newFilename := strings.Replace(
file.Name(), "btcd.log", "output_btcd_chainbackend.log", 1,
file.Name(), "btcd.log",
"output_btcd_chainbackend.log", 1,
)
logDestination := fmt.Sprintf(
"%s/%s", GetLogDir(), newFilename,
"%s/%s", node.GetLogDir(), newFilename,
)
err := CopyFile(logDestination, logFile)
err := node.CopyFile(logDestination, logFile)
if err != nil {
errStr += fmt.Sprintf("unable to copy file: %v\n", err)
errStr += fmt.Sprintf("unable to copy file: "+
"%v\n", err)
}
}

View file

@ -9,45 +9,72 @@ import (
"sync"
"testing"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/stretchr/testify/require"
)
// WebFeeService defines an interface that's used to provide fee estimation
// service used in the integration tests. It must provide an URL so that a lnd
// node can be started with the flag `--feeurl` and uses the customized fee
// estimator.
type WebFeeService interface {
// Start starts the service.
Start() error
// Stop stops the service.
Stop() error
// URL returns the service's endpoint.
URL() string
// SetFeeRate sets the estimated fee rate for a given confirmation
// target.
SetFeeRate(feeRate chainfee.SatPerKWeight, conf uint32)
}
const (
// feeServiceTarget is the confirmation target for which a fee estimate
// is returned. Requests for higher confirmation targets will fall back
// to this.
feeServiceTarget = 1
// DefaultFeeRateSatPerKw specifies the default fee rate used in the
// tests.
DefaultFeeRateSatPerKw = 12500
)
// feeService runs a web service that provides fee estimation information.
type feeService struct {
feeEstimates
// FeeService runs a web service that provides fee estimation information.
type FeeService struct {
*testing.T
t *testing.T
srv *http.Server
wg sync.WaitGroup
url string
feeRateMap map[uint32]uint32
url string
srv *http.Server
wg sync.WaitGroup
lock sync.Mutex
}
// feeEstimates contains the current fee estimates.
type feeEstimates struct {
Fees map[uint32]uint32 `json:"fee_by_block_target"`
}
// Compile-time check for the WebFeeService interface.
var _ WebFeeService = (*FeeService)(nil)
// startFeeService spins up a go-routine to serve fee estimates.
func startFeeService(t *testing.T) *feeService {
port := NextAvailablePort()
f := feeService{
t: t,
url: fmt.Sprintf("http://localhost:%v/fee-estimates.json", port),
// Start spins up a go-routine to serve fee estimates.
func NewFeeService(t *testing.T) *FeeService {
t.Helper()
port := node.NextAvailablePort()
f := FeeService{
T: t,
url: fmt.Sprintf(
"http://localhost:%v/fee-estimates.json", port,
),
}
// Initialize default fee estimate.
f.Fees = map[uint32]uint32{feeServiceTarget: 50000}
f.feeRateMap = map[uint32]uint32{
feeServiceTarget: DefaultFeeRateSatPerKw,
}
listenAddr := fmt.Sprintf(":%v", port)
mux := http.NewServeMux()
@ -58,57 +85,60 @@ func startFeeService(t *testing.T) *feeService {
Handler: mux,
}
return &f
}
// Start starts the web server.
func (f *FeeService) Start() error {
f.wg.Add(1)
go func() {
defer f.wg.Done()
if err := f.srv.ListenAndServe(); err != http.ErrServerClosed {
f.t.Errorf("error: cannot start fee api: %v", err)
require.NoErrorf(f, err, "cannot start fee api")
}
}()
return &f
return nil
}
// handleRequest handles a client request for fee estimates.
func (f *feeService) handleRequest(w http.ResponseWriter, r *http.Request) {
func (f *FeeService) handleRequest(w http.ResponseWriter, r *http.Request) {
f.lock.Lock()
defer f.lock.Unlock()
bytes, err := json.Marshal(f.feeEstimates)
if err != nil {
f.t.Errorf("error: cannot serialize estimates: %v", err)
return
}
bytes, err := json.Marshal(
struct {
Fees map[uint32]uint32 `json:"fee_by_block_target"`
}{
Fees: f.feeRateMap,
},
)
require.NoErrorf(f, err, "cannot serialize estimates")
_, err = io.WriteString(w, string(bytes))
if err != nil {
f.t.Errorf("error: cannot send estimates: %v", err)
}
require.NoError(f, err, "cannot send estimates")
}
// stop stops the web server.
func (f *feeService) stop() {
if err := f.srv.Shutdown(context.Background()); err != nil {
f.t.Errorf("error: cannot stop fee api: %v", err)
}
// Stop stops the web server.
func (f *FeeService) Stop() error {
err := f.srv.Shutdown(context.Background())
require.NoError(f, err, "cannot stop fee api")
f.wg.Wait()
return nil
}
// setFee changes the current fee estimate for the fixed confirmation target.
func (f *feeService) setFee(fee chainfee.SatPerKWeight) {
// SetFeeRate sets a fee for the given confirmation target.
func (f *FeeService) SetFeeRate(fee chainfee.SatPerKWeight, conf uint32) {
f.lock.Lock()
defer f.lock.Unlock()
f.Fees[feeServiceTarget] = uint32(fee.FeePerKVByte())
f.feeRateMap[conf] = uint32(fee.FeePerKVByte())
}
// setFeeWithConf sets a fee for the given confirmation target.
func (f *feeService) setFeeWithConf(fee chainfee.SatPerKWeight, conf uint32) {
f.lock.Lock()
defer f.lock.Unlock()
f.Fees[conf] = uint32(fee.FeePerKVByte())
// URL returns the service endpoint.
func (f *FeeService) URL() string {
return f.url
}

View file

@ -1,39 +0,0 @@
package lntest
import (
"io/ioutil"
"net/http"
"testing"
"time"
"github.com/stretchr/testify/require"
)
// TestFeeService tests the itest fee estimating web service.
func TestFeeService(t *testing.T) {
service := startFeeService(t)
defer service.stop()
service.setFee(5000)
// Wait for service to start accepting connections.
var resp *http.Response
require.Eventually(
t,
func() bool {
var err error
resp, err = http.Get(service.url) // nolint:bodyclose
return err == nil
},
10*time.Second, time.Second,
)
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
require.NoError(t, err)
require.Equal(
t, "{\"fee_by_block_target\":{\"1\":20000}}", string(body),
)
}

View file

@ -1,4 +1,4 @@
package lntemp
package lntest
import (
"context"
@ -17,9 +17,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntemp/rpc"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/rpc"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/lnwire"
@ -38,6 +37,10 @@ const (
// numBlocksOpenChannel specifies the number of blocks mined when
// opening a channel.
numBlocksOpenChannel = 6
// lndErrorChanSize specifies the buffer size used to receive errors
// from lnd process.
lndErrorChanSize = 10
)
// TestCase defines a test case that's been used in the integration test.
@ -85,7 +88,7 @@ type HarnessTest struct {
// 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
runCtx context.Context //nolint:containedctx
cancel context.CancelFunc
// stopChainBackend points to the cleanup function returned by the
@ -100,12 +103,15 @@ type HarnessTest struct {
// NewHarnessTest creates a new instance of a harnessTest from a regular
// testing.T instance.
func NewHarnessTest(t *testing.T, lndBinary string, feeService WebFeeService,
dbBackend lntest.DatabaseBackend) *HarnessTest {
dbBackend node.DatabaseBackend) *HarnessTest {
t.Helper()
// Create the run context.
ctxt, cancel := context.WithCancel(context.Background())
manager := newNodeManager(lndBinary, dbBackend)
return &HarnessTest{
T: t,
manager: manager,
@ -114,7 +120,7 @@ func NewHarnessTest(t *testing.T, lndBinary string, feeService WebFeeService,
cancel: cancel,
// We need to use buffered channel here as we don't want to
// block sending errors.
lndErrorChan: make(chan error, 10),
lndErrorChan: make(chan error, lndErrorChanSize),
}
}
@ -180,21 +186,18 @@ func (h *HarnessTest) SetupStandbyNodes() {
h.Alice = h.NewNode("Alice", lndArgs)
h.Bob = h.NewNode("Bob", lndArgs)
// First, make a connection between the two nodes. This will wait until
// both nodes are fully started since the Connect RPC is guarded behind
// the server.Started() flag that waits for all subsystems to be ready.
h.ConnectNodes(h.Alice, h.Bob)
addrReq := &lnrpc.NewAddressRequest{
Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH,
}
// Load up the wallets of the seeder nodes with 10 outputs of 10 BTC
const initialFund = 1 * btcutil.SatoshiPerBitcoin
// Load up the wallets of the seeder nodes with 100 outputs of 1 BTC
// each.
nodes := []*node.HarnessNode{h.Alice, h.Bob}
for _, hn := range nodes {
h.manager.standbyNodes[hn.Cfg.NodeID] = hn
for i := 0; i < 10; i++ {
for i := 0; i < 100; i++ {
resp := hn.RPC.NewAddress(addrReq)
addr, err := btcutil.DecodeAddress(
@ -207,7 +210,7 @@ func (h *HarnessTest) SetupStandbyNodes() {
output := &wire.TxOut{
PkScript: addrScript,
Value: 10 * btcutil.SatoshiPerBitcoin,
Value: initialFund,
}
h.Miner.SendOutput(output, defaultMinerFeeRate)
}
@ -215,7 +218,7 @@ func (h *HarnessTest) SetupStandbyNodes() {
// We generate several blocks in order to give the outputs created
// above a good number of confirmations.
const totalTxes = 20
const totalTxes = 200
h.MineBlocksAndAssertNumTxes(numBlocksSendOutput, totalTxes)
// Now we want to wait for the nodes to catch up.
@ -223,7 +226,7 @@ func (h *HarnessTest) SetupStandbyNodes() {
h.WaitForBlockchainSync(h.Bob)
// Now block until both wallets have fully synced up.
expectedBalance := int64(btcutil.SatoshiPerBitcoin * 100)
const expectedBalance = 100 * initialFund
err := wait.NoError(func() error {
aliceResp := h.Alice.RPC.WalletBalance()
bobResp := h.Bob.RPC.WalletBalance()
@ -286,6 +289,8 @@ func (h *HarnessTest) RunTestCase(testCase *TestCase) {
// resetStandbyNodes resets all standby nodes by attaching the new testing.T
// and restarting them with the original config.
func (h *HarnessTest) resetStandbyNodes(t *testing.T) {
t.Helper()
for _, hn := range h.manager.standbyNodes {
// Inherit the testing.T.
h.T = t
@ -313,7 +318,7 @@ func (h *HarnessTest) Subtest(t *testing.T) *HarnessTest {
Miner: h.Miner,
standbyNodes: h.standbyNodes,
feeService: h.feeService,
lndErrorChan: make(chan error, 10),
lndErrorChan: make(chan error, lndErrorChanSize),
}
// Inherit context from the main test.
@ -341,6 +346,7 @@ func (h *HarnessTest) Subtest(t *testing.T) *HarnessTest {
// Don't bother run the cleanups if the test is failed.
if st.Failed() {
st.Log("test failed, skipped cleanup")
st.shutdownAllNodes()
return
}
@ -381,10 +387,21 @@ func (h *HarnessTest) Subtest(t *testing.T) *HarnessTest {
// shutdownNonStandbyNodes will shutdown any non-standby nodes.
func (h *HarnessTest) shutdownNonStandbyNodes() {
h.shutdownNodes(true)
}
// shutdownAllNodes will shutdown all running nodes.
func (h *HarnessTest) shutdownAllNodes() {
h.shutdownNodes(false)
}
// shutdownNodes will shutdown any non-standby nodes. If skipStandby is false,
// all the standby nodes will be shutdown too.
func (h *HarnessTest) shutdownNodes(skipStandby bool) {
for nid, node := range h.manager.activeNodes {
// If it's a standby node, skip.
_, ok := h.manager.standbyNodes[nid]
if ok {
if ok && skipStandby {
continue
}
@ -394,7 +411,11 @@ func (h *HarnessTest) shutdownNonStandbyNodes() {
err := wait.NoError(func() error {
return h.manager.shutdownNode(node)
}, DefaultTimeout)
require.NoErrorf(h, err, "unable to shutdown %s", node.Name())
// Instead of returning the error, we will log it instead. This
// is needed so other nodes can continue their shutdown
// processes.
h.Logf("unable to shutdown %s, got err: %v", node.Name(), err)
}
}
@ -636,7 +657,7 @@ func (h *HarnessTest) NewNodeEtcd(name string, etcdCfg *etcd.Config,
leaderSessionTTL int) *node.HarnessNode {
// We don't want to use the embedded etcd instance.
h.manager.dbBackend = lntest.BackendBbolt
h.manager.dbBackend = node.BackendBbolt
extraArgs := node.ExtraArgsEtcd(
etcdCfg, name, cluster, leaderSessionTTL,
@ -659,7 +680,7 @@ func (h *HarnessTest) NewNodeWithSeedEtcd(name string, etcdCfg *etcd.Config,
leaderSessionTTL int) (*node.HarnessNode, []string, []byte) {
// We don't want to use the embedded etcd instance.
h.manager.dbBackend = lntest.BackendBbolt
h.manager.dbBackend = node.BackendBbolt
// Create a request to generate a new aezeed. The new seed will have
// the same password as the internal wallet.
@ -1082,7 +1103,19 @@ func (h *HarnessTest) CloseChannelAssertPending(hn *node.HarnessNode,
// transaction to be broadcast, then wait for the closing tx to be seen
// within the network.
event, err := h.ReceiveCloseChannelUpdate(stream)
require.NoError(h, err)
if err != nil {
// TODO(yy): remove the sleep once the following bug is fixed.
// We may receive the error `cannot co-op close channel with
// active htlcs` or `link failed to shutdown` if we close the
// channel. We need to investigate the order of settling the
// payments and updating commitments to properly fix it.
time.Sleep(2 * time.Second)
// Give it another chance.
stream = hn.RPC.CloseChannel(closeReq)
event, err = h.ReceiveCloseChannelUpdate(stream)
require.NoError(h, err)
}
pendingClose, ok := event.Update.(*lnrpc.CloseStatusUpdate_ClosePending)
require.Truef(h, ok, "expected channel close update, instead got %v",
@ -1277,7 +1310,7 @@ func (h *HarnessTest) completePaymentRequestsAssertStatus(hn *node.HarnessNode,
send := func(payReq string) {
req := &routerrpc.SendPaymentRequest{
PaymentRequest: payReq,
TimeoutSeconds: defaultPaymentTimeout,
TimeoutSeconds: int32(wait.PaymentTimeout.Seconds()),
FeeLimitMsat: noFeeLimitMsat,
}
stream := hn.RPC.SendPayment(req)
@ -1293,7 +1326,7 @@ func (h *HarnessTest) completePaymentRequestsAssertStatus(hn *node.HarnessNode,
}
// Wait for all payments to report the expected status.
timer := time.After(DefaultTimeout)
timer := time.After(wait.PaymentTimeout)
select {
case stream := <-results:
h.AssertPaymentStatusFromStream(stream, status)
@ -1402,7 +1435,7 @@ func (h *HarnessTest) CleanupForceClose(hn *node.HarnessNode,
//
// The commit sweep resolver is able to broadcast the sweep tx up to
// one block before the CSV elapses, so wait until defaulCSV-1.
h.MineBlocks(lntest.DefaultCSV - 1)
h.MineBlocks(node.DefaultCSV - 1)
// The node should now sweep the funds, clean up by mining the sweeping
// tx.
@ -1686,7 +1719,7 @@ func (h *HarnessTest) OpenMultiChannelsAsync(
case cp := <-r.result:
channelPoints = append(channelPoints, cp)
case <-time.After(lntest.ChannelOpenTimeout):
case <-time.After(wait.ChannelOpenTimeout):
require.Failf(h, "timeout", "wait channel point "+
"timeout for channel %s=>%s", r.Local.Name(),
r.Remote.Name())

View file

@ -1,4 +1,4 @@
package lntemp
package lntest
import (
"bytes"
@ -23,8 +23,8 @@ import (
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntemp/rpc"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/rpc"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/stretchr/testify/require"
@ -38,6 +38,7 @@ func (h *HarnessTest) WaitForBlockchainSync(hn *node.HarnessNode) {
if resp.SyncedToChain {
return nil
}
return fmt.Errorf("%s is not synced to chain", hn.Name())
}, DefaultTimeout)
@ -145,6 +146,12 @@ func (h *HarnessTest) EnsureConnected(a, b *node.HarnessNode) {
// connected to the peer.
errConnectionRequested := "connection request in progress"
// windowsErr is an error we've seen from windows build where
// connecting to an already connected node gives such error from the
// receiver side.
windowsErr := "An established connection was aborted by the software " +
"in your host machine."
tryConnect := func(a, b *node.HarnessNode) error {
bInfo := b.RPC.GetInfo()
@ -165,17 +172,21 @@ func (h *HarnessTest) EnsureConnected(a, b *node.HarnessNode) {
return nil
}
// If the connection is in process, we return no error.
if strings.Contains(err.Error(), errConnectionRequested) {
return nil
}
// If the two are already connected, we return early with no
// error.
if strings.Contains(err.Error(), "already connected to peer") {
return nil
}
// Otherwise we log the error to console.
h.Logf("EnsureConnected %s=>%s got err: %v", a.Name(),
b.Name(), err)
// If the connection is in process, we return no error.
if strings.Contains(err.Error(), errConnectionRequested) {
return nil
}
// We may get connection refused error if we happens to be in
// the middle of a previous node disconnection, e.g., a restart
// from one of the nodes.
@ -183,6 +194,16 @@ func (h *HarnessTest) EnsureConnected(a, b *node.HarnessNode) {
return nil
}
// Check for windows error. If Alice connects to Bob, Alice
// will throw "i/o timeout" and Bob will give windowsErr.
if strings.Contains(err.Error(), windowsErr) {
return nil
}
if strings.Contains(err.Error(), "i/o timeout") {
return nil
}
return err
}
@ -231,8 +252,10 @@ func (h *HarnessTest) AssertNumEdges(hn *node.HarnessNode,
// slice.
edges = chanGraph.Edges[old:]
}
return nil
}
return errNumNotMatched(hn.Name(), "num of channel edges",
expected, total-old, total, old)
}, DefaultTimeout)
@ -925,7 +948,9 @@ func (h *HarnessTest) AssertNodesNumPendingOpenChannels(a, b *node.HarnessNode,
func (h *HarnessTest) AssertPaymentStatusFromStream(stream rpc.PaymentClient,
status lnrpc.Payment_PaymentStatus) *lnrpc.Payment {
return h.assertPaymentStatusWithTimeout(stream, status, DefaultTimeout)
return h.assertPaymentStatusWithTimeout(
stream, status, wait.PaymentTimeout,
)
}
// AssertPaymentSucceedWithTimeout asserts that a payment is succeeded within
@ -1166,7 +1191,9 @@ func (h *HarnessTest) AssertActiveHtlcs(hn *node.HarnessNode,
h := hex.EncodeToString(htlc.HashLock)
_, ok := htlcHashes[h]
if ok {
return fmt.Errorf("duplicate HashLock")
return fmt.Errorf("duplicate HashLock "+
"in PendingHtlcs: %v",
ch.PendingHtlcs)
}
htlcHashes[h] = struct{}{}
}
@ -1732,7 +1759,8 @@ func (h *HarnessTest) AssertNumPayments(hn *node.HarnessNode,
return errNumNotMatched(hn.Name(), "num of payments",
num, len(payments), have+len(payments), have)
}, DefaultTimeout)
require.NoError(h, err, "timeout checking num of payments")
require.NoError(h, err, "%s: timeout checking num of payments",
hn.Name())
return payments
}
@ -1745,7 +1773,8 @@ func (h *HarnessTest) AssertNumNodeAnns(hn *node.HarnessNode,
// We will get the current number of channel updates first and add it
// to our expected number of newly created channel updates.
anns, err := hn.Watcher.WaitForNumNodeUpdates(pubkey, num)
require.NoError(h, err, "failed to assert num of channel updates")
require.NoError(h, err, "%s: failed to assert num of node anns",
hn.Name())
return anns
}
@ -1757,7 +1786,8 @@ func (h *HarnessTest) AssertNumChannelUpdates(hn *node.HarnessNode,
op := h.OutPointFromChannelPoint(chanPoint)
err := hn.Watcher.WaitForNumChannelUpdates(op, num)
require.NoError(h, err, "failed to assert num of channel updates")
require.NoError(h, err, "%s: failed to assert num of channel updates",
hn.Name())
}
// CreateBurnAddr creates a random burn address of the given type.

View file

@ -1,18 +1,26 @@
package lntest
import (
"bytes"
"context"
"fmt"
"io/ioutil"
"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 (
@ -21,16 +29,21 @@ const (
// 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
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
runCtx context.Context
// children contexts for RPC requests.
runCtx context.Context //nolint:containedctx
cancel context.CancelFunc
// logPath is the directory path of the miner's logs.
@ -42,21 +55,30 @@ type HarnessMiner struct {
// NewMiner creates a new miner using btcd backend with the default log file
// dir and name.
func NewMiner() (*HarnessMiner, error) {
return newMiner(minerLogDir, minerLogFilename)
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(tempDir, tempLogFilename string) (*HarnessMiner, error) {
return newMiner(tempDir, tempLogFilename)
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(minerDirName, logFilename string) (*HarnessMiner, error) {
func newMiner(ctxb context.Context, t *testing.T, minerDirName,
logFilename string) *HarnessMiner {
t.Helper()
handler := &rpcclient.NotificationHandlers{}
btcdBinary := GetBtcdBinary()
baseLogPath := fmt.Sprintf("%s/%s", GetLogDir(), minerDirName)
btcdBinary := node.GetBtcdBinary()
baseLogPath := fmt.Sprintf("%s/%s", node.GetLogDir(), minerDirName)
args := []string{
"--rejectnonstd",
@ -71,42 +93,28 @@ func newMiner(minerDirName, logFilename string) (*HarnessMiner, error) {
}
miner, err := rpctest.New(harnessNetParams, handler, args, btcdBinary)
if err != nil {
return nil, fmt.Errorf("unable to create mining node: %v", err)
}
require.NoError(t, err, "unable to create mining node")
ctxt, cancel := context.WithCancel(context.Background())
m := &HarnessMiner{
ctxt, cancel := context.WithCancel(ctxb)
return &HarnessMiner{
T: t,
Harness: miner,
runCtx: ctxt,
cancel: cancel,
logPath: baseLogPath,
logFilename: logFilename,
}
return m, nil
}
// Stop shuts down the miner and saves its logs.
func (h *HarnessMiner) Stop() error {
h.cancel()
if err := h.TearDown(); err != nil {
return fmt.Errorf("tear down miner got error: %s", err)
}
return h.saveLogs()
}
// saveLogs copies the node logs and save it to the file specified by
// h.logFilename.
func (h *HarnessMiner) saveLogs() error {
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 := ioutil.ReadDir(path)
if err != nil {
return fmt.Errorf("unable to read log directory: %v", err)
}
require.NoError(h, err, "unable to read log directory")
for _, file := range files {
newFilename := strings.Replace(
@ -116,46 +124,332 @@ func (h *HarnessMiner) saveLogs() error {
logFile := fmt.Sprintf("%s/%s", path, file.Name())
err := CopyFile(filepath.Clean(copyPath), logFile)
if err != nil {
return fmt.Errorf("unable to copy file: %v", err)
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
}
}
if err = os.RemoveAll(h.logPath); err != nil {
return fmt.Errorf("cannot remove dir %s: %v", h.logPath, err)
}
return nil
require.Failf(h, "tx was not included in block", "tx:%v, block has:%v",
txid, blockTxes)
}
// waitForTxInMempool blocks until the target txid is seen in the mempool. If
// the transaction isn't seen within the network before the passed timeout,
// then an error is returned.
func (h *HarnessMiner) waitForTxInMempool(txid chainhash.Hash) error {
ticker := time.NewTicker(50 * time.Millisecond)
defer ticker.Stop()
// 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 {
var mempool []*chainhash.Hash
for {
select {
case <-h.runCtx.Done():
return fmt.Errorf("NetworkHarness has been torn down")
case <-time.After(DefaultTimeout):
return fmt.Errorf("wanted %v, found %v txs "+
"in mempool: %v", txid, len(mempool), mempool)
// 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)
case <-ticker.C:
var err error
mempool, err = h.Client.GetRawMempool()
// 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
}
// 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.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
}
for _, mempoolTx := range mempool {
if *mempoolTx == txid {
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")
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
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
package lntemp
package lntest
import (
"context"
@ -8,8 +8,7 @@ import (
"testing"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp/node"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/lightningnetwork/lnd/lntest/wait"
)
@ -30,7 +29,7 @@ type nodeManager struct {
lndBinary string
// dbBackend sets the database backend to use.
dbBackend lntest.DatabaseBackend
dbBackend node.DatabaseBackend
// activeNodes is a map of all running nodes, format:
// {pubkey: *HarnessNode}.
@ -50,7 +49,7 @@ type nodeManager struct {
// newNodeManager creates a new node manager instance.
func newNodeManager(lndBinary string,
dbBackend lntest.DatabaseBackend) *nodeManager {
dbBackend node.DatabaseBackend) *nodeManager {
return &nodeManager{
lndBinary: lndBinary,
@ -80,7 +79,7 @@ func (nm *nodeManager) newNode(t *testing.T, name string, extraArgs []string,
BackendCfg: nm.chainBackend,
ExtraArgs: extraArgs,
FeeURL: nm.feeServiceURL,
DbBackend: nm.dbBackend,
DBBackend: nm.dbBackend,
NodeID: nm.nextNodeID(),
LndBinary: nm.lndBinary,
NetParams: harnessNetParams,

View file

@ -1,4 +1,4 @@
package lntemp
package lntest
import (
"context"
@ -6,7 +6,7 @@ import (
"testing"
"github.com/btcsuite/btcd/integration/rpctest"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/node"
"github.com/stretchr/testify/require"
)
@ -23,11 +23,11 @@ func SetupHarness(t *testing.T, binaryPath, dbBackendName string,
t.Log("Setting up HarnessTest...")
// Parse testing flags that influence our test execution.
logDir := lntest.GetLogDir()
logDir := node.GetLogDir()
require.NoError(t, os.MkdirAll(logDir, 0700), "create log dir failed")
// Parse database backend
dbBackend := prepareDbBackend(t, dbBackendName)
dbBackend := prepareDBBackend(t, dbBackendName)
// Create a new HarnessTest.
ht := NewHarnessTest(t, binaryPath, feeService, dbBackend)
@ -82,9 +82,9 @@ func prepareMiner(ctxt context.Context, t *testing.T) *HarnessMiner {
// prepareChainBackend creates a new chain backend.
func prepareChainBackend(t *testing.T,
minerAddr string) (lntest.BackendConfig, func()) {
minerAddr string) (node.BackendConfig, func()) {
chainBackend, cleanUp, err := lntest.NewBackend(
chainBackend, cleanUp, err := NewBackend(
minerAddr, harnessNetParams,
)
require.NoError(t, err, "new backend")
@ -94,23 +94,23 @@ func prepareChainBackend(t *testing.T,
}
}
// prepareDbBackend parses a DatabaseBackend based on the name given.
func prepareDbBackend(t *testing.T,
dbBackendName string) lntest.DatabaseBackend {
// prepareDBBackend parses a DatabaseBackend based on the name given.
func prepareDBBackend(t *testing.T,
dbBackendName string) node.DatabaseBackend {
var dbBackend lntest.DatabaseBackend
var dbBackend node.DatabaseBackend
switch dbBackendName {
case "bbolt":
dbBackend = lntest.BackendBbolt
dbBackend = node.BackendBbolt
case "etcd":
dbBackend = lntest.BackendEtcd
dbBackend = node.BackendEtcd
case "postgres":
dbBackend = lntest.BackendPostgres
dbBackend = node.BackendPostgres
case "sqlite":
dbBackend = lntest.BackendSqlite
dbBackend = node.BackendSqlite
default:
require.Fail(t, "unknown db backend")

File diff suppressed because it is too large Load diff

View file

@ -1,9 +0,0 @@
//go:build !rpctest
// +build !rpctest
package itest
import "github.com/lightningnetwork/lnd/lntemp"
// TODO(yy): remove the temp.
var allTestCasesTemp = []*lntemp.TestCase{}

View file

@ -1,241 +0,0 @@
package itest
import (
"flag"
"fmt"
"os"
"strings"
"testing"
"time"
"github.com/btcsuite/btcd/integration/rpctest"
"github.com/lightningnetwork/lnd/lntest"
"github.com/stretchr/testify/require"
)
var (
// tempTest is a flag used to mark whether we should run the old or the
// new test cases. Used here so we can transit smoothly during our new
// itest construction.
//
// TODO(yy): remove temp flag.
tempTest = flag.Bool("temptest", false, "run the new tests(temp)")
)
// getTestCaseSplitTranche returns the sub slice of the test cases that should
// be run as the current split tranche as well as the index and slice offset of
// the tranche.
func getTestCaseSplitTrancheOld() ([]*testCase, uint, uint) {
numTranches := defaultSplitTranches
if testCasesSplitTranches != nil {
numTranches = *testCasesSplitTranches
}
runTranche := defaultRunTranche
if testCasesRunTranche != nil {
runTranche = *testCasesRunTranche
}
// There's a special flake-hunt mode where we run the same test multiple
// times in parallel. In that case the tranche index is equal to the
// thread ID, but we need to actually run all tests for the regex
// selection to work.
threadID := runTranche
if numTranches == 1 {
runTranche = 0
}
numCases := uint(len(allTestCases))
testsPerTranche := numCases / numTranches
trancheOffset := runTranche * testsPerTranche
trancheEnd := trancheOffset + testsPerTranche
if trancheEnd > numCases || runTranche == numTranches-1 {
trancheEnd = numCases
}
return allTestCases[trancheOffset:trancheEnd], threadID, trancheOffset
}
// TestLightningNetworkDaemon performs a series of integration tests amongst a
// programmatically driven network of lnd nodes.
func TestLightningNetworkDaemon(t *testing.T) {
if *tempTest {
t.Skip("Running new tests, old tests are skipped")
}
// If no tests are registered, then we can exit early.
if len(allTestCases) == 0 {
t.Skip("integration tests not selected with flag 'rpctest'")
}
// Parse testing flags that influence our test execution.
logDir := lntest.GetLogDir()
require.NoError(t, os.MkdirAll(logDir, 0700))
testCases, trancheIndex, trancheOffset := getTestCaseSplitTrancheOld()
lntest.ApplyPortOffset(uint32(trancheIndex) * 1000)
// Before we start any node, we need to make sure that any btcd node
// that is started through the RPC harness uses a unique port as well to
// avoid any port collisions.
rpctest.ListenAddressGenerator = lntest.GenerateBtcdListenerAddresses
// Declare the network harness here to gain access to its
// 'OnTxAccepted' call back.
var lndHarness *lntest.NetworkHarness
// Create an instance of the btcd's rpctest.Harness that will act as
// the miner for all tests. This will be used to fund the wallets of
// the nodes within the test network and to drive blockchain related
// events within the network. Revert the default setting of accepting
// non-standard 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.
//
// We will also connect it to our chain backend.
miner, err := lntest.NewMiner()
require.NoError(t, err, "failed to create new miner")
defer func() {
require.NoError(t, miner.Stop(), "failed to stop miner")
}()
// Start a chain backend.
chainBackend, cleanUp, err := lntest.NewBackend(
miner.P2PAddress(), harnessNetParams,
)
require.NoError(t, err, "new backend")
defer func() {
require.NoError(t, cleanUp(), "cleanup")
}()
// 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
// 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, chainBackend.ConnectMiner(), "connect miner")
// Parse database backend
var dbBackend lntest.DatabaseBackend
switch *dbBackendFlag {
case "bbolt":
dbBackend = lntest.BackendBbolt
case "etcd":
dbBackend = lntest.BackendEtcd
case "postgres":
dbBackend = lntest.BackendPostgres
case "sqlite":
dbBackend = lntest.BackendSqlite
default:
require.Fail(t, "unknown db backend")
}
// Now we can set up our test harness (LND instance), with the chain
// backend we just created.
ht := newHarnessTest(t, nil)
binary := ht.getLndBinary()
lndHarness, err = lntest.NewNetworkHarness(
miner, chainBackend, binary, dbBackend,
)
if err != nil {
ht.Fatalf("unable to create lightning network harness: %v", err)
}
defer lndHarness.Stop()
// 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 to
// help debug.
go func() {
for {
select {
case err, more := <-lndHarness.ProcessErrors():
if !more {
return
}
ht.Logf("lnd finished with error (stderr):\n%v",
err)
}
}
}()
// Next mine enough blocks in order for segwit and the CSV package
// soft-fork to activate on SimNet.
numBlocks := harnessNetParams.MinerConfirmationWindow * 2
if _, err := miner.Client.Generate(numBlocks); err != nil {
ht.Fatalf("unable to generate blocks: %v", err)
}
// With the btcd harness created, we can now complete the
// initialization of the network. args - list of lnd arguments,
// example: "--debuglevel=debug"
// TODO(roasbeef): create master balanced channel with all the monies?
aliceBobArgs := []string{
"--default-remote-max-htlcs=483",
"--dust-threshold=5000000",
}
// Run the subset of the test cases selected in this tranche.
for idx, testCase := range testCases {
testCase := testCase
name := fmt.Sprintf("tranche%02d/%02d-of-%d/%s/%s",
trancheIndex, trancheOffset+uint(idx)+1,
len(allTestCases), chainBackend.Name(), testCase.name)
success := t.Run(name, func(t1 *testing.T) {
cleanTestCaseName := strings.ReplaceAll(
testCase.name, " ", "_",
)
err = lndHarness.SetUp(
t1, cleanTestCaseName, aliceBobArgs,
)
require.NoError(t1,
err, "unable to set up test lightning network",
)
defer func() {
require.NoError(t1, lndHarness.TearDown())
}()
lndHarness.EnsureConnected(
t1, lndHarness.Alice, lndHarness.Bob,
)
logLine := fmt.Sprintf(
"STARTING ============ %v ============\n",
testCase.name,
)
lndHarness.Alice.AddToLogf(logLine)
lndHarness.Bob.AddToLogf(logLine)
// Start every test with the default static fee estimate.
lndHarness.SetFeeEstimate(12500)
// Create a separate harness test for the testcase to
// avoid overwriting the external harness test that is
// tied to the parent test.
ht := newHarnessTest(t1, lndHarness)
ht.RunTestCase(testCase)
})
// Stop at the first failure. Mimic behavior of original test
// framework.
if !success {
// Log failure time to help relate the lnd logs to the
// failure.
t.Logf("Failure time: %v", time.Now().Format(
"2006-01-02 15:04:05.000",
))
break
}
}
}

View file

@ -1,6 +0,0 @@
//go:build !rpctest
// +build !rpctest
package itest
var allTestCases = []*testCase{}

View file

@ -1,11 +0,0 @@
//go:build rpctest
// +build rpctest
package itest
var allTestCases = []*testCase{
{
name: "async bidirectional payments",
test: testBidirectionalAsyncPayments,
},
}

View file

@ -1,302 +0,0 @@
<time> [ERR] BRAR: Unable to broadcast justice tx: Transaction rejected: output already spent
<time> [ERR] BRAR: Unable to check for spentness of outpoint=<chan_point>: TxNotifier is exiting
<time> [ERR] BRAR: Unable to register for conf for txid(<hex>): TxNotifier is exiting
<time> [ERR] BRAR: Unable to register for block notifications: chainntnfs: system interrupt while attempting to register for block epoch notification.
<time> [ERR] BTCN: Broadcast attempt failed: rejected by <ip>: replacement transaction <hex> has an insufficient absolute fee: needs <amt>, has <amt>
<time> [ERR] BTCN: Broadcast attempt failed: rejected by <ip>: replacement transaction <hex> has an insufficient fee rate: needs more than <amt>, has <amt>
<time> [ERR] BTCN: Broadcast attempt failed: rejected by <ip>: transaction already exists
<time> [ERR] BTCN: Can't accept connection: unable to accept connection from <ip>: chacha20poly1305: message authentication failed
<time> [ERR] BTCN: Can't accept connection: unable to accept connection from <ip>: EOF
<time> [ERR] BTCN: Can't accept connection: unable to accept connection from <ip>: read tcp <ip>-><ip>: i/o timeout
<time> [ERR] BTCN: Query failed with 0 out of 1 filters received
<time> [ERR] BTCN: unable to get filter for hash=<hex>, retrying: neutrino shutting down
<time> [ERR] BTCN: unable to get filter for hash=<hex>, retrying: unable to fetch cfilter
<time> [ERR] BTCN: Unable to process block connected (height=<height>, hash=<hex>): out of order block <hex>: expected PrevBlock <hex>, got <hex>
<time> [ERR] BTCN: Unknown connid=<id>
<time> [ERR] CHAC: Received an error: rpc error: code = Canceled desc = context canceled, shutting down
<time> [ERR] CHFT: Close channel <chan_point> unknown to store
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to advance state: channel not found
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to broadcast close tx: Transaction rejected: output already spent
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to force close: channel not found
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to mark commitment broadcasted: channel not found
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to progress *contractcourt.commitSweepResolver: remote party swept utxo
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to progress *contractcourt.commitSweepResolver: chainntnfs: system interrupt while attempting to register for block epoch notification.
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to progress *contractcourt.htlcOutgoingContestResolver: chain notifier shutting down
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to progress *contractcourt.htlcOutgoingContestResolver: chainntnfs: system interrupt while attempting to register for block epoch notification.
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to progress *contractcourt.htlcOutgoingContestResolver: resolver canceled
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to progress *contractcourt.htlcOutgoingContestResolver: the client has been shutdown
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to progress *contractcourt.htlcOutgoingContestResolver: unable to create pre-image from witness: invalid preimage length of 33, want 32
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to progress *contractcourt.htlcSuccessResolver: Transaction rejected: output already spent
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to progress *contractcourt.htlcTimeoutResolver: htlcswitch shutting down
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unable to progress *contractcourt.htlcTimeoutResolver: TxNotifier is exiting
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unexpected local commitment confirmed while in StateDefault
<time> [ERR] CNCT: ChannelArbitrator(<chan_point>): unexpected local on-chain channel close
<time> [ERR] CNCT: *contractcourt.commitSweepResolver(<chan_point>): unable to sweep input: remote party swept utxo
<time> [ERR] CNCT: Unable to advance state: channel not found
<time> [ERR] CNCT: unable to hand breached contract off to breachArbiter: server is shutting down
<time> [ERR] CNCT: unable to handle channel breach for chan_point=<chan_point>: server is shutting down
<time> [ERR] CNCT: Unable to handle known remote state: unable to handle channel breach for chan_point=<chan_point>: server is shutting down
<time> [ERR] CRTR: Channel update of ourselves received
<time> [ERR] CRTR: Error collecting result for shard <number> for payment <hex>: shard handler exiting
<time> [ERR] CRTR: Error encountered during rescan: rescan exited
<time> [ERR] CRTR: Failed sending attempt <number> for payment <hex> to switch: could not add downstream htlc
<time> [ERR] CRTR: Failed sending attempt <number> for payment <hex> to switch: insufficient bandwidth to route htlc
<time> [ERR] CRTR: Failed sending attempt <number> for payment <hex> to switch: UnknownNextPeer
<time> [ERR] CRTR: out of order block: expecting height=<height>, got height=<height>
<time> [ERR] CRTR: Payment <hex> failed: error
<time> [ERR] CRTR: Payment <hex> failed: incorrect_payment_details
<time> [ERR] CRTR: Payment <hex> failed: insufficient_balance
<time> [ERR] CRTR: Payment <hex> failed: no_route
<time> [ERR] CRTR: Payment <hex> failed: router shutting down
<time> [ERR] CRTR: Payment <hex> failed: timeout
<time> [ERR] CRTR: Resuming payment <hex> failed: error.
<time> [ERR] CRTR: Resuming payment <hex> failed: incorrect_payment_details.
<time> [ERR] CRTR: Resuming payment <hex> failed: no_route.
<time> [ERR] CRTR: Resuming payment <hex> failed: router shutting down.
<time> [ERR] CRTR: unable to add channel: edge not found
<time> [ERR] CRTR: Unable to retrieve channel by id: edge not found
<time> [ERR] DISC: channel announcement proof for short_chan_id=<cid> isn't valid: can't verify first bitcoin signature
<time> [ERR] DISC: router shutting down
<time> [ERR] DISC: unable add proof to the channel chanID=<hex>: edge marked as zombie
<time> [ERR] DISC: unable add proof to the channel chanID=<hex>: edge not found
<time> [ERR] DISC: unable to add channel: edge not found
<time> [ERR] DISC: Unable to reply to peer query: set tcp <ip>: use of closed network connection
<time> [ERR] DISC: Unable to reply to peer query: write tcp <ip>-><ip>: use of closed network connection
<time> [ERR] DISC: Unable to reply to peer query: write tcp <ip>-><ip>: write: broken pipe
<time> [ERR] DISC: Unable to reply to peer query: write tcp <ip>-><ip>: write: connection reset by peer
<time> [ERR] FNDG: received funding error from <hex>: chan_id=<hex>, err=channel too large
<time> [ERR] FNDG: received funding error from <hex>: chan_id=<hex>, err=chan size of 0.16777216 BTC exceeds maximum chan size of 0.16777215 BTC
<time> [ERR] FNDG: received funding error from <hex>: chan_id=<hex>, err=chan size of 10.00000001 BTC exceeds maximum chan size of 0.16777215 BTC
<time> [ERR] FNDG: received funding error from <hex>: chan_id=<hex>, err=chan size of 10.00000001 BTC exceeds maximum chan size of 10 BTC
<time> [ERR] FNDG: received funding error from <hex>: chan_id=<hex>, err=Number of pending channels exceed maximum
<time> [ERR] FNDG: received funding error from <hex>: chan_id=<hex>, err=Synchronizing blockchain
<time> [ERR] FNDG: received funding error from <hex>: chan_id=<hex>, err=chan size of 0.001 BTC is below min chan size of 0.002 BTC
<time> [ERR] FNDG: received funding error from <hex>: chan_id=<hex>, err=funding failed due to internal error
<time> [ERR] FNDG: Unable to add new channel <chan_point> with peer <hex>: canceled adding new channel
<time> [ERR] FNDG: Unable to add new channel <chan_point> with peer <hex>: peer exiting
<time> [ERR] FNDG: Unable to add new channel <chan_point> with peer <hex>: unable to get best block: the client has been shutdown
<time> [ERR] FNDG: Unable to advance pending state of ChannelPoint(<chan_point>): error waiting for funding confirmation for ChannelPoint(<chan_point>): epoch client shutting down
<time> [ERR] FNDG: Unable to advance pending state of ChannelPoint(<chan_point>): error waiting for funding confirmation for ChannelPoint(<chan_point>): funding manager shutting down
<time> [ERR] FNDG: Unable to advance pending state of ChannelPoint(<chan_point>): error waiting for funding confirmation for ChannelPoint(<chan_point>): waiting for fundingconfirmation failed
<time> [ERR] FNDG: Unable to advance state(<chan_point>): error sending channel announcement: ChainNotifier shutting down, cannot complete funding flow for ChannelPoint(<chan_point>)
<time> [ERR] FNDG: Unable to advance state(<chan_point>): error sending channel announcement: channel announcement failed: channel announcement proof for short_chan_id=<cid> isn't valid: can't verify first bitcoin signature
<time> [ERR] FNDG: Unable to advance state(<chan_point>): error sending channel announcement: channel announcement failed: funding manager shutting down
<time> [ERR] FNDG: Unable to advance state(<chan_point>): error sending channel announcement: channel announcement failed: gossiper is shutting down
<time> [ERR] FNDG: Unable to advance state(<chan_point>): error sending channel announcement: channel announcement failed: router shutting down
<time> [ERR] FNDG: Unable to advance state(<chan_point>): error sending channel announcement: channel announcement failed: unable add proof to the channel chanID=<hex>: edge marked as zombie
<time> [ERR] FNDG: Unable to advance state(<chan_point>): error sending channel announcement: channel announcement failed: unable add proof to the channel chanID=<hex>: edge not found
<time> [ERR] FNDG: Unable to advance state(<chan_point>): error sending channel announcement: unable to register for confirmation of ChannelPoint(<chan_point>): chain notifier shutting down
<time> [ERR] FNDG: Unable to advance state(<chan_point>): error sending channel announcement: unable to register for confirmation of ChannelPoint(<chan_point>): TxNotifier is exiting
<time> [ERR] FNDG: Unable to advance state(<chan_point>): failed adding to router graph: error sending channel announcement: gossiper is shutting down
<time> [ERR] FNDG: Unable to advance state(<chan_point>): failed adding to router graph: error sending channel announcement: router shutting down
<time> [ERR] FNDG: Unable to advance state(<chan_point>): failed adding to router graph: error sending channel update: router shutting down
<time> [ERR] FNDG: Unable to advance state(<chan_point>): failed adding to router graph: funding manager shutting down
<time> [ERR] FNDG: Unable to advance state(<chan_point>): failed sending fundingLocked: funding manager shutting down
<time> [ERR] FNDG: Unable to advance state(<chan_point>): funding manager shutting down
<time> [ERR] FNDG: unable to cancel reservation: no active reservations for peer(<hex>)
<time> [ERR] FNDG: Unable to handle funding accept message for peer_key=<hex>, pending_chan_id=<hex>: aborting PSBT flow: user canceled funding
<time> [ERR] FNDG: unable to report short chan id: link <hex> not found
<time> [ERR] FNDG: Unable to send channel proof: channel announcement proof for short_chan_id=<cid> isn't valid: can't verify first bitcoin signature
<time> [ERR] FNDG: Unable to send channel proof: gossiper is shutting down
<time> [ERR] FNDG: Unable to send channel proof: unable add proof to the channel chanID=<hex>: edge marked as zombie
<time> [ERR] FNDG: Unable to send channel proof: unable add proof to the channel chanID=<hex>: edge not found
<time> [ERR] FNDG: Unable to send node announcement: gossiper is shutting down
<time> [ERR] FNDG: Unable to send node announcement: router shutting down
<time> [ERR] FNDG: unable to open channel to NodeKey(<hex>): remote canceled funding, possibly timed out: received funding error from <hex>: chan_id=<hex>, err=chan size of 0.001 BTC is below min chan size of 0.002 BTC
<time> [ERR] HSWC: AmountBelowMinimum(amt=<amt>, update=(lnwire.ChannelUpdate) {
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: ChannelPoint(<chan_point>): received error from peer: chan_id=<hex>, err=internal error with error: remote error
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: ChannelPoint(<chan_point>): received error from peer: chan_id=<hex>, err=invalid update with error: remote error
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: ChannelPoint(<chan_point>): received error from peer: chan_id=<hex>, err=sync error with error: remote error
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: ChannelPoint(<chan_point>): received error from peer: chan_id=<hex>, err=unable to resume channel, recovery required with error: remote error
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: unable to handle upstream settle HTLC: Invalid payment preimage <hex> for hash <hex> with error: invalid update
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: unable to synchronize channel states: ChannelPoint(<chan_point>) with CommitPoint(<hex>) had possible local commitment state data loss with error: unable to resume channel, recovery required
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: unable to synchronize channel states: possible remote commitment state data loss with error: sync error
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: unable to synchronize channel states: Unable to send chan sync message for ChannelPoint(<chan_point>): peer exiting with error: unable to resume channel, recovery required
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: unable to synchronize channel states: unable to send chan sync message for ChannelPoint(<chan_point>): set tcp <ip>: use of closed network connection with error: unable to resume channel, recovery required
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: unable to synchronize channel states: unable to send chan sync message for ChannelPoint(<chan_point>): set tcp <ip>: use of closed network connection with error: unable to resume channel, recovery required
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: unable to synchronize channel states: Unable to send chan sync message for ChannelPoint(<chan_point>): write tcp <ip>-><ip>: use of closed network connection with error: unable to resume channel, recovery required
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: unable to synchronize channel states: Unable to send chan sync message for ChannelPoint(<chan_point>): write tcp <ip>-><ip>: write: broken pipe with error: unable to resume channel, recovery required
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: unable to synchronize channel states: unable to send chan sync message for ChannelPoint(<chan_point>): write tcp <ip>-><ip>: write: connection reset by peer with error: unable to resume channel, recovery required
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: unable to update commitment: link shutting down with error: internal error
<time> [ERR] HSWC: ChannelLink(<chan_point>): link failed, exiting htlcManager
<time> [ERR] HSWC: ChannelLink(<chan_point>): unable to cancel incoming HTLC for circuit-key=(Chan ID=<chan>, HTLC ID=0): HTLC with ID 0 has already been failed
<time> [ERR] HSWC: ChannelLink(<chan_point>): unable to decode onion hop iterator: TemporaryChannelFailure
<time> [ERR] HSWC: ChannelLink(<chan_point>): unable to update signals
<time> [ERR] HSWC: ChannelLink(<chan_point>): unhandled error while forwarding htlc packet over htlcswitch: AmountBelowMinimum(amt=4000 mSAT, update=(lnwire.ChannelUpdate) {
<time> [ERR] HSWC: ChannelLink(<chan_point>): unhandled error while forwarding htlc packet over htlcswitch: circuit has already been closed
<time> [ERR] HSWC: ChannelLink(<chan_point>): unhandled error while forwarding htlc packet over htlcswitch: insufficient bandwidth to route htlc
<time> [ERR] HSWC: ChannelLink(<chan_point>): unhandled error while forwarding htlc packet over htlcswitch: node configured to disallow forwards
<time> [ERR] HSWC: ChannelLink(<chan_point>): unhandled error while forwarding htlc packet over htlcswitch: UnknownNextPeer
<time> [ERR] HSWC: FeeInsufficient(htlc_amt==<amt>, update=(lnwire.ChannelUpdate) {
<time> [ERR] HSWC: insufficient bandwidth to route htlc
<time> [ERR] HSWC: Link <chan> not found
<time> [ERR] HSWC: Link <chan> policy for local forward not satisfied
<time> [ERR] HSWC: node configured to disallow forwards
<time> [ERR] HSWC: unable to de-obfuscate onion failure (hash=<hex>, pid=<pid>): invalid error length: expected 292 got 0
<time> [ERR] HSWC: unable to find target channel for HTLC fail: channel ID = <chan>, HTLC ID = <id>
<time> [ERR] HSWC: Unable to forward resolution msg: unable to find target channel for HTLC fail: channel ID = <chan>, HTLC ID = <id>
<time> [ERR] HSWC: unable to process onion packet: sphinx packet replay attempted
<time> [ERR] HSWC: Unhandled error while reforwarding htlc settle/fail over htlcswitch: AmountBelowMinimum(amt=<amt>, update=(lnwire.ChannelUpdate) {
<time> [ERR] HSWC: Unhandled error while reforwarding htlc settle/fail over htlcswitch: circuit has already been closed
<time> [ERR] HSWC: Unhandled error while reforwarding htlc settle/fail over htlcswitch: FeeInsufficient(htlc_amt==<amt>, update=(lnwire.ChannelUpdate) {
<time> [ERR] HSWC: Unhandled error while reforwarding htlc settle/fail over htlcswitch: insufficient bandwidth to route htlc
<time> [ERR] HSWC: Unhandled error while reforwarding htlc settle/fail over htlcswitch: node configured to disallow forwards
<time> [ERR] HSWC: Unhandled error while reforwarding htlc settle/fail over htlcswitch: UnknownNextPeer
<time> [ERR] HSWC: UnknownNextPeer
<time> [ERR] LNWL: ChannelPoint(<chan_point>): sync failed: remote believes our tail height is <height>, while we have <height>!
<time> [ERR] LNWL: ChannelPoint(<chan_point>): sync failed: remote's next commit height is <height>, while we believe it is <height>!
<time> [ERR] LNWL: ChannelPoint(<chan_point>): sync failed with local data loss: remote believes our tail height is <height>, while we have <height>!
<time> [ERR] LNWL: Neutrino rescan ended with error: rescan exited
<time> [ERR] LNWL: Notifying unmined tx notification (<hex>) while creating notification for blocks
<time> [ERR] LNWL: Rescan for <num> addresses failed: the client has been shutdown
<time> [ERR] LTND: Unable to lookup witness: no witnesses
<time> [ERR] NANN: Unable to retrieve chan status for Channel(<chan_point>): edge not found
<time> [ERR] NANN: Unable to retrieve chan status for Channel(<chan_point>): unable to extract ChannelUpdate for channel <chan_point>
<time> [ERR] NANN: Unable to sign update disabling channel(<chan_point>): edge not found
<time> [ERR] NTFN: chain notifier shutting down
<time> [ERR] NTFN: Error during rescan: rescan exited
<time> [ERR] NTFN: Failed getting UTXO: get utxo request cancelled
<time> [ERR] NTFN: Rescan to determine the spend details of <chan_point> failed: the client has been shutdown
<time> [ERR] NTFN: Unable to fetch block header: the client has been shutdown
<time> [ERR] NTFN: unable to find blockhash for height=<height>: -1: Block number out of range
<time> [ERR] NTFN: unable to get block: Post "http://<ip>": dial tcp <ip>: connect: connection refused
<time> [ERR] NTFN: unable to get block: Post "http://<ip>": dial tcp <ip>: connect: connection reset by peer
<time> [ERR] NTFN: unable to get block: Post "http://<ip>": read tcp <ip>-><ip>: read: connection reset by peer
<time> [ERR] NTFN: unable to get block: the client has been shutdown
<time> [ERR] NTFN: unable to get hash from block with height 790
<time> [ERR] NTFN: unable to get missed blocks: starting height <height> is greater than ending height <height>
<time> [ERR] NTFN: Unable to rewind chain from height <height> to height <height>: unable to find blockhash for disconnected height=<height>: -1: Block number out of range
<time> [ERR] NTFN: Unable to rewind chain from height <height> to height <height>: unable to find blockhash for disconnected height=<height>: -8: Block height out of range
<time> [ERR] NTNF: unable to get hash from block with height <height>
<time> [ERR] PEER: Allowed test error from <ip> (inbound): ReadMessage: unhandled command [sendaddrv2]
<time> [ERR] PEER: resend failed: unable to fetch channel sync messages for peer <hex>@<ip>: unable to find closed channel summary
<time> [ERR] PEER: unable to close channel, ChannelID(<hex>) is unknown
<time> [ERR] PEER: unable to force close link(<chan>): ChainArbitrator exiting
<time> [ERR] PEER: unable to force close link(<chan>): channel not found
<time> [ERR] PEER: unable to force close link(<chan>): unable to find arbitrator
<time> [ERR] PEER: unable to get best block: the client has been shutdown
<time> [ERR] PEER: unable to send msg to remote peer: peer exiting
<time> [ERR] PEER: unable to send msg to remote peer: write tcp <ip>-><ip>: write: broken pipe
<time> [ERR] PEER: unable to send msg to remote peer: write tcp <ip>-><ip>: write: connection reset by peer
<time> [ERR] RPCS: [/chainrpc.ChainNotifier/RegisterBlockEpochNtfn]: chain notifier shutting down
<time> [ERR] RPCS: [/chainrpc.ChainNotifier/RegisterBlockEpochNtfn]: context canceled
<time> [ERR] RPCS: [closechannel] unable to close ChannelPoint(<chan_point>): chain notifier shutting down
<time> [ERR] RPCS: [connectpeer]: error connecting to peer: already connected to peer: <hex>@<ip>
<time> [ERR] RPCS: [connectpeer]: error connecting to peer: dial tcp <ip>: i/o timeout
<time> [ERR] RPCS: [connectpeer]: error connecting to peer: dial tcp <ip>: i/o timeout
<time> [ERR] RPCS: [connectpeer]: error connecting to peer: read tcp <ip>-><ip>: i/o timeout
<time> [ERR] RPCS: Failed receiving from stream: rpc error: code = Canceled desc = context canceled
<time> [ERR] RPCS: Failed receiving from stream: rpc error: code = DeadlineExceeded desc = context deadline exceeded
<time> [ERR] RPCS: Failed sending error response: rpc error: code = Canceled desc = context canceled
<time> [ERR] RPCS: Failed sending error response: rpc error: code = Internal desc = transport: transport: the stream is done or WriteHeader was already called
<time> [ERR] RPCS: Failed sending response: rpc error: code = Canceled desc = context canceled
<time> [ERR] RPCS: Failed sending response: rpc error: code = Internal desc = transport: transport: the stream is done or WriteHeader was already called
<time> [ERR] RPCS: [/invoicesrpc.Invoices/SubscribeSingleInvoice]: rpc error: code = Canceled desc = context canceled
<time> [ERR] RPCS: [/lnrpc.Lightning/BatchOpenChannel]: batch funding failed: error batch opening channel, initial negotiation failed: remote canceled funding, possibly timed out: received funding error from <hex>: chan_id=<hex>, err=chan size of 0.001 BTC is below min chan size of 0.002 BTC
<time> [ERR] RPCS: [/lnrpc.Lightning/BakeMacaroon]: invalid permission action. supported actions are [read write generate], supported entities are [onchain offchain address message peers info invoices signer macaroon uri]
<time> [ERR] RPCS: [/lnrpc.Lightning/BakeMacaroon]: invalid permission entity. supported actions are [read write generate], supported entities are [onchain offchain address message peers info invoices signer macaroon uri]
<time> [ERR] RPCS: [/lnrpc.Lightning/BakeMacaroon]: permission list cannot be empty. specify at least one action/entity pair. supported actions are [read write generate], supported entities are [onchain offchain address message peers info invoices signer macaroon uri]
<time> [ERR] RPCS: [/lnrpc.Lightning/ChannelAcceptor]: rpc error: code = Canceled desc = context canceled
<time> [ERR] RPCS: [/lnrpc.Lightning/CloseChannel]: cannot close channel with state: ChanStatusRestored
<time> [ERR] RPCS: [/lnrpc.Lightning/CloseChannel]: cannot co-op close frozen channel as initiator until height=3059, (current_height=3055)
<time> [ERR] RPCS: [/lnrpc.Lightning/CloseChannel]: cannot co-op close frozen channel as initiator until height=<height>, (current_height=<height>)
<time> [ERR] RPCS: [/lnrpc.Lightning/CloseChannel]: chain notifier shutting down
<time> [ERR] RPCS: [/lnrpc.Lightning/CloseChannel]: must specify channel point in close channel
<time> [ERR] RPCS: [/lnrpc.Lightning/CloseChannel]: rpc error: code = DeadlineExceeded desc = context deadline exceeded
<time> [ERR] RPCS: [/lnrpc.Lightning/CloseChannel]: server is still in the process of starting
<time> [ERR] RPCS: [/lnrpc.Lightning/ConnectPeer]: already connected to peer: <hex>@<ip>
<time> [ERR] RPCS: [/lnrpc.Lightning/ConnectPeer]: dial tcp <ip>: i/o timeout
<time> [ERR] RPCS: [/lnrpc.Lightning/ConnectPeer]: dial tcp <ip>: i/o timeout
<time> [ERR] RPCS: [/lnrpc.Lightning/ConnectPeer]: read tcp <ip>-><ip>: i/o timeout
<time> [ERR] RPCS: [/lnrpc.Lightning/ConnectPeer]: server is still in the process of starting
<time> [ERR] RPCS: [/lnrpc.Lightning/DeleteMacaroonID]: the specified ID cannot be deleted
<time> [ERR] RPCS: [/lnrpc.Lightning/FundingStateStep]: pendingChanID(<hex>) already has intent registered
<time> [ERR] RPCS: [/lnrpc.Lightning/GetChanInfo]: edge marked as zombie
<time> [ERR] RPCS: [/lnrpc.Lightning/GetChanInfo]: edge not found
<time> [ERR] RPCS: [/lnrpc.Lightning/OpenChannel]: channels cannot be created before the wallet is fully synced
<time> [ERR] RPCS: [/lnrpc.Lightning/OpenChannel]: received funding error from <hex>: chan_id=<hex>, err=channel too large
<time> [ERR] RPCS: [/lnrpc.Lightning/OpenChannel]: received funding error from <hex>: chan_id=<hex>, err=chan size of 0.16777216 BTC exceeds maximum chan size of 0.16777215 BTC
<time> [ERR] RPCS: [/lnrpc.Lightning/OpenChannel]: received funding error from <hex>: chan_id=<hex>, err=chan size of 10.00000001 BTC exceeds maximum chan size of 0.16777215 BTC
<time> [ERR] RPCS: [/lnrpc.Lightning/OpenChannel]: received funding error from <hex>: chan_id=<hex>, err=chan size of 10.00000001 BTC exceeds maximum chan size of 10 BTC
<time> [ERR] RPCS: [/lnrpc.Lightning/OpenChannel]: received funding error from <hex>: chan_id=<hex>, err=Number of pending channels exceed maximum
<time> [ERR] RPCS: [/lnrpc.Lightning/OpenChannel]: received funding error from <hex>: chan_id=<hex>, err=Synchronizing blockchain
<time> [ERR] RPCS: [/lnrpc.Lightning/PendingChannels]: unable to find arbitrator
<time> [ERR] RPCS: [/lnrpc.Lightning/SendCoins]: address: tb1qfc8fusa98jx8uvnhzavxccqlzvg749tvjw82tg is not valid for this network: regtest
<time> [ERR] RPCS: [/lnrpc.Lightning/SendCoins]: amount set while SendAll is active
<time> [ERR] RPCS: [/lnrpc.Lightning/SendCoins]: cannot send coins to pubkeys
<time> [ERR] RPCS: [/lnrpc.Lightning/SendCoins]: unknown address type
<time> [ERR] RPCS: [/lnrpc.Lightning/SendPayment]: rpc error: code = Canceled desc = context canceled
<time> [ERR] RPCS: [/lnrpc.Lightning/SendPayment]: rpc error: code = DeadlineExceeded desc = context deadline exceeded
<time> [ERR] RPCS: [/lnrpc.Lightning/SendPayment]: rpc server shutting down
<time> [ERR] RPCS: [/lnrpc.Lightning/SendToRoute]: rpc error: code = Canceled desc = context canceled
<time> [ERR] RPCS: [/lnrpc.Lightning/SendToRoute]: rpc error: code = DeadlineExceeded desc = context deadline exceeded
<time> [ERR] RPCS: [/lnrpc.Lightning/SendToRoute]: rpc server shutting down
<time> [ERR] RPCS: [/lnrpc.Lightning/SubscribeChannelEvents]: rpc error: code = Canceled desc = context canceled
<time> [ERR] RPCS: [/lnrpc.Lightning/SubscribeChannelGraph]: ChannelRouter shutting down
<time> [ERR] RPCS: [/lnrpc.Lightning/SubscribeChannelGraph]: router not started
<time> [ERR] RPCS: [/lnrpc.Lightning/SubscribeChannelGraph]: rpc error: code = Canceled desc = context canceled
<time> [ERR] RPCS: [/lnrpc.Lightning/SubscribeChannelGraph]: rpc error: code = DeadlineExceeded desc = context deadline exceeded
<time> [ERR] RPCS: [/lnrpc.Lightning/SubscribeChannelGraph]: rpc error: code = Internal desc = transport: transport: the stream is done or WriteHeader was already called
<time> [ERR] RPCS: [/lnrpc.Lightning/SubscribeInvoices]: rpc error: code = Canceled desc = context canceled
<time> [ERR] RPCS: [/routerrpc.Router/HtlcInterceptor]: rpc error: code = Canceled desc = context canceled
<time> [ERR] RPCS: [/routerrpc.Router/SendPayment]: routerrpc server shutting down
<time> [ERR] RPCS: [/routerrpc.Router/SendPaymentV2]: context canceled
<time> [ERR] RPCS: [/routerrpc.Router/SendPaymentV2]: context deadline exceeded
<time> [ERR] RPCS: [/routerrpc.Router/SendPaymentV2]: routerrpc server shutting down
<time> [ERR] RPCS: [/routerrpc.Router/SubscribeHtlcEvents]: context canceled
<time> [ERR] RPCS: [/routerrpc.Router/SubscribeHtlcEvents]: htlc event subscription terminated
<time> [ERR] RPCS: [/routerrpc.Router/SubscribeHtlcEvents]: context deadline exceeded
<time> [ERR] RPCS: [/routerrpc.Route<time> [INF] LTND: Listening on the p2p interface is disabled!
<time> [ERR] RPCS: [/signrpc.Signer/DeriveSharedKey]: must provide ephemeral pubkey
<time> [ERR] RPCS: [/signrpc.Signer/DeriveSharedKey]: use either key_desc or key_loc
<time> [ERR] RPCS: [/signrpc.Signer/DeriveSharedKey]: use either raw_key_bytes or key_index
<time> [ERR] RPCS: [/signrpc.Signer/DeriveSharedKey]: when setting key_desc the field key_desc.key_loc must also be set
<time> [ERR] RPCS: [/lnrpc.Lightning/BakeMacaroon]: permission denied
<time> [ERR] RPCS: [/lnrpc.Lightning/GetInfo]: cannot retrieve macaroon: cannot get macaroon: root key with id doesn't exist
<time> [ERR] RPCS: [/lnrpc.Lightning/GetInfo]: caveat "ipaddr 1.1.1.1" not satisfied: macaroon locked to different IP address
<time> [ERR] RPCS: [/lnrpc.Lightning/GetInfo]: caveat "time-before <time>" not satisfied: macaroon has expired
<time> [ERR] RPCS: [/lnrpc.Lightning/GetInfo]: expected 1 macaroon, got 0
<time> [ERR] RPCS: [/lnrpc.Lightning/GetInfo]: permission denied
<time> [ERR] RPCS: [/lnrpc.Lightning/GetInfo]: the RPC server is in the process of starting up, but not yet ready to accept calls
<time> [ERR] RPCS: [/lnrpc.Lightning/GetInfo]: wallet locked, unlock it to enable full RPC access
<time> [ERR] RPCS: [/lnrpc.Lightning/ListMacaroonIDs]: cannot retrieve macaroon: cannot get macaroon: root key with id 1 doesn't exist
<time> [ERR] RPCS: [/lnrpc.Lightning/NewAddress]: permission denied
<time> [ERR] RPCS: unable to open channel to NodeKey(<hex>): received funding error from <hex>: chan_id=<hex>, err=channel too large
<time> [ERR] RPCS: unable to open channel to NodeKey(<hex>): received funding error from <hex>: chan_id=<hex>, err=chan size of 0.16777216 BTC exceeds maximum chan size of 0.16777215 BTC
<time> [ERR] RPCS: unable to open channel to NodeKey(<hex>): received funding error from <hex>: chan_id=<hex>, err=chan size of 10.00000001 BTC exceeds maximum chan size of 0.16777215 BTC
<time> [ERR] RPCS: unable to open channel to NodeKey(<hex>): received funding error from <hex>: chan_id=<hex>, err=chan size of 10.00000001 BTC exceeds maximum chan size of 10 BTC
<time> [ERR] RPCS: unable to open channel to NodeKey(<hex>): received funding error from <hex>: chan_id=<hex>, err=Number of pending channels exceed maximum
<time> [ERR] RPCS: unable to open channel to NodeKey(<hex>): received funding error from <hex>: chan_id=<hex>, err=Synchronizing blockchain
<time> [ERR] RPCS: [/walletrpc.WalletKit/LabelTransaction]: cannot label transaction with empty label
<time> [ERR] RPCS: [/walletrpc.WalletKit/LabelTransaction]: transaction already labelled
<time> [ERR] RPCS: Websocket receive error from <ip>: read tcp4 <ip>-><ip>: use of closed network connection
<time> [ERR] RPCS: Websocket receive error from <ip>: websocket: close 1006 unexpected EOF
<time> [ERR] RPCS: WS: error closing upgraded conn: write tcp4 <ip>-><ip>: write: connection reset by peer
<time> [ERR] SRVR: Unable to connect to <hex>@<ip>: dial tcp <ip>: i/o timeout
<time> [ERR] SRVR: Unable to connect to <hex>@<ip>: dial tcp <ip>: i/o timeout
<time> [ERR] SRVR: Unable to connect to <hex>@<ip>: read tcp <ip>-><ip>: i/o timeout
<time> [ERR] SRVR: Unable to retrieve advertised address for node <hex>: no advertised addresses found
<time> [ERR] SRVR: Unable to retrieve advertised address for node <hex>: unable to find node
<time> [ERR] UTXN: error while graduating class at height=<height>: TxNotifier is exiting
<time> [ERR] UTXN: Failed to sweep first-stage HTLC (CLTV-delayed) output <chan_point>
<time> [ERR] UTXN: Notification chan closed, can't advance output <chan_point>
<time> [ERR] DISC: Unable to rebroadcast stale announcements: unable to retrieve outgoing channels: channel from self node has no policy
<time> [ERR] RPCS: [/lnrpc.Lightning/OpenChannel]: reserved wallet balance invalidated: transaction would leave insufficient funds for fee bumping anchor channel closings (see debug log for details)
<time> [ERR] RPCS: [/lnrpc.Lightning/SendCoins]: reserved wallet balance invalidated: transaction would leave insufficient funds for fee bumping anchor channel closings (see debug log for details)
<time> [ERR] RPCS: unable to open channel to NodeKey(<hex>): reserved wallet balance invalidated: transaction would leave insufficient funds for fee bumping anchor channel closings (see debug log for details)
<time> [ERR] NANN: Unable to retrieve chan status for Channel(<chan_point>): unable to extract ChannelUpdate
<time> [ERR] NTFN: Unable to rewind chain from height 1 to height -1: unable to find blockhash for disconnected height=<height>: -8: Block height out of range
<time> [ERR] RPCS: WS: error writing message: websocket: close sent
<time> [ERR] RPCS: [/routerrpc.Router/XImportMissionControl]: pair: <hex> -> <hex>: invalid failure: msat: <amt> and sat: 0.0000002 BTC values not equal
<time> [ERR] BTCN: utxo scan failed: neutrino shutting down
<time> [ERR] RPCS: [/lnrpc.Lightning/SubscribeChannelGraph]: context canceled
<time> [ERR] RPCS: [/lnrpc.Lightning/SubscribeInvoices]: context canceled
<time> [ERR] RPCS: [/lnrpc.Lightning/SubscribeChannelGraph]: context deadline exceeded
<time> [ERR] RPCS: [/invoicesrpc.Invoices/SubscribeSingleInvoice]: context canceled
<time> [ERR] RPCS: [/lnrpc.State/SubscribeState]: context canceled
<time> [ERR] NTFN: Failed to update rescan progress: database not open
<time> [ERR] HSWC: ChannelLink(<chan_point>): failing link: process hodl queue: unable to update commitment: link shutting down with error: internal error
<time> [ERR] INVC: SettleHodlInvoice with preimage <hex>: invoice already canceled
<time> [ERR] RPCS: [/invoicesrpc.Invoices/SettleInvoice]: invoice already canceled
<time> [ERR] HSWC: ChannelLink(<chan_point>): outgoing htlc(<hex>) has insufficient fee: expected 33000, got 1020
<time> [ERR] RPCS: [/lnrpc.Lightning/CloseChannel]: rpc error: code = Canceled desc = context canceled

View file

@ -1,351 +0,0 @@
package itest
import (
"bytes"
"context"
"flag"
"fmt"
"math"
"os"
"path/filepath"
"runtime"
"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/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/stretchr/testify/require"
)
var (
harnessNetParams = &chaincfg.RegressionNetParams
// lndExecutable is the full path to the lnd binary.
lndExecutable = flag.String(
"lndexec", itestLndBinary, "full path to lnd binary",
)
slowMineDelay = 20 * time.Millisecond
)
const (
testFeeBase = 1e+6
defaultCSV = lntest.DefaultCSV
defaultTimeout = lntest.DefaultTimeout
minerMempoolTimeout = lntest.MinerMempoolTimeout
channelCloseTimeout = lntest.ChannelCloseTimeout
itestLndBinary = "../../lnd-itest"
anchorSize = 330
noFeeLimitMsat = math.MaxInt64
AddrTypeWitnessPubkeyHash = lnrpc.AddressType_WITNESS_PUBKEY_HASH
AddrTypeNestedPubkeyHash = lnrpc.AddressType_NESTED_PUBKEY_HASH
AddrTypeTaprootPubkey = lnrpc.AddressType_TAPROOT_PUBKEY
)
// harnessTest wraps a regular testing.T providing enhanced error detection
// and propagation. All error will be augmented with a full stack-trace in
// order to aid in debugging. Additionally, any panics caused by active
// test cases will also be handled and represented as fatals.
type harnessTest struct {
t *testing.T
// testCase is populated during test execution and represents the
// current test case.
testCase *testCase
// lndHarness is a reference to the current network harness. Will be
// nil if not yet set up.
lndHarness *lntest.NetworkHarness
}
// newHarnessTest creates a new instance of a harnessTest from a regular
// testing.T instance.
func newHarnessTest(t *testing.T, net *lntest.NetworkHarness) *harnessTest {
return &harnessTest{t, nil, net}
}
// Skipf calls the underlying testing.T's Skip method, causing the current test
// to be skipped.
func (h *harnessTest) Skipf(format string, args ...interface{}) {
h.t.Skipf(format, args...)
}
// Fatalf causes the current active test case to fail with a fatal error. All
// integration tests should mark test failures solely with this method due to
// the error stack traces it produces.
func (h *harnessTest) Fatalf(format string, a ...interface{}) {
if h.lndHarness != nil {
h.lndHarness.SaveProfilesPages(h.t)
}
stacktrace := errors.Wrap(fmt.Sprintf(format, a...), 1).ErrorStack()
if h.testCase != nil {
h.t.Fatalf("Failed: (%v): exited with error: \n"+
"%v", h.testCase.name, stacktrace)
} else {
h.t.Fatalf("Error outside of test: %v", stacktrace)
}
}
// RunTestCase executes a harness test case. Any errors or panics will be
// represented as fatal.
func (h *harnessTest) RunTestCase(testCase *testCase) {
h.testCase = testCase
defer func() {
h.testCase = nil
}()
defer func() {
if err := recover(); err != nil {
description := errors.Wrap(err, 2).ErrorStack()
h.t.Fatalf("Failed: (%v) panicked with: \n%v",
h.testCase.name, description)
}
}()
testCase.test(h.lndHarness, h)
}
func (h *harnessTest) Logf(format string, args ...interface{}) {
h.t.Logf(format, args...)
}
func (h *harnessTest) Log(args ...interface{}) {
h.t.Log(args...)
}
func (h *harnessTest) getLndBinary() string {
binary := itestLndBinary
lndExec := ""
if lndExecutable != nil && *lndExecutable != "" {
lndExec = *lndExecutable
}
if lndExec == "" && runtime.GOOS == "windows" {
// Windows (even in a bash like environment like git bash as on
// Travis) doesn't seem to like relative paths to exe files...
currentDir, err := os.Getwd()
if err != nil {
h.Fatalf("unable to get working directory: %v", err)
}
targetPath := filepath.Join(currentDir, "../../lnd-itest.exe")
binary, err = filepath.Abs(targetPath)
if err != nil {
h.Fatalf("unable to get absolute path: %v", err)
}
} else if lndExec != "" {
binary = lndExec
}
return binary
}
type testCase struct {
name string
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 mineBlocksFast(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.Client, numTxs, minerMempoolTimeout,
)
if err != nil {
t.Fatalf("unable to find txns in mempool: %v", err)
}
}
blocks := make([]*wire.MsgBlock, num)
blockHashes, err := net.Miner.Client.Generate(num)
if err != nil {
t.Fatalf("unable to generate blocks: %v", err)
}
for i, blockHash := range blockHashes {
block, err := net.Miner.Client.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
}
// mineBlocksSlow mines 'num' of blocks and checks that blocks are present in
// the mining node's blockchain. numTxs should be set to the number of
// transactions (excluding the coinbase) we expect to be included in the first
// mined block. Between each mined block an artificial delay is introduced to
// give all network participants time to catch up.
//
// NOTE: This function currently is just an alias for mineBlocksSlow.
func mineBlocks(t *harnessTest, net *lntest.NetworkHarness,
num uint32, numTxs int) []*wire.MsgBlock {
return mineBlocksSlow(t, net, num, numTxs)
}
// mineBlocksSlow mines 'num' of blocks and checks that blocks are present in
// the mining node's blockchain. numTxs should be set to the number of
// transactions (excluding the coinbase) we expect to be included in the first
// mined block. Between each mined block an artificial delay is introduced to
// give all network participants time to catch up.
func mineBlocksSlow(t *harnessTest, net *lntest.NetworkHarness,
num uint32, numTxs int) []*wire.MsgBlock {
t.t.Helper()
// 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.Client, numTxs, minerMempoolTimeout,
)
require.NoError(t.t, err, "unable to find txns in mempool")
}
blocks := make([]*wire.MsgBlock, num)
blockHashes := make([]*chainhash.Hash, 0, num)
for i := uint32(0); i < num; i++ {
generatedHashes, err := net.Miner.Client.Generate(1)
require.NoError(t.t, err, "generate blocks")
blockHashes = append(blockHashes, generatedHashes...)
time.Sleep(slowMineDelay)
}
for i, blockHash := range blockHashes {
block, err := net.Miner.Client.GetBlock(blockHash)
require.NoError(t.t, err, "get blocks")
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, account string) {
t.t.Helper()
ctxb := context.Background()
err := wait.NoError(func() error {
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
unspent, err := node.WalletKitClient.ListUnspent(
ctxt, &walletrpc.ListUnspentRequest{
Account: account,
},
)
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)
require.NoError(t.t, err)
}

View file

@ -1,468 +0,0 @@
package itest
import (
"context"
"crypto/rand"
"fmt"
"io"
"time"
"github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/rpcclient"
"github.com/btcsuite/btcd/wire"
"github.com/go-errors/errors"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lntemp"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/stretchr/testify/require"
)
// completePaymentRequests sends payments from a lightning node to complete all
// payment requests. If the awaitResponse parameter is true, this function
// does not return until all payments successfully complete without errors.
func completePaymentRequests(client lnrpc.LightningClient,
routerClient routerrpc.RouterClient, paymentRequests []string,
awaitResponse bool) error {
ctxb := context.Background()
ctx, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
// We start by getting the current state of the client's channels. This
// is needed to ensure the payments actually have been committed before
// we return.
req := &lnrpc.ListChannelsRequest{}
listResp, err := client.ListChannels(ctx, req)
if err != nil {
return err
}
// send sends a payment and returns an error if it doesn't succeeded.
send := func(payReq string) error {
ctxc, cancel := context.WithCancel(ctx)
defer cancel()
payStream, err := routerClient.SendPaymentV2(
ctxc,
&routerrpc.SendPaymentRequest{
PaymentRequest: payReq,
TimeoutSeconds: 60,
FeeLimitMsat: noFeeLimitMsat,
},
)
if err != nil {
return err
}
resp, err := getPaymentResult(payStream)
if err != nil {
return err
}
if resp.Status != lnrpc.Payment_SUCCEEDED {
return errors.New(resp.FailureReason)
}
return nil
}
// Launch all payments simultaneously.
results := make(chan error)
for _, payReq := range paymentRequests {
go func(payReq string) {
err := send(payReq)
if awaitResponse {
results <- err
}
}(payReq)
}
// If awaiting a response, verify that all payments succeeded.
if awaitResponse {
for range paymentRequests {
err := <-results
if err != nil {
return err
}
}
return nil
}
// We are not waiting for feedback in the form of a response, but we
// should still wait long enough for the server to receive and handle
// the send before cancelling the request. We wait for the number of
// updates to one of our channels has increased before we return.
err = wait.Predicate(func() bool {
newListResp, err := client.ListChannels(ctx, req)
if err != nil {
return false
}
// If the number of open channels is now lower than before
// attempting the payments, it means one of the payments
// triggered a force closure (for example, due to an incorrect
// preimage). Return early since it's clear the payment was
// attempted.
if len(newListResp.Channels) < len(listResp.Channels) {
return true
}
for _, c1 := range listResp.Channels {
for _, c2 := range newListResp.Channels {
if c1.ChannelPoint != c2.ChannelPoint {
continue
}
// If this channel has an increased numbr of
// updates, we assume the payments are
// committed, and we can return.
if c2.NumUpdates > c1.NumUpdates {
return true
}
}
}
return false
}, defaultTimeout)
if err != nil {
return err
}
return nil
}
// makeFakePayHash creates random pre image hash.
func makeFakePayHash(t *harnessTest) []byte {
randBuf := make([]byte, 32)
if _, err := rand.Read(randBuf); err != nil {
t.Fatalf("internal error, cannot generate random string: %v", err)
}
return randBuf
}
// createPayReqs is a helper method that will create a slice of payment
// requests for the given node.
func createPayReqs(node *lntest.HarnessNode, paymentAmt btcutil.Amount,
numInvoices int) ([]string, [][]byte, []*lnrpc.Invoice, error) {
payReqs := make([]string, numInvoices)
rHashes := make([][]byte, numInvoices)
invoices := make([]*lnrpc.Invoice, numInvoices)
for i := 0; i < numInvoices; i++ {
preimage := make([]byte, 32)
_, err := rand.Read(preimage)
if err != nil {
return nil, nil, nil, fmt.Errorf("unable to generate "+
"preimage: %v", err)
}
invoice := &lnrpc.Invoice{
Memo: "testing",
RPreimage: preimage,
Value: int64(paymentAmt),
}
ctxt, _ := context.WithTimeout(
context.Background(), defaultTimeout,
)
resp, err := node.AddInvoice(ctxt, invoice)
if err != nil {
return nil, nil, nil, fmt.Errorf("unable to add "+
"invoice: %v", err)
}
// Set the payment address in the invoice so the caller can
// properly use it.
invoice.PaymentAddr = resp.PaymentAddr
payReqs[i] = resp.PaymentRequest
rHashes[i] = resp.RHash
invoices[i] = invoice
}
return payReqs, rHashes, invoices, nil
}
// getChanInfo is a helper method for getting channel info for a node's sole
// channel.
func getChanInfo(node *lntest.HarnessNode) (*lnrpc.Channel, error) {
ctxb := context.Background()
ctx, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
req := &lnrpc.ListChannelsRequest{}
channelInfo, err := node.ListChannels(ctx, req)
if err != nil {
return nil, err
}
if len(channelInfo.Channels) != 1 {
return nil, fmt.Errorf("node should only have a single "+
"channel, instead it has %v", len(channelInfo.Channels))
}
return channelInfo.Channels[0], nil
}
// commitTypeHasAnchors returns whether commitType uses anchor outputs.
func commitTypeHasAnchors(commitType lnrpc.CommitmentType) bool {
switch commitType {
case lnrpc.CommitmentType_ANCHORS,
lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE:
return true
default:
return false
}
}
// nodeArgsForCommitType returns the command line flag to supply to enable this
// commitment type.
func nodeArgsForCommitType(commitType lnrpc.CommitmentType) []string {
switch commitType {
case lnrpc.CommitmentType_LEGACY:
return []string{"--protocol.legacy.committweak"}
case lnrpc.CommitmentType_STATIC_REMOTE_KEY:
return []string{}
case lnrpc.CommitmentType_ANCHORS:
return []string{"--protocol.anchors"}
case lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE:
return []string{
"--protocol.anchors",
"--protocol.script-enforced-lease",
}
}
return nil
}
// calcStaticFee calculates appropriate fees for commitment transactions. This
// function provides a simple way to allow test balance assertions to take fee
// calculations into account.
func calcStaticFee(c lnrpc.CommitmentType, numHTLCs int) btcutil.Amount {
const htlcWeight = input.HTLCWeight
var (
feePerKw = chainfee.SatPerKWeight(
lntemp.DefaultFeeRateSatPerKw,
)
commitWeight = input.CommitWeight
anchors = btcutil.Amount(0)
)
// The anchor commitment type is slightly heavier, and we must also add
// the value of the two anchors to the resulting fee the initiator
// pays. In addition the fee rate is capped at 10 sat/vbyte for anchor
// channels.
if commitTypeHasAnchors(c) {
feePerKw = chainfee.SatPerKVByte(
lnwallet.DefaultAnchorsCommitMaxFeeRateSatPerVByte * 1000,
).FeePerKWeight()
commitWeight = input.AnchorCommitWeight
anchors = 2 * anchorSize
}
return feePerKw.FeeForWeight(int64(commitWeight+htlcWeight*numHTLCs)) +
anchors
}
// channelCommitType retrieves the active channel commitment type for the given
// chan point.
func channelCommitType(node *lntest.HarnessNode,
chanPoint *lnrpc.ChannelPoint) (lnrpc.CommitmentType, error) {
ctxb := context.Background()
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
req := &lnrpc.ListChannelsRequest{}
channels, err := node.ListChannels(ctxt, req)
if err != nil {
return 0, fmt.Errorf("listchannels failed: %v", err)
}
for _, c := range channels.Channels {
if c.ChannelPoint == txStr(chanPoint) {
return c.CommitmentType, nil
}
}
return 0, fmt.Errorf("channel point %v not found", chanPoint)
}
// calculateMaxHtlc re-implements the RequiredRemoteChannelReserve of the
// funding manager's config, which corresponds to the maximum MaxHTLC value we
// allow users to set when updating a channel policy.
func calculateMaxHtlc(chanCap btcutil.Amount) uint64 {
reserve := lnwire.NewMSatFromSatoshis(chanCap / 100)
max := lnwire.NewMSatFromSatoshis(chanCap) - reserve
return uint64(max)
}
// waitForNodeBlockHeight queries the node for its current block height until
// it reaches the passed height.
func waitForNodeBlockHeight(node *lntest.HarnessNode, height int32) error {
ctxb := context.Background()
ctx, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
var predErr error
err := wait.Predicate(func() bool {
info, err := node.GetInfo(ctx, &lnrpc.GetInfoRequest{})
if err != nil {
predErr = err
return false
}
if int32(info.BlockHeight) != height {
predErr = fmt.Errorf("expected block height to "+
"be %v, was %v", height, info.BlockHeight)
return false
}
return true
}, defaultTimeout)
if err != nil {
return predErr
}
return nil
}
// getNTxsFromMempool polls until finding the desired number of transactions in
// the provided miner's mempool and returns the full transactions to the caller.
func getNTxsFromMempool(miner *rpcclient.Client, n int,
timeout time.Duration) ([]*wire.MsgTx, error) {
txids, err := waitForNTxsInMempool(miner, n, timeout)
if err != nil {
return nil, err
}
var txes []*wire.MsgTx
for _, txid := range txids {
tx, err := miner.GetRawTransaction(txid)
if err != nil {
return nil, err
}
txes = append(txes, tx.MsgTx())
}
return txes, nil
}
// getTxFee retrieves parent transactions and reconstructs the fee paid.
func getTxFee(miner *rpcclient.Client, tx *wire.MsgTx) (btcutil.Amount, error) {
var balance btcutil.Amount
for _, in := range tx.TxIn {
parentHash := in.PreviousOutPoint.Hash
rawTx, err := miner.GetRawTransaction(&parentHash)
if err != nil {
return 0, err
}
parent := rawTx.MsgTx()
balance += btcutil.Amount(
parent.TxOut[in.PreviousOutPoint.Index].Value,
)
}
for _, out := range tx.TxOut {
balance -= btcutil.Amount(out.Value)
}
return balance, nil
}
// channelSubscription houses the proxied update and error chans for a node's
// channel subscriptions.
type channelSubscription struct {
updateChan chan *lnrpc.ChannelEventUpdate
errChan chan error
quit chan struct{}
}
// subscribeChannelNotifications subscribes to channel updates and launches a
// goroutine that forwards these to the returned channel.
func subscribeChannelNotifications(ctxb context.Context, t *harnessTest,
node *lntest.HarnessNode) channelSubscription {
// We'll first start by establishing a notification client which will
// send us notifications upon channels becoming active, inactive or
// closed.
req := &lnrpc.ChannelEventSubscription{}
ctx, cancelFunc := context.WithCancel(ctxb)
chanUpdateClient, err := node.SubscribeChannelEvents(ctx, req)
if err != nil {
t.Fatalf("unable to create channel update client: %v", err)
}
// We'll launch a goroutine that will be responsible for proxying all
// notifications recv'd from the client into the channel below.
errChan := make(chan error, 1)
quit := make(chan struct{})
chanUpdates := make(chan *lnrpc.ChannelEventUpdate, 20)
go func() {
defer cancelFunc()
for {
select {
case <-quit:
return
default:
chanUpdate, err := chanUpdateClient.Recv()
select {
case <-quit:
return
default:
}
if err == io.EOF {
return
} else if err != nil {
select {
case errChan <- err:
case <-quit:
}
return
}
select {
case chanUpdates <- chanUpdate:
case <-quit:
return
}
}
}
}()
return channelSubscription{
updateChan: chanUpdates,
errChan: errChan,
quit: quit,
}
}
// findTxAtHeight gets all of the transactions that a node's wallet has a record
// of at the target height, and finds and returns the tx with the target txid,
// failing if it is not found.
func findTxAtHeight(t *harnessTest, height int32,
target string, node *lntest.HarnessNode) *lnrpc.Transaction {
ctxb := context.Background()
ctx, cancel := context.WithTimeout(ctxb, defaultTimeout)
defer cancel()
txns, err := node.LightningClient.GetTransactions(
ctx, &lnrpc.GetTransactionsRequest{
StartHeight: height,
EndHeight: height,
},
)
require.NoError(t.t, err, "could not get transactions")
for _, tx := range txns.Transactions {
if tx.TxHash == target {
return tx
}
}
return nil
}

View file

@ -7,6 +7,7 @@ import (
"fmt"
"github.com/btcsuite/btcd/chaincfg"
"github.com/lightningnetwork/lnd/lntest/node"
)
// NeutrinoBackendConfig is an implementation of the BackendConfig interface
@ -17,7 +18,7 @@ type NeutrinoBackendConfig struct {
// A compile time assertion to ensure NeutrinoBackendConfig meets the
// BackendConfig interface.
var _ BackendConfig = (*NeutrinoBackendConfig)(nil)
var _ node.BackendConfig = (*NeutrinoBackendConfig)(nil)
// GenArgs returns the arguments needed to be passed to LND at startup for
// using this node as a chain backend.

View file

@ -1,20 +1,63 @@
package node
import (
"flag"
"fmt"
"io"
"net"
"os"
"path"
"path/filepath"
"sync/atomic"
"github.com/btcsuite/btcd/chaincfg"
"github.com/lightningnetwork/lnd/chanbackup"
"github.com/lightningnetwork/lnd/kvdb/etcd"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/wait"
)
const (
// ListenerFormat is the format string that is used to generate local
// listener addresses.
ListenerFormat = "127.0.0.1:%d"
// DefaultCSV is the CSV delay (remotedelay) we will start our test
// nodes with.
DefaultCSV = 4
// defaultNodePort is the start of the range for listening ports of
// harness nodes. Ports are monotonically increasing starting from this
// number and are determined by the results of NextAvailablePort().
defaultNodePort = 5555
)
var (
// lastPort is the last port determined to be free for use by a new
// node. It should be used atomically.
lastPort uint32 = defaultNodePort
// logOutput is a flag that can be set to append the output from the
// seed nodes to log files.
logOutput = flag.Bool("logoutput", false,
"log output from node n to file output-n.log")
// logSubDir is the default directory where the logs are written to if
// logOutput is true.
logSubDir = flag.String("logdir", ".", "default dir to write logs to")
// btcdExecutable is the full path to the btcd binary.
btcdExecutable = flag.String(
"btcdexec", "", "full path to btcd binary",
)
)
type DatabaseBackend int
const (
BackendBbolt DatabaseBackend = iota
BackendEtcd
BackendPostgres
BackendSqlite
)
// Option is a function for updating a node's configuration.
@ -73,7 +116,7 @@ type BaseNodeConfig struct {
FeeURL string
DbBackend lntest.DatabaseBackend
DBBackend DatabaseBackend
PostgresDsn string
// NodeID is a unique ID used to identify the node.
@ -83,12 +126,12 @@ type BaseNodeConfig struct {
// compiled with all required itest flags.
LndBinary string
// backupDbDir is the path where a database backup is stored, if any.
backupDbDir string
// backupDBDir is the path where a database backup is stored, if any.
backupDBDir string
// postgresDbName is the name of the postgres database where lnd data
// postgresDBName is the name of the postgres database where lnd data
// is stored in.
postgresDbName string
postgresDBName string
}
func (cfg BaseNodeConfig) P2PAddr() string {
@ -126,16 +169,16 @@ func (cfg BaseNodeConfig) ChanBackupPath() string {
// current lightning network test.
func (cfg *BaseNodeConfig) GenerateListeningPorts() {
if cfg.P2PPort == 0 {
cfg.P2PPort = lntest.NextAvailablePort()
cfg.P2PPort = NextAvailablePort()
}
if cfg.RPCPort == 0 {
cfg.RPCPort = lntest.NextAvailablePort()
cfg.RPCPort = NextAvailablePort()
}
if cfg.RESTPort == 0 {
cfg.RESTPort = lntest.NextAvailablePort()
cfg.RESTPort = NextAvailablePort()
}
if cfg.ProfilePort == 0 {
cfg.ProfilePort = lntest.NextAvailablePort()
cfg.ProfilePort = NextAvailablePort()
}
}
@ -169,8 +212,7 @@ func (cfg *BaseNodeConfig) GenArgs() []string {
"--accept-keysend",
"--keep-failed-payment-attempts",
fmt.Sprintf("--db.batch-commit-interval=%v", commitInterval),
fmt.Sprintf("--bitcoin.defaultremotedelay=%v",
lntest.DefaultCSV),
fmt.Sprintf("--bitcoin.defaultremotedelay=%v", DefaultCSV),
fmt.Sprintf("--rpclisten=%v", cfg.RPCAddr()),
fmt.Sprintf("--restlisten=%v", cfg.RESTAddr()),
fmt.Sprintf("--restcors=https://%v", cfg.RESTAddr()),
@ -182,7 +224,6 @@ func (cfg *BaseNodeConfig) GenArgs() []string {
fmt.Sprintf("--invoicemacaroonpath=%v", cfg.InvoiceMacPath),
fmt.Sprintf("--trickledelay=%v", trickleDelay),
fmt.Sprintf("--profile=%d", cfg.ProfilePort),
fmt.Sprintf("--caches.rpc-graph-cache-duration=%d", 0),
// Use a small batch window so we can broadcast our sweep
// transactions faster.
@ -191,27 +232,32 @@ func (cfg *BaseNodeConfig) GenArgs() []string {
// Use a small batch delay so we can broadcast the
// announcements quickly in the tests.
"--gossip.sub-batch-delay=5ms",
// Use a small cache duration so the `DescribeGraph` can be
// updated quicker.
"--caches.rpc-graph-cache-duration=100ms",
}
args = append(args, nodeArgs...)
if cfg.Password == nil {
args = append(args, "--noseedbackup")
}
switch cfg.DbBackend {
case lntest.BackendEtcd:
switch cfg.DBBackend {
case BackendEtcd:
args = append(args, "--db.backend=etcd")
args = append(args, "--db.etcd.embedded")
args = append(
args, fmt.Sprintf(
"--db.etcd.embedded_client_port=%v",
lntest.NextAvailablePort(),
NextAvailablePort(),
),
)
args = append(
args, fmt.Sprintf(
"--db.etcd.embedded_peer_port=%v",
lntest.NextAvailablePort(),
NextAvailablePort(),
),
)
args = append(
@ -221,14 +267,14 @@ func (cfg *BaseNodeConfig) GenArgs() []string {
),
)
case lntest.BackendPostgres:
case BackendPostgres:
args = append(args, "--db.backend=postgres")
args = append(args, "--db.postgres.dsn="+cfg.PostgresDsn)
case lntest.BackendSqlite:
case BackendSqlite:
args = append(args, "--db.backend=sqlite")
args = append(args, fmt.Sprintf("--db.sqlite.busytimeout=%v",
lntest.SqliteBusyTimeout))
wait.SqliteBusyTimeout))
}
if cfg.FeeURL != "" {
@ -272,3 +318,86 @@ func ExtraArgsEtcd(etcdCfg *etcd.Config, name string, cluster bool,
return extraArgs
}
// NextAvailablePort returns the first port that is available for listening by
// a new node. It panics if no port is found and the maximum available TCP port
// is reached.
func NextAvailablePort() int {
port := atomic.AddUint32(&lastPort, 1)
for port < 65535 {
// If there are no errors while attempting to listen on this
// port, close the socket and return it as available. While it
// could be the case that some other process picks up this port
// between the time the socket is closed and it's reopened in
// the harness node, in practice in CI servers this seems much
// less likely than simply some other process already being
// bound at the start of the tests.
addr := fmt.Sprintf(ListenerFormat, port)
l, err := net.Listen("tcp4", addr)
if err == nil {
err := l.Close()
if err == nil {
return int(port)
}
}
port = atomic.AddUint32(&lastPort, 1)
}
// No ports available? Must be a mistake.
panic("no ports available for listening")
}
// GetLogDir returns the passed --logdir flag or the default value if it wasn't
// set.
func GetLogDir() string {
if logSubDir != nil && *logSubDir != "" {
return *logSubDir
}
return "."
}
// CopyFile copies the file src to dest.
func CopyFile(dest, src string) error {
s, err := os.Open(src)
if err != nil {
return err
}
defer s.Close()
d, err := os.Create(dest)
if err != nil {
return err
}
if _, err := io.Copy(d, s); err != nil {
d.Close()
return err
}
return d.Close()
}
// GetBtcdBinary returns the full path to the binary of the custom built btcd
// executable or an empty string if none is set.
func GetBtcdBinary() string {
if btcdExecutable != nil {
return *btcdExecutable
}
return ""
}
// GenerateBtcdListenerAddresses is a function that returns two listener
// addresses with unique ports and should be used to overwrite rpctest's
// default generator which is prone to use colliding ports.
func GenerateBtcdListenerAddresses() (string, string) {
return fmt.Sprintf(ListenerFormat, NextAvailablePort()),
fmt.Sprintf(ListenerFormat, NextAvailablePort())
}
// ApplyPortOffset adds the given offset to the lastPort variable, making it
// possible to run the tests in parallel without colliding on the same ports.
func ApplyPortOffset(offset uint32) {
_ = atomic.AddUint32(&lastPort, offset)
}

View file

@ -18,8 +18,7 @@ import (
"github.com/jackc/pgx/v4/pgxpool"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp/rpc"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/rpc"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/macaroons"
"google.golang.org/grpc"
@ -81,7 +80,7 @@ type HarnessNode struct {
// 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
runCtx context.Context //nolint:containedctx
cancel context.CancelFunc
// filename is the log file's name.
@ -117,9 +116,9 @@ func NewHarnessNode(t *testing.T, cfg *BaseNodeConfig) (*HarnessNode, error) {
// Create temporary database.
var dbName string
if cfg.DbBackend == lntest.BackendPostgres {
if cfg.DBBackend == BackendPostgres {
var err error
dbName, err = createTempPgDb()
dbName, err = createTempPgDB()
if err != nil {
return nil, err
}
@ -127,7 +126,7 @@ func NewHarnessNode(t *testing.T, cfg *BaseNodeConfig) (*HarnessNode, error) {
}
cfg.OriginalExtraArgs = cfg.ExtraArgs
cfg.postgresDbName = dbName
cfg.postgresDBName = dbName
return &HarnessNode{
T: t,
@ -324,7 +323,7 @@ func (hn *HarnessNode) ConnectRPCWithMacaroon(mac *macaroon.Macaroon) (
hn.Cfg.TLSCertPath, "",
)
return err
}, DefaultTimeout)
}, wait.DefaultTimeout)
if err != nil {
return nil, fmt.Errorf("error reading TLS cert: %v", err)
}
@ -334,7 +333,7 @@ func (hn *HarnessNode) ConnectRPCWithMacaroon(mac *macaroon.Macaroon) (
grpc.WithTransportCredentials(tlsCreds),
}
ctx, cancel := context.WithTimeout(hn.runCtx, DefaultTimeout)
ctx, cancel := context.WithTimeout(hn.runCtx, wait.DefaultTimeout)
defer cancel()
if mac == nil {
@ -354,7 +353,7 @@ func (hn *HarnessNode) ConnectRPCWithMacaroon(mac *macaroon.Macaroon) (
func (hn *HarnessNode) ConnectRPC() (*grpc.ClientConn, error) {
// If we should use a macaroon, always take the admin macaroon as a
// default.
mac, err := hn.ReadMacaroon(hn.Cfg.AdminMacPath, DefaultTimeout)
mac, err := hn.ReadMacaroon(hn.Cfg.AdminMacPath, wait.DefaultTimeout)
if err != nil {
return nil, err
}
@ -375,7 +374,7 @@ func (hn *HarnessNode) StartLndCmd(ctxb context.Context) error {
hn.runCtx, hn.cancel = context.WithCancel(ctxb)
args := hn.Cfg.GenArgs()
hn.cmd = exec.Command(hn.Cfg.LndBinary, args...) //nolint:gosec
hn.cmd = exec.Command(hn.Cfg.LndBinary, args...)
// Redirect stderr output to buffer
var errb bytes.Buffer
@ -383,7 +382,7 @@ func (hn *HarnessNode) StartLndCmd(ctxb context.Context) error {
// If the logoutput flag is passed, redirect output from the nodes to
// log files.
if *lntest.LogOutput {
if *logOutput {
err := addLogFile(hn)
if err != nil {
return err
@ -540,7 +539,7 @@ func (hn *HarnessNode) waitTillServerState(
for {
select {
case <-time.After(lntest.NodeStartTimeout):
case <-time.After(wait.NodeStartTimeout):
return fmt.Errorf("timeout waiting for server state")
case err := <-errChan:
return fmt.Errorf("receive server state err: %v", err)
@ -581,7 +580,7 @@ func (hn *HarnessNode) initLightningClient() error {
"got err: %v", err)
}
case <-time.After(DefaultTimeout):
case <-time.After(wait.DefaultTimeout):
return fmt.Errorf("timeout creating topology client stream")
}
@ -615,8 +614,8 @@ func (hn *HarnessNode) attachPubKey() error {
// cleanup cleans up all the temporary files created by the node's process.
func (hn *HarnessNode) cleanup() error {
if hn.Cfg.backupDbDir != "" {
err := os.RemoveAll(hn.Cfg.backupDbDir)
if hn.Cfg.backupDBDir != "" {
err := os.RemoveAll(hn.Cfg.backupDBDir)
if err != nil {
return fmt.Errorf("unable to remove backup dir: %v",
err)
@ -650,9 +649,10 @@ func (hn *HarnessNode) waitForProcessExit() {
// Otherwise, we print the error, break the select and save
// logs.
hn.printErrf("wait process exit got err: %v", err)
break
case <-time.After(DefaultTimeout * 2):
case <-time.After(wait.DefaultTimeout):
hn.printErrf("timeout waiting for process to exit")
}
@ -705,7 +705,7 @@ func (hn *HarnessNode) Stop() error {
default:
return nil
}
}, DefaultTimeout)
}, wait.DefaultTimeout)
if err != nil {
return err
}
@ -720,7 +720,7 @@ func (hn *HarnessNode) Stop() error {
// If the goroutines fail to finish before timeout, we'll print
// the error to console and continue.
select {
case <-time.After(DefaultTimeout):
case <-time.After(wait.DefaultTimeout):
hn.printErrf("timeout on wait group")
case <-done:
}
@ -784,23 +784,23 @@ func (hn *HarnessNode) Kill() error {
// printErrf prints an error to the console.
func (hn *HarnessNode) printErrf(format string, a ...interface{}) {
fmt.Printf("itest error from [%s:%s]: %s\n", // nolint:forbidigo
fmt.Printf("itest error from [%s:%s]: %s\n", //nolint:forbidigo
hn.Cfg.LogFilenamePrefix, hn.Cfg.Name,
fmt.Sprintf(format, a...))
}
// BackupDB creates a backup of the current database.
func (hn *HarnessNode) BackupDB() error {
if hn.Cfg.backupDbDir != "" {
if hn.Cfg.backupDBDir != "" {
return fmt.Errorf("backup already created")
}
if hn.Cfg.postgresDbName != "" {
if hn.Cfg.postgresDBName != "" {
// Backup database.
backupDBName := hn.Cfg.postgresDbName + "_backup"
backupDBName := hn.Cfg.postgresDBName + "_backup"
err := executePgQuery(
"CREATE DATABASE " + backupDBName + " WITH TEMPLATE " +
hn.Cfg.postgresDbName,
hn.Cfg.postgresDBName,
)
if err != nil {
return err
@ -818,7 +818,7 @@ func (hn *HarnessNode) BackupDB() error {
err)
}
hn.Cfg.backupDbDir = tempDir
hn.Cfg.backupDBDir = tempDir
}
return nil
@ -826,39 +826,39 @@ func (hn *HarnessNode) BackupDB() error {
// RestoreDB restores a database backup.
func (hn *HarnessNode) RestoreDB() error {
if hn.Cfg.postgresDbName != "" {
if hn.Cfg.postgresDBName != "" {
// Restore database.
backupDBName := hn.Cfg.postgresDbName + "_backup"
backupDBName := hn.Cfg.postgresDBName + "_backup"
err := executePgQuery(
"DROP DATABASE " + hn.Cfg.postgresDbName,
"DROP DATABASE " + hn.Cfg.postgresDBName,
)
if err != nil {
return err
}
err = executePgQuery(
"ALTER DATABASE " + backupDBName + " RENAME TO " +
hn.Cfg.postgresDbName,
hn.Cfg.postgresDBName,
)
if err != nil {
return err
}
} else {
// Restore files.
if hn.Cfg.backupDbDir == "" {
if hn.Cfg.backupDBDir == "" {
return fmt.Errorf("no database backup created")
}
err := copyAll(hn.Cfg.DBDir(), hn.Cfg.backupDbDir)
err := copyAll(hn.Cfg.DBDir(), hn.Cfg.backupDBDir)
if err != nil {
return fmt.Errorf("unable to copy database files: %w",
err)
}
if err := os.RemoveAll(hn.Cfg.backupDbDir); err != nil {
if err := os.RemoveAll(hn.Cfg.backupDBDir); err != nil {
return fmt.Errorf("unable to remove backup dir: %w",
err)
}
hn.Cfg.backupDbDir = ""
hn.Cfg.backupDBDir = ""
}
return nil
@ -868,8 +868,8 @@ func postgresDatabaseDsn(dbName string) string {
return fmt.Sprintf(postgresDsn, dbName)
}
// createTempPgDb creates a temp postgres database.
func createTempPgDb() (string, error) {
// createTempPgDB creates a temp postgres database.
func createTempPgDB() (string, error) {
// Create random database name.
randBytes := make([]byte, 8)
_, err := rand.Read(randBytes)
@ -918,10 +918,8 @@ func getFinalizedLogFilePrefix(hn *HarnessNode) string {
hn.PubKey[:logPubKeyBytes],
)
return fmt.Sprintf("%s/%d-%s-%s-%s",
lntest.GetLogDir(), hn.Cfg.NodeID,
hn.Cfg.LogFilenamePrefix,
hn.Cfg.Name, pubKeyHex)
return fmt.Sprintf("%s/%d-%s-%s-%s", GetLogDir(), hn.Cfg.NodeID,
hn.Cfg.LogFilenamePrefix, hn.Cfg.Name, pubKeyHex)
}
// finalizeLogfile makes sure the log file cleanup function is initialized,
@ -935,7 +933,7 @@ func finalizeLogfile(hn *HarnessNode) {
hn.logFile.Close()
// If logoutput flag is not set, return early.
if !*lntest.LogOutput {
if !*logOutput {
return
}
@ -948,7 +946,7 @@ func finalizeLogfile(hn *HarnessNode) {
// finalizeEtcdLog saves the etcd log files when test ends.
func finalizeEtcdLog(hn *HarnessNode) {
// Exit early if this is not etcd backend.
if hn.Cfg.DbBackend != lntest.BackendEtcd {
if hn.Cfg.DBBackend != BackendEtcd {
return
}
@ -964,7 +962,7 @@ func finalizeEtcdLog(hn *HarnessNode) {
func addLogFile(hn *HarnessNode) error {
var fileName string
dir := lntest.GetLogDir()
dir := GetLogDir()
fileName = fmt.Sprintf("%s/%d-%s-%s-%s.log", dir, hn.Cfg.NodeID,
hn.Cfg.LogFilenamePrefix, hn.Cfg.Name,
hex.EncodeToString(hn.PubKey[:logPubKeyBytes]))
@ -1028,7 +1026,7 @@ func copyAll(dstDir, srcDir string) error {
if err != nil {
return err
}
} else if err := lntest.CopyFile(dstPath, srcPath); err != nil {
} else if err := CopyFile(dstPath, srcPath); err != nil {
return err
}
}

View file

@ -9,7 +9,7 @@ import (
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntemp/rpc"
"github.com/lightningnetwork/lnd/lntest/rpc"
"github.com/lightningnetwork/lnd/lnutils"
)

View file

@ -11,8 +11,7 @@ import (
"github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lntemp/rpc"
"github.com/lightningnetwork/lnd/lntest"
"github.com/lightningnetwork/lnd/lntest/rpc"
"github.com/lightningnetwork/lnd/lntest/wait"
"github.com/lightningnetwork/lnd/lnutils"
)
@ -31,9 +30,6 @@ const (
// watchPolicyUpdate specifies that this is a request to watch a policy
// update event.
watchPolicyUpdate
// TODO(yy): remove once temp tests is finished.
DefaultTimeout = lntest.DefaultTimeout
)
// chanWatchRequest is a request to the lightningNetworkWatcher to be notified
@ -123,7 +119,7 @@ func (nw *nodeWatcher) WaitForNumChannelUpdates(op wire.OutPoint,
"want %d, got %d", expected, num)
}
return wait.NoError(checkNumUpdates, DefaultTimeout)
return wait.NoError(checkNumUpdates, wait.DefaultTimeout)
}
// WaitForNumNodeUpdates will block until a given number of node updates has
@ -142,8 +138,7 @@ func (nw *nodeWatcher) WaitForNumNodeUpdates(pubkey string,
return fmt.Errorf("timeout waiting for num node updates, "+
"want %d, got %d", expected, num)
}
err := wait.NoError(checkNumUpdates, DefaultTimeout)
err := wait.NoError(checkNumUpdates, wait.DefaultTimeout)
return updates, err
}
@ -161,7 +156,7 @@ func (nw *nodeWatcher) WaitForChannelOpen(chanPoint *lnrpc.ChannelPoint) error {
chanWatchType: watchOpenChannel,
}
timer := time.After(DefaultTimeout)
timer := time.After(wait.DefaultTimeout)
select {
case <-eventChan:
return nil
@ -192,7 +187,7 @@ func (nw *nodeWatcher) WaitForChannelClose(
chanWatchType: watchCloseChannel,
}
timer := time.After(DefaultTimeout)
timer := time.After(wait.DefaultTimeout)
select {
case <-eventChan:
closedChan, ok := nw.state.closedChans.Load(op)
@ -218,7 +213,7 @@ func (nw *nodeWatcher) WaitForChannelPolicyUpdate(
op := nw.rpc.MakeOutpoint(chanPoint)
ticker := time.NewTicker(wait.PollInterval)
timer := time.After(DefaultTimeout)
timer := time.After(wait.DefaultTimeout)
defer ticker.Stop()
eventChan := make(chan struct{})

Some files were not shown because too many files have changed in this diff Show more