Merge pull request #6825 from yyforyongyu/6-new-itest
itest: fix previously known test flakes
This commit is contained in:
134 files changed
+2162
-8844
No files matched your search
+11
-97
@@ -186,10 +186,10 @@ jobs:
|
|||||||
parallel: true
|
parallel: true
|
||||||
|
|
||||||
########################
|
########################
|
||||||
# run integration tests
|
# run ubuntu integration tests
|
||||||
########################
|
########################
|
||||||
integration-test:
|
ubuntu-integration-test:
|
||||||
name: run itests
|
name: run ubuntu itests
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')'
|
if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')'
|
||||||
strategy:
|
strategy:
|
||||||
@@ -230,17 +230,18 @@ jobs:
|
|||||||
|
|
||||||
- name: Zip log files on failure
|
- name: Zip log files on failure
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
timeout-minutes: 1 # timeout after 1 minute
|
timeout-minutes: 5 # timeout after 5 minute
|
||||||
run: 7z a logs-itest-${{ matrix.name }}.zip lntest/itest/**/*.log
|
run: 7z a logs-itest-${{ matrix.name }}.zip itest/**/*.log
|
||||||
|
|
||||||
- name: Upload log files on failure
|
- name: Upload log files on failure
|
||||||
uses: actions/upload-artifact@v2.2.4
|
uses: actions/upload-artifact@v3
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
with:
|
with:
|
||||||
name: logs-itest-${{ matrix.name }}
|
name: logs-itest-${{ matrix.name }}
|
||||||
path: logs-itest-${{ matrix.name }}.zip
|
path: logs-itest-${{ matrix.name }}.zip
|
||||||
retention-days: 5
|
retention-days: 5
|
||||||
|
|
||||||
|
|
||||||
########################
|
########################
|
||||||
# run windows integration test
|
# run windows integration test
|
||||||
########################
|
########################
|
||||||
@@ -258,102 +259,15 @@ jobs:
|
|||||||
go-version: '${{ env.GO_VERSION }}'
|
go-version: '${{ env.GO_VERSION }}'
|
||||||
|
|
||||||
- name: run itest
|
- 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
|
- name: Zip log files on failure
|
||||||
if: ${{ 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
|
- name: Upload log files on failure
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v3
|
||||||
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
|
|
||||||
if: ${{ failure() }}
|
if: ${{ failure() }}
|
||||||
with:
|
with:
|
||||||
name: logs-itest-windows
|
name: logs-itest-windows
|
||||||
|
|||||||
+6
-6
@@ -32,12 +32,12 @@ _testmain.go
|
|||||||
/lncli-itest
|
/lncli-itest
|
||||||
|
|
||||||
# Integration test log files
|
# Integration test log files
|
||||||
lntest/itest/*.log
|
itest/*.log
|
||||||
lntest/itest/.backendlogs
|
itest/.backendlogs
|
||||||
lntest/itest/.minerlogs
|
itest/.minerlogs
|
||||||
lntest/itest/lnd-itest
|
itest/lnd-itest
|
||||||
lntest/itest/btcd-itest
|
itest/btcd-itest
|
||||||
lntest/itest/.logs-*
|
itest/.logs-*
|
||||||
|
|
||||||
cmd/cmd
|
cmd/cmd
|
||||||
*.key
|
*.key
|
||||||
|
|||||||
+4
-7
@@ -27,6 +27,7 @@ run:
|
|||||||
- kvdb_etcd
|
- kvdb_etcd
|
||||||
- kvdb_postgres
|
- kvdb_postgres
|
||||||
- kvdb_sqlite
|
- kvdb_sqlite
|
||||||
|
- integration
|
||||||
|
|
||||||
linters-settings:
|
linters-settings:
|
||||||
govet:
|
govet:
|
||||||
@@ -96,6 +97,7 @@ linters-settings:
|
|||||||
ignored-functions:
|
ignored-functions:
|
||||||
- 'math.*'
|
- 'math.*'
|
||||||
- 'strconv.ParseInt'
|
- 'strconv.ParseInt'
|
||||||
|
- 'errors.Wrap'
|
||||||
|
|
||||||
|
|
||||||
linters:
|
linters:
|
||||||
@@ -237,14 +239,9 @@ issues:
|
|||||||
linters:
|
linters:
|
||||||
- forbidigo
|
- forbidigo
|
||||||
|
|
||||||
# Fix false positives because of build flags in itest directory.
|
- path: itest/.*
|
||||||
- path: lntest/itest/.*
|
|
||||||
linters:
|
linters:
|
||||||
- unused
|
- paralleltest
|
||||||
- unparam
|
|
||||||
- govet
|
|
||||||
# itest case can be very long so we disable long function check.
|
|
||||||
- funlen
|
|
||||||
|
|
||||||
- path: lnmock/*
|
- path: lnmock/*
|
||||||
linters:
|
linters:
|
||||||
|
|||||||
+2
-18
@@ -32,31 +32,15 @@ sudo: required
|
|||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
include:
|
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
|
- stage: Integration Test
|
||||||
name: Bitcoind Integration ARM
|
name: Bitcoind Integration ARM
|
||||||
script:
|
script:
|
||||||
- bash ./scripts/install_bitcoind.sh
|
- 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
|
arch: arm64
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
after_failure:
|
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 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'
|
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'
|
||||||
@@ -93,19 +93,19 @@ build:
|
|||||||
|
|
||||||
build-itest:
|
build-itest:
|
||||||
@$(call print, "Building itest btcd and lnd.")
|
@$(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="integration" -o 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="$(ITEST_TAGS)" -o itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd
|
||||||
|
|
||||||
@$(call print, "Building itest binary for ${backend} backend.")
|
@$(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:
|
build-itest-race:
|
||||||
@$(call print, "Building itest btcd and lnd with race detector.")
|
@$(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=0 $(GOBUILD) -tags="integration" -o 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=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.")
|
@$(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:
|
install:
|
||||||
@$(call print, "Installing lnd and lncli.")
|
@$(call print, "Installing lnd and lncli.")
|
||||||
@@ -164,7 +164,7 @@ endif
|
|||||||
|
|
||||||
itest-only: db-instance
|
itest-only: db-instance
|
||||||
@$(call print, "Running integration tests with ${backend} backend.")
|
@$(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)
|
EXEC_SUFFIX=$(EXEC_SUFFIX) scripts/itest_part.sh 0 1 $(TEST_FLAGS) $(ITEST_FLAGS)
|
||||||
|
|
||||||
itest: build-itest itest-only
|
itest: build-itest itest-only
|
||||||
@@ -173,7 +173,7 @@ itest-race: build-itest-race itest-only
|
|||||||
|
|
||||||
itest-parallel: build-itest db-instance
|
itest-parallel: build-itest db-instance
|
||||||
@$(call print, "Running tests")
|
@$(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)
|
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:
|
itest-clean:
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
//go:build rpctest
|
//go:build integration
|
||||||
// +build rpctest
|
|
||||||
|
|
||||||
package aezeed
|
package aezeed
|
||||||
|
|
||||||
@@ -1,6 +1,3 @@
|
|||||||
//go:build !rpctest
|
|
||||||
// +build !rpctest
|
|
||||||
|
|
||||||
package contractcourt
|
package contractcourt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -497,10 +497,10 @@ func newChainSet(chanState *channeldb.OpenChannel) (*chainSet, error) {
|
|||||||
"chan_point=%v", chanState.FundingOutpoint)
|
"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,
|
chanState.FundingOutpoint, chanState.ChanType,
|
||||||
spew.Sdump(localCommit))
|
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,
|
chanState.FundingOutpoint, chanState.ChanType,
|
||||||
spew.Sdump(remoteCommit))
|
spew.Sdump(remoteCommit))
|
||||||
|
|
||||||
@@ -527,7 +527,7 @@ func newChainSet(chanState *channeldb.OpenChannel) (*chainSet, error) {
|
|||||||
var remotePendingCommit *channeldb.ChannelCommitment
|
var remotePendingCommit *channeldb.ChannelCommitment
|
||||||
if remoteChainTip != nil {
|
if remoteChainTip != nil {
|
||||||
remotePendingCommit = &remoteChainTip.Commitment
|
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,
|
"remote_pending_commit=%v", chanState.FundingOutpoint,
|
||||||
chanState.ChanType,
|
chanState.ChanType,
|
||||||
spew.Sdump(remoteChainTip.Commitment))
|
spew.Sdump(remoteChainTip.Commitment))
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
//go:build !rpctest
|
|
||||||
// +build !rpctest
|
|
||||||
|
|
||||||
package contractcourt
|
package contractcourt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
//go:build !rpctest
|
|
||||||
// +build !rpctest
|
|
||||||
|
|
||||||
package contractcourt
|
package contractcourt
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -316,6 +316,11 @@ type Config struct {
|
|||||||
// ChannelID. This is used to sign updates for them if the channel has
|
// ChannelID. This is used to sign updates for them if the channel has
|
||||||
// no AuthProof and the option-scid-alias feature bit was negotiated.
|
// no AuthProof and the option-scid-alias feature bit was negotiated.
|
||||||
GetAlias func(lnwire.ChannelID) (lnwire.ShortChannelID, error)
|
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
|
// processedNetworkMsg is a wrapper around networkMsg and a boolean. It is
|
||||||
@@ -3016,6 +3021,16 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
|||||||
ann.ShortChannelID,
|
ann.ShortChannelID,
|
||||||
)
|
)
|
||||||
if err != nil {
|
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)
|
proof := channeldb.NewWaitingProof(nMsg.isRemote, ann)
|
||||||
err := d.cfg.WaitingProofStore.Add(proof)
|
err := d.cfg.WaitingProofStore.Add(proof)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -697,6 +697,12 @@ func createChannelAnnouncement(blockHeight uint32, key1, key2 *btcec.PrivateKey,
|
|||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mockFindChannel(node *btcec.PublicKey, chanID lnwire.ChannelID) (
|
||||||
|
*channeldb.OpenChannel, error) {
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
type testCtx struct {
|
type testCtx struct {
|
||||||
gossiper *AuthenticatedGossiper
|
gossiper *AuthenticatedGossiper
|
||||||
router *mockGraphSource
|
router *mockGraphSource
|
||||||
@@ -792,6 +798,7 @@ func createTestCtx(t *testing.T, startHeight uint32) (*testCtx, error) {
|
|||||||
SignAliasUpdate: signAliasUpdate,
|
SignAliasUpdate: signAliasUpdate,
|
||||||
FindBaseByAlias: findBaseByAlias,
|
FindBaseByAlias: findBaseByAlias,
|
||||||
GetAlias: getAlias,
|
GetAlias: getAlias,
|
||||||
|
FindChannel: mockFindChannel,
|
||||||
}, selfKeyDesc)
|
}, selfKeyDesc)
|
||||||
|
|
||||||
if err := gossiper.Start(); err != nil {
|
if err := gossiper.Start(); err != nil {
|
||||||
|
|||||||
@@ -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
|
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)
|
[`networkHarness`framework](https://github.com/lightningnetwork/lnd/blob/master/lntest/harness.go)
|
||||||
contained within `lnd`. For example integration tests, see
|
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
|
- 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).
|
shouldn't be any of those in the logs, see [Use of Log Levels](#use-of-log-levels).
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -44,7 +44,7 @@ to test the RPCs and to showcase the different use cases.
|
|||||||
### 3-of-3 Taproot key spend path (BIP-0086)
|
### 3-of-3 Taproot key spend path (BIP-0086)
|
||||||
|
|
||||||
See `testTaprootMuSig2KeySpendBip86` in
|
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.
|
the full code.
|
||||||
|
|
||||||
This example uses combines the public keys of 3 participants into a shared
|
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
|
### 3-of-3 Taproot key spend path with root hash commitment
|
||||||
|
|
||||||
See `testTaprootMuSig2KeySpendRootHash` in
|
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.
|
the full code.
|
||||||
|
|
||||||
This is very similar to the above example but with the main difference that the
|
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
|
### 3-of-3 `OP_CHECKSIG` in Taproot script spend path
|
||||||
|
|
||||||
See `testTaprootMuSig2CombinedLeafKeySpend` in
|
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.
|
the full code.
|
||||||
|
|
||||||
This example is definitely the most involved one. To be able to use a MuSig2
|
This example is definitely the most involved one. To be able to use a MuSig2
|
||||||
|
|||||||
@@ -487,7 +487,8 @@ PRs([6776](https://github.com/lightningnetwork/lnd/pull/6776),
|
|||||||
[7242](https://github.com/lightningnetwork/lnd/pull/7242),
|
[7242](https://github.com/lightningnetwork/lnd/pull/7242),
|
||||||
[7245](https://github.com/lightningnetwork/lnd/pull/7245)),
|
[7245](https://github.com/lightningnetwork/lnd/pull/7245)),
|
||||||
[6823](https://github.com/lightningnetwork/lnd/pull/6823),
|
[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.
|
refactor the itest for code health and maintenance.
|
||||||
|
|
||||||
# Contributors (Alphabetical Order)
|
# Contributors (Alphabetical Order)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
//go:build rpctest
|
//go:build integration
|
||||||
|
|
||||||
package funding
|
package funding
|
||||||
|
|
||||||
@@ -108,6 +108,11 @@ const (
|
|||||||
// for the funding transaction to be confirmed before forgetting
|
// for the funding transaction to be confirmed before forgetting
|
||||||
// channels that aren't initiated by us. 2016 blocks is ~2 weeks.
|
// channels that aren't initiated by us. 2016 blocks is ~2 weeks.
|
||||||
maxWaitNumBlocksFundingConf = 2016
|
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 (
|
var (
|
||||||
@@ -1320,6 +1325,25 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer,
|
|||||||
return
|
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
|
// 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
|
// synced to the network as we won't be able to properly validate the
|
||||||
// confirmation of the funding transaction.
|
// confirmation of the funding transaction.
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
//go:build !rpctest
|
|
||||||
// +build !rpctest
|
|
||||||
|
|
||||||
package funding
|
package funding
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
@@ -2743,6 +2743,15 @@ func (l *channelLink) handleSwitchPacket(pkt *htlcPacket) error {
|
|||||||
//
|
//
|
||||||
// NOTE: Part of the ChannelLink interface.
|
// NOTE: Part of the ChannelLink interface.
|
||||||
func (l *channelLink) HandleChannelUpdate(message lnwire.Message) {
|
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)
|
l.mailBox.AddMessage(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+106
@@ -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
|
||||||
|
```
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
//go:build !integration
|
||||||
|
|
||||||
|
package itest
|
||||||
|
|
||||||
|
import "github.com/lightningnetwork/lnd/lntest"
|
||||||
|
|
||||||
|
var allTestCases = []*lntest.TestCase{}
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
//go:build rpctest
|
//go:build integration
|
||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import "github.com/lightningnetwork/lnd/lntemp"
|
import "github.com/lightningnetwork/lnd/lntest"
|
||||||
|
|
||||||
// TODO(yy): remove the temp.
|
var allTestCases = []*lntest.TestCase{
|
||||||
var allTestCasesTemp = []*lntemp.TestCase{
|
|
||||||
{
|
{
|
||||||
Name: "update channel status",
|
Name: "update channel status",
|
||||||
TestFunc: testUpdateChanStatus,
|
TestFunc: testUpdateChanStatus,
|
||||||
@@ -509,4 +507,8 @@ var allTestCasesTemp = []*lntemp.TestCase{
|
|||||||
Name: "zero conf reorg edge existence",
|
Name: "zero conf reorg edge existence",
|
||||||
TestFunc: testZeroConfReorg,
|
TestFunc: testZeroConfReorg,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "async bidirectional payments",
|
||||||
|
TestFunc: testBidirectionalAsyncPayments,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
@@ -11,15 +11,15 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// testSendPaymentAMPInvoice tests that we can send an AMP payment to a
|
// testSendPaymentAMPInvoice tests that we can send an AMP payment to a
|
||||||
// specified AMP invoice using SendPaymentV2.
|
// specified AMP invoice using SendPaymentV2.
|
||||||
func testSendPaymentAMPInvoice(ht *lntemp.HarnessTest) {
|
func testSendPaymentAMPInvoice(ht *lntest.HarnessTest) {
|
||||||
succeed := ht.Run("native payaddr", func(t *testing.T) {
|
succeed := ht.Run("native payaddr", func(t *testing.T) {
|
||||||
tt := ht.Subtest(t)
|
tt := ht.Subtest(t)
|
||||||
testSendPaymentAMPInvoiceCase(tt, false)
|
testSendPaymentAMPInvoiceCase(tt, false)
|
||||||
@@ -36,7 +36,7 @@ func testSendPaymentAMPInvoice(ht *lntemp.HarnessTest) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSendPaymentAMPInvoiceCase(ht *lntemp.HarnessTest,
|
func testSendPaymentAMPInvoiceCase(ht *lntest.HarnessTest,
|
||||||
useExternalPayAddr bool) {
|
useExternalPayAddr bool) {
|
||||||
|
|
||||||
mts := newMppTestScenario(ht)
|
mts := newMppTestScenario(ht)
|
||||||
@@ -196,7 +196,7 @@ func testSendPaymentAMPInvoiceCase(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// testSendPaymentAMPInvoiceRepeat tests that it's possible to pay an AMP
|
// testSendPaymentAMPInvoiceRepeat tests that it's possible to pay an AMP
|
||||||
// invoice multiple times by having the client generate a new setID each time.
|
// 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
|
// 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
|
// primarily test the recurring payment feature. So we'll re-use the
|
||||||
carol := ht.NewNode("Carol", nil)
|
carol := ht.NewNode("Carol", nil)
|
||||||
@@ -218,7 +218,7 @@ func testSendPaymentAMPInvoiceRepeat(ht *lntemp.HarnessTest) {
|
|||||||
// Establish a channel between Carol and Dave.
|
// Establish a channel between Carol and Dave.
|
||||||
chanAmt := btcutil.Amount(100_000)
|
chanAmt := btcutil.Amount(100_000)
|
||||||
ht.OpenChannel(
|
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
|
// 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
|
// testSendPaymentAMP tests that we can send an AMP payment to a specified
|
||||||
// destination using SendPaymentV2.
|
// destination using SendPaymentV2.
|
||||||
func testSendPaymentAMP(ht *lntemp.HarnessTest) {
|
func testSendPaymentAMP(ht *lntest.HarnessTest) {
|
||||||
mts := newMppTestScenario(ht)
|
mts := newMppTestScenario(ht)
|
||||||
const paymentAmt = btcutil.Amount(300000)
|
const paymentAmt = btcutil.Amount(300000)
|
||||||
|
|
||||||
@@ -460,7 +460,7 @@ func testSendPaymentAMP(ht *lntemp.HarnessTest) {
|
|||||||
mts.closeChannels()
|
mts.closeChannels()
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSendToRouteAMP(ht *lntemp.HarnessTest) {
|
func testSendToRouteAMP(ht *lntest.HarnessTest) {
|
||||||
mts := newMppTestScenario(ht)
|
mts := newMppTestScenario(ht)
|
||||||
const (
|
const (
|
||||||
paymentAmt = btcutil.Amount(300000)
|
paymentAmt = btcutil.Amount(300000)
|
||||||
@@ -18,8 +18,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/funding"
|
"github.com/lightningnetwork/lnd/funding"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -34,7 +34,7 @@ type (
|
|||||||
// that'll return the same node, but with its state restored via a
|
// 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
|
// custom method. We use this to abstract away _how_ a node is restored
|
||||||
// from our assertions once the node has been fully restored itself.
|
// 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,
|
oldNode *node.HarnessNode, backupFilePath string,
|
||||||
password []byte, mnemonic []string) nodeRestorer
|
password []byte, mnemonic []string) nodeRestorer
|
||||||
)
|
)
|
||||||
@@ -50,12 +50,12 @@ type chanRestoreScenario struct {
|
|||||||
dave *node.HarnessNode
|
dave *node.HarnessNode
|
||||||
password []byte
|
password []byte
|
||||||
mnemonic []string
|
mnemonic []string
|
||||||
params lntemp.OpenChannelParams
|
params lntest.OpenChannelParams
|
||||||
}
|
}
|
||||||
|
|
||||||
// newChanRestoreScenario creates a new scenario that has two nodes, Carol and
|
// newChanRestoreScenario creates a new scenario that has two nodes, Carol and
|
||||||
// Dave, connected and funded.
|
// Dave, connected and funded.
|
||||||
func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
|
func newChanRestoreScenario(ht *lntest.HarnessTest, ct lnrpc.CommitmentType,
|
||||||
zeroConf bool) *chanRestoreScenario {
|
zeroConf bool) *chanRestoreScenario {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -70,7 +70,7 @@ func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ct != lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE {
|
if ct != lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE {
|
||||||
args := nodeArgsForCommitType(ct)
|
args := lntest.NodeArgsForCommitType(ct)
|
||||||
nodeArgs = append(nodeArgs, args...)
|
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
|
// For the anchor output case we need two UTXOs for Carol so she can
|
||||||
// sweep both the local and remote anchor.
|
// sweep both the local and remote anchor.
|
||||||
if commitTypeHasAnchors(ct) {
|
if lntest.CommitTypeHasAnchors(ct) {
|
||||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,7 +112,7 @@ func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
|
|||||||
dave: dave,
|
dave: dave,
|
||||||
mnemonic: mnemonic,
|
mnemonic: mnemonic,
|
||||||
password: password,
|
password: password,
|
||||||
params: lntemp.OpenChannelParams{
|
params: lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
ZeroConf: zeroConf,
|
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
|
// restoreDave will call the `nodeRestorer` and asserts Dave is restored by
|
||||||
// checking his wallet balance against zero.
|
// checking his wallet balance against zero.
|
||||||
func (c *chanRestoreScenario) restoreDave(ht *lntemp.HarnessTest,
|
func (c *chanRestoreScenario) restoreDave(ht *lntest.HarnessTest,
|
||||||
restoredNodeFunc nodeRestorer) *node.HarnessNode {
|
restoredNodeFunc nodeRestorer) *node.HarnessNode {
|
||||||
|
|
||||||
// Next, we'll make a new Dave and start the bulk of our recovery
|
// 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.
|
// 4. validate pending channel state and check we cannot force close it.
|
||||||
// 5. validate Carol's UTXOs.
|
// 5. validate Carol's UTXOs.
|
||||||
// 6. assert DLP is executed.
|
// 6. assert DLP is executed.
|
||||||
func (c *chanRestoreScenario) testScenario(ht *lntemp.HarnessTest,
|
func (c *chanRestoreScenario) testScenario(ht *lntest.HarnessTest,
|
||||||
restoredNodeFunc nodeRestorer) {
|
restoredNodeFunc nodeRestorer) {
|
||||||
|
|
||||||
carol, dave := c.carol, c.dave
|
carol, dave := c.carol, c.dave
|
||||||
@@ -212,7 +212,7 @@ func (c *chanRestoreScenario) testScenario(ht *lntemp.HarnessTest,
|
|||||||
// let's start up Carol again.
|
// let's start up Carol again.
|
||||||
require.NoError(ht, restartCarol(), "restart carol failed")
|
require.NoError(ht, restartCarol(), "restart carol failed")
|
||||||
|
|
||||||
if commitTypeHasAnchors(c.params.CommitmentType) {
|
if lntest.CommitTypeHasAnchors(c.params.CommitmentType) {
|
||||||
ht.AssertNumUTXOs(carol, 2)
|
ht.AssertNumUTXOs(carol, 2)
|
||||||
} else {
|
} else {
|
||||||
ht.AssertNumUTXOs(carol, 1)
|
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 from initial wallet creation. We'll also alternate between
|
||||||
// restoring form the on disk file, and restoring from the exported RPC command
|
// restoring form the on disk file, and restoring from the exported RPC command
|
||||||
// as well.
|
// as well.
|
||||||
func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
func testChannelBackupRestoreBasic(ht *lntest.HarnessTest) {
|
||||||
var testCases = []struct {
|
var testCases = []struct {
|
||||||
name string
|
name string
|
||||||
restoreMethod restoreMethodType
|
restoreMethod restoreMethodType
|
||||||
@@ -241,7 +241,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||||||
// was the initiator, of the non-advertised channel.
|
// was the initiator, of the non-advertised channel.
|
||||||
{
|
{
|
||||||
name: "restore from RPC backup",
|
name: "restore from RPC backup",
|
||||||
restoreMethod: func(st *lntemp.HarnessTest,
|
restoreMethod: func(st *lntest.HarnessTest,
|
||||||
oldNode *node.HarnessNode,
|
oldNode *node.HarnessNode,
|
||||||
backupFilePath string,
|
backupFilePath string,
|
||||||
password []byte,
|
password []byte,
|
||||||
@@ -269,7 +269,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||||||
// interface.
|
// interface.
|
||||||
{
|
{
|
||||||
name: "restore from backup file",
|
name: "restore from backup file",
|
||||||
restoreMethod: func(st *lntemp.HarnessTest,
|
restoreMethod: func(st *lntest.HarnessTest,
|
||||||
oldNode *node.HarnessNode,
|
oldNode *node.HarnessNode,
|
||||||
backupFilePath string,
|
backupFilePath string,
|
||||||
password []byte,
|
password []byte,
|
||||||
@@ -293,7 +293,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||||||
// prior mnemonic and new backup seed.
|
// prior mnemonic and new backup seed.
|
||||||
{
|
{
|
||||||
name: "restore during creation",
|
name: "restore during creation",
|
||||||
restoreMethod: func(st *lntemp.HarnessTest,
|
restoreMethod: func(st *lntest.HarnessTest,
|
||||||
oldNode *node.HarnessNode,
|
oldNode *node.HarnessNode,
|
||||||
backupFilePath string,
|
backupFilePath string,
|
||||||
password []byte,
|
password []byte,
|
||||||
@@ -325,7 +325,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||||||
// re-created, using the Unlock call.
|
// re-created, using the Unlock call.
|
||||||
{
|
{
|
||||||
name: "restore during unlock",
|
name: "restore during unlock",
|
||||||
restoreMethod: func(st *lntemp.HarnessTest,
|
restoreMethod: func(st *lntest.HarnessTest,
|
||||||
oldNode *node.HarnessNode,
|
oldNode *node.HarnessNode,
|
||||||
backupFilePath string,
|
backupFilePath string,
|
||||||
password []byte,
|
password []byte,
|
||||||
@@ -362,7 +362,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||||||
// make sure imports can be canceled and later resumed.
|
// make sure imports can be canceled and later resumed.
|
||||||
{
|
{
|
||||||
name: "restore from backup file twice",
|
name: "restore from backup file twice",
|
||||||
restoreMethod: func(st *lntemp.HarnessTest,
|
restoreMethod: func(st *lntest.HarnessTest,
|
||||||
oldNode *node.HarnessNode,
|
oldNode *node.HarnessNode,
|
||||||
backupFilePath string,
|
backupFilePath string,
|
||||||
password []byte,
|
password []byte,
|
||||||
@@ -376,6 +376,8 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||||||
// Now that we have Dave's backup file, we'll
|
// Now that we have Dave's backup file, we'll
|
||||||
// create a new nodeRestorer that will restore
|
// create a new nodeRestorer that will restore
|
||||||
// using the on-disk channel.backup.
|
// using the on-disk channel.backup.
|
||||||
|
//
|
||||||
|
//nolint:lll
|
||||||
backup := &lnrpc.RestoreChanBackupRequest_MultiChanBackup{
|
backup := &lnrpc.RestoreChanBackupRequest_MultiChanBackup{
|
||||||
MultiChanBackup: multi,
|
MultiChanBackup: multi,
|
||||||
}
|
}
|
||||||
@@ -420,7 +422,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||||||
// ensuring that after Dave restores his channel state according to the
|
// ensuring that after Dave restores his channel state according to the
|
||||||
// testCase, the DLP protocol is executed properly and both nodes are made
|
// testCase, the DLP protocol is executed properly and both nodes are made
|
||||||
// whole.
|
// whole.
|
||||||
func runChanRestoreScenarioBasic(ht *lntemp.HarnessTest,
|
func runChanRestoreScenarioBasic(ht *lntest.HarnessTest,
|
||||||
restoreMethod restoreMethodType) {
|
restoreMethod restoreMethodType) {
|
||||||
|
|
||||||
// Create a new retore scenario.
|
// Create a new retore scenario.
|
||||||
@@ -445,7 +447,7 @@ func runChanRestoreScenarioBasic(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// testChannelBackupRestoreUnconfirmed tests that we're able to restore from
|
// testChannelBackupRestoreUnconfirmed tests that we're able to restore from
|
||||||
// disk file and the exported RPC command for unconfirmed channel.
|
// 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
|
// Use the channel backup file that contains an unconfirmed channel and
|
||||||
// make sure recovery works as well.
|
// make sure recovery works as well.
|
||||||
ht.Run("restore unconfirmed channel file", func(t *testing.T) {
|
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
|
// runChanRestoreScenarioUnConfirmed checks that Dave is able to restore for an
|
||||||
// unconfirmed channel.
|
// unconfirmed channel.
|
||||||
func runChanRestoreScenarioUnConfirmed(ht *lntemp.HarnessTest, useFile bool) {
|
func runChanRestoreScenarioUnConfirmed(ht *lntest.HarnessTest, useFile bool) {
|
||||||
// Create a new retore scenario.
|
// Create a new retore scenario.
|
||||||
crs := newChanRestoreScenario(
|
crs := newChanRestoreScenario(
|
||||||
ht, lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE, false,
|
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,
|
// testChannelBackupRestoreCommitTypes tests that we're able to recover from,
|
||||||
// and initiate the DLP protocol for different channel commitment types and
|
// and initiate the DLP protocol for different channel commitment types and
|
||||||
// zero-conf channel.
|
// zero-conf channel.
|
||||||
func testChannelBackupRestoreCommitTypes(ht *lntemp.HarnessTest) {
|
func testChannelBackupRestoreCommitTypes(ht *lntest.HarnessTest) {
|
||||||
var testCases = []struct {
|
var testCases = []struct {
|
||||||
name string
|
name string
|
||||||
ct lnrpc.CommitmentType
|
ct lnrpc.CommitmentType
|
||||||
@@ -584,7 +586,7 @@ func testChannelBackupRestoreCommitTypes(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// runChanRestoreScenarioCommitTypes tests that the DLP is applied for
|
// runChanRestoreScenarioCommitTypes tests that the DLP is applied for
|
||||||
// different channel commitment types and zero-conf channel.
|
// different channel commitment types and zero-conf channel.
|
||||||
func runChanRestoreScenarioCommitTypes(ht *lntemp.HarnessTest,
|
func runChanRestoreScenarioCommitTypes(ht *lntest.HarnessTest,
|
||||||
ct lnrpc.CommitmentType, zeroConf bool) {
|
ct lnrpc.CommitmentType, zeroConf bool) {
|
||||||
|
|
||||||
// Create a new retore scenario.
|
// Create a new retore scenario.
|
||||||
@@ -606,7 +608,7 @@ func runChanRestoreScenarioCommitTypes(ht *lntemp.HarnessTest,
|
|||||||
_, minerHeight := ht.Miner.GetBestBlock()
|
_, minerHeight := ht.Miner.GetBestBlock()
|
||||||
thawHeight := uint32(minerHeight + thawHeightDelta)
|
thawHeight := uint32(minerHeight + thawHeightDelta)
|
||||||
|
|
||||||
fundingShim, _, _ = deriveFundingShim(
|
fundingShim, _ = deriveFundingShim(
|
||||||
ht, dave, carol, crs.params.Amt, thawHeight, true,
|
ht, dave, carol, crs.params.Amt, thawHeight, true,
|
||||||
)
|
)
|
||||||
crs.params.FundingShim = fundingShim
|
crs.params.FundingShim = fundingShim
|
||||||
@@ -639,7 +641,7 @@ func runChanRestoreScenarioCommitTypes(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// testChannelBackupRestoreLegacy checks a channel with the legacy revocation
|
// testChannelBackupRestoreLegacy checks a channel with the legacy revocation
|
||||||
// producer format and makes sure old SCBs can still be recovered.
|
// 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.
|
// Create a new retore scenario.
|
||||||
crs := newChanRestoreScenario(
|
crs := newChanRestoreScenario(
|
||||||
ht, lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE, false,
|
ht, lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE, false,
|
||||||
@@ -668,7 +670,7 @@ func testChannelBackupRestoreLegacy(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// testChannelBackupRestoreForceClose checks that Dave can restore from force
|
// testChannelBackupRestoreForceClose checks that Dave can restore from force
|
||||||
// closed channels.
|
// closed channels.
|
||||||
func testChannelBackupRestoreForceClose(ht *lntemp.HarnessTest) {
|
func testChannelBackupRestoreForceClose(ht *lntest.HarnessTest) {
|
||||||
// Restore a channel that was force closed by dave just before going
|
// Restore a channel that was force closed by dave just before going
|
||||||
// offline.
|
// offline.
|
||||||
success := ht.Run("from backup file anchors", func(t *testing.T) {
|
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
|
// runChanRestoreScenarioForceClose creates anchor-enabled force close channels
|
||||||
// and checks that Dave is able to restore from them.
|
// 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(
|
crs := newChanRestoreScenario(
|
||||||
ht, lnrpc.CommitmentType_ANCHORS, zeroConf,
|
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,
|
// testChannelBackupUpdates tests that both the streaming channel update RPC,
|
||||||
// and the on-disk channel.backup are updated each time a channel is
|
// and the on-disk channel.backup are updated each time a channel is
|
||||||
// opened/closed.
|
// opened/closed.
|
||||||
func testChannelBackupUpdates(ht *lntemp.HarnessTest) {
|
func testChannelBackupUpdates(ht *lntest.HarnessTest) {
|
||||||
alice := ht.Alice
|
alice := ht.Alice
|
||||||
|
|
||||||
// First, we'll make a temp directory that we'll use to store our
|
// 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)
|
chanAmt := btcutil.Amount(1000000)
|
||||||
for i := 0; i < numChans; i++ {
|
for i := 0; i < numChans; i++ {
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
alice, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
chanPoints = append(chanPoints, chanPoint)
|
chanPoints = append(chanPoints, chanPoint)
|
||||||
}
|
}
|
||||||
@@ -962,7 +964,7 @@ func testChannelBackupUpdates(ht *lntemp.HarnessTest) {
|
|||||||
// testExportChannelBackup tests that we're able to properly export either a
|
// testExportChannelBackup tests that we're able to properly export either a
|
||||||
// targeted channel's backup, or export backups of all the currents open
|
// targeted channel's backup, or export backups of all the currents open
|
||||||
// channels.
|
// 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
|
// 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
|
// open channels and also export backups that we'll examine throughout
|
||||||
// the test.
|
// the test.
|
||||||
@@ -979,7 +981,7 @@ func testExportChannelBackup(ht *lntemp.HarnessTest) {
|
|||||||
chanAmt := btcutil.Amount(1000000)
|
chanAmt := btcutil.Amount(1000000)
|
||||||
for i := 0; i < numChans; i++ {
|
for i := 0; i < numChans; i++ {
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
alice, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
chanPoints = append(chanPoints, chanPoint)
|
chanPoints = append(chanPoints, chanPoint)
|
||||||
}
|
}
|
||||||
@@ -1022,17 +1024,20 @@ func testExportChannelBackup(ht *lntemp.HarnessTest) {
|
|||||||
require.NoError(ht, err, "timeout checking num single backup")
|
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()
|
chanSnapshot := carol.RPC.ExportAllChanBackups()
|
||||||
|
|
||||||
return func(found bool, chanPoints map[wire.OutPoint]struct{}) {
|
return func(found bool, chanPoints map[wire.OutPoint]struct{}) {
|
||||||
|
num := len(chanSnapshot.MultiChanBackup.MultiChanBackup)
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case found && chanSnapshot.MultiChanBackup == nil:
|
case found && chanSnapshot.MultiChanBackup == nil:
|
||||||
require.Fail(ht, "multi-backup not present")
|
require.Fail(ht, "multi-backup not present")
|
||||||
|
|
||||||
case !found && chanSnapshot.MultiChanBackup != nil &&
|
case !found && chanSnapshot.MultiChanBackup != nil &&
|
||||||
(len(chanSnapshot.MultiChanBackup.MultiChanBackup) !=
|
num != chanbackup.NilMultiSizePacked:
|
||||||
chanbackup.NilMultiSizePacked):
|
|
||||||
|
|
||||||
require.Fail(ht, "found multi-backup when "+
|
require.Fail(ht, "found multi-backup when "+
|
||||||
"non should be found")
|
"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
|
// 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
|
// up-to-date party will force close the channel, giving the outdated party the
|
||||||
// opportunity to sweep its output.
|
// opportunity to sweep its output.
|
||||||
func testDataLossProtection(ht *lntemp.HarnessTest) {
|
func testDataLossProtection(ht *lntest.HarnessTest) {
|
||||||
const (
|
const (
|
||||||
chanAmt = funding.MaxBtcFundingAmount
|
chanAmt = funding.MaxBtcFundingAmount
|
||||||
paymentAmt = 10000
|
paymentAmt = 10000
|
||||||
@@ -1107,22 +1112,20 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
|
|||||||
// directly from the miner.
|
// directly from the miner.
|
||||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||||
|
|
||||||
// timeTravel is a method that will make Carol open a channel to the
|
// timeTravelDave is a method that will make Carol open a channel to
|
||||||
// passed node, settle a series of payments, then reset the node back
|
// Dave, settle a series of payments, then Dave back to the state
|
||||||
// to the state before the payments happened. When this method returns
|
// before the payments happened. When this method returns Dave will
|
||||||
// the node will be unaware of the new state updates. The returned
|
// be unaware of the new state updates. The returned function can be
|
||||||
// function can be used to restart the node in this state.
|
// used to restart Dave in this state.
|
||||||
timeTravel := func(node *node.HarnessNode) (func() error,
|
timeTravelDave := func() (func() error, *lnrpc.ChannelPoint, int64) {
|
||||||
*lnrpc.ChannelPoint, int64) {
|
|
||||||
|
|
||||||
// We must let the node communicate with Carol before they are
|
// We must let the node communicate with Carol before they are
|
||||||
// able to open channel, so we connect them.
|
// 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
|
// We'll first open up a channel between them with a 0.5 BTC
|
||||||
// value.
|
// value.
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
carol, node, lntemp.OpenChannelParams{
|
carol, dave, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -1132,17 +1135,17 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
|
|||||||
// the channel.
|
// the channel.
|
||||||
// TODO(halseth): have dangling HTLCs on the commitment, able to
|
// TODO(halseth): have dangling HTLCs on the commitment, able to
|
||||||
// retrieve funds?
|
// retrieve funds?
|
||||||
payReqs, _, _ := ht.CreatePayReqs(node, paymentAmt, numInvoices)
|
payReqs, _, _ := ht.CreatePayReqs(dave, paymentAmt, numInvoices)
|
||||||
|
|
||||||
// Send payments from Carol using 3 of the payment hashes
|
// Send payments from Carol using 3 of the payment hashes
|
||||||
// generated above.
|
// generated above.
|
||||||
ht.CompletePaymentRequests(carol, payReqs[:numInvoices/2])
|
ht.CompletePaymentRequests(carol, payReqs[:numInvoices/2])
|
||||||
|
|
||||||
// Next query for the node's channel state, as we sent 3
|
// Next query for Dave's channel state, as we sent 3 payments
|
||||||
// payments of 10k satoshis each, it should now see his balance
|
// of 10k satoshis each, it should now see his balance as being
|
||||||
// as being 30k satoshis.
|
// 30k satoshis.
|
||||||
nodeChan := ht.AssertChannelLocalBalance(
|
nodeChan := ht.AssertChannelLocalBalance(
|
||||||
node, chanPoint, 30_000,
|
dave, chanPoint, 30_000,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Grab the current commitment height (update number), we'll
|
// 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
|
// With the temporary file created, copy the current state into
|
||||||
// the temporary file we created above. Later after more
|
// the temporary file we created above. Later after more
|
||||||
// updates, we'll restore this state.
|
// updates, we'll restore this state.
|
||||||
ht.BackupDB(node)
|
ht.BackupDB(dave)
|
||||||
|
|
||||||
// Reconnect the peers after the restart that was needed for
|
// Reconnect the peers after the restart that was needed for
|
||||||
// the db backup.
|
// 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.
|
// payment hashes.
|
||||||
ht.CompletePaymentRequests(carol, payReqs[numInvoices/2:])
|
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
|
// database state which has the *prior* channel state over his
|
||||||
// current most up to date state. With this, we essentially
|
// 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.
|
// history.
|
||||||
ht.RestartNodeAndRestoreDB(node)
|
ht.RestartNodeAndRestoreDB(dave)
|
||||||
|
|
||||||
// Make sure the channel is still there from the PoV of the
|
// Make sure the channel is still there from the PoV of Dave.
|
||||||
// node.
|
ht.AssertNodeNumChannels(dave, 1)
|
||||||
ht.AssertNodeNumChannels(node, 1)
|
|
||||||
|
|
||||||
// Now query for the channel state, it should show that it's at
|
// Now query for the channel state, it should show that it's at
|
||||||
// a state number in the past, not the *latest* state.
|
// a state number in the past, not the *latest* state.
|
||||||
ht.AssertChannelNumUpdates(node, stateNumPreCopy, chanPoint)
|
ht.AssertChannelNumUpdates(dave, stateNumPreCopy, chanPoint)
|
||||||
|
|
||||||
balResp := node.RPC.WalletBalance()
|
balResp := dave.RPC.WalletBalance()
|
||||||
restart := ht.SuspendNode(node)
|
restart := ht.SuspendNode(dave)
|
||||||
|
|
||||||
return restart, chanPoint, balResp.ConfirmedBalance
|
return restart, chanPoint, balResp.ConfirmedBalance
|
||||||
}
|
}
|
||||||
|
|
||||||
// Reset Dave to a state where he has an outdated channel state.
|
// 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
|
// We make a note of the nodes' current on-chain balances, to make sure
|
||||||
// they are able to retrieve the channel funds eventually,
|
// 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.
|
// closed channel, such that Dave can retrieve his funds.
|
||||||
//
|
//
|
||||||
// We start by letting Dave time travel back to an outdated state.
|
// 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()
|
carolBalResp = carol.RPC.WalletBalance()
|
||||||
carolStartingBalance = carolBalResp.ConfirmedBalance
|
carolStartingBalance = carolBalResp.ConfirmedBalance
|
||||||
@@ -1255,7 +1265,7 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
|
|||||||
// createLegacyRevocationChannel creates a single channel using the legacy
|
// createLegacyRevocationChannel creates a single channel using the legacy
|
||||||
// revocation producer format by using PSBT to signal a special pending channel
|
// revocation producer format by using PSBT to signal a special pending channel
|
||||||
// ID.
|
// ID.
|
||||||
func createLegacyRevocationChannel(ht *lntemp.HarnessTest,
|
func createLegacyRevocationChannel(ht *lntest.HarnessTest,
|
||||||
chanAmt, pushAmt btcutil.Amount, from, to *node.HarnessNode) {
|
chanAmt, pushAmt btcutil.Amount, from, to *node.HarnessNode) {
|
||||||
|
|
||||||
// We'll signal to the wallet that we also want to create a channel
|
// 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,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
FundingShim: shim,
|
FundingShim: shim,
|
||||||
@@ -1295,8 +1305,9 @@ func createLegacyRevocationChannel(ht *lntemp.HarnessTest,
|
|||||||
}
|
}
|
||||||
fundResp := from.RPC.FundPsbt(fundReq)
|
fundResp := from.RPC.FundPsbt(fundReq)
|
||||||
|
|
||||||
// We have a PSBT that has no witness data yet, which is exactly what we
|
// We have a PSBT that has no witness data yet, which is exactly what
|
||||||
// need for the next step of verifying the PSBT with the funding intents.
|
// we need for the next step of verifying the PSBT with the funding
|
||||||
|
// intents.
|
||||||
msg := &lnrpc.FundingTransitionMsg{
|
msg := &lnrpc.FundingTransitionMsg{
|
||||||
Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{
|
Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{
|
||||||
PsbtVerify: &lnrpc.FundingPsbtVerify{
|
PsbtVerify: &lnrpc.FundingPsbtVerify{
|
||||||
@@ -1345,7 +1356,7 @@ func createLegacyRevocationChannel(ht *lntemp.HarnessTest,
|
|||||||
// chanRestoreViaRPC is a helper test method that returns a nodeRestorer
|
// chanRestoreViaRPC is a helper test method that returns a nodeRestorer
|
||||||
// instance which will restore the target node from a password+seed, then
|
// instance which will restore the target node from a password+seed, then
|
||||||
// trigger a SCB restore using the RPC interface.
|
// 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,
|
mnemonic []string, multi []byte,
|
||||||
oldNode *node.HarnessNode) nodeRestorer {
|
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
|
// Note: this function is only used in this test file and has been made
|
||||||
// specifically for testChanRestoreScenario.
|
// specifically for testChanRestoreScenario.
|
||||||
func assertTimeLockSwept(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode,
|
func assertTimeLockSwept(ht *lntest.HarnessTest, carol, dave *node.HarnessNode,
|
||||||
carolStartingBalance, daveStartingBalance int64) {
|
carolStartingBalance, daveStartingBalance int64) {
|
||||||
|
|
||||||
// We expect Carol to sweep her funds and also the anchor tx.
|
// 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
|
// 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
|
// 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.
|
// 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,
|
carol *node.HarnessNode, carolStartingBalance int64,
|
||||||
dave *node.HarnessNode, daveStartingBalance int64,
|
dave *node.HarnessNode, daveStartingBalance int64,
|
||||||
commitType lnrpc.CommitmentType) {
|
commitType lnrpc.CommitmentType) {
|
||||||
|
|
||||||
|
ht.Helper()
|
||||||
|
|
||||||
// Increase the fee estimate so that the following force close tx will
|
// Increase the fee estimate so that the following force close tx will
|
||||||
// be cpfp'ed.
|
// be cpfp'ed.
|
||||||
ht.SetFeeEstimate(30000)
|
ht.SetFeeEstimate(30000)
|
||||||
@@ -1467,7 +1480,7 @@ func assertDLPExecuted(ht *lntemp.HarnessTest,
|
|||||||
// Upon reconnection, the nodes should detect that Dave is out of sync.
|
// Upon reconnection, the nodes should detect that Dave is out of sync.
|
||||||
// Carol should force close the channel using her latest commitment.
|
// Carol should force close the channel using her latest commitment.
|
||||||
expectedTxes := 1
|
expectedTxes := 1
|
||||||
if commitTypeHasAnchors(commitType) {
|
if lntest.CommitTypeHasAnchors(commitType) {
|
||||||
expectedTxes = 2
|
expectedTxes = 2
|
||||||
}
|
}
|
||||||
ht.Miner.AssertNumTxsInMempool(expectedTxes)
|
ht.Miner.AssertNumTxsInMempool(expectedTxes)
|
||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/funding"
|
"github.com/lightningnetwork/lnd/funding"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
// testChannelBalance creates a new channel between Alice and Bob, then checks
|
// testChannelBalance creates a new channel between Alice and Bob, then checks
|
||||||
// channel balance to be equal amount specified while creation of channel.
|
// 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
|
// Open a channel with 0.16 BTC between Alice and Bob, ensuring the
|
||||||
// channel has been opened properly.
|
// channel has been opened properly.
|
||||||
amount := funding.MaxBtcFundingAmount
|
amount := funding.MaxBtcFundingAmount
|
||||||
@@ -52,16 +52,16 @@ func testChannelBalance(ht *lntemp.HarnessTest) {
|
|||||||
ht.EnsureConnected(alice, bob)
|
ht.EnsureConnected(alice, bob)
|
||||||
|
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{Amt: amount},
|
alice, bob, lntest.OpenChannelParams{Amt: amount},
|
||||||
)
|
)
|
||||||
cType := ht.GetChannelCommitType(alice, chanPoint)
|
cType := ht.GetChannelCommitType(alice, chanPoint)
|
||||||
|
|
||||||
// As this is a single funder channel, Alice's balance should be
|
// As this is a single funder channel, Alice's balance should be
|
||||||
// exactly 0.5 BTC since now state transitions have taken place yet.
|
// 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.
|
// 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
|
// Finally close the channel between Alice and Bob, asserting that the
|
||||||
// channel has been properly closed on-chain.
|
// 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
|
// 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
|
// in a build of pending Htlcs. We expect the channels unsettled balance to
|
||||||
// equal the sum of all the Pending Htlcs.
|
// equal the sum of all the Pending Htlcs.
|
||||||
func testChannelUnsettledBalance(ht *lntemp.HarnessTest) {
|
func testChannelUnsettledBalance(ht *lntest.HarnessTest) {
|
||||||
const chanAmt = btcutil.Amount(1000000)
|
const chanAmt = btcutil.Amount(1000000)
|
||||||
|
|
||||||
// Creates a helper closure to be used below which asserts the proper
|
// 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.
|
// Open a channel between Alice and Carol.
|
||||||
chanPointAlice := ht.OpenChannel(
|
chanPointAlice := ht.OpenChannel(
|
||||||
alice, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
alice, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
cType := ht.GetChannelCommitType(alice, chanPointAlice)
|
cType := ht.GetChannelCommitType(alice, chanPointAlice)
|
||||||
|
|
||||||
// Check alice's channel balance, which should have zero remote and zero
|
// Check alice's channel balance, which should have zero remote and zero
|
||||||
// pending balance.
|
// 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
|
// Check carol's channel balance, which should have zero local and zero
|
||||||
// pending balance.
|
// 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.
|
// Channel should be ready for payments.
|
||||||
const (
|
const (
|
||||||
@@ -195,7 +199,8 @@ func testChannelUnsettledBalance(ht *lntemp.HarnessTest) {
|
|||||||
// Check alice's channel balance, which should have a remote unsettled
|
// Check alice's channel balance, which should have a remote unsettled
|
||||||
// balance that equals to the amount of invoices * payAmt. The remote
|
// balance that equals to the amount of invoices * payAmt. The remote
|
||||||
// balance remains zero.
|
// 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)
|
checkChannelBalance(alice, aliceLocal, 0, 0, numInvoices*payAmt)
|
||||||
|
|
||||||
// Check carol's channel balance, which should have a local unsettled
|
// Check carol's channel balance, which should have a local unsettled
|
||||||
+85
-20
@@ -13,8 +13,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainreg"
|
"github.com/lightningnetwork/lnd/chainreg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"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
|
// Note that whether the deadline is used or not is implicitly checked by its
|
||||||
// corresponding fee rates.
|
// corresponding fee rates.
|
||||||
func testCommitmentTransactionDeadline(ht *lntemp.HarnessTest) {
|
func testCommitmentTransactionDeadline(ht *lntest.HarnessTest) {
|
||||||
// Get the default max fee rate used in sweeping the commitment
|
// Get the default max fee rate used in sweeping the commitment
|
||||||
// transaction.
|
// transaction.
|
||||||
defaultMax := lnwallet.DefaultAnchorsCommitMaxFeeRateSatPerVByte
|
defaultMax := lnwallet.DefaultAnchorsCommitMaxFeeRateSatPerVByte
|
||||||
@@ -72,7 +72,7 @@ func testCommitmentTransactionDeadline(ht *lntemp.HarnessTest) {
|
|||||||
setupNode := func(name string) *node.HarnessNode {
|
setupNode := func(name string) *node.HarnessNode {
|
||||||
// Create the node.
|
// Create the node.
|
||||||
args := []string{"--hodl.exit-settle"}
|
args := []string{"--hodl.exit-settle"}
|
||||||
args = append(args, nodeArgsForCommitType(
|
args = append(args, lntest.NodeArgsForCommitType(
|
||||||
lnrpc.CommitmentType_ANCHORS)...,
|
lnrpc.CommitmentType_ANCHORS)...,
|
||||||
)
|
)
|
||||||
node := ht.NewNode(name, args)
|
node := ht.NewNode(name, args)
|
||||||
@@ -104,7 +104,7 @@ func testCommitmentTransactionDeadline(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// Open a channel between Alice and Bob.
|
// Open a channel between Alice and Bob.
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: 10e6,
|
Amt: 10e6,
|
||||||
PushAmt: 5e6,
|
PushAmt: 5e6,
|
||||||
},
|
},
|
||||||
@@ -194,7 +194,7 @@ func testCommitmentTransactionDeadline(ht *lntemp.HarnessTest) {
|
|||||||
// process.
|
// process.
|
||||||
//
|
//
|
||||||
// TODO(roasbeef): also add an unsettled HTLC before force closing.
|
// 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
|
// We'll test the scenario for some of the commitment types, to ensure
|
||||||
// outputs can be swept.
|
// outputs can be swept.
|
||||||
commitTypes := []lnrpc.CommitmentType{
|
commitTypes := []lnrpc.CommitmentType{
|
||||||
@@ -209,7 +209,7 @@ func testChannelForceClosure(ht *lntemp.HarnessTest) {
|
|||||||
success := ht.Run(testName, func(t *testing.T) {
|
success := ht.Run(testName, func(t *testing.T) {
|
||||||
st := ht.Subtest(t)
|
st := ht.Subtest(t)
|
||||||
|
|
||||||
args := nodeArgsForCommitType(channelType)
|
args := lntest.NodeArgsForCommitType(channelType)
|
||||||
alice := st.NewNode("Alice", args)
|
alice := st.NewNode("Alice", args)
|
||||||
defer st.Shutdown(alice)
|
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) {
|
alice, carol *node.HarnessNode, channelType lnrpc.CommitmentType) {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -268,7 +268,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||||||
carolStartingBalance := carolBalResp.ConfirmedBalance
|
carolStartingBalance := carolBalResp.ConfirmedBalance
|
||||||
|
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, carol, lntemp.OpenChannelParams{
|
alice, carol, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
},
|
},
|
||||||
@@ -600,6 +600,20 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||||||
// Update current height
|
// Update current height
|
||||||
_, curHeight = ht.Miner.GetBestBlock()
|
_, 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 {
|
err = wait.NoError(func() error {
|
||||||
// Now that the commit output has been fully swept, check to
|
// Now that the commit output has been fully swept, check to
|
||||||
// see that the channel remains open for the pending htlc
|
// 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
|
// The commitment funds will have been recovered after the
|
||||||
// commit txn was included in the last block. The htlc funds
|
// commit txn was included in the last block. The htlc funds
|
||||||
// will be shown in limbo.
|
// will be shown in limbo.
|
||||||
err := checkPendingChannelNumHtlcs(forceClose, numInvoices)
|
err := checkPendingChannelNumHtlcs(forceClose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -659,7 +673,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// We should now be at the block just before the utxo nursery
|
// We should now be at the block just before the utxo nursery
|
||||||
// will attempt to broadcast the htlc timeout transactions.
|
// will attempt to broadcast the htlc timeout transactions.
|
||||||
err = checkPendingChannelNumHtlcs(forceClose, numInvoices)
|
err = checkPendingChannelNumHtlcs(forceClose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -702,9 +716,9 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// Retrieve each htlc timeout txn from the mempool, and ensure it is
|
// Retrieve each htlc timeout txn from the mempool, and ensure it is
|
||||||
// well-formed. This entails verifying that each only spends from
|
// well-formed. This entails verifying that each only spends from
|
||||||
// output, and that that output is from the commitment txn. In case
|
// output, and that output is from the commitment txn. In case this is
|
||||||
// this is an anchor channel, the transactions are aggregated by the
|
// an anchor channel, the transactions are aggregated by the sweeper
|
||||||
// sweeper into one.
|
// into one.
|
||||||
numInputs := 1
|
numInputs := 1
|
||||||
if channelType == lnrpc.CommitmentType_ANCHORS {
|
if channelType == lnrpc.CommitmentType_ANCHORS {
|
||||||
numInputs = numInvoices + 1
|
numInputs = numInvoices + 1
|
||||||
@@ -796,7 +810,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// We record the htlc amount less fees here, so that we know
|
// We record the htlc amount less fees here, so that we know
|
||||||
// what value to expect for the second stage of our htlc
|
// what value to expect for the second stage of our htlc
|
||||||
// htlc resolution.
|
// resolution.
|
||||||
htlcLessFees = uint64(outputs[0].Value)
|
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 fmt.Errorf("htlc funds should still be in limbo")
|
||||||
}
|
}
|
||||||
|
|
||||||
return checkPendingChannelNumHtlcs(forceClose, numInvoices)
|
return checkPendingChannelNumHtlcs(forceClose)
|
||||||
}, defaultTimeout)
|
}, defaultTimeout)
|
||||||
require.NoError(ht, err, "timeout while checking force closed channel")
|
require.NoError(ht, err, "timeout while checking force closed channel")
|
||||||
|
|
||||||
@@ -913,7 +927,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||||||
forceClose := ht.AssertChannelPendingForceClose(
|
forceClose := ht.AssertChannelPendingForceClose(
|
||||||
alice, chanPoint,
|
alice, chanPoint,
|
||||||
)
|
)
|
||||||
err := checkPendingChannelNumHtlcs(forceClose, numInvoices)
|
err := checkPendingChannelNumHtlcs(forceClose)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -986,7 +1000,7 @@ func padCLTV(cltv uint32) uint32 {
|
|||||||
// testFailingChannel tests that we will fail the channel by force closing it
|
// 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
|
// in the case where a counterparty tries to settle an HTLC with the wrong
|
||||||
// preimage.
|
// preimage.
|
||||||
func testFailingChannel(ht *lntemp.HarnessTest) {
|
func testFailingChannel(ht *lntest.HarnessTest) {
|
||||||
const paymentAmt = 10000
|
const paymentAmt = 10000
|
||||||
|
|
||||||
chanAmt := lnd.MaxFundingAmount
|
chanAmt := lnd.MaxFundingAmount
|
||||||
@@ -999,7 +1013,7 @@ func testFailingChannel(ht *lntemp.HarnessTest) {
|
|||||||
ht.ConnectNodes(alice, carol)
|
ht.ConnectNodes(alice, carol)
|
||||||
|
|
||||||
// Let Alice connect and open a channel to 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
|
// With the channel open, we'll create a invoice for Carol that Alice
|
||||||
// will attempt to pay.
|
// will attempt to pay.
|
||||||
@@ -1058,7 +1072,7 @@ func testFailingChannel(ht *lntemp.HarnessTest) {
|
|||||||
// type matches a set of expected resolutions.
|
// type matches a set of expected resolutions.
|
||||||
//
|
//
|
||||||
// NOTE: only used in current test file.
|
// 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) {
|
chanPoint *lnrpc.ChannelPoint, expected map[string]*lnrpc.Resolution) {
|
||||||
|
|
||||||
op := ht.OutPointFromChannelPoint(chanPoint)
|
op := ht.OutPointFromChannelPoint(chanPoint)
|
||||||
@@ -1087,3 +1101,54 @@ func assertReports(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
|||||||
require.Equal(ht, expected, res)
|
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
|
||||||
|
}
|
||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/peersrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/peersrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -40,7 +40,7 @@ import (
|
|||||||
// take more than 5 seconds to finish, the channel will be marked as disabled,
|
// 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
|
// thus a following operation will fail if it relies on the channel being
|
||||||
// enabled.
|
// enabled.
|
||||||
func testUpdateChanStatus(ht *lntemp.HarnessTest) {
|
func testUpdateChanStatus(ht *lntest.HarnessTest) {
|
||||||
// Create two fresh nodes and open a channel between them.
|
// Create two fresh nodes and open a channel between them.
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
args := []string{
|
args := []string{
|
||||||
@@ -57,7 +57,7 @@ func testUpdateChanStatus(ht *lntemp.HarnessTest) {
|
|||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
chanAmt := btcutil.Amount(100000)
|
chanAmt := btcutil.Amount(100000)
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
defer ht.CloseChannel(alice, chanPoint)
|
defer ht.CloseChannel(alice, chanPoint)
|
||||||
|
|
||||||
@@ -141,7 +141,7 @@ func testUpdateChanStatus(ht *lntemp.HarnessTest) {
|
|||||||
FeeRateMilliMsat: int64(chainreg.DefaultBitcoinFeeRate),
|
FeeRateMilliMsat: int64(chainreg.DefaultBitcoinFeeRate),
|
||||||
TimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta,
|
TimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta,
|
||||||
MinHtlc: 1000, // default value
|
MinHtlc: 1000, // default value
|
||||||
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
|
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manually disable the channel and ensure that a "Disabled = true"
|
// 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
|
// testUnannouncedChannels checks unannounced channels are not returned by
|
||||||
// describeGraph RPC request unless explicitly asked for.
|
// describeGraph RPC request unless explicitly asked for.
|
||||||
func testUnannouncedChannels(ht *lntemp.HarnessTest) {
|
func testUnannouncedChannels(ht *lntest.HarnessTest) {
|
||||||
amount := funding.MaxBtcFundingAmount
|
amount := funding.MaxBtcFundingAmount
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
|
|
||||||
// Open a channel between Alice and Bob, ensuring the
|
// Open a channel between Alice and Bob, ensuring the
|
||||||
// channel has been opened properly.
|
// channel has been opened properly.
|
||||||
chanOpenUpdate := ht.OpenChannelAssertStream(
|
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
|
// 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)
|
ht.CloseChannel(alice, fundingChanPoint)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testGraphTopologyNotifications(ht *lntemp.HarnessTest) {
|
func testGraphTopologyNotifications(ht *lntest.HarnessTest) {
|
||||||
ht.Run("pinned", func(t *testing.T) {
|
ht.Run("pinned", func(t *testing.T) {
|
||||||
subT := ht.Subtest(t)
|
subT := ht.Subtest(t)
|
||||||
testGraphTopologyNtfns(subT, true)
|
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
|
const chanAmt = funding.MaxBtcFundingAmount
|
||||||
|
|
||||||
// Spin up Bob first, since we will need to grab his pubkey when
|
// 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.
|
// Open a new channel between Alice and Bob.
|
||||||
chanPoint := ht.OpenChannel(
|
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
|
// 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
|
// 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
|
// appears in the network, the proper notification is dispatched. Note
|
||||||
// that a node that does not have any channels open is ignored, so first
|
// that a node that does not have any channels open is ignored, so
|
||||||
// we disconnect Alice and Bob, open a channel between Bob and Carol,
|
// first we disconnect Alice and Bob, open a channel between Bob and
|
||||||
// and finally connect Alice to Bob again.
|
// Carol, and finally connect Alice to Bob again.
|
||||||
ht.DisconnectNodes(alice, bob)
|
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)
|
carol := ht.NewNode("Carol", nil)
|
||||||
ht.ConnectNodes(bob, carol)
|
ht.ConnectNodes(bob, carol)
|
||||||
chanPoint = ht.OpenChannel(
|
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
|
// Reconnect Alice and Bob. This should result in the nodes syncing up
|
||||||
// their respective graph state, with the new addition being the
|
// their respective graph state, with the new addition being the
|
||||||
// existence of Carol in the graph, and also the channel between Bob
|
// 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
|
// testNodeAnnouncement ensures that when a node is started with one or more
|
||||||
// external IP addresses specified on the command line, that those addresses
|
// external IP addresses specified on the command line, that those addresses
|
||||||
// announced to the network and reported in the network graph.
|
// 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
|
alice, bob := ht.Alice, ht.Bob
|
||||||
|
|
||||||
advertisedAddrs := []string{
|
advertisedAddrs := []string{
|
||||||
@@ -392,7 +405,7 @@ func testNodeAnnouncement(ht *lntemp.HarnessTest) {
|
|||||||
// ensures that Alice receives the node announcement from Bob as part of
|
// ensures that Alice receives the node announcement from Bob as part of
|
||||||
// the announcement broadcast.
|
// the announcement broadcast.
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
bob, dave, lntemp.OpenChannelParams{Amt: 1000000},
|
bob, dave, lntest.OpenChannelParams{Amt: 1000000},
|
||||||
)
|
)
|
||||||
|
|
||||||
assertAddrs := func(addrsFound []string, targetAddrs ...string) {
|
assertAddrs := func(addrsFound []string, targetAddrs ...string) {
|
||||||
@@ -421,7 +434,7 @@ func testNodeAnnouncement(ht *lntemp.HarnessTest) {
|
|||||||
// testUpdateNodeAnnouncement ensures that the RPC endpoint validates
|
// testUpdateNodeAnnouncement ensures that the RPC endpoint validates
|
||||||
// the requests correctly and that the new node announcement is brodcasted
|
// the requests correctly and that the new node announcement is brodcasted
|
||||||
// with the right information after updating our node.
|
// with the right information after updating our node.
|
||||||
func testUpdateNodeAnnouncement(ht *lntemp.HarnessTest) {
|
func testUpdateNodeAnnouncement(ht *lntest.HarnessTest) {
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
|
|
||||||
var lndArgs []string
|
var lndArgs []string
|
||||||
@@ -500,7 +513,7 @@ func testUpdateNodeAnnouncement(ht *lntemp.HarnessTest) {
|
|||||||
// ensures that Alice receives the node announcement from Bob as part of
|
// ensures that Alice receives the node announcement from Bob as part of
|
||||||
// the announcement broadcast.
|
// the announcement broadcast.
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
bob, dave, lntemp.OpenChannelParams{
|
bob, dave, lntest.OpenChannelParams{
|
||||||
Amt: 1000000,
|
Amt: 1000000,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -637,7 +650,7 @@ func testUpdateNodeAnnouncement(ht *lntemp.HarnessTest) {
|
|||||||
// assertSyncType asserts that the peer has an expected syncType.
|
// assertSyncType asserts that the peer has an expected syncType.
|
||||||
//
|
//
|
||||||
// NOTE: only made for tests in this file.
|
// 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) {
|
peer string, syncType lnrpc.Peer_SyncType) {
|
||||||
|
|
||||||
resp := hn.RPC.ListPeers()
|
resp := hn.RPC.ListPeers()
|
||||||
@@ -693,7 +706,7 @@ func compareNodeAnns(n1, n2 *lnrpc.NodeUpdate) error {
|
|||||||
// the response expected values.
|
// the response expected values.
|
||||||
//
|
//
|
||||||
// NOTE: only used for tests in this file.
|
// NOTE: only used for tests in this file.
|
||||||
func assertUpdateNodeAnnouncementResponse(ht *lntemp.HarnessTest,
|
func assertUpdateNodeAnnouncementResponse(ht *lntest.HarnessTest,
|
||||||
response *peersrpc.NodeAnnouncementUpdateResponse,
|
response *peersrpc.NodeAnnouncementUpdateResponse,
|
||||||
expectedOps map[string]int) {
|
expectedOps map[string]int) {
|
||||||
|
|
||||||
@@ -10,37 +10,22 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/funding"
|
"github.com/lightningnetwork/lnd/funding"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"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"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/stretchr/testify/require"
|
"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
|
// testUpdateChannelPolicy tests that policy updates made to a channel
|
||||||
// gets propagated to other nodes in the network.
|
// gets propagated to other nodes in the network.
|
||||||
func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
func testUpdateChannelPolicy(ht *lntest.HarnessTest) {
|
||||||
const (
|
const (
|
||||||
defaultFeeBase = 1000
|
defaultFeeBase = 1000
|
||||||
defaultFeeRate = 1
|
defaultFeeRate = 1
|
||||||
defaultTimeLockDelta = chainreg.DefaultBitcoinTimeLockDelta
|
defaultTimeLockDelta = chainreg.DefaultBitcoinTimeLockDelta
|
||||||
defaultMinHtlc = 1000
|
defaultMinHtlc = 1000
|
||||||
)
|
)
|
||||||
defaultMaxHtlc := calculateMaxHtlc(funding.MaxBtcFundingAmount)
|
defaultMaxHtlc := lntest.CalculateMaxHtlc(funding.MaxBtcFundingAmount)
|
||||||
|
|
||||||
chanAmt := funding.MaxBtcFundingAmount
|
chanAmt := funding.MaxBtcFundingAmount
|
||||||
pushAmt := chanAmt / 2
|
pushAmt := chanAmt / 2
|
||||||
@@ -49,7 +34,7 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// Create a channel Alice->Bob.
|
// Create a channel Alice->Bob.
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
},
|
},
|
||||||
@@ -102,7 +87,7 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
|||||||
// part of his ChannelUpdate.
|
// part of his ChannelUpdate.
|
||||||
const customMinHtlc = 5000
|
const customMinHtlc = 5000
|
||||||
chanPoint2 := ht.OpenChannel(
|
chanPoint2 := ht.OpenChannel(
|
||||||
carol, bob, lntemp.OpenChannelParams{
|
carol, bob, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
MinHtlc: customMinHtlc,
|
MinHtlc: customMinHtlc,
|
||||||
@@ -182,9 +167,9 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
|||||||
payAmt = btcutil.Amount(4)
|
payAmt = btcutil.Amount(4)
|
||||||
amtSat := int64(payAmt)
|
amtSat := int64(payAmt)
|
||||||
amtMSat := int64(lnwire.NewMSatFromSatoshis(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[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
|
routes.Routes[0].Hops[1].AmtToForwardMsat = amtMSat
|
||||||
|
|
||||||
// Send the payment with the modified value.
|
// Send the payment with the modified value.
|
||||||
@@ -215,9 +200,9 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
|||||||
payAmt = btcutil.Amount(5)
|
payAmt = btcutil.Amount(5)
|
||||||
amtSat = int64(payAmt)
|
amtSat = int64(payAmt)
|
||||||
amtMSat = int64(lnwire.NewMSatFromSatoshis(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[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
|
routes.Routes[0].Hops[1].AmtToForwardMsat = amtMSat
|
||||||
|
|
||||||
// Manually set the MPP payload a new for each payment since
|
// 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.
|
// We'll now open a channel from Alice directly to Carol.
|
||||||
ht.ConnectNodes(alice, carol)
|
ht.ConnectNodes(alice, carol)
|
||||||
chanPoint3 := ht.OpenChannel(
|
chanPoint3 := ht.OpenChannel(
|
||||||
alice, carol, lntemp.OpenChannelParams{
|
alice, carol, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
},
|
},
|
||||||
@@ -439,7 +424,7 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
|||||||
// chan-disable-timeout flags here. For instance, if some operations take more
|
// 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
|
// 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.
|
// 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
|
const chanAmt = 100000
|
||||||
|
|
||||||
alice, bob := ht.Alice, ht.Bob
|
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
|
// We now proceed to open channels: Alice=>Bob, Alice=>Carol and
|
||||||
// Eve=>Carol.
|
// Eve=>Carol.
|
||||||
p := lntemp.OpenChannelParams{Amt: chanAmt}
|
p := lntest.OpenChannelParams{Amt: chanAmt}
|
||||||
reqs := []*lntemp.OpenChannelRequest{
|
reqs := []*lntest.OpenChannelRequest{
|
||||||
{Local: alice, Remote: bob, Param: p},
|
{Local: alice, Remote: bob, Param: p},
|
||||||
{Local: alice, Remote: carol, Param: p},
|
{Local: alice, Remote: carol, Param: p},
|
||||||
{Local: eve, Remote: carol, Param: p},
|
{Local: eve, Remote: carol, Param: p},
|
||||||
@@ -528,7 +513,7 @@ func testSendUpdateDisableChannel(ht *lntemp.HarnessTest) {
|
|||||||
FeeRateMilliMsat: int64(chainreg.DefaultBitcoinFeeRate),
|
FeeRateMilliMsat: int64(chainreg.DefaultBitcoinFeeRate),
|
||||||
TimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta,
|
TimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta,
|
||||||
MinHtlc: 1000, // default value
|
MinHtlc: 1000, // default value
|
||||||
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
|
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
|
||||||
Disabled: true,
|
Disabled: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -670,7 +655,7 @@ func testSendUpdateDisableChannel(ht *lntemp.HarnessTest) {
|
|||||||
// Bob will update the base fee via UpdateChannelPolicy, we will test that
|
// 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
|
// Alice will not fail the payment and send it using the updated channel
|
||||||
// policy.
|
// policy.
|
||||||
func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
|
func testUpdateChannelPolicyForPrivateChannel(ht *lntest.HarnessTest) {
|
||||||
const (
|
const (
|
||||||
chanAmt = btcutil.Amount(100000)
|
chanAmt = btcutil.Amount(100000)
|
||||||
paymentAmt = 20000
|
paymentAmt = 20000
|
||||||
@@ -683,7 +668,7 @@ func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// Open a channel with 100k satoshis between Alice and Bob.
|
// Open a channel with 100k satoshis between Alice and Bob.
|
||||||
chanPointAliceBob := ht.OpenChannel(
|
chanPointAliceBob := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -696,7 +681,7 @@ func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// Open a channel with 100k satoshis between Bob and Carol.
|
// Open a channel with 100k satoshis between Bob and Carol.
|
||||||
chanPointBobCarol := ht.OpenChannel(
|
chanPointBobCarol := ht.OpenChannel(
|
||||||
bob, carol, lntemp.OpenChannelParams{
|
bob, carol, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
Private: true,
|
Private: true,
|
||||||
},
|
},
|
||||||
@@ -729,6 +714,19 @@ func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// Alice pays the invoices. She will use the updated baseFeeMSat in the
|
// Alice pays the invoices. She will use the updated baseFeeMSat in the
|
||||||
// payment
|
// 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}
|
payReqs := []string{resp.PaymentRequest}
|
||||||
ht.CompletePaymentRequests(alice, payReqs)
|
ht.CompletePaymentRequests(alice, payReqs)
|
||||||
|
|
||||||
@@ -770,14 +768,14 @@ func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
|
|||||||
// testUpdateChannelPolicyFeeRateAccuracy tests that updating the channel policy
|
// testUpdateChannelPolicyFeeRateAccuracy tests that updating the channel policy
|
||||||
// rounds fee rate values correctly as well as setting fee rate with ppm works
|
// rounds fee rate values correctly as well as setting fee rate with ppm works
|
||||||
// as expected.
|
// as expected.
|
||||||
func testUpdateChannelPolicyFeeRateAccuracy(ht *lntemp.HarnessTest) {
|
func testUpdateChannelPolicyFeeRateAccuracy(ht *lntest.HarnessTest) {
|
||||||
chanAmt := funding.MaxBtcFundingAmount
|
chanAmt := funding.MaxBtcFundingAmount
|
||||||
pushAmt := chanAmt / 2
|
pushAmt := chanAmt / 2
|
||||||
|
|
||||||
// Create a channel Alice -> Bob.
|
// Create a channel Alice -> Bob.
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
},
|
},
|
||||||
@@ -841,7 +839,7 @@ func testUpdateChannelPolicyFeeRateAccuracy(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// assertNodesPolicyUpdate checks that a given policy update has been received
|
// assertNodesPolicyUpdate checks that a given policy update has been received
|
||||||
// by a list of given nodes.
|
// 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,
|
advertisingNode *node.HarnessNode, policy *lnrpc.RoutingPolicy,
|
||||||
chanPoint *lnrpc.ChannelPoint) {
|
chanPoint *lnrpc.ChannelPoint) {
|
||||||
|
|
||||||
@@ -5,7 +5,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -13,7 +13,7 @@ import (
|
|||||||
// testCustomMessage tests sending and receiving of overridden custom message
|
// testCustomMessage tests sending and receiving of overridden custom message
|
||||||
// types (within the message type range usually reserved for protocol messages)
|
// types (within the message type range usually reserved for protocol messages)
|
||||||
// via the send and subscribe custom message APIs.
|
// via the send and subscribe custom message APIs.
|
||||||
func testCustomMessage(ht *lntemp.HarnessTest) {
|
func testCustomMessage(ht *lntest.HarnessTest) {
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -82,7 +82,7 @@ func testCustomMessage(ht *lntemp.HarnessTest) {
|
|||||||
require.Equal(ht, bob.PubKey[:], msg.Peer, "first msg "+
|
require.Equal(ht, bob.PubKey[:], msg.Peer, "first msg "+
|
||||||
"peer wrong")
|
"peer wrong")
|
||||||
|
|
||||||
case <-time.After(defaultTimeout):
|
case <-time.After(lntest.DefaultTimeout):
|
||||||
ht.Fatalf("alice did not receive first custom message: %v",
|
ht.Fatalf("alice did not receive first custom message: %v",
|
||||||
msgType)
|
msgType)
|
||||||
}
|
}
|
||||||
@@ -151,7 +151,7 @@ func testCustomMessage(ht *lntemp.HarnessTest) {
|
|||||||
require.Equal(ht, bob.PubKey[:], msg.Peer, "second "+
|
require.Equal(ht, bob.PubKey[:], msg.Peer, "second "+
|
||||||
"message peer")
|
"message peer")
|
||||||
|
|
||||||
case <-time.After(defaultTimeout):
|
case <-time.After(lntest.DefaultTimeout):
|
||||||
ht.Fatalf("alice did not receive second custom message")
|
ht.Fatalf("alice did not receive second custom message")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,12 +12,12 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/kvdb"
|
"github.com/lightningnetwork/lnd/kvdb"
|
||||||
"github.com/lightningnetwork/lnd/lncfg"
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func assertLeader(ht *lntemp.HarnessTest, observer cluster.LeaderElector,
|
func assertLeader(ht *lntest.HarnessTest, observer cluster.LeaderElector,
|
||||||
expected string) {
|
expected string) {
|
||||||
|
|
||||||
leader, err := observer.Leader(ht.Context())
|
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
|
// 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
|
// single cluster (sharing the same identity) one can hand over the leader role
|
||||||
// to the other (failing over after graceful shutdown or forceful abort).
|
// to the other (failing over after graceful shutdown or forceful abort).
|
||||||
func testEtcdFailover(ht *lntemp.HarnessTest) {
|
func testEtcdFailover(ht *lntest.HarnessTest) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
kill bool
|
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(
|
etcdCfg, cleanup, err := kvdb.StartEtcdTestBackend(
|
||||||
ht.T.TempDir(), uint16(lntest.NextAvailablePort()),
|
ht.T.TempDir(), uint16(node.NextAvailablePort()),
|
||||||
uint16(lntest.NextAvailablePort()), "",
|
uint16(node.NextAvailablePort()), "",
|
||||||
)
|
)
|
||||||
require.NoError(ht, err, "Failed to start etcd instance")
|
require.NoError(ht, err, "Failed to start etcd instance")
|
||||||
defer cleanup()
|
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
|
// Open a channel with 100k satoshis between Carol and Alice with Alice
|
||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
chanAmt := btcutil.Amount(100_000)
|
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
|
// At this point Carol-1 is the elected leader, while Carol-2 will wait
|
||||||
// to become the leader when Carol-1 stops.
|
// to become the leader when Carol-1 stops.
|
||||||
+14
-11
@@ -9,8 +9,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainreg"
|
"github.com/lightningnetwork/lnd/chainreg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/routing/route"
|
"github.com/lightningnetwork/lnd/routing/route"
|
||||||
@@ -34,7 +34,7 @@ type interceptorTestCase struct {
|
|||||||
|
|
||||||
// testForwardInterceptorDedupHtlc tests that upon reconnection, duplicate
|
// testForwardInterceptorDedupHtlc tests that upon reconnection, duplicate
|
||||||
// HTLCs aren't re-notified using the HTLC interceptor API.
|
// 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.
|
// Initialize the test context with 3 connected nodes.
|
||||||
ts := newInterceptorTestScenario(ht)
|
ts := newInterceptorTestScenario(ht)
|
||||||
|
|
||||||
@@ -42,8 +42,8 @@ func testForwardInterceptorDedupHtlc(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// Open and wait for channels.
|
// Open and wait for channels.
|
||||||
const chanAmt = btcutil.Amount(300000)
|
const chanAmt = btcutil.Amount(300000)
|
||||||
p := lntemp.OpenChannelParams{Amt: chanAmt}
|
p := lntest.OpenChannelParams{Amt: chanAmt}
|
||||||
reqs := []*lntemp.OpenChannelRequest{
|
reqs := []*lntest.OpenChannelRequest{
|
||||||
{Local: alice, Remote: bob, Param: p},
|
{Local: alice, Remote: bob, Param: p},
|
||||||
{Local: bob, Remote: carol, Param: p},
|
{Local: bob, Remote: carol, Param: p},
|
||||||
}
|
}
|
||||||
@@ -106,6 +106,7 @@ func testForwardInterceptorDedupHtlc(ht *lntemp.HarnessTest) {
|
|||||||
ht.EnsureConnected(bob, alice)
|
ht.EnsureConnected(bob, alice)
|
||||||
|
|
||||||
// Here we wait for the channel to be active again.
|
// Here we wait for the channel to be active again.
|
||||||
|
ht.AssertChannelExists(alice, cpAB)
|
||||||
ht.AssertChannelExists(bob, cpAB)
|
ht.AssertChannelExists(bob, cpAB)
|
||||||
|
|
||||||
// Now that the channel is active we make sure the test passes as
|
// 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).
|
// 3. Intercepted held htlcs result in no payment (invoice is not settled).
|
||||||
// 4. When Interceptor disconnects it resumes all held htlcs, which result in
|
// 4. When Interceptor disconnects it resumes all held htlcs, which result in
|
||||||
// valid payment (invoice is settled).
|
// valid payment (invoice is settled).
|
||||||
func testForwardInterceptorBasic(ht *lntemp.HarnessTest) {
|
func testForwardInterceptorBasic(ht *lntest.HarnessTest) {
|
||||||
ts := newInterceptorTestScenario(ht)
|
ts := newInterceptorTestScenario(ht)
|
||||||
|
|
||||||
alice, bob, carol := ts.alice, ts.bob, ts.carol
|
alice, bob, carol := ts.alice, ts.bob, ts.carol
|
||||||
|
|
||||||
// Open and wait for channels.
|
// Open and wait for channels.
|
||||||
const chanAmt = btcutil.Amount(300000)
|
const chanAmt = btcutil.Amount(300000)
|
||||||
p := lntemp.OpenChannelParams{Amt: chanAmt}
|
p := lntest.OpenChannelParams{Amt: chanAmt}
|
||||||
reqs := []*lntemp.OpenChannelRequest{
|
reqs := []*lntest.OpenChannelRequest{
|
||||||
{Local: alice, Remote: bob, Param: p},
|
{Local: alice, Remote: bob, Param: p},
|
||||||
{Local: bob, Remote: carol, Param: p},
|
{Local: bob, Remote: carol, Param: p},
|
||||||
}
|
}
|
||||||
@@ -296,7 +297,8 @@ func testForwardInterceptorBasic(ht *lntemp.HarnessTest) {
|
|||||||
restartAlice := ht.SuspendNode(alice)
|
restartAlice := ht.SuspendNode(alice)
|
||||||
require.NoError(ht, restartAlice(), "failed to restart 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)
|
ht.AssertChannelExists(bob, cpAB)
|
||||||
|
|
||||||
// Create a new interceptor as the old one has quit.
|
// 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
|
// interceptorTestScenario is a helper struct to hold the test context and
|
||||||
// provide the needed functionality.
|
// provide the needed functionality.
|
||||||
type interceptorTestScenario struct {
|
type interceptorTestScenario struct {
|
||||||
ht *lntemp.HarnessTest
|
ht *lntest.HarnessTest
|
||||||
alice, bob, carol *node.HarnessNode
|
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.
|
// Among them, Alice and Bob are standby nodes and Carol is a new node.
|
||||||
func newInterceptorTestScenario(
|
func newInterceptorTestScenario(
|
||||||
ht *lntemp.HarnessTest) *interceptorTestScenario {
|
ht *lntest.HarnessTest) *interceptorTestScenario {
|
||||||
|
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
carol := ht.NewNode("carol", nil)
|
carol := ht.NewNode("carol", nil)
|
||||||
@@ -416,6 +418,7 @@ func (c *interceptorTestScenario) prepareTestCases() []*interceptorTestCase {
|
|||||||
t.invoice = invoice
|
t.invoice = invoice
|
||||||
t.payAddr = payReq.PaymentAddr
|
t.payAddr = payReq.PaymentAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
return cases
|
return cases
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -13,8 +13,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/labels"
|
"github.com/lightningnetwork/lnd/labels"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -24,7 +24,7 @@ import (
|
|||||||
// Bob, then immediately closes the channel after asserting some expected post
|
// Bob, then immediately closes the channel after asserting some expected post
|
||||||
// conditions. Finally, the chain itself is checked to ensure the closing
|
// conditions. Finally, the chain itself is checked to ensure the closing
|
||||||
// transaction was mined.
|
// transaction was mined.
|
||||||
func testBasicChannelFunding(ht *lntemp.HarnessTest) {
|
func testBasicChannelFunding(ht *lntest.HarnessTest) {
|
||||||
// Run through the test with combinations of all the different
|
// Run through the test with combinations of all the different
|
||||||
// commitment types.
|
// commitment types.
|
||||||
allTypes := []lnrpc.CommitmentType{
|
allTypes := []lnrpc.CommitmentType{
|
||||||
@@ -35,20 +35,20 @@ func testBasicChannelFunding(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// testFunding is a function closure that takes Carol and Dave's
|
// testFunding is a function closure that takes Carol and Dave's
|
||||||
// commitment types and test the funding flow.
|
// commitment types and test the funding flow.
|
||||||
testFunding := func(ht *lntemp.HarnessTest, carolCommitType,
|
testFunding := func(ht *lntest.HarnessTest, carolCommitType,
|
||||||
daveCommitType lnrpc.CommitmentType) {
|
daveCommitType lnrpc.CommitmentType) {
|
||||||
|
|
||||||
// Based on the current tweak variable for Carol, we'll
|
// Based on the current tweak variable for Carol, we'll
|
||||||
// preferentially signal the legacy commitment format. We do
|
// preferentially signal the legacy commitment format. We do
|
||||||
// the same for Dave shortly below.
|
// the same for Dave shortly below.
|
||||||
carolArgs := nodeArgsForCommitType(carolCommitType)
|
carolArgs := lntest.NodeArgsForCommitType(carolCommitType)
|
||||||
carol := ht.NewNode("Carol", carolArgs)
|
carol := ht.NewNode("Carol", carolArgs)
|
||||||
|
|
||||||
// Each time, we'll send Carol a new set of coins in order to
|
// Each time, we'll send Carol a new set of coins in order to
|
||||||
// fund the channel.
|
// fund the channel.
|
||||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||||
|
|
||||||
daveArgs := nodeArgsForCommitType(daveCommitType)
|
daveArgs := lntest.NodeArgsForCommitType(daveCommitType)
|
||||||
dave := ht.NewNode("Dave", daveArgs)
|
dave := ht.NewNode("Dave", daveArgs)
|
||||||
|
|
||||||
// Before we start the test, we'll ensure both sides are
|
// 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,
|
// 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
|
// then return a function closure that should be called to assert proper
|
||||||
// channel closure.
|
// channel closure.
|
||||||
func basicChannelFundingTest(ht *lntemp.HarnessTest,
|
func basicChannelFundingTest(ht *lntest.HarnessTest,
|
||||||
alice, bob *node.HarnessNode,
|
alice, bob *node.HarnessNode,
|
||||||
fundingShim *lnrpc.FundingShim) (*lnrpc.Channel,
|
fundingShim *lnrpc.FundingShim) (*lnrpc.Channel,
|
||||||
*lnrpc.Channel, func()) {
|
*lnrpc.Channel, func()) {
|
||||||
@@ -181,7 +181,7 @@ func basicChannelFundingTest(ht *lntemp.HarnessTest,
|
|||||||
// assertions will be executed to ensure the funding process completed
|
// assertions will be executed to ensure the funding process completed
|
||||||
// successfully.
|
// successfully.
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
FundingShim: fundingShim,
|
FundingShim: fundingShim,
|
||||||
@@ -193,7 +193,7 @@ func basicChannelFundingTest(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// With the channel open, ensure that the amount specified above has
|
// With the channel open, ensure that the amount specified above has
|
||||||
// properly been pushed to Bob.
|
// properly been pushed to Bob.
|
||||||
aliceLocalBalance := chanAmt - pushAmt - calcStaticFee(cType, 0)
|
aliceLocalBalance := chanAmt - pushAmt - lntest.CalcStaticFee(cType, 0)
|
||||||
checkChannelBalance(
|
checkChannelBalance(
|
||||||
alice, aliceChannelBalance, aliceLocalBalance, pushAmt,
|
alice, aliceChannelBalance, aliceLocalBalance, pushAmt,
|
||||||
)
|
)
|
||||||
@@ -216,7 +216,7 @@ func basicChannelFundingTest(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// testUnconfirmedChannelFunding tests that our unconfirmed change outputs can
|
// testUnconfirmedChannelFunding tests that our unconfirmed change outputs can
|
||||||
// be used to fund channels.
|
// be used to fund channels.
|
||||||
func testUnconfirmedChannelFunding(ht *lntemp.HarnessTest) {
|
func testUnconfirmedChannelFunding(ht *lntest.HarnessTest) {
|
||||||
const (
|
const (
|
||||||
chanAmt = funding.MaxBtcFundingAmount
|
chanAmt = funding.MaxBtcFundingAmount
|
||||||
pushAmt = btcutil.Amount(100000)
|
pushAmt = btcutil.Amount(100000)
|
||||||
@@ -236,7 +236,7 @@ func testUnconfirmedChannelFunding(ht *lntemp.HarnessTest) {
|
|||||||
ht.ConnectNodes(carol, alice)
|
ht.ConnectNodes(carol, alice)
|
||||||
|
|
||||||
chanOpenUpdate := ht.OpenChannelAssertStream(
|
chanOpenUpdate := ht.OpenChannelAssertStream(
|
||||||
carol, alice, lntemp.OpenChannelParams{
|
carol, alice, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
SpendUnconfirmed: true,
|
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
|
// Note that atm we haven't obtained the chanPoint yet, so we use the
|
||||||
// type directly.
|
// type directly.
|
||||||
cType := lnrpc.CommitmentType_STATIC_REMOTE_KEY
|
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)
|
checkChannelBalance(carol, 0, 0, carolLocalBalance, pushAmt)
|
||||||
|
|
||||||
// For Alice, her local/remote balances should be zero, and the
|
// 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
|
// testChannelFundingInputTypes tests that any type of supported input type can
|
||||||
// be used to fund channels.
|
// 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.
|
// We'll start off by creating a node for Carol.
|
||||||
carol := ht.NewNode("Carol", nil)
|
carol := ht.NewNode("Carol", nil)
|
||||||
|
|
||||||
@@ -342,7 +347,7 @@ func testChannelFundingInputTypes(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// runChannelFundingInputTypes tests that any type of supported input type can
|
// runChannelFundingInputTypes tests that any type of supported input type can
|
||||||
// be used to fund channels.
|
// be used to fund channels.
|
||||||
func runChannelFundingInputTypes(ht *lntemp.HarnessTest, alice,
|
func runChannelFundingInputTypes(ht *lntest.HarnessTest, alice,
|
||||||
carol *node.HarnessNode) {
|
carol *node.HarnessNode) {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -411,7 +416,7 @@ func runChannelFundingInputTypes(ht *lntemp.HarnessTest, alice,
|
|||||||
funder((chanAmt*11)/10, carol)
|
funder((chanAmt*11)/10, carol)
|
||||||
|
|
||||||
chanOpenUpdate := ht.OpenChannelAssertStream(
|
chanOpenUpdate := ht.OpenChannelAssertStream(
|
||||||
carol, alice, lntemp.OpenChannelParams{
|
carol, alice, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -423,7 +428,7 @@ func runChannelFundingInputTypes(ht *lntemp.HarnessTest, alice,
|
|||||||
// Note that atm we haven't obtained the chanPoint yet, so we
|
// Note that atm we haven't obtained the chanPoint yet, so we
|
||||||
// use the type directly.
|
// use the type directly.
|
||||||
cType := lnrpc.CommitmentType_STATIC_REMOTE_KEY
|
cType := lnrpc.CommitmentType_STATIC_REMOTE_KEY
|
||||||
carolLocalBalance := chanAmt - calcStaticFee(cType, 0)
|
carolLocalBalance := chanAmt - lntest.CalcStaticFee(cType, 0)
|
||||||
checkChannelBalance(carol, 0, 0, carolLocalBalance, 0)
|
checkChannelBalance(carol, 0, 0, carolLocalBalance, 0)
|
||||||
|
|
||||||
// For Alice, her local/remote balances should be zero, and the
|
// 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
|
// sendAllCoinsConfirm sends all coins of the node's wallet to the given address
|
||||||
// and awaits one confirmation.
|
// and awaits one confirmation.
|
||||||
func sendAllCoinsConfirm(ht *lntemp.HarnessTest, node *node.HarnessNode,
|
func sendAllCoinsConfirm(ht *lntest.HarnessTest, node *node.HarnessNode,
|
||||||
addr string) {
|
addr string) {
|
||||||
|
|
||||||
sweepReq := &lnrpc.SendCoinsRequest{
|
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
|
// testExternalFundingChanPoint tests that we're able to carry out a normal
|
||||||
// channel funding workflow given a channel point that was constructed outside
|
// channel funding workflow given a channel point that was constructed outside
|
||||||
// the main daemon.
|
// 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
|
// First, we'll create two new nodes that we'll use to open channel
|
||||||
// between for this test.
|
// between for this test.
|
||||||
carol := ht.NewNode("carol", nil)
|
carol := ht.NewNode("carol", nil)
|
||||||
@@ -496,11 +501,11 @@ func testExternalFundingChanPoint(ht *lntemp.HarnessTest) {
|
|||||||
// a transaction that will never be published.
|
// a transaction that will never be published.
|
||||||
const thawHeight uint32 = 10
|
const thawHeight uint32 = 10
|
||||||
const chanSize = funding.MaxBtcFundingAmount
|
const chanSize = funding.MaxBtcFundingAmount
|
||||||
fundingShim1, chanPoint1, _ := deriveFundingShim(
|
fundingShim1, chanPoint1 := deriveFundingShim(
|
||||||
ht, carol, dave, chanSize, thawHeight, false,
|
ht, carol, dave, chanSize, thawHeight, false,
|
||||||
)
|
)
|
||||||
ht.OpenChannelAssertPending(
|
ht.OpenChannelAssertPending(
|
||||||
carol, dave, lntemp.OpenChannelParams{
|
carol, dave, lntest.OpenChannelParams{
|
||||||
Amt: chanSize,
|
Amt: chanSize,
|
||||||
FundingShim: fundingShim1,
|
FundingShim: fundingShim1,
|
||||||
},
|
},
|
||||||
@@ -512,7 +517,7 @@ func testExternalFundingChanPoint(ht *lntemp.HarnessTest) {
|
|||||||
// externally funded, we should still be able to open another one. Let's
|
// 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
|
// do exactly that now. For this one we publish the transaction so we
|
||||||
// can mine it later.
|
// can mine it later.
|
||||||
fundingShim2, chanPoint2, _ := deriveFundingShim(
|
fundingShim2, chanPoint2 := deriveFundingShim(
|
||||||
ht, carol, dave, chanSize, thawHeight, true,
|
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.
|
// representation of channels if the system is restarted or disconnected.
|
||||||
// testFundingPersistence mirrors testBasicChannelFunding, but adds restarts
|
// testFundingPersistence mirrors testBasicChannelFunding, but adds restarts
|
||||||
// and checks for the state of channels with unconfirmed funding transactions.
|
// and checks for the state of channels with unconfirmed funding transactions.
|
||||||
func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
|
func testChannelFundingPersistence(ht *lntest.HarnessTest) {
|
||||||
chanAmt := funding.MaxBtcFundingAmount
|
chanAmt := funding.MaxBtcFundingAmount
|
||||||
pushAmt := btcutil.Amount(0)
|
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
|
// Create a new channel that requires 5 confs before it's considered
|
||||||
// open, then broadcast the funding transaction
|
// open, then broadcast the funding transaction
|
||||||
param := lntemp.OpenChannelParams{
|
param := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
}
|
}
|
||||||
@@ -676,7 +681,7 @@ func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// The channel should be listed in the peer information returned by
|
// The channel should be listed in the peer information returned by
|
||||||
// both peers.
|
// both peers.
|
||||||
chanPoint := lntemp.ChanPointFromPendingUpdate(update)
|
chanPoint := lntest.ChanPointFromPendingUpdate(update)
|
||||||
|
|
||||||
// Re-lookup our transaction in the block that it confirmed in.
|
// Re-lookup our transaction in the block that it confirmed in.
|
||||||
tx = ht.AssertTxAtHeight(alice, height, fundingTxID)
|
tx = ht.AssertTxAtHeight(alice, height, fundingTxID)
|
||||||
@@ -685,6 +690,11 @@ func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
|
|||||||
chanAlice := ht.AssertChannelExists(alice, chanPoint)
|
chanAlice := ht.AssertChannelExists(alice, chanPoint)
|
||||||
ht.AssertChannelExists(carol, 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
|
// Create an additional check for our channel assertion that will
|
||||||
// check that our label is as expected.
|
// check that our label is as expected.
|
||||||
shortChanID := lnwire.NewShortChanIDFromInt(chanAlice.ChanId)
|
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
|
// testBatchChanFunding makes sure multiple channels can be opened in one batch
|
||||||
// transaction in an atomic way.
|
// 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
|
// 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
|
// to during this test. Carol has a high minimum funding amount that
|
||||||
// we'll use to trigger an error during the batch channel open.
|
// 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
|
// deriveFundingShim creates a channel funding shim by deriving the necessary
|
||||||
// keys on both sides.
|
// keys on both sides.
|
||||||
func deriveFundingShim(ht *lntemp.HarnessTest,
|
func deriveFundingShim(ht *lntest.HarnessTest,
|
||||||
carol, dave *node.HarnessNode, chanSize btcutil.Amount,
|
carol, dave *node.HarnessNode, chanSize btcutil.Amount,
|
||||||
thawHeight uint32, publish bool) (*lnrpc.FundingShim,
|
thawHeight uint32, publish bool) (*lnrpc.FundingShim,
|
||||||
*lnrpc.ChannelPoint, *chainhash.Hash) {
|
*lnrpc.ChannelPoint) {
|
||||||
|
|
||||||
keyLoc := &signrpc.KeyLocator{KeyFamily: 9999}
|
keyLoc := &signrpc.KeyLocator{KeyFamily: 9999}
|
||||||
carolFundingKey := carol.RPC.DeriveKey(keyLoc)
|
carolFundingKey := carol.RPC.DeriveKey(keyLoc)
|
||||||
@@ -882,5 +892,5 @@ func deriveFundingShim(ht *lntemp.HarnessTest,
|
|||||||
}
|
}
|
||||||
fundingShim.GetChanPointShim().RemoteKey = daveFundingKey.RawKeyBytes
|
fundingShim.GetChanPointShim().RemoteKey = daveFundingKey.RawKeyBytes
|
||||||
|
|
||||||
return fundingShim, chanPoint, txid
|
return fundingShim, chanPoint
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"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/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -15,11 +15,11 @@ import (
|
|||||||
|
|
||||||
// testHoldInvoiceForceClose tests cancellation of accepted hold invoices which
|
// testHoldInvoiceForceClose tests cancellation of accepted hold invoices which
|
||||||
// would otherwise trigger force closes when they expire.
|
// 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.
|
// Open a channel between alice and bob.
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{Amt: 300000},
|
alice, bob, lntest.OpenChannelParams{Amt: 300000},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Create a non-dust hold invoice for bob.
|
// Create a non-dust hold invoice for bob.
|
||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
// testHoldInvoicePersistence tests that a sender to a hold-invoice, can be
|
// testHoldInvoicePersistence tests that a sender to a hold-invoice, can be
|
||||||
// restarted before the payment gets settled, and still be able to receive the
|
// restarted before the payment gets settled, and still be able to receive the
|
||||||
// preimage.
|
// preimage.
|
||||||
func testHoldInvoicePersistence(ht *lntemp.HarnessTest) {
|
func testHoldInvoicePersistence(ht *lntest.HarnessTest) {
|
||||||
const (
|
const (
|
||||||
chanAmt = btcutil.Amount(1000000)
|
chanAmt = btcutil.Amount(1000000)
|
||||||
numPayments = 10
|
numPayments = 10
|
||||||
@@ -34,7 +34,7 @@ func testHoldInvoicePersistence(ht *lntemp.HarnessTest) {
|
|||||||
// Open a channel between Alice and Carol which is private so that we
|
// Open a channel between Alice and Carol which is private so that we
|
||||||
// cover the addition of hop hints for hold invoices.
|
// cover the addition of hop hints for hold invoices.
|
||||||
chanPointAlice := ht.OpenChannel(
|
chanPointAlice := ht.OpenChannel(
|
||||||
alice, carol, lntemp.OpenChannelParams{
|
alice, carol, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
Private: true,
|
Private: true,
|
||||||
},
|
},
|
||||||
@@ -45,7 +45,7 @@ func testHoldInvoicePersistence(ht *lntemp.HarnessTest) {
|
|||||||
// has at least one public channel in the graph. We open a public
|
// has at least one public channel in the graph. We open a public
|
||||||
// channel from Alice -> Bob and wait for Carol to see it.
|
// channel from Alice -> Bob and wait for Carol to see it.
|
||||||
chanPointBob := ht.OpenChannel(
|
chanPointBob := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/macaroons"
|
"github.com/lightningnetwork/lnd/macaroons"
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -23,7 +23,7 @@ import (
|
|||||||
// enabled on the gRPC interface, no requests with missing or invalid
|
// enabled on the gRPC interface, no requests with missing or invalid
|
||||||
// macaroons are allowed. Further, the specific access rights (read/write,
|
// macaroons are allowed. Further, the specific access rights (read/write,
|
||||||
// entity based) and first-party caveats are tested as well.
|
// entity based) and first-party caveats are tested as well.
|
||||||
func testMacaroonAuthentication(ht *lntemp.HarnessTest) {
|
func testMacaroonAuthentication(ht *lntest.HarnessTest) {
|
||||||
var (
|
var (
|
||||||
infoReq = &lnrpc.GetInfoRequest{}
|
infoReq = &lnrpc.GetInfoRequest{}
|
||||||
newAddrReq = &lnrpc.NewAddressRequest{
|
newAddrReq = &lnrpc.NewAddressRequest{
|
||||||
@@ -294,7 +294,7 @@ func testMacaroonAuthentication(ht *lntemp.HarnessTest) {
|
|||||||
// testBakeMacaroon checks that when creating macaroons, the permissions param
|
// testBakeMacaroon checks that when creating macaroons, the permissions param
|
||||||
// in the request must be set correctly, and the baked macaroon has the intended
|
// in the request must be set correctly, and the baked macaroon has the intended
|
||||||
// permissions.
|
// permissions.
|
||||||
func testBakeMacaroon(ht *lntemp.HarnessTest) {
|
func testBakeMacaroon(ht *lntest.HarnessTest) {
|
||||||
var testNode = ht.Alice
|
var testNode = ht.Alice
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
@@ -518,7 +518,7 @@ func testBakeMacaroon(ht *lntemp.HarnessTest) {
|
|||||||
// specified ID and invalidates all macaroons derived from the key with that ID.
|
// specified ID and invalidates all macaroons derived from the key with that ID.
|
||||||
// Also, it checks deleting the reserved marcaroon ID, DefaultRootKeyID or is
|
// Also, it checks deleting the reserved marcaroon ID, DefaultRootKeyID or is
|
||||||
// forbidden.
|
// forbidden.
|
||||||
func testDeleteMacaroonID(ht *lntemp.HarnessTest) {
|
func testDeleteMacaroonID(ht *lntest.HarnessTest) {
|
||||||
var (
|
var (
|
||||||
ctxb = ht.Context()
|
ctxb = ht.Context()
|
||||||
testNode = ht.Alice
|
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
|
// 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
|
// the admin macaroon in the response. It then checks that the password
|
||||||
// change of the wallet can also happen stateless.
|
// change of the wallet can also happen stateless.
|
||||||
func testStatelessInit(ht *lntemp.HarnessTest) {
|
func testStatelessInit(ht *lntest.HarnessTest) {
|
||||||
var (
|
var (
|
||||||
initPw = []byte("stateless")
|
initPw = []byte("stateless")
|
||||||
newPw = []byte("stateless-new")
|
newPw = []byte("stateless-new")
|
||||||
@@ -1,6 +1,3 @@
|
|||||||
//go:build rpctest
|
|
||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
@@ -8,14 +5,14 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/funding"
|
"github.com/lightningnetwork/lnd/funding"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
)
|
)
|
||||||
|
|
||||||
// testMaxChannelSize tests that lnd handles --maxchansize parameter correctly.
|
// testMaxChannelSize tests that lnd handles --maxchansize parameter correctly.
|
||||||
// Wumbo nodes should enforce a default soft limit of 10 BTC by default. This
|
// Wumbo nodes should enforce a default soft limit of 10 BTC by default. This
|
||||||
// limit can be adjusted with --maxchansize config option.
|
// 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
|
// We'll make two new nodes, both wumbo but with the default limit on
|
||||||
// maximum channel size (10 BTC)
|
// maximum channel size (10 BTC)
|
||||||
wumboNode := ht.NewNode(
|
wumboNode := ht.NewNode(
|
||||||
@@ -42,7 +39,7 @@ func testMaxChannelSize(ht *lntemp.HarnessTest) {
|
|||||||
)
|
)
|
||||||
ht.OpenChannelAssertErr(
|
ht.OpenChannelAssertErr(
|
||||||
wumboNode, wumboNode2,
|
wumboNode, wumboNode2,
|
||||||
lntemp.OpenChannelParams{Amt: chanAmt}, expectedErr,
|
lntest.OpenChannelParams{Amt: chanAmt}, expectedErr,
|
||||||
)
|
)
|
||||||
|
|
||||||
// We'll now make another wumbo node with appropriate maximum channel
|
// 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.
|
// Creating a wumbo channel between these two nodes should succeed.
|
||||||
ht.EnsureConnected(wumboNode, wumboNode3)
|
ht.EnsureConnected(wumboNode, wumboNode3)
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
wumboNode, wumboNode3, lntemp.OpenChannelParams{Amt: chanAmt},
|
wumboNode, wumboNode3, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
|
|
||||||
ht.CloseChannel(wumboNode, chanPoint)
|
ht.CloseChannel(wumboNode, chanPoint)
|
||||||
@@ -4,8 +4,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -14,14 +14,14 @@ import (
|
|||||||
// channel where we have already reached the limit of the number of htlcs that
|
// 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
|
// 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.
|
// 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
|
// Setup a channel between Alice and Bob where Alice will only allow
|
||||||
// Bob to add a maximum of 5 htlcs to her commitment.
|
// Bob to add a maximum of 5 htlcs to her commitment.
|
||||||
maxHtlcs := 5
|
maxHtlcs := 5
|
||||||
|
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: 1000000,
|
Amt: 1000000,
|
||||||
PushAmt: 800000,
|
PushAmt: 800000,
|
||||||
RemoteMaxHtlcs: uint16(maxHtlcs),
|
RemoteMaxHtlcs: uint16(maxHtlcs),
|
||||||
@@ -84,7 +84,7 @@ type holdSubscription struct {
|
|||||||
|
|
||||||
// cancel updates a hold invoice to cancel from the recipient and consumes
|
// cancel updates a hold invoice to cancel from the recipient and consumes
|
||||||
// updates from the payer until it has reached a final, failed state.
|
// 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[:])
|
h.recipient.RPC.CancelInvoice(h.hash[:])
|
||||||
|
|
||||||
invUpdate := ht.ReceiveSingleInvoice(h.invSubscription)
|
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
|
// 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
|
// the sender and asserts that we have reached the accepted state where htlcs
|
||||||
// are locked in for the payment.
|
// 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 {
|
receiver *node.HarnessNode) *holdSubscription {
|
||||||
|
|
||||||
hash := [lntypes.HashSize]byte{byte(idx + 1)}
|
hash := [lntypes.HashSize]byte{byte(idx + 1)}
|
||||||
@@ -15,8 +15,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@@ -28,7 +28,7 @@ import (
|
|||||||
// disconnect at any point.
|
// disconnect at any point.
|
||||||
//
|
//
|
||||||
// TODO(yy): move to lnd_network_test.
|
// 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
|
// We'll start both nodes with a high backoff so that they don't
|
||||||
// reconnect automatically during our test.
|
// reconnect automatically during our test.
|
||||||
args := []string{
|
args := []string{
|
||||||
@@ -49,7 +49,7 @@ func testDisconnectingTargetPeer(ht *lntemp.HarnessTest) {
|
|||||||
// Create a new channel that requires 1 confs before it's considered
|
// Create a new channel that requires 1 confs before it's considered
|
||||||
// open, then broadcast the funding transaction
|
// open, then broadcast the funding transaction
|
||||||
const numConfs = 1
|
const numConfs = 1
|
||||||
p := lntemp.OpenChannelParams{
|
p := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ func testDisconnectingTargetPeer(ht *lntemp.HarnessTest) {
|
|||||||
// configuration arguments to force Carol to replay the same sphinx packet
|
// configuration arguments to force Carol to replay the same sphinx packet
|
||||||
// after reconnecting to Dave, and compare the returned failure message with
|
// after reconnecting to Dave, and compare the returned failure message with
|
||||||
// what we expect for replayed onion packets.
|
// 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
|
// Open a channel with 100k satoshis between Carol and Dave with Carol
|
||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
chanAmt := btcutil.Amount(100000)
|
chanAmt := btcutil.Amount(100000)
|
||||||
@@ -135,7 +135,7 @@ func testSphinxReplayPersistence(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
ht.ConnectNodes(carol, dave)
|
ht.ConnectNodes(carol, dave)
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
carol, dave, lntemp.OpenChannelParams{
|
carol, dave, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -150,7 +150,7 @@ func testSphinxReplayPersistence(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
ht.ConnectNodes(fred, carol)
|
ht.ConnectNodes(fred, carol)
|
||||||
chanPointFC := ht.OpenChannel(
|
chanPointFC := ht.OpenChannel(
|
||||||
fred, carol, lntemp.OpenChannelParams{
|
fred, carol, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -232,7 +232,7 @@ func testSphinxReplayPersistence(ht *lntemp.HarnessTest) {
|
|||||||
// tests the values in all ChannelConstraints are returned as expected. Once
|
// tests the values in all ChannelConstraints are returned as expected. Once
|
||||||
// ListChannels becomes mature, a test against all fields in ListChannels
|
// ListChannels becomes mature, a test against all fields in ListChannels
|
||||||
// should be performed.
|
// should be performed.
|
||||||
func testListChannels(ht *lntemp.HarnessTest) {
|
func testListChannels(ht *lntest.HarnessTest) {
|
||||||
const aliceRemoteMaxHtlcs = 50
|
const aliceRemoteMaxHtlcs = 50
|
||||||
const bobRemoteMaxHtlcs = 100
|
const bobRemoteMaxHtlcs = 100
|
||||||
|
|
||||||
@@ -255,7 +255,7 @@ func testListChannels(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
chanAmt := btcutil.Amount(100000)
|
chanAmt := btcutil.Amount(100000)
|
||||||
pushAmt := btcutil.Amount(1000)
|
pushAmt := btcutil.Amount(1000)
|
||||||
p := lntemp.OpenChannelParams{
|
p := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
MinHtlc: customizedMinHtlc,
|
MinHtlc: customizedMinHtlc,
|
||||||
@@ -337,7 +337,7 @@ func testListChannels(ht *lntemp.HarnessTest) {
|
|||||||
// testMaxPendingChannels checks that error is returned from remote peer if
|
// testMaxPendingChannels checks that error is returned from remote peer if
|
||||||
// max pending channel number was exceeded and that '--maxpendingchannels' flag
|
// max pending channel number was exceeded and that '--maxpendingchannels' flag
|
||||||
// exists and works properly.
|
// exists and works properly.
|
||||||
func testMaxPendingChannels(ht *lntemp.HarnessTest) {
|
func testMaxPendingChannels(ht *lntest.HarnessTest) {
|
||||||
maxPendingChannels := lncfg.DefaultMaxPendingChannels + 1
|
maxPendingChannels := lncfg.DefaultMaxPendingChannels + 1
|
||||||
amount := funding.MaxBtcFundingAmount
|
amount := funding.MaxBtcFundingAmount
|
||||||
|
|
||||||
@@ -362,7 +362,7 @@ func testMaxPendingChannels(ht *lntemp.HarnessTest) {
|
|||||||
)
|
)
|
||||||
for i := 0; i < maxPendingChannels; i++ {
|
for i := 0; i < maxPendingChannels; i++ {
|
||||||
stream := ht.OpenChannelAssertStream(
|
stream := ht.OpenChannelAssertStream(
|
||||||
alice, carol, lntemp.OpenChannelParams{
|
alice, carol, lntest.OpenChannelParams{
|
||||||
Amt: amount,
|
Amt: amount,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -372,7 +372,7 @@ func testMaxPendingChannels(ht *lntemp.HarnessTest) {
|
|||||||
// Carol exhausted available amount of pending channels, next open
|
// Carol exhausted available amount of pending channels, next open
|
||||||
// channel request should cause ErrorGeneric to be sent back to Alice.
|
// channel request should cause ErrorGeneric to be sent back to Alice.
|
||||||
ht.OpenChannelAssertErr(
|
ht.OpenChannelAssertErr(
|
||||||
alice, carol, lntemp.OpenChannelParams{
|
alice, carol, lntest.OpenChannelParams{
|
||||||
Amt: amount,
|
Amt: amount,
|
||||||
}, lnwire.ErrMaxPendingChannels,
|
}, lnwire.ErrMaxPendingChannels,
|
||||||
)
|
)
|
||||||
@@ -415,7 +415,7 @@ func testMaxPendingChannels(ht *lntemp.HarnessTest) {
|
|||||||
// testGarbageCollectLinkNodes tests that we properly garbage collect link
|
// testGarbageCollectLinkNodes tests that we properly garbage collect link
|
||||||
// nodes from the database and the set of persistent connections within the
|
// nodes from the database and the set of persistent connections within the
|
||||||
// server.
|
// server.
|
||||||
func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
|
func testGarbageCollectLinkNodes(ht *lntest.HarnessTest) {
|
||||||
const chanAmt = 1000000
|
const chanAmt = 1000000
|
||||||
|
|
||||||
alice, bob := ht.Alice, ht.Bob
|
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
|
// Open a channel between Alice and Bob which will later be
|
||||||
// cooperatively closed.
|
// cooperatively closed.
|
||||||
coopChanPoint := ht.OpenChannel(
|
coopChanPoint := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -435,7 +435,7 @@ func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
|
|||||||
// Open a channel between Alice and Carol which will later be force
|
// Open a channel between Alice and Carol which will later be force
|
||||||
// closed.
|
// closed.
|
||||||
forceCloseChanPoint := ht.OpenChannel(
|
forceCloseChanPoint := ht.OpenChannel(
|
||||||
alice, carol, lntemp.OpenChannelParams{
|
alice, carol, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -447,7 +447,7 @@ func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
ht.ConnectNodes(alice, dave)
|
ht.ConnectNodes(alice, dave)
|
||||||
persistentChanPoint := ht.OpenChannel(
|
persistentChanPoint := ht.OpenChannel(
|
||||||
alice, dave, lntemp.OpenChannelParams{
|
alice, dave, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -527,7 +527,7 @@ func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
|
|||||||
// testRejectHTLC tests that a node can be created with the flag --rejecthtlc.
|
// 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
|
// This means that the node will reject all forwarded HTLCs but can still
|
||||||
// accept direct HTLCs as well as send HTLCs.
|
// accept direct HTLCs as well as send HTLCs.
|
||||||
func testRejectHTLC(ht *lntemp.HarnessTest) {
|
func testRejectHTLC(ht *lntest.HarnessTest) {
|
||||||
// RejectHTLC
|
// RejectHTLC
|
||||||
// Alice ------> Carol ------> Bob
|
// Alice ------> Carol ------> Bob
|
||||||
//
|
//
|
||||||
@@ -548,14 +548,14 @@ func testRejectHTLC(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// Open a channel between Alice and Carol.
|
// Open a channel between Alice and Carol.
|
||||||
chanPointAlice := ht.OpenChannel(
|
chanPointAlice := ht.OpenChannel(
|
||||||
alice, carol, lntemp.OpenChannelParams{
|
alice, carol, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Open a channel between Carol and Bob.
|
// Open a channel between Carol and Bob.
|
||||||
chanPointCarol := ht.OpenChannel(
|
chanPointCarol := ht.OpenChannel(
|
||||||
carol, bob, lntemp.OpenChannelParams{
|
carol, bob, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -623,14 +623,14 @@ func testRejectHTLC(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// testNodeSignVerify checks that only connected nodes are allowed to perform
|
// testNodeSignVerify checks that only connected nodes are allowed to perform
|
||||||
// signing and verifying messages.
|
// signing and verifying messages.
|
||||||
func testNodeSignVerify(ht *lntemp.HarnessTest) {
|
func testNodeSignVerify(ht *lntest.HarnessTest) {
|
||||||
chanAmt := funding.MaxBtcFundingAmount
|
chanAmt := funding.MaxBtcFundingAmount
|
||||||
pushAmt := btcutil.Amount(100000)
|
pushAmt := btcutil.Amount(100000)
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
|
|
||||||
// Create a channel between alice and bob.
|
// Create a channel between alice and bob.
|
||||||
aliceBobCh := ht.OpenChannel(
|
aliceBobCh := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
},
|
},
|
||||||
@@ -670,11 +670,11 @@ func testNodeSignVerify(ht *lntemp.HarnessTest) {
|
|||||||
// testAbandonChannel abandons a channel and asserts that it is no longer open
|
// 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
|
// and not in one of the pending closure states. It also verifies that the
|
||||||
// abandoned channel is reported as closed with close type 'abandoned'.
|
// 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
|
alice, bob := ht.Alice, ht.Bob
|
||||||
|
|
||||||
// First establish a channel between Alice and Bob.
|
// First establish a channel between Alice and Bob.
|
||||||
channelParam := lntemp.OpenChannelParams{
|
channelParam := lntest.OpenChannelParams{
|
||||||
Amt: funding.MaxBtcFundingAmount,
|
Amt: funding.MaxBtcFundingAmount,
|
||||||
PushAmt: btcutil.Amount(100000),
|
PushAmt: btcutil.Amount(100000),
|
||||||
}
|
}
|
||||||
@@ -741,7 +741,7 @@ func testAbandonChannel(ht *lntemp.HarnessTest) {
|
|||||||
// wallet into a single target address at the specified fee rate.
|
// wallet into a single target address at the specified fee rate.
|
||||||
//
|
//
|
||||||
// TODO(yy): expand this test to also use P2TR.
|
// 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
|
// First, we'll make a new node, ainz who'll we'll use to test wallet
|
||||||
// sweeping.
|
// sweeping.
|
||||||
//
|
//
|
||||||
@@ -917,7 +917,7 @@ func testSweepAllCoins(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// testListAddresses tests that we get all the addresses and their
|
// testListAddresses tests that we get all the addresses and their
|
||||||
// corresponding balance correctly.
|
// 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
|
// First, we'll make a new node - Alice, which will be generating
|
||||||
// new addresses.
|
// new addresses.
|
||||||
alice := ht.NewNode("Alice", nil)
|
alice := ht.NewNode("Alice", nil)
|
||||||
@@ -964,7 +964,8 @@ func testListAddresses(ht *lntemp.HarnessTest) {
|
|||||||
})
|
})
|
||||||
generatedAddr[resp.Address] = addressDetails{
|
generatedAddr[resp.Address] = addressDetails{
|
||||||
Balance: 400_000,
|
Balance: 400_000,
|
||||||
Type: walletrpc.AddressType_HYBRID_NESTED_WITNESS_PUBKEY_HASH,
|
Type: walletrpc.
|
||||||
|
AddressType_HYBRID_NESTED_WITNESS_PUBKEY_HASH,
|
||||||
}
|
}
|
||||||
|
|
||||||
for addr, addressDetail := range generatedAddr {
|
for addr, addressDetail := range generatedAddr {
|
||||||
@@ -985,7 +986,7 @@ func testListAddresses(ht *lntemp.HarnessTest) {
|
|||||||
foundAddresses := 0
|
foundAddresses := 0
|
||||||
for _, addressList := range addressLists.AccountWithAddresses {
|
for _, addressList := range addressLists.AccountWithAddresses {
|
||||||
addresses := addressList.Addresses
|
addresses := addressList.Addresses
|
||||||
derivationPath, err := lntemp.ParseDerivationPath(
|
derivationPath, err := lntest.ParseDerivationPath(
|
||||||
addressList.DerivationPath,
|
addressList.DerivationPath,
|
||||||
)
|
)
|
||||||
require.NoError(ht, err)
|
require.NoError(ht, err)
|
||||||
@@ -1023,7 +1024,7 @@ func testListAddresses(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
for _, addressList := range addressLists.AccountWithAddresses {
|
for _, addressList := range addressLists.AccountWithAddresses {
|
||||||
addresses := addressList.Addresses
|
addresses := addressList.Addresses
|
||||||
derivationPath, err := lntemp.ParseDerivationPath(
|
derivationPath, err := lntest.ParseDerivationPath(
|
||||||
addressList.DerivationPath,
|
addressList.DerivationPath,
|
||||||
)
|
)
|
||||||
require.NoError(ht, err)
|
require.NoError(ht, err)
|
||||||
@@ -1053,7 +1054,7 @@ func testListAddresses(ht *lntemp.HarnessTest) {
|
|||||||
require.Equal(ht, len(generatedAddr), foundAddresses)
|
require.Equal(ht, len(generatedAddr), foundAddresses)
|
||||||
}
|
}
|
||||||
|
|
||||||
func assertChannelConstraintsEqual(ht *lntemp.HarnessTest,
|
func assertChannelConstraintsEqual(ht *lntest.HarnessTest,
|
||||||
want, got *lnrpc.ChannelConstraints) {
|
want, got *lnrpc.ChannelConstraints) {
|
||||||
|
|
||||||
require.Equal(ht, want.CsvDelay, got.CsvDelay, "CsvDelay mismatched")
|
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
|
// testSignVerifyMessageWithAddr tests signing and also verifying a signature
|
||||||
// on a message with a provided address.
|
// 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.
|
// Using different nodes to sign the message and verify the signature.
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
|
|
||||||
@@ -7,8 +7,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainreg"
|
"github.com/lightningnetwork/lnd/chainreg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/routing/route"
|
"github.com/lightningnetwork/lnd/routing/route"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
// testSendToRouteMultiPath tests that we are able to successfully route a
|
// testSendToRouteMultiPath tests that we are able to successfully route a
|
||||||
// payment using multiple shards across different paths, by using SendToRoute.
|
// payment using multiple shards across different paths, by using SendToRoute.
|
||||||
func testSendToRouteMultiPath(ht *lntemp.HarnessTest) {
|
func testSendToRouteMultiPath(ht *lntest.HarnessTest) {
|
||||||
mts := newMppTestScenario(ht)
|
mts := newMppTestScenario(ht)
|
||||||
|
|
||||||
// To ensure the payment goes through separate paths, we'll set a
|
// 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,
|
// It has two standby nodes, alice and bob, and three new nodes, carol, dave,
|
||||||
// and eve.
|
// and eve.
|
||||||
type mppTestScenario struct {
|
type mppTestScenario struct {
|
||||||
ht *lntemp.HarnessTest
|
ht *lntest.HarnessTest
|
||||||
|
|
||||||
alice, bob, carol, dave, eve *node.HarnessNode
|
alice, bob, carol, dave, eve *node.HarnessNode
|
||||||
nodes []*node.HarnessNode
|
nodes []*node.HarnessNode
|
||||||
@@ -179,7 +179,7 @@ type mppTestScenario struct {
|
|||||||
// Alice -- Carol ---- Bob
|
// Alice -- Carol ---- Bob
|
||||||
// \ /
|
// \ /
|
||||||
// \__ Dave ____/
|
// \__ Dave ____/
|
||||||
func newMppTestScenario(ht *lntemp.HarnessTest) *mppTestScenario {
|
func newMppTestScenario(ht *lntest.HarnessTest) *mppTestScenario {
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
ht.RestartNodeWithExtraArgs(bob, []string{
|
ht.RestartNodeWithExtraArgs(bob, []string{
|
||||||
"--maxpendingchannels=2",
|
"--maxpendingchannels=2",
|
||||||
@@ -256,36 +256,36 @@ type mppOpenChannelRequest struct {
|
|||||||
//
|
//
|
||||||
// NOTE: all the channels are open together to save blocks mined.
|
// NOTE: all the channels are open together to save blocks mined.
|
||||||
func (m *mppTestScenario) openChannels(r *mppOpenChannelRequest) {
|
func (m *mppTestScenario) openChannels(r *mppOpenChannelRequest) {
|
||||||
reqs := []*lntemp.OpenChannelRequest{
|
reqs := []*lntest.OpenChannelRequest{
|
||||||
{
|
{
|
||||||
Local: m.alice,
|
Local: m.alice,
|
||||||
Remote: m.carol,
|
Remote: m.carol,
|
||||||
Param: lntemp.OpenChannelParams{Amt: r.amtAliceCarol},
|
Param: lntest.OpenChannelParams{Amt: r.amtAliceCarol},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Local: m.alice,
|
Local: m.alice,
|
||||||
Remote: m.dave,
|
Remote: m.dave,
|
||||||
Param: lntemp.OpenChannelParams{Amt: r.amtAliceDave},
|
Param: lntest.OpenChannelParams{Amt: r.amtAliceDave},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Local: m.carol,
|
Local: m.carol,
|
||||||
Remote: m.bob,
|
Remote: m.bob,
|
||||||
Param: lntemp.OpenChannelParams{Amt: r.amtCarolBob},
|
Param: lntest.OpenChannelParams{Amt: r.amtCarolBob},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Local: m.carol,
|
Local: m.carol,
|
||||||
Remote: m.eve,
|
Remote: m.eve,
|
||||||
Param: lntemp.OpenChannelParams{Amt: r.amtCarolEve},
|
Param: lntest.OpenChannelParams{Amt: r.amtCarolEve},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Local: m.dave,
|
Local: m.dave,
|
||||||
Remote: m.bob,
|
Remote: m.bob,
|
||||||
Param: lntemp.OpenChannelParams{Amt: r.amtDaveBob},
|
Param: lntest.OpenChannelParams{Amt: r.amtDaveBob},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Local: m.eve,
|
Local: m.eve,
|
||||||
Remote: m.bob,
|
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.
|
// active htlcs` or `link failed to shutdown` if we close the channel.
|
||||||
// We need to investigate the order of settling the payments and
|
// We need to investigate the order of settling the payments and
|
||||||
// updating commitments to understand and fix .
|
// updating commitments to understand and fix .
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(5 * time.Second)
|
||||||
|
|
||||||
// Close all channels without mining the closing transactions.
|
// Close all channels without mining the closing transactions.
|
||||||
m.ht.CloseChannelAssertPending(m.alice, m.channelPoints[0], false)
|
m.ht.CloseChannelAssertPending(m.alice, m.channelPoints[0], false)
|
||||||
+22
-23
@@ -6,12 +6,12 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/funding"
|
"github.com/lightningnetwork/lnd/funding"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/stretchr/testify/require"
|
"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,
|
// In this test we wish to exercise the daemon's correct parsing,
|
||||||
// handling, and propagation of errors that occur while processing a
|
// handling, and propagation of errors that occur while processing a
|
||||||
// multi-hop payment.
|
// multi-hop payment.
|
||||||
@@ -39,23 +39,22 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
|||||||
// and Bob.
|
// and Bob.
|
||||||
chanPointAlice := ht.OpenChannel(
|
chanPointAlice := ht.OpenChannel(
|
||||||
alice, bob,
|
alice, bob,
|
||||||
lntemp.OpenChannelParams{Amt: chanAmt},
|
lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Next, we'll create a connection from Bob to Carol, and open a
|
// Next, we'll create a connection from Bob to Carol, and open a
|
||||||
// channel between them so we have the topology: Alice -> Bob -> Carol.
|
// channel between them so we have the topology: Alice -> Bob -> Carol.
|
||||||
// The channel created will be of lower capacity that the one created
|
// The channel created will be of lower capacity that the one created
|
||||||
// above.
|
// above.
|
||||||
const bobChanAmt = funding.MaxBtcFundingAmount
|
|
||||||
chanPointBob := ht.OpenChannel(
|
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.
|
// Ensure that Alice has Carol in her routing table before proceeding.
|
||||||
ht.AssertTopologyChannelOpen(alice, chanPointBob)
|
ht.AssertTopologyChannelOpen(alice, chanPointBob)
|
||||||
|
|
||||||
cType := ht.GetChannelCommitType(alice, chanPointAlice)
|
cType := ht.GetChannelCommitType(alice, chanPointAlice)
|
||||||
commitFee := calcStaticFee(cType, 0)
|
commitFee := lntest.CalcStaticFee(cType, 0)
|
||||||
|
|
||||||
assertBaseBalance := func() {
|
assertBaseBalance := func() {
|
||||||
// Alice has opened a channel with Bob with zero push amount,
|
// Alice has opened a channel with Bob with zero push amount,
|
||||||
@@ -153,24 +152,24 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
|||||||
assertAliceAndBob := func() {
|
assertAliceAndBob := func() {
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
aliceEvents, routerrpc.HtlcEvent_SEND,
|
aliceEvents, routerrpc.HtlcEvent_SEND,
|
||||||
lntemp.HtlcEventForward,
|
lntest.HtlcEventForward,
|
||||||
)
|
)
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
aliceEvents, routerrpc.HtlcEvent_SEND,
|
aliceEvents, routerrpc.HtlcEvent_SEND,
|
||||||
lntemp.HtlcEventForwardFail,
|
lntest.HtlcEventForwardFail,
|
||||||
)
|
)
|
||||||
|
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
bobEvents, routerrpc.HtlcEvent_FORWARD,
|
bobEvents, routerrpc.HtlcEvent_FORWARD,
|
||||||
lntemp.HtlcEventForward,
|
lntest.HtlcEventForward,
|
||||||
)
|
)
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
bobEvents, routerrpc.HtlcEvent_FORWARD,
|
bobEvents, routerrpc.HtlcEvent_FORWARD,
|
||||||
lntemp.HtlcEventForwardFail,
|
lntest.HtlcEventForwardFail,
|
||||||
)
|
)
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
bobEvents, routerrpc.HtlcEvent_UNKNOWN,
|
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
|
// There's also a final htlc event that gives the final outcome of the
|
||||||
// htlc.
|
// htlc.
|
||||||
ht.AssertHtlcEventTypes(
|
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
|
// 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
|
// There's also a final htlc event that gives the final outcome of the
|
||||||
// htlc.
|
// htlc.
|
||||||
ht.AssertHtlcEventTypes(
|
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
|
// 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.
|
// settle event and a final htlc event for her receive.
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
bobEvents, routerrpc.HtlcEvent_SEND,
|
bobEvents, routerrpc.HtlcEvent_SEND,
|
||||||
lntemp.HtlcEventForward,
|
lntest.HtlcEventForward,
|
||||||
)
|
)
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
bobEvents, routerrpc.HtlcEvent_SEND,
|
bobEvents, routerrpc.HtlcEvent_SEND,
|
||||||
lntemp.HtlcEventSettle,
|
lntest.HtlcEventSettle,
|
||||||
)
|
)
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
carolEvents, routerrpc.HtlcEvent_RECEIVE,
|
carolEvents, routerrpc.HtlcEvent_RECEIVE,
|
||||||
lntemp.HtlcEventSettle,
|
lntest.HtlcEventSettle,
|
||||||
)
|
)
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
carolEvents, routerrpc.HtlcEvent_UNKNOWN,
|
carolEvents, routerrpc.HtlcEvent_UNKNOWN,
|
||||||
lntemp.HtlcEventFinal,
|
lntest.HtlcEventFinal,
|
||||||
)
|
)
|
||||||
|
|
||||||
amtSent += toSend
|
amtSent += toSend
|
||||||
@@ -316,11 +315,11 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
|||||||
// Alice should have a forwarding event and a forwarding failure.
|
// Alice should have a forwarding event and a forwarding failure.
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
aliceEvents, routerrpc.HtlcEvent_SEND,
|
aliceEvents, routerrpc.HtlcEvent_SEND,
|
||||||
lntemp.HtlcEventForward,
|
lntest.HtlcEventForward,
|
||||||
)
|
)
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
aliceEvents, routerrpc.HtlcEvent_SEND,
|
aliceEvents, routerrpc.HtlcEvent_SEND,
|
||||||
lntemp.HtlcEventForwardFail,
|
lntest.HtlcEventForwardFail,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bob should have a link failure because the htlc failed on his
|
// 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
|
// There's also a final htlc event that gives the final outcome of the
|
||||||
// htlc.
|
// htlc.
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
bobEvents, routerrpc.HtlcEvent_UNKNOWN, lntemp.HtlcEventFinal,
|
bobEvents, routerrpc.HtlcEvent_UNKNOWN, lntest.HtlcEventFinal,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Generate new invoice to not pay same invoice twice.
|
// 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.
|
// Alice should have a forwarding event and subsequent fail.
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
aliceEvents, routerrpc.HtlcEvent_SEND,
|
aliceEvents, routerrpc.HtlcEvent_SEND,
|
||||||
lntemp.HtlcEventForward,
|
lntest.HtlcEventForward,
|
||||||
)
|
)
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
aliceEvents, routerrpc.HtlcEvent_SEND,
|
aliceEvents, routerrpc.HtlcEvent_SEND,
|
||||||
lntemp.HtlcEventForwardFail,
|
lntest.HtlcEventForwardFail,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Bob should have a link failure because he could not find the next
|
// 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
|
// There's also a final htlc event that gives the final outcome of the
|
||||||
// htlc.
|
// htlc.
|
||||||
ht.AssertHtlcEventTypes(
|
ht.AssertHtlcEventTypes(
|
||||||
bobEvents, routerrpc.HtlcEvent_UNKNOWN, lntemp.HtlcEventFinal,
|
bobEvents, routerrpc.HtlcEvent_UNKNOWN, lntest.HtlcEventFinal,
|
||||||
)
|
)
|
||||||
|
|
||||||
// Finally, immediately close the channel. This function will also
|
// Finally, immediately close the channel. This function will also
|
||||||
@@ -5,12 +5,12 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainreg"
|
"github.com/lightningnetwork/lnd/chainreg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testMultiHopPayments(ht *lntemp.HarnessTest) {
|
func testMultiHopPayments(ht *lntest.HarnessTest) {
|
||||||
const chanAmt = btcutil.Amount(100000)
|
const chanAmt = btcutil.Amount(100000)
|
||||||
|
|
||||||
// As preliminary setup, we'll create two new nodes: Carol and Dave,
|
// 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
|
// Open a channel with 100k satoshis between Alice and Bob with Alice
|
||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
chanPointAlice := ht.OpenChannel(
|
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
|
// We'll create Dave and establish a channel to Alice. Dave will be
|
||||||
// running an older node that requires the legacy onion payload.
|
// running an older node that requires the legacy onion payload.
|
||||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, dave)
|
ht.FundCoins(btcutil.SatoshiPerBitcoin, dave)
|
||||||
chanPointDave := ht.OpenChannel(
|
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
|
// Next, we'll create Carol and establish a channel to from her to
|
||||||
// Dave.
|
// Dave.
|
||||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||||
chanPointCarol := ht.OpenChannel(
|
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
|
// 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
|
// Set the fee policies of the Alice -> Bob and the Dave -> Alice
|
||||||
// channel edges to relatively large non default values. This makes it
|
// channel edges to relatively large non default values. This makes it
|
||||||
// possible to pick up more subtle fee calculation errors.
|
// possible to pick up more subtle fee calculation errors.
|
||||||
maxHtlc := calculateMaxHtlc(chanAmt)
|
maxHtlc := lntest.CalculateMaxHtlc(chanAmt)
|
||||||
const aliceBaseFeeSat = 1
|
const aliceBaseFeeSat = 1
|
||||||
const aliceFeeRatePPM = 100000
|
const aliceFeeRatePPM = 100000
|
||||||
updateChannelPolicy(
|
updateChannelPolicy(
|
||||||
@@ -222,7 +222,7 @@ func testMultiHopPayments(ht *lntemp.HarnessTest) {
|
|||||||
// policy update.
|
// policy update.
|
||||||
//
|
//
|
||||||
// NOTE: only used in current test.
|
// 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,
|
chanPoint *lnrpc.ChannelPoint, baseFee int64,
|
||||||
feeRate int64, timeLockDelta uint32,
|
feeRate int64, timeLockDelta uint32,
|
||||||
maxHtlc uint64, listenerNode *node.HarnessNode) {
|
maxHtlc uint64, listenerNode *node.HarnessNode) {
|
||||||
@@ -12,10 +12,9 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"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"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/routing"
|
"github.com/lightningnetwork/lnd/routing"
|
||||||
"github.com/stretchr/testify/require"
|
"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.
|
// 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)
|
c lnrpc.CommitmentType, zeroConf bool)
|
||||||
|
|
||||||
// runMultiHopHtlcClaimTest is a helper method to build test cases based on
|
// runMultiHopHtlcClaimTest is a helper method to build test cases based on
|
||||||
// different commitment types and zero-conf config and run them.
|
// 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 {
|
for _, typeAndConf := range commitWithZeroConf {
|
||||||
typeAndConf := typeAndConf
|
typeAndConf := typeAndConf
|
||||||
name := fmt.Sprintf("zeroconf=%v/committype=%v",
|
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
|
// Create the nodes here so that separate logs will be created
|
||||||
// for Alice and Bob.
|
// for Alice and Bob.
|
||||||
args := nodeArgsForCommitType(typeAndConf.commitType)
|
args := lntest.NodeArgsForCommitType(typeAndConf.commitType)
|
||||||
if typeAndConf.zeroConf {
|
if typeAndConf.zeroConf {
|
||||||
args = append(
|
args = append(
|
||||||
args, "--protocol.option-scid-alias",
|
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
|
// 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
|
// canceled backwards. Once the timeout has been reached, then we should sweep
|
||||||
// it on-chain, and cancel the HTLC backwards.
|
// it on-chain, and cancel the HTLC backwards.
|
||||||
func testMultiHopHtlcLocalTimeout(ht *lntemp.HarnessTest) {
|
func testMultiHopHtlcLocalTimeout(ht *lntest.HarnessTest) {
|
||||||
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcLocalTimeout)
|
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcLocalTimeout)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runMultiHopHtlcLocalTimeout(ht *lntemp.HarnessTest,
|
func runMultiHopHtlcLocalTimeout(ht *lntest.HarnessTest,
|
||||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||||
|
|
||||||
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
|
// 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
|
// Bob's force close transaction should now be found in the mempool. If
|
||||||
// there are anchors, we also expect Bob's anchor sweep.
|
// there are anchors, we also expect Bob's anchor sweep.
|
||||||
expectedTxes := 1
|
expectedTxes := 1
|
||||||
hasAnchors := commitTypeHasAnchors(c)
|
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||||
if hasAnchors {
|
if hasAnchors {
|
||||||
expectedTxes = 2
|
expectedTxes = 2
|
||||||
}
|
}
|
||||||
@@ -369,11 +272,11 @@ func runMultiHopHtlcLocalTimeout(ht *lntemp.HarnessTest,
|
|||||||
// transaction. In this scenario, the node that sent the outgoing HTLC should
|
// transaction. In this scenario, the node that sent the outgoing HTLC should
|
||||||
// extract the preimage from the sweep transaction, and finish settling the
|
// extract the preimage from the sweep transaction, and finish settling the
|
||||||
// HTLC backwards into the route.
|
// HTLC backwards into the route.
|
||||||
func testMultiHopReceiverChainClaim(ht *lntemp.HarnessTest) {
|
func testMultiHopReceiverChainClaim(ht *lntest.HarnessTest) {
|
||||||
runMultiHopHtlcClaimTest(ht, runMultiHopReceiverChainClaim)
|
runMultiHopHtlcClaimTest(ht, runMultiHopReceiverChainClaim)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runMultiHopReceiverChainClaim(ht *lntemp.HarnessTest,
|
func runMultiHopReceiverChainClaim(ht *lntest.HarnessTest,
|
||||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||||
|
|
||||||
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
|
// 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
|
// transaction in order to go to the chain and sweep her HTLC. If there
|
||||||
// are anchors, Carol also sweeps hers.
|
// are anchors, Carol also sweeps hers.
|
||||||
expectedTxes := 1
|
expectedTxes := 1
|
||||||
hasAnchors := commitTypeHasAnchors(c)
|
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||||
if hasAnchors {
|
if hasAnchors {
|
||||||
expectedTxes = 2
|
expectedTxes = 2
|
||||||
}
|
}
|
||||||
@@ -567,13 +470,13 @@ func runMultiHopReceiverChainClaim(ht *lntemp.HarnessTest,
|
|||||||
// commitment on-chain early, then it eventually recognizes this HTLC as one
|
// 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
|
// that's timed out. At this point, the node should timeout the HTLC using the
|
||||||
// HTLC timeout transaction, then cancel it backwards as normal.
|
// HTLC timeout transaction, then cancel it backwards as normal.
|
||||||
func testMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest) {
|
func testMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest) {
|
||||||
runMultiHopHtlcClaimTest(
|
runMultiHopHtlcClaimTest(
|
||||||
ht, runMultiHopLocalForceCloseOnChainHtlcTimeout,
|
ht, runMultiHopLocalForceCloseOnChainHtlcTimeout,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
|
func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest,
|
||||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||||
|
|
||||||
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
|
// 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
|
// Now that all parties have the HTLC locked in, we'll immediately
|
||||||
// force close the Bob -> Carol channel. This should trigger contract
|
// force close the Bob -> Carol channel. This should trigger contract
|
||||||
// resolution mode for both of them.
|
// resolution mode for both of them.
|
||||||
hasAnchors := commitTypeHasAnchors(c)
|
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||||
stream, _ := ht.CloseChannelAssertPending(bob, bobChanPoint, true)
|
stream, _ := ht.CloseChannelAssertPending(bob, bobChanPoint, true)
|
||||||
closeTx := ht.AssertStreamChannelForceClosed(
|
closeTx := ht.AssertStreamChannelForceClosed(
|
||||||
bob, bobChanPoint, hasAnchors, stream,
|
bob, bobChanPoint, hasAnchors, stream,
|
||||||
@@ -723,13 +626,13 @@ func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
|
|||||||
// channel, then we properly timeout the HTLC directly on *their* commitment
|
// channel, then we properly timeout the HTLC directly on *their* commitment
|
||||||
// transaction once the timeout has expired. Once we sweep the transaction, we
|
// transaction once the timeout has expired. Once we sweep the transaction, we
|
||||||
// should also cancel back the initial HTLC.
|
// should also cancel back the initial HTLC.
|
||||||
func testMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest) {
|
func testMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest) {
|
||||||
runMultiHopHtlcClaimTest(
|
runMultiHopHtlcClaimTest(
|
||||||
ht, runMultiHopRemoteForceCloseOnChainHtlcTimeout,
|
ht, runMultiHopRemoteForceCloseOnChainHtlcTimeout,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
|
func runMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest,
|
||||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||||
|
|
||||||
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
|
// 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
|
// transaction. This will let us exercise that Bob is able to sweep the
|
||||||
// expired HTLC on Carol's version of the commitment transaction. If
|
// expired HTLC on Carol's version of the commitment transaction. If
|
||||||
// Carol has an anchor, it will be swept too.
|
// Carol has an anchor, it will be swept too.
|
||||||
hasAnchors := commitTypeHasAnchors(c)
|
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||||
closeStream, _ := ht.CloseChannelAssertPending(
|
closeStream, _ := ht.CloseChannelAssertPending(
|
||||||
carol, bobChanPoint, true,
|
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
|
// 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
|
// 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.
|
// 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)
|
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcLocalChainClaim)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runMultiHopHtlcLocalChainClaim(ht *lntemp.HarnessTest,
|
func runMultiHopHtlcLocalChainClaim(ht *lntest.HarnessTest,
|
||||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||||
|
|
||||||
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
|
// 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
|
// At this point, Bob decides that he wants to exit the channel
|
||||||
// immediately, so he force closes his commitment transaction.
|
// immediately, so he force closes his commitment transaction.
|
||||||
hasAnchors := commitTypeHasAnchors(c)
|
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||||
closeStream, _ := ht.CloseChannelAssertPending(
|
closeStream, _ := ht.CloseChannelAssertPending(
|
||||||
bob, aliceChanPoint, true,
|
bob, aliceChanPoint, true,
|
||||||
)
|
)
|
||||||
@@ -985,7 +888,7 @@ func runMultiHopHtlcLocalChainClaim(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// Carol's commitment transaction should now be in the mempool. If
|
// Carol's commitment transaction should now be in the mempool. If
|
||||||
// there is an anchor, Carol will sweep that too.
|
// there is an anchor, Carol will sweep that too.
|
||||||
if commitTypeHasAnchors(c) {
|
if lntest.CommitTypeHasAnchors(c) {
|
||||||
expectedTxes = 2
|
expectedTxes = 2
|
||||||
}
|
}
|
||||||
ht.Miner.AssertNumTxsInMempool(expectedTxes)
|
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
|
// 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
|
// HTLC directly on-chain using the preimage in order to ensure that we don't
|
||||||
// lose any funds.
|
// lose any funds.
|
||||||
func testMultiHopHtlcRemoteChainClaim(ht *lntemp.HarnessTest) {
|
func testMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest) {
|
||||||
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcRemoteChainClaim)
|
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcRemoteChainClaim)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runMultiHopHtlcRemoteChainClaim(ht *lntemp.HarnessTest,
|
func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest,
|
||||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||||
|
|
||||||
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
|
// 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
|
// Next, Alice decides that she wants to exit the channel, so she'll
|
||||||
// immediately force close the channel by broadcast her commitment
|
// immediately force close the channel by broadcast her commitment
|
||||||
// transaction.
|
// transaction.
|
||||||
hasAnchors := commitTypeHasAnchors(c)
|
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||||
closeStream, _ := ht.CloseChannelAssertPending(
|
closeStream, _ := ht.CloseChannelAssertPending(
|
||||||
alice, aliceChanPoint, true,
|
alice, aliceChanPoint, true,
|
||||||
)
|
)
|
||||||
@@ -1443,11 +1346,11 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntemp.HarnessTest,
|
|||||||
// resolve them using the second level timeout and success transactions. In
|
// resolve them using the second level timeout and success transactions. In
|
||||||
// case of anchor channels, the second-level spends can also be aggregated and
|
// case of anchor channels, the second-level spends can also be aggregated and
|
||||||
// properly feebumped, so we'll check that as well.
|
// properly feebumped, so we'll check that as well.
|
||||||
func testMultiHopHtlcAggregation(ht *lntemp.HarnessTest) {
|
func testMultiHopHtlcAggregation(ht *lntest.HarnessTest) {
|
||||||
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcAggregation)
|
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcAggregation)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runMultiHopHtlcAggregation(ht *lntemp.HarnessTest,
|
func runMultiHopHtlcAggregation(ht *lntest.HarnessTest,
|
||||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||||
|
|
||||||
// First, we'll create a three hop network: Alice -> Bob -> Carol.
|
// 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
|
// Bob's force close transaction should now be found in the mempool. If
|
||||||
// there are anchors, we also expect Bob's anchor sweep.
|
// there are anchors, we also expect Bob's anchor sweep.
|
||||||
hasAnchors := commitTypeHasAnchors(c)
|
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||||
expectedTxes := 1
|
expectedTxes := 1
|
||||||
if hasAnchors {
|
if hasAnchors {
|
||||||
expectedTxes = 2
|
expectedTxes = 2
|
||||||
@@ -1825,7 +1728,7 @@ func runMultiHopHtlcAggregation(ht *lntemp.HarnessTest,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// createThreeHopNetwork creates a topology of `Alice -> Bob -> Carol`.
|
// 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,
|
alice, bob *node.HarnessNode, carolHodl bool, c lnrpc.CommitmentType,
|
||||||
zeroConf bool) (*lnrpc.ChannelPoint,
|
zeroConf bool) (*lnrpc.ChannelPoint,
|
||||||
*lnrpc.ChannelPoint, *node.HarnessNode) {
|
*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.
|
// 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
|
// 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.
|
// HTLC, this way it'll force Bob to go to chain to resolve the HTLC.
|
||||||
carolFlags := nodeArgsForCommitType(c)
|
carolFlags := lntest.NodeArgsForCommitType(c)
|
||||||
if carolHodl {
|
if carolHodl {
|
||||||
carolFlags = append(carolFlags, "--hodl.exit-settle")
|
carolFlags = append(carolFlags, "--hodl.exit-settle")
|
||||||
}
|
}
|
||||||
@@ -1871,7 +1774,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
|
|||||||
if c == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE {
|
if c == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE {
|
||||||
_, minerHeight := ht.Miner.GetBestBlock()
|
_, minerHeight := ht.Miner.GetBestBlock()
|
||||||
thawHeight = uint32(minerHeight + thawHeightDelta)
|
thawHeight = uint32(minerHeight + thawHeightDelta)
|
||||||
aliceFundingShim, _, _ = deriveFundingShim(
|
aliceFundingShim, _ = deriveFundingShim(
|
||||||
ht, alice, bob, chanAmt, thawHeight, true,
|
ht, alice, bob, chanAmt, thawHeight, true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1887,7 +1790,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
|
|||||||
go acceptChannel(ht.T, true, acceptStream)
|
go acceptChannel(ht.T, true, acceptStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
aliceParams := lntemp.OpenChannelParams{
|
aliceParams := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
CommitmentType: c,
|
CommitmentType: c,
|
||||||
FundingShim: aliceFundingShim,
|
FundingShim: aliceFundingShim,
|
||||||
@@ -1904,7 +1807,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
|
|||||||
// open, our topology looks like: A -> B -> C.
|
// open, our topology looks like: A -> B -> C.
|
||||||
var bobFundingShim *lnrpc.FundingShim
|
var bobFundingShim *lnrpc.FundingShim
|
||||||
if c == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE {
|
if c == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE {
|
||||||
bobFundingShim, _, _ = deriveFundingShim(
|
bobFundingShim, _ = deriveFundingShim(
|
||||||
ht, bob, carol, chanAmt, thawHeight, true,
|
ht, bob, carol, chanAmt, thawHeight, true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1916,7 +1819,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
|
|||||||
go acceptChannel(ht.T, true, acceptStream)
|
go acceptChannel(ht.T, true, acceptStream)
|
||||||
}
|
}
|
||||||
|
|
||||||
bobParams := lntemp.OpenChannelParams{
|
bobParams := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
CommitmentType: c,
|
CommitmentType: c,
|
||||||
FundingShim: bobFundingShim,
|
FundingShim: bobFundingShim,
|
||||||
@@ -3,12 +3,12 @@ package itest
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/lncfg"
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"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"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
// testNetworkConnectionTimeout checks that the connectiontimeout is taking
|
// testNetworkConnectionTimeout checks that the connectiontimeout is taking
|
||||||
// effect. It creates a node with a small connection timeout value, and
|
// effect. It creates a node with a small connection timeout value, and
|
||||||
// connects it to a non-routable IP address.
|
// connects it to a non-routable IP address.
|
||||||
func testNetworkConnectionTimeout(ht *lntemp.HarnessTest) {
|
func testNetworkConnectionTimeout(ht *lntest.HarnessTest) {
|
||||||
var (
|
var (
|
||||||
// testPub is a random public key for testing only.
|
// testPub is a random public key for testing only.
|
||||||
testPub = "0332bda7da70fefe4b6ab92f53b3c4f4ee7999" +
|
testPub = "0332bda7da70fefe4b6ab92f53b3c4f4ee7999" +
|
||||||
@@ -75,7 +75,7 @@ func testNetworkConnectionTimeout(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// testReconnectAfterIPChange verifies that if a persistent inbound node changes
|
// testReconnectAfterIPChange verifies that if a persistent inbound node changes
|
||||||
// its listening address then it's peer will still be able to reconnect to it.
|
// 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
|
// In this test, the following network will be set up. A single
|
||||||
// dash line represents a peer connection and a double dash line
|
// dash line represents a peer connection and a double dash line
|
||||||
// represents a channel.
|
// 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
|
// We derive an extra port for Dave, and we initialise his node with
|
||||||
// the port advertised as `--externalip` arguments.
|
// 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.
|
// Create a new node, Dave, which will initialize a P2P port for him.
|
||||||
daveArgs := []string{fmt.Sprintf("--externalip=127.0.0.1:%d", ip2)}
|
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
|
// ensures that Charlie receives the node announcement from Alice as
|
||||||
// part of the announcement broadcast.
|
// part of the announcement broadcast.
|
||||||
chanPoint := ht.OpenChannel(
|
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
|
// waitForNodeAnnouncement is a closure used to wait on the given graph
|
||||||
@@ -184,7 +184,7 @@ func testReconnectAfterIPChange(ht *lntemp.HarnessTest) {
|
|||||||
// address.
|
// address.
|
||||||
|
|
||||||
// Change Dave's listening port and restart.
|
// Change Dave's listening port and restart.
|
||||||
dave.Cfg.P2PPort = lntest.NextAvailablePort()
|
dave.Cfg.P2PPort = node.NextAvailablePort()
|
||||||
dave.Cfg.ExtraArgs = []string{
|
dave.Cfg.ExtraArgs = []string{
|
||||||
fmt.Sprintf(
|
fmt.Sprintf(
|
||||||
"--externalip=127.0.0.1:%d", dave.Cfg.P2PPort,
|
"--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
|
// testAddPeerConfig tests that the "--addpeer" config flag successfully adds
|
||||||
// a new peer.
|
// a new peer.
|
||||||
func testAddPeerConfig(ht *lntemp.HarnessTest) {
|
func testAddPeerConfig(ht *lntest.HarnessTest) {
|
||||||
alice := ht.Alice
|
alice := ht.Alice
|
||||||
info := alice.RPC.GetInfo()
|
info := alice.RPC.GetInfo()
|
||||||
|
|
||||||
@@ -220,6 +220,9 @@ func testAddPeerConfig(ht *lntemp.HarnessTest) {
|
|||||||
args := []string{fmt.Sprintf("--addpeer=%v", alicePeerAddress)}
|
args := []string{fmt.Sprintf("--addpeer=%v", alicePeerAddress)}
|
||||||
carol := ht.NewNode("Carol", args)
|
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)
|
ht.EnsureConnected(alice, carol)
|
||||||
|
|
||||||
// If we list Carol's peers, Alice should already be
|
// If we list Carol's peers, Alice should already be
|
||||||
@@ -2,15 +2,14 @@ package itest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/neutrinorpc"
|
"github.com/lightningnetwork/lnd/lnrpc/neutrinorpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// testNeutrino checks that the neutrino sub-server can fetch compact
|
// testNeutrino checks that the neutrino sub-server can fetch compact
|
||||||
// block filters, server status and connect to a connected peer.
|
// block filters, server status and connect to a connected peer.
|
||||||
func testNeutrino(ht *lntemp.HarnessTest) {
|
func testNeutrino(ht *lntest.HarnessTest) {
|
||||||
if ht.ChainBackendName() != lntest.NeutrinoBackendName {
|
if !ht.IsNeutrinoBackend() {
|
||||||
ht.Skipf("skipping test for non neutrino backends")
|
ht.Skipf("skipping test for non neutrino backends")
|
||||||
}
|
}
|
||||||
|
|
||||||
+2
-2
@@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
package itest
|
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
|
// testEtcdFailover is an empty itest when LND is not compiled with etcd
|
||||||
// support.
|
// support.
|
||||||
func testEtcdFailover(ht *lntemp.HarnessTest) {}
|
func testEtcdFailover(ht *lntest.HarnessTest) {}
|
||||||
@@ -5,11 +5,11 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testNonstdSweep(ht *lntemp.HarnessTest) {
|
func testNonstdSweep(ht *lntest.HarnessTest) {
|
||||||
p2shAddr, err := btcutil.NewAddressScriptHash(
|
p2shAddr, err := btcutil.NewAddressScriptHash(
|
||||||
make([]byte, 1), harnessNetParams,
|
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)
|
carol := ht.NewNode("carol", nil)
|
||||||
|
|
||||||
// Give Carol a UTXO so SendCoins will behave as expected.
|
// Give Carol a UTXO so SendCoins will behave as expected.
|
||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/sweep"
|
"github.com/lightningnetwork/lnd/sweep"
|
||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
// testChainKit tests ChainKit RPC endpoints.
|
// 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
|
// Test functions registered as test cases spin up separate nodes
|
||||||
// during execution. By calling sub-test functions as seen below we
|
// during execution. By calling sub-test functions as seen below we
|
||||||
// avoid the need to start separate nodes.
|
// 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
|
// testChainKitGetBlock ensures that given a block hash, the RPC endpoint
|
||||||
// returns the correct target block.
|
// returns the correct target block.
|
||||||
func testChainKitGetBlock(ht *lntemp.HarnessTest) {
|
func testChainKitGetBlock(ht *lntest.HarnessTest) {
|
||||||
// Get best block hash.
|
// Get best block hash.
|
||||||
bestBlockRes := ht.Alice.RPC.GetBestBlock(nil)
|
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
|
// testChainKitGetBlockHash ensures that given a block height, the RPC endpoint
|
||||||
// returns the correct target block hash.
|
// returns the correct target block hash.
|
||||||
func testChainKitGetBlockHash(ht *lntemp.HarnessTest) {
|
func testChainKitGetBlockHash(ht *lntest.HarnessTest) {
|
||||||
// Get best block hash.
|
// Get best block hash.
|
||||||
bestBlockRes := ht.Alice.RPC.GetBestBlock(nil)
|
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.
|
// rate by broadcasting a Child-Pays-For-Parent (CPFP) transaction.
|
||||||
//
|
//
|
||||||
// TODO(wilmer): Add RBF case once btcd supports it.
|
// 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(ht, ht.Alice, ht.Bob)
|
||||||
}
|
}
|
||||||
|
|
||||||
// runCPFP ensures that the daemon can bump an unconfirmed transaction's fee
|
// runCPFP ensures that the daemon can bump an unconfirmed transaction's fee
|
||||||
// rate by broadcasting a Child-Pays-For-Parent (CPFP) transaction.
|
// 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
|
// Skip this test for neutrino, as it's not aware of mempool
|
||||||
// transactions.
|
// transactions.
|
||||||
if ht.IsNeutrinoBackend() {
|
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",
|
return fmt.Errorf("expected 0 pending sweeps, found %d",
|
||||||
len(resp.PendingSweeps))
|
len(resp.PendingSweeps))
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}, defaultTimeout)
|
}, defaultTimeout)
|
||||||
require.NoError(ht, err, "timeout checking bob's pending sweeps")
|
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
|
// testAnchorReservedValue tests that we won't allow sending transactions when
|
||||||
// that would take the value we reserve for anchor fee bumping out of our
|
// that would take the value we reserve for anchor fee bumping out of our
|
||||||
// wallet.
|
// wallet.
|
||||||
func testAnchorReservedValue(ht *lntemp.HarnessTest) {
|
func testAnchorReservedValue(ht *lntest.HarnessTest) {
|
||||||
// Start two nodes supporting anchor channels.
|
// 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
|
// NOTE: we cannot reuse the standby node here as the test requires the
|
||||||
// node to start with no UTXOs.
|
// 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.
|
// wallet, without a change output. This should not be allowed.
|
||||||
ht.OpenChannelAssertErr(
|
ht.OpenChannelAssertErr(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
}, lnwallet.ErrReservedValueInvalidated,
|
}, lnwallet.ErrReservedValueInvalidated,
|
||||||
)
|
)
|
||||||
@@ -211,13 +212,13 @@ func testAnchorReservedValue(ht *lntemp.HarnessTest) {
|
|||||||
// Alice opens a smaller channel. This works since it will have a
|
// Alice opens a smaller channel. This works since it will have a
|
||||||
// change output.
|
// change output.
|
||||||
chanPoint1 := ht.OpenChannel(
|
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
|
// If Alice tries to open another anchor channel to Bob, Bob should not
|
||||||
// reject it as he is not contributing any funds.
|
// reject it as he is not contributing any funds.
|
||||||
chanPoint2 := ht.OpenChannel(
|
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
|
// 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)
|
ht.EnsureConnected(alice, bob)
|
||||||
|
|
||||||
chanPoint3 := ht.OpenChannel(
|
chanPoint3 := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt / 4},
|
alice, bob, lntest.OpenChannelParams{Amt: chanAmt / 4},
|
||||||
)
|
)
|
||||||
chanPoints := []*lnrpc.ChannelPoint{chanPoint1, chanPoint2, chanPoint3}
|
chanPoints := []*lnrpc.ChannelPoint{chanPoint1, chanPoint2, chanPoint3}
|
||||||
|
|
||||||
@@ -276,6 +277,7 @@ func testAnchorReservedValue(ht *lntemp.HarnessTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
balance = resp.TotalBalance
|
balance = resp.TotalBalance
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}, defaultTimeout)
|
}, defaultTimeout)
|
||||||
require.NoError(ht, err, "timeout checking alice's balance")
|
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
|
// 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
|
// 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.
|
// 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
|
// First, we'll create two new nodes that both default to anchor
|
||||||
// channels.
|
// channels.
|
||||||
//
|
//
|
||||||
// NOTE: The itests differ here as anchors is default off vs the normal
|
// NOTE: The itests differ here as anchors is default off vs the normal
|
||||||
// lnd binary.
|
// lnd binary.
|
||||||
args := nodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
|
args := lntest.NodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
|
||||||
alice := ht.NewNode("Alice", args)
|
alice := ht.NewNode("Alice", args)
|
||||||
defer ht.Shutdown(alice)
|
|
||||||
|
|
||||||
bob := ht.NewNode("Bob", args)
|
bob := ht.NewNode("Bob", args)
|
||||||
defer ht.Shutdown(bob)
|
|
||||||
|
|
||||||
ht.EnsureConnected(alice, 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
|
// Open the channel between the two nodes and wait for it to confirm
|
||||||
// fully.
|
// fully.
|
||||||
aliceChanPoint1 := ht.OpenChannel(
|
aliceChanPoint1 := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: firstChanSize,
|
Amt: firstChanSize,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -493,7 +492,7 @@ func testAnchorThirdPartySpend(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// assertAnchorOutputLost asserts that the anchor output for the given channel
|
// assertAnchorOutputLost asserts that the anchor output for the given channel
|
||||||
// has the state of being lost.
|
// 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) {
|
chanPoint *lnrpc.ChannelPoint) {
|
||||||
|
|
||||||
cp := ht.OutPointFromChannelPoint(chanPoint)
|
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.
|
// 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
|
// In practice, we just re-use the existing witness, and track on our own
|
||||||
// output producing a 1-in-1-out transaction.
|
// output producing a 1-in-1-out transaction.
|
||||||
func genAnchorSweep(ht *lntemp.HarnessTest,
|
func genAnchorSweep(ht *lntest.HarnessTest,
|
||||||
aliceAnchor *lntemp.SweptOutput, anchorCsv uint32) *btcutil.Tx {
|
aliceAnchor *lntest.SweptOutput, anchorCsv uint32) *btcutil.Tx {
|
||||||
|
|
||||||
// At this point, we have the transaction that Alice used to try to
|
// At this point, we have the transaction that Alice used to try to
|
||||||
// sweep her anchor. As this is actually just something anyone can
|
// sweep her anchor. As this is actually just something anyone can
|
||||||
@@ -10,9 +10,9 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainreg"
|
"github.com/lightningnetwork/lnd/chainreg"
|
||||||
"github.com/lightningnetwork/lnd/funding"
|
"github.com/lightningnetwork/lnd/funding"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -20,7 +20,7 @@ import (
|
|||||||
// testOpenChannelAfterReorg tests that in the case where we have an open
|
// testOpenChannelAfterReorg tests that in the case where we have an open
|
||||||
// channel where the funding tx gets reorged out, the channel will no
|
// channel where the funding tx gets reorged out, the channel will no
|
||||||
// longer be present in the node's routing table.
|
// 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.
|
// Skip test for neutrino, as we cannot disconnect the miner at will.
|
||||||
// TODO(halseth): remove when either can disconnect at will, or restart
|
// TODO(halseth): remove when either can disconnect at will, or restart
|
||||||
// node with connection to new miner.
|
// 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.
|
// Set up a new miner that we can use to cause a reorg.
|
||||||
tempLogDir := ".tempminerlogs"
|
tempLogDir := ".tempminerlogs"
|
||||||
logFilename := "output-open_channel_reorg-temp_miner.log"
|
logFilename := "output-open_channel_reorg-temp_miner.log"
|
||||||
tempMiner := lntemp.NewTempMiner(
|
tempMiner := lntest.NewTempMiner(
|
||||||
ht.Context(), ht.T, tempLogDir, logFilename,
|
ht.Context(), ht.T, tempLogDir, logFilename,
|
||||||
)
|
)
|
||||||
defer tempMiner.Stop()
|
defer tempMiner.Stop()
|
||||||
@@ -68,7 +68,7 @@ func testOpenChannelAfterReorg(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// Create a new channel that requires 1 confs before it's considered
|
// Create a new channel that requires 1 confs before it's considered
|
||||||
// open, then broadcast the funding transaction
|
// open, then broadcast the funding transaction
|
||||||
params := lntemp.OpenChannelParams{
|
params := lntest.OpenChannelParams{
|
||||||
Amt: funding.MaxBtcFundingAmount,
|
Amt: funding.MaxBtcFundingAmount,
|
||||||
Private: true,
|
Private: true,
|
||||||
}
|
}
|
||||||
@@ -172,7 +172,7 @@ func testOpenChannelAfterReorg(ht *lntemp.HarnessTest) {
|
|||||||
// ChannelUpdate --> defaultBaseFee, provided FeeRate
|
// ChannelUpdate --> defaultBaseFee, provided FeeRate
|
||||||
// 4.) baseFee and feeRate provided to OpenChannelRequest
|
// 4.) baseFee and feeRate provided to OpenChannelRequest
|
||||||
// ChannelUpdate --> provided baseFee, provided feeRate.
|
// ChannelUpdate --> provided baseFee, provided feeRate.
|
||||||
func testOpenChannelUpdateFeePolicy(ht *lntemp.HarnessTest) {
|
func testOpenChannelUpdateFeePolicy(ht *lntest.HarnessTest) {
|
||||||
const (
|
const (
|
||||||
defaultBaseFee = 1000
|
defaultBaseFee = 1000
|
||||||
defaultFeeRate = 1
|
defaultFeeRate = 1
|
||||||
@@ -182,12 +182,12 @@ func testOpenChannelUpdateFeePolicy(ht *lntemp.HarnessTest) {
|
|||||||
optionalFeeRate = 1337
|
optionalFeeRate = 1337
|
||||||
)
|
)
|
||||||
|
|
||||||
defaultMaxHtlc := calculateMaxHtlc(funding.MaxBtcFundingAmount)
|
defaultMaxHtlc := lntest.CalculateMaxHtlc(funding.MaxBtcFundingAmount)
|
||||||
|
|
||||||
chanAmt := funding.MaxBtcFundingAmount
|
chanAmt := funding.MaxBtcFundingAmount
|
||||||
pushAmt := chanAmt / 2
|
pushAmt := chanAmt / 2
|
||||||
|
|
||||||
feeScenarios := []lntemp.OpenChannelParams{
|
feeScenarios := []lntest.OpenChannelParams{
|
||||||
{
|
{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
@@ -259,8 +259,8 @@ func testOpenChannelUpdateFeePolicy(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
|
|
||||||
runTestCase := func(ht *lntemp.HarnessTest,
|
runTestCase := func(ht *lntest.HarnessTest,
|
||||||
fs lntemp.OpenChannelParams,
|
fs lntest.OpenChannelParams,
|
||||||
alicePolicy, bobPolicy *lnrpc.RoutingPolicy) {
|
alicePolicy, bobPolicy *lnrpc.RoutingPolicy) {
|
||||||
|
|
||||||
// Create a channel Alice->Bob.
|
// Create a channel Alice->Bob.
|
||||||
@@ -305,14 +305,14 @@ func testOpenChannelUpdateFeePolicy(ht *lntemp.HarnessTest) {
|
|||||||
// testBasicChannelCreationAndUpdates tests multiple channel opening and
|
// testBasicChannelCreationAndUpdates tests multiple channel opening and
|
||||||
// closing, and ensures that if a node is subscribed to channel updates they
|
// closing, and ensures that if a node is subscribed to channel updates they
|
||||||
// will be received correctly for both cooperative and force closed channels.
|
// 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(ht, ht.Alice, ht.Bob)
|
||||||
}
|
}
|
||||||
|
|
||||||
// runBasicChannelCreationAndUpdates tests multiple channel opening and closing,
|
// runBasicChannelCreationAndUpdates tests multiple channel opening and closing,
|
||||||
// and ensures that if a node is subscribed to channel updates they will be
|
// and ensures that if a node is subscribed to channel updates they will be
|
||||||
// received correctly for both cooperative and force closed channels.
|
// received correctly for both cooperative and force closed channels.
|
||||||
func runBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest,
|
func runBasicChannelCreationAndUpdates(ht *lntest.HarnessTest,
|
||||||
alice, bob *node.HarnessNode) {
|
alice, bob *node.HarnessNode) {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -329,7 +329,7 @@ func runBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest,
|
|||||||
chanPoints := make([]*lnrpc.ChannelPoint, numChannels)
|
chanPoints := make([]*lnrpc.ChannelPoint, numChannels)
|
||||||
for i := 0; i < numChannels; i++ {
|
for i := 0; i < numChannels; i++ {
|
||||||
chanPoints[i] = ht.OpenChannel(
|
chanPoints[i] = ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: amount,
|
Amt: amount,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -458,8 +458,8 @@ func runBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// assertMinerBlockHeightDelta ensures that tempMiner is 'delta' blocks ahead
|
// assertMinerBlockHeightDelta ensures that tempMiner is 'delta' blocks ahead
|
||||||
// of miner.
|
// of miner.
|
||||||
func assertMinerBlockHeightDelta(ht *lntemp.HarnessTest,
|
func assertMinerBlockHeightDelta(ht *lntest.HarnessTest,
|
||||||
miner, tempMiner *lntemp.HarnessMiner, delta int32) {
|
miner, tempMiner *lntest.HarnessMiner, delta int32) {
|
||||||
|
|
||||||
// Ensure the chain lengths are what we expect.
|
// Ensure the chain lengths are what we expect.
|
||||||
err := wait.NoError(func() error {
|
err := wait.NoError(func() error {
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"crypto/sha256"
|
"crypto/sha256"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -11,14 +10,13 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"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"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func testListPayments(ht *lntemp.HarnessTest) {
|
func testListPayments(ht *lntest.HarnessTest) {
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
|
|
||||||
// Check that there are no payments before test.
|
// Check that there are no payments before test.
|
||||||
@@ -28,7 +26,7 @@ func testListPayments(ht *lntemp.HarnessTest) {
|
|||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
chanAmt := btcutil.Amount(100000)
|
chanAmt := btcutil.Amount(100000)
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get the number of invoices Bob already has.
|
// 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
|
// 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
|
// transition with a payment that updates the commitment state and verify that
|
||||||
// the pending state is up to date.
|
// the pending state is up to date.
|
||||||
func testPaymentFollowingChannelOpen(ht *lntemp.HarnessTest) {
|
func testPaymentFollowingChannelOpen(ht *lntest.HarnessTest) {
|
||||||
const paymentAmt = btcutil.Amount(100)
|
const paymentAmt = btcutil.Amount(100)
|
||||||
channelCapacity := paymentAmt * 1000
|
channelCapacity := paymentAmt * 1000
|
||||||
|
|
||||||
// We first establish a channel between Alice and Bob.
|
// We first establish a channel between Alice and Bob.
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
p := lntemp.OpenChannelParams{
|
p := lntest.OpenChannelParams{
|
||||||
Amt: channelCapacity,
|
Amt: channelCapacity,
|
||||||
}
|
}
|
||||||
pendingUpdate := ht.OpenChannelAssertPending(alice, bob, p)
|
pendingUpdate := ht.OpenChannelAssertPending(alice, bob, p)
|
||||||
@@ -198,7 +196,7 @@ func testPaymentFollowingChannelOpen(ht *lntemp.HarnessTest) {
|
|||||||
ht.MineBlocksAndAssertNumTxes(6, 1)
|
ht.MineBlocksAndAssertNumTxes(6, 1)
|
||||||
|
|
||||||
// We verify that the channel is open from both nodes point of view.
|
// 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.AssertNodesNumPendingOpenChannels(alice, bob, 0)
|
||||||
ht.AssertChannelExists(alice, chanPoint)
|
ht.AssertChannelExists(alice, chanPoint)
|
||||||
ht.AssertChannelExists(bob, chanPoint)
|
ht.AssertChannelExists(bob, chanPoint)
|
||||||
@@ -226,7 +224,7 @@ func testPaymentFollowingChannelOpen(ht *lntemp.HarnessTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// testAsyncPayments tests the performance of the async payments.
|
// 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
|
// We use new nodes here as the benchmark test creates lots of data
|
||||||
// which can be costly to be carried on.
|
// which can be costly to be carried on.
|
||||||
alice := ht.NewNode("Alice", []string{"--pending-commit-interval=3m"})
|
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.
|
// 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
|
const paymentAmt = 100
|
||||||
|
|
||||||
// First establish a channel with a capacity equals to the overall
|
// 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.
|
// Alice should send all money from her side to Bob.
|
||||||
channelCapacity := btcutil.Amount(paymentAmt * 2000)
|
channelCapacity := btcutil.Amount(paymentAmt * 2000)
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{Amt: channelCapacity},
|
alice, bob, lntest.OpenChannelParams{Amt: channelCapacity},
|
||||||
)
|
)
|
||||||
|
|
||||||
info := ht.QueryChannelByChanPoint(alice, chanPoint)
|
info := ht.QueryChannelByChanPoint(alice, chanPoint)
|
||||||
@@ -273,7 +271,7 @@ func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
|
|||||||
settled := make(chan struct{})
|
settled := make(chan struct{})
|
||||||
defer close(settled)
|
defer close(settled)
|
||||||
|
|
||||||
timeout := lntest.AsyncBenchmarkTimeout * 2
|
timeout := wait.AsyncBenchmarkTimeout
|
||||||
for i := 0; i < numInvoices; i++ {
|
for i := 0; i < numInvoices; i++ {
|
||||||
payReq := bobPayReqs[i]
|
payReq := bobPayReqs[i]
|
||||||
go func() {
|
go func() {
|
||||||
@@ -304,46 +302,13 @@ func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
|
|||||||
// All payments have been sent, mark the finish time.
|
// All payments have been sent, mark the finish time.
|
||||||
timeTaken := time.Since(now)
|
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
|
// Wait for the revocation to be received so alice no longer has
|
||||||
// pending htlcs listed and has correct balances. This is needed due to
|
// pending htlcs listed and has correct balances. This is needed due to
|
||||||
// the fact that we now pipeline the settles.
|
// 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.
|
// 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: Elapsed time: ", timeTaken)
|
||||||
ht.Log("\tBenchmark info: TPS: ",
|
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
|
// testBidirectionalAsyncPayments tests that nodes are able to send the
|
||||||
// payments to each other in async manner without blocking.
|
// payments to each other in async manner without blocking.
|
||||||
func testBidirectionalAsyncPayments(net *lntest.NetworkHarness, t *harnessTest) {
|
func testBidirectionalAsyncPayments(ht *lntest.HarnessTest) {
|
||||||
ctxb := context.Background()
|
const paymentAmt = 1000
|
||||||
|
|
||||||
const (
|
// We use new nodes here as the benchmark test creates lots of data
|
||||||
paymentAmt = 1000
|
// 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
|
// First establish a channel with a capacity equals to the overall
|
||||||
// amount of payments, between Alice and Bob, at the end of the test
|
// amount of payments, between Alice and Bob, at the end of the test
|
||||||
// Alice should send all money from her side to Bob.
|
// Alice should send all money from her side to Bob.
|
||||||
chanPoint := openChannelAndAssert(
|
chanPoint := ht.OpenChannel(
|
||||||
t, net, net.Alice, net.Bob,
|
alice, bob, lntest.OpenChannelParams{
|
||||||
lntest.OpenChannelParams{
|
|
||||||
Amt: paymentAmt * 2000,
|
Amt: paymentAmt * 2000,
|
||||||
PushAmt: paymentAmt * 1000,
|
PushAmt: paymentAmt * 1000,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
info, err := getChanInfo(net.Alice)
|
info := ht.QueryChannelByChanPoint(alice, chanPoint)
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to get alice channel info: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// We'll create a number of invoices equal the max number of HTLCs that
|
// 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
|
// 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
|
// With the channel open, we'll create invoices for Bob that Alice
|
||||||
// will pay to in order to advance the state of the channel.
|
// will pay to in order to advance the state of the channel.
|
||||||
bobPayReqs, _, _, err := createPayReqs(
|
bobPayReqs, _, _ := ht.CreatePayReqs(bob, paymentAmt, numInvoices)
|
||||||
net.Bob, paymentAmt, numInvoices,
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to create pay reqs: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// With the channel open, we'll create invoices for Alice that Bob
|
// With the channel open, we'll create invoices for Alice that Bob
|
||||||
// will pay to in order to advance the state of the channel.
|
// will pay to in order to advance the state of the channel.
|
||||||
alicePayReqs, _, _, err := createPayReqs(
|
alicePayReqs, _, _ := ht.CreatePayReqs(alice, paymentAmt, numInvoices)
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset mission control to prevent previous payment results from
|
// Reset mission control to prevent previous payment results from
|
||||||
// interfering with this test. A new channel has been opened, but
|
// interfering with this test. A new channel has been opened, but
|
||||||
// mission control operates on node pairs.
|
// mission control operates on node pairs.
|
||||||
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
|
alice.RPC.ResetMissionControl()
|
||||||
_, err = net.Alice.RouterClient.ResetMissionControl(
|
|
||||||
ctxt, &routerrpc.ResetMissionControlRequest{},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatalf("unable to reset mc for alice: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send payments from Alice to Bob and from Bob to Alice in async
|
// Send payments from Alice to Bob and from Bob to Alice in async
|
||||||
// manner.
|
// manner.
|
||||||
errChan := make(chan error)
|
settled := make(chan struct{})
|
||||||
statusChan := make(chan *lnrpc.Payment)
|
defer close(settled)
|
||||||
|
|
||||||
send := func(node *lntest.HarnessNode, payReq string) {
|
timeout := wait.AsyncBenchmarkTimeout * 2
|
||||||
go func() {
|
send := func(node *node.HarnessNode, payReq string) {
|
||||||
ctxt, _ = context.WithTimeout(
|
req := &routerrpc.SendPaymentRequest{
|
||||||
ctxb, lntest.AsyncBenchmarkTimeout,
|
PaymentRequest: payReq,
|
||||||
)
|
TimeoutSeconds: int32(timeout.Seconds()),
|
||||||
stream, err := node.RouterClient.SendPaymentV2(
|
FeeLimitMsat: noFeeLimitMsat,
|
||||||
ctxt,
|
}
|
||||||
&routerrpc.SendPaymentRequest{
|
// AssertPaymentStatusWithTimeout will assert that the
|
||||||
PaymentRequest: payReq,
|
// payment is settled.
|
||||||
TimeoutSeconds: 60,
|
stream := node.RPC.SendPayment(req)
|
||||||
FeeLimitMsat: noFeeLimitMsat,
|
ht.AssertPaymentSucceedWithTimeout(stream, timeout)
|
||||||
},
|
|
||||||
)
|
|
||||||
if err != nil {
|
|
||||||
errChan <- err
|
|
||||||
}
|
|
||||||
result, err := getPaymentResult(stream)
|
|
||||||
if err != nil {
|
|
||||||
errChan <- err
|
|
||||||
}
|
|
||||||
|
|
||||||
statusChan <- result
|
settled <- struct{}{}
|
||||||
}()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < numInvoices; i++ {
|
for i := 0; i < numInvoices; i++ {
|
||||||
send(net.Bob, alicePayReqs[i])
|
go send(bob, alicePayReqs[i])
|
||||||
send(net.Alice, bobPayReqs[i])
|
go send(alice, bobPayReqs[i])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expect all payments to succeed.
|
// Expect all payments to succeed.
|
||||||
|
timer := time.After(timeout)
|
||||||
for i := 0; i < 2*numInvoices; i++ {
|
for i := 0; i < 2*numInvoices; i++ {
|
||||||
select {
|
select {
|
||||||
case result := <-statusChan:
|
case <-settled:
|
||||||
if result.Status != lnrpc.Payment_SUCCEEDED {
|
case <-timer:
|
||||||
t.Fatalf("payment error: %v", result.Status)
|
require.Fail(ht, "timeout", "wait payment failed")
|
||||||
}
|
|
||||||
|
|
||||||
case err := <-errChan:
|
|
||||||
t.Fatalf("payment error: %v", err)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Wait for Alice and Bob to receive revocations messages, and update
|
// Wait for Alice and Bob to receive revocations messages, and update
|
||||||
// states, i.e. balance info.
|
// states, i.e. balance info.
|
||||||
err = wait.NoError(func() error {
|
assertChannelState(ht, alice, chanPoint, aliceAmt, bobAmt)
|
||||||
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)
|
|
||||||
|
|
||||||
// Next query for Bob's and Alice's channel states, in order to confirm
|
// Next query for Bob's and Alice's channel states, in order to confirm
|
||||||
// that all payment have been successful transmitted.
|
// that all payment have been successful transmitted.
|
||||||
err = wait.NoError(func() error {
|
assertChannelState(ht, bob, chanPoint, bobAmt, aliceAmt)
|
||||||
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)
|
|
||||||
|
|
||||||
// Finally, immediately close the channel. This function will also
|
// Finally, immediately close the channel. This function will also
|
||||||
// block until the channel is closed and will additionally assert the
|
// block until the channel is closed and will additionally assert the
|
||||||
// relevant channel closing post conditions.
|
// 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)
|
const chanAmt = btcutil.Amount(500000)
|
||||||
|
|
||||||
alice, bob := ht.Alice, ht.Bob
|
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
|
// Open a channel with 500k satoshis between Alice and Bob with Alice
|
||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
chanPoint := ht.OpenChannel(
|
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.
|
// Next create a new invoice for Bob requesting 1k satoshis.
|
||||||
@@ -672,3 +559,36 @@ func testInvoiceSubscriptions(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
ht.CloseChannel(alice, chanPoint)
|
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")
|
||||||
|
}
|
||||||
@@ -2,8 +2,6 @@ package itest
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcec/v2"
|
"github.com/btcsuite/btcd/btcec/v2"
|
||||||
@@ -20,16 +18,15 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"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"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// testPsbtChanFunding makes sure a channel can be opened between carol and dave
|
// testPsbtChanFunding makes sure a channel can be opened between carol and dave
|
||||||
// by using a Partially Signed Bitcoin Transaction that funds the channel
|
// by using a Partially Signed Bitcoin Transaction that funds the channel
|
||||||
// multisig funding output.
|
// 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
|
// 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
|
// 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.
|
// 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
|
// runPsbtChanFunding makes sure a channel can be opened between carol and dave
|
||||||
// by using a Partially Signed Bitcoin Transaction that funds the channel
|
// by using a Partially Signed Bitcoin Transaction that funds the channel
|
||||||
// multisig funding output.
|
// 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
|
const chanSize = funding.MaxBtcFundingAmount
|
||||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, dave)
|
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
|
// by specifying a PSBT shim. We use the NoPublish flag here to avoid
|
||||||
// publishing the whole batch TX too early.
|
// publishing the whole batch TX too early.
|
||||||
chanUpdates, tempPsbt := ht.OpenChannelPsbt(
|
chanUpdates, tempPsbt := ht.OpenChannelPsbt(
|
||||||
carol, dave, lntemp.OpenChannelParams{
|
carol, dave, lntest.OpenChannelParams{
|
||||||
Amt: chanSize,
|
Amt: chanSize,
|
||||||
FundingShim: &lnrpc.FundingShim{
|
FundingShim: &lnrpc.FundingShim{
|
||||||
Shim: &lnrpc.FundingShim_PsbtShim{
|
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
|
// Alice. We will publish the batch TX once this channel funding is
|
||||||
// complete.
|
// complete.
|
||||||
chanUpdates2, psbtBytes2 := ht.OpenChannelPsbt(
|
chanUpdates2, psbtBytes2 := ht.OpenChannelPsbt(
|
||||||
carol, alice, lntemp.OpenChannelParams{
|
carol, alice, lntest.OpenChannelParams{
|
||||||
Amt: chanSize,
|
Amt: chanSize,
|
||||||
FundingShim: &lnrpc.FundingShim{
|
FundingShim: &lnrpc.FundingShim{
|
||||||
Shim: &lnrpc.FundingShim_PsbtShim{
|
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
|
// and dave by using a Partially Signed Bitcoin Transaction that funds the
|
||||||
// channel multisig funding output and is fully funded by an external third
|
// channel multisig funding output and is fully funded by an external third
|
||||||
// party.
|
// party.
|
||||||
func testPsbtChanFundingExternal(ht *lntemp.HarnessTest) {
|
func testPsbtChanFundingExternal(ht *lntest.HarnessTest) {
|
||||||
const chanSize = funding.MaxBtcFundingAmount
|
const chanSize = funding.MaxBtcFundingAmount
|
||||||
|
|
||||||
// First, we'll create two new nodes that we'll use to open channels
|
// 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
|
// by specifying a PSBT shim. We use the NoPublish flag here to avoid
|
||||||
// publishing the whole batch TX too early.
|
// publishing the whole batch TX too early.
|
||||||
chanUpdates, tempPsbt := ht.OpenChannelPsbt(
|
chanUpdates, tempPsbt := ht.OpenChannelPsbt(
|
||||||
carol, dave, lntemp.OpenChannelParams{
|
carol, dave, lntest.OpenChannelParams{
|
||||||
Amt: chanSize,
|
Amt: chanSize,
|
||||||
FundingShim: &lnrpc.FundingShim{
|
FundingShim: &lnrpc.FundingShim{
|
||||||
Shim: &lnrpc.FundingShim_PsbtShim{
|
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
|
// Alice. We will publish the batch TX once this channel funding is
|
||||||
// complete.
|
// complete.
|
||||||
chanUpdates2, psbtBytes2 := ht.OpenChannelPsbt(
|
chanUpdates2, psbtBytes2 := ht.OpenChannelPsbt(
|
||||||
carol, alice, lntemp.OpenChannelParams{
|
carol, alice, lntest.OpenChannelParams{
|
||||||
Amt: chanSize,
|
Amt: chanSize,
|
||||||
FundingShim: &lnrpc.FundingShim{
|
FundingShim: &lnrpc.FundingShim{
|
||||||
Shim: &lnrpc.FundingShim_PsbtShim{
|
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
|
// 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
|
// wallet to fund the channel while creating reserve output in the same
|
||||||
// transaction.
|
// transaction.
|
||||||
func testPsbtChanFundingSingleStep(ht *lntemp.HarnessTest) {
|
func testPsbtChanFundingSingleStep(ht *lntest.HarnessTest) {
|
||||||
const chanSize = funding.MaxBtcFundingAmount
|
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
|
// 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
|
// between for this test. But in this case both nodes have an empty
|
||||||
// wallet.
|
// wallet.
|
||||||
carol := ht.NewNode("carol", args)
|
carol := ht.NewNode("carol", args)
|
||||||
defer ht.Shutdown(carol)
|
|
||||||
|
|
||||||
dave := ht.NewNode("dave", args)
|
dave := ht.NewNode("dave", args)
|
||||||
defer ht.Shutdown(dave)
|
|
||||||
|
|
||||||
alice := ht.Alice
|
alice := ht.Alice
|
||||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, 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
|
// Now that we have the pending channel ID, Carol will open the channel
|
||||||
// by specifying a PSBT shim.
|
// by specifying a PSBT shim.
|
||||||
chanUpdates, tempPsbt := ht.OpenChannelPsbt(
|
chanUpdates, tempPsbt := ht.OpenChannelPsbt(
|
||||||
carol, dave, lntemp.OpenChannelParams{
|
carol, dave, lntest.OpenChannelParams{
|
||||||
Amt: chanSize,
|
Amt: chanSize,
|
||||||
FundingShim: &lnrpc.FundingShim{
|
FundingShim: &lnrpc.FundingShim{
|
||||||
Shim: &lnrpc.FundingShim_PsbtShim{
|
Shim: &lnrpc.FundingShim_PsbtShim{
|
||||||
@@ -576,7 +570,7 @@ func testPsbtChanFundingSingleStep(ht *lntemp.HarnessTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// testSignPsbt tests that the SignPsbt RPC works correctly.
|
// testSignPsbt tests that the SignPsbt RPC works correctly.
|
||||||
func testSignPsbt(ht *lntemp.HarnessTest) {
|
func testSignPsbt(ht *lntest.HarnessTest) {
|
||||||
runSignPsbtSegWitV0P2WKH(ht, ht.Alice)
|
runSignPsbtSegWitV0P2WKH(ht, ht.Alice)
|
||||||
runSignPsbtSegWitV0NP2WKH(ht, ht.Alice)
|
runSignPsbtSegWitV0NP2WKH(ht, ht.Alice)
|
||||||
runSignPsbtSegWitV1KeySpendBip86(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
|
// runSignPsbtSegWitV0P2WKH tests that the SignPsbt RPC works correctly for a
|
||||||
// SegWit v0 p2wkh input.
|
// 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
|
// 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
|
// 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
|
// 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
|
// runSignPsbtSegWitV0NP2WKH tests that the SignPsbt RPC works correctly for a
|
||||||
// SegWit v0 np2wkh input.
|
// SegWit v0 np2wkh input.
|
||||||
func runSignPsbtSegWitV0NP2WKH(ht *lntemp.HarnessTest,
|
func runSignPsbtSegWitV0NP2WKH(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode) {
|
alice *node.HarnessNode) {
|
||||||
|
|
||||||
// We test that we can sign a PSBT that spends funds from an input that
|
// 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
|
// runSignPsbtSegWitV1KeySpendBip86 tests that the SignPsbt RPC works correctly
|
||||||
// for a SegWit v1 p2tr key spend BIP-0086 input.
|
// for a SegWit v1 p2tr key spend BIP-0086 input.
|
||||||
func runSignPsbtSegWitV1KeySpendBip86(ht *lntemp.HarnessTest,
|
func runSignPsbtSegWitV1KeySpendBip86(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode) {
|
alice *node.HarnessNode) {
|
||||||
|
|
||||||
// Derive a key we can use for signing.
|
// Derive a key we can use for signing.
|
||||||
@@ -803,7 +797,7 @@ func runSignPsbtSegWitV1KeySpendBip86(ht *lntemp.HarnessTest,
|
|||||||
// runSignPsbtSegWitV1KeySpendRootHash tests that the SignPsbt RPC works
|
// runSignPsbtSegWitV1KeySpendRootHash tests that the SignPsbt RPC works
|
||||||
// correctly for a SegWit v1 p2tr key spend that also commits to a script tree
|
// correctly for a SegWit v1 p2tr key spend that also commits to a script tree
|
||||||
// root hash.
|
// root hash.
|
||||||
func runSignPsbtSegWitV1KeySpendRootHash(ht *lntemp.HarnessTest,
|
func runSignPsbtSegWitV1KeySpendRootHash(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode) {
|
alice *node.HarnessNode) {
|
||||||
|
|
||||||
// Derive a key we can use for signing.
|
// 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
|
// runSignPsbtSegWitV1ScriptSpend tests that the SignPsbt RPC works correctly
|
||||||
// for a SegWit v1 p2tr script spend.
|
// for a SegWit v1 p2tr script spend.
|
||||||
func runSignPsbtSegWitV1ScriptSpend(ht *lntemp.HarnessTest,
|
func runSignPsbtSegWitV1ScriptSpend(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode) {
|
alice *node.HarnessNode) {
|
||||||
|
|
||||||
// Derive a key we can use for signing.
|
// 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
|
// runFundAndSignPsbt makes sure we can sign PSBTs that were funded by our
|
||||||
// internal wallet.
|
// internal wallet.
|
||||||
func runFundAndSignPsbt(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
func runFundAndSignPsbt(ht *lntest.HarnessTest, alice *node.HarnessNode) {
|
||||||
alice.AddToLogf("================ runFundAndSignPsbt ===============")
|
alice.AddToLogf("================ runFundAndSignPsbt ===============")
|
||||||
|
|
||||||
// We'll be using a "main" address where we send the funds to and from
|
// 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
|
// 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
|
// attempts to create a sweep transaction that is signed using the SignPsbt RPC
|
||||||
// that spends that output again.
|
// 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),
|
pkScript []byte, decorateUnsigned func(*psbt.Packet),
|
||||||
verifySigned 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
|
// assertPsbtFundSignSpend funds a PSBT from the internal wallet and then
|
||||||
// attempts to sign it by using the SignPsbt or FinalizePsbt method.
|
// 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,
|
fundOutputs map[string]uint64, changeType walletrpc.ChangeAddressType,
|
||||||
useFinalize bool) {
|
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
|
// assertChangeScriptType checks if the given script has the right type given
|
||||||
// the change address type we used in FundPsbt. By default, the script should
|
// the change address type we used in FundPsbt. By default, the script should
|
||||||
// be a P2WPKH one.
|
// be a P2WPKH one.
|
||||||
func assertChangeScriptType(ht *lntemp.HarnessTest, script []byte,
|
func assertChangeScriptType(ht *lntest.HarnessTest, script []byte,
|
||||||
fundChangeType walletrpc.ChangeAddressType) {
|
fundChangeType walletrpc.ChangeAddressType) {
|
||||||
|
|
||||||
switch fundChangeType {
|
switch fundChangeType {
|
||||||
@@ -1163,7 +1157,7 @@ func assertChangeScriptType(ht *lntemp.HarnessTest, script []byte,
|
|||||||
|
|
||||||
// deriveInternalKey derives a signing key and returns its descriptor, full
|
// deriveInternalKey derives a signing key and returns its descriptor, full
|
||||||
// derivation path and parsed public key.
|
// derivation path and parsed public key.
|
||||||
func deriveInternalKey(ht *lntemp.HarnessTest,
|
func deriveInternalKey(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode) (*signrpc.KeyDescriptor, *btcec.PublicKey,
|
alice *node.HarnessNode) (*signrpc.KeyDescriptor, *btcec.PublicKey,
|
||||||
[]uint32) {
|
[]uint32) {
|
||||||
|
|
||||||
@@ -1187,96 +1181,9 @@ func deriveInternalKey(ht *lntemp.HarnessTest,
|
|||||||
return keyDesc, parsedPubKey, fullDerivationPath
|
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
|
// sendAllCoinsToAddrType sweeps all coins from the wallet and sends them to a
|
||||||
// new address of the given type.
|
// new address of the given type.
|
||||||
func sendAllCoinsToAddrType(ht *lntemp.HarnessTest,
|
func sendAllCoinsToAddrType(ht *lntest.HarnessTest,
|
||||||
hn *node.HarnessNode, addrType lnrpc.AddressType) {
|
hn *node.HarnessNode, addrType lnrpc.AddressType) {
|
||||||
|
|
||||||
resp := hn.RPC.NewAddress(&lnrpc.NewAddressRequest{
|
resp := hn.RPC.NewAddress(&lnrpc.NewAddressRequest{
|
||||||
@@ -15,8 +15,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -24,7 +24,7 @@ import (
|
|||||||
|
|
||||||
// testGetRecoveryInfo checks whether lnd gives the right information about
|
// testGetRecoveryInfo checks whether lnd gives the right information about
|
||||||
// the wallet recovery process.
|
// the wallet recovery process.
|
||||||
func testGetRecoveryInfo(ht *lntemp.HarnessTest) {
|
func testGetRecoveryInfo(ht *lntest.HarnessTest) {
|
||||||
// First, create a new node with strong passphrase and grab the mnemonic
|
// First, create a new node with strong passphrase and grab the mnemonic
|
||||||
// used for key derivation. This will bring up Carol with an empty
|
// used for key derivation. This will bring up Carol with an empty
|
||||||
// wallet, and such that she is synced up.
|
// 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
|
// when providing a valid aezeed that owns outputs on the chain. This test
|
||||||
// performs multiple restorations using the same seed and various recovery
|
// performs multiple restorations using the same seed and various recovery
|
||||||
// windows to ensure we detect funds properly.
|
// 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
|
// First, create a new node with strong passphrase and grab the mnemonic
|
||||||
// used for key derivation. This will bring up Carol with an empty
|
// used for key derivation. This will bring up Carol with an empty
|
||||||
// wallet, and such that she is synced up.
|
// 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
|
// 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
|
// internal scopes while re-scanning to be in line with the logic in other areas
|
||||||
// of the wallet code.
|
// 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
|
// 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
|
// enabled. This won't have any effect on the first startup but will
|
||||||
// come into effect after we re-start the node.
|
// come into effect after we re-start the node.
|
||||||
@@ -11,8 +11,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -55,24 +55,24 @@ var (
|
|||||||
|
|
||||||
// testRemoteSigner tests that a watch-only wallet can use a remote signing
|
// testRemoteSigner tests that a watch-only wallet can use a remote signing
|
||||||
// wallet to perform any signing or ECDH operations.
|
// wallet to perform any signing or ECDH operations.
|
||||||
func testRemoteSigner(ht *lntemp.HarnessTest) {
|
func testRemoteSigner(ht *lntest.HarnessTest) {
|
||||||
type testCase struct {
|
type testCase struct {
|
||||||
name string
|
name string
|
||||||
randomSeed bool
|
randomSeed bool
|
||||||
sendCoins bool
|
sendCoins bool
|
||||||
fn func(tt *lntemp.HarnessTest,
|
fn func(tt *lntest.HarnessTest,
|
||||||
wo, carol *node.HarnessNode)
|
wo, carol *node.HarnessNode)
|
||||||
}
|
}
|
||||||
|
|
||||||
subTests := []testCase{{
|
subTests := []testCase{{
|
||||||
name: "random seed",
|
name: "random seed",
|
||||||
randomSeed: true,
|
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.
|
// Nothing more to test here.
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "account import",
|
name: "account import",
|
||||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||||
runWalletImportAccountScenario(
|
runWalletImportAccountScenario(
|
||||||
tt, walletrpc.AddressType_WITNESS_PUBKEY_HASH,
|
tt, walletrpc.AddressType_WITNESS_PUBKEY_HASH,
|
||||||
carol, wo,
|
carol, wo,
|
||||||
@@ -81,36 +81,36 @@ func testRemoteSigner(ht *lntemp.HarnessTest) {
|
|||||||
}, {
|
}, {
|
||||||
name: "basic channel open close",
|
name: "basic channel open close",
|
||||||
sendCoins: true,
|
sendCoins: true,
|
||||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||||
runBasicChannelCreationAndUpdates(tt, wo, carol)
|
runBasicChannelCreationAndUpdates(tt, wo, carol)
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "channel funding input types",
|
name: "channel funding input types",
|
||||||
sendCoins: false,
|
sendCoins: false,
|
||||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||||
runChannelFundingInputTypes(tt, carol, wo)
|
runChannelFundingInputTypes(tt, carol, wo)
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "async payments",
|
name: "async payments",
|
||||||
sendCoins: true,
|
sendCoins: true,
|
||||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||||
runAsyncPayments(tt, wo, carol)
|
runAsyncPayments(tt, wo, carol)
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "shared key",
|
name: "shared key",
|
||||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||||
runDeriveSharedKey(tt, wo)
|
runDeriveSharedKey(tt, wo)
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "cpfp",
|
name: "cpfp",
|
||||||
sendCoins: true,
|
sendCoins: true,
|
||||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||||
runCPFP(tt, wo, carol)
|
runCPFP(tt, wo, carol)
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "psbt",
|
name: "psbt",
|
||||||
randomSeed: true,
|
randomSeed: true,
|
||||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||||
runPsbtChanFunding(tt, carol, wo)
|
runPsbtChanFunding(tt, carol, wo)
|
||||||
runSignPsbtSegWitV0P2WKH(tt, wo)
|
runSignPsbtSegWitV0P2WKH(tt, wo)
|
||||||
runSignPsbtSegWitV1KeySpendBip86(tt, wo)
|
runSignPsbtSegWitV1KeySpendBip86(tt, wo)
|
||||||
@@ -125,20 +125,20 @@ func testRemoteSigner(ht *lntemp.HarnessTest) {
|
|||||||
}, {
|
}, {
|
||||||
name: "sign output raw",
|
name: "sign output raw",
|
||||||
sendCoins: true,
|
sendCoins: true,
|
||||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||||
runSignOutputRaw(tt, wo)
|
runSignOutputRaw(tt, wo)
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "sign verify msg",
|
name: "sign verify msg",
|
||||||
sendCoins: true,
|
sendCoins: true,
|
||||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||||
runSignVerifyMessage(tt, wo)
|
runSignVerifyMessage(tt, wo)
|
||||||
},
|
},
|
||||||
}, {
|
}, {
|
||||||
name: "taproot",
|
name: "taproot",
|
||||||
sendCoins: true,
|
sendCoins: true,
|
||||||
randomSeed: true,
|
randomSeed: true,
|
||||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||||
testTaprootSendCoinsKeySpendBip86(tt, wo)
|
testTaprootSendCoinsKeySpendBip86(tt, wo)
|
||||||
testTaprootComputeInputScriptKeySpendBip86(tt, wo)
|
testTaprootComputeInputScriptKeySpendBip86(tt, wo)
|
||||||
testTaprootSignOutputRawScriptSpend(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,
|
subTest testCase) (*node.HarnessNode,
|
||||||
*node.HarnessNode, *node.HarnessNode) {
|
*node.HarnessNode, *node.HarnessNode) {
|
||||||
|
|
||||||
@@ -5,13 +5,13 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// testResHandoff tests that the contractcourt is able to properly hand-off
|
// testResHandoff tests that the contractcourt is able to properly hand-off
|
||||||
// resolution messages to the switch.
|
// resolution messages to the switch.
|
||||||
func testResHandoff(ht *lntemp.HarnessTest) {
|
func testResHandoff(ht *lntest.HarnessTest) {
|
||||||
const (
|
const (
|
||||||
chanAmt = btcutil.Amount(1000000)
|
chanAmt = btcutil.Amount(1000000)
|
||||||
paymentAmt = 50000
|
paymentAmt = 50000
|
||||||
@@ -22,14 +22,13 @@ func testResHandoff(ht *lntemp.HarnessTest) {
|
|||||||
// First we'll create a channel between Alice and Bob.
|
// First we'll create a channel between Alice and Bob.
|
||||||
ht.EnsureConnected(alice, bob)
|
ht.EnsureConnected(alice, bob)
|
||||||
|
|
||||||
params := lntemp.OpenChannelParams{Amt: chanAmt}
|
params := lntest.OpenChannelParams{Amt: chanAmt}
|
||||||
chanPointAlice := ht.OpenChannel(alice, bob, params)
|
chanPointAlice := ht.OpenChannel(alice, bob, params)
|
||||||
|
|
||||||
// Create a new node Carol that will be in hodl mode. This is used to
|
// Create a new node Carol that will be in hodl mode. This is used to
|
||||||
// trigger the behavior of checkRemoteDanglingActions in the
|
// trigger the behavior of checkRemoteDanglingActions in the
|
||||||
// contractcourt. This will cause Bob to fail the HTLC back to Alice.
|
// contractcourt. This will cause Bob to fail the HTLC back to Alice.
|
||||||
carol := ht.NewNode("Carol", []string{"--hodl.commit"})
|
carol := ht.NewNode("Carol", []string{"--hodl.commit"})
|
||||||
defer ht.Shutdown(carol)
|
|
||||||
|
|
||||||
// Connect Bob to Carol.
|
// Connect Bob to Carol.
|
||||||
ht.ConnectNodes(bob, carol)
|
ht.ConnectNodes(bob, carol)
|
||||||
@@ -23,8 +23,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/verrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/verrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ var (
|
|||||||
|
|
||||||
// testRestAPI tests that the most important features of the REST API work
|
// testRestAPI tests that the most important features of the REST API work
|
||||||
// correctly.
|
// correctly.
|
||||||
func testRestAPI(ht *lntemp.HarnessTest) {
|
func testRestAPI(ht *lntest.HarnessTest) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
run func(*testing.T, *node.HarnessNode, *node.HarnessNode)
|
run func(*testing.T, *node.HarnessNode, *node.HarnessNode)
|
||||||
@@ -201,7 +201,7 @@ func testRestAPI(ht *lntemp.HarnessTest) {
|
|||||||
}}
|
}}
|
||||||
wsTestCases := []struct {
|
wsTestCases := []struct {
|
||||||
name string
|
name string
|
||||||
run func(ht *lntemp.HarnessTest)
|
run func(ht *lntest.HarnessTest)
|
||||||
}{{
|
}{{
|
||||||
name: "websocket subscription",
|
name: "websocket subscription",
|
||||||
run: wsTestCaseSubscription,
|
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.
|
// Find out the current best block so we can subscribe to the next one.
|
||||||
hash, height := ht.Miner.GetBestBlock()
|
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.
|
// Find out the current best block so we can subscribe to the next one.
|
||||||
hash, height := ht.Miner.GetBestBlock()
|
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{}
|
initialRequest := &lnrpc.ChannelAcceptResponse{}
|
||||||
url := "/v1/channels/acceptor"
|
url := "/v1/channels/acceptor"
|
||||||
|
|
||||||
@@ -530,7 +530,7 @@ func wsTestCaseBiDirectionalSubscription(ht *lntemp.HarnessTest) {
|
|||||||
const numChannels = 3
|
const numChannels = 3
|
||||||
for i := 0; i < numChannels; i++ {
|
for i := 0; i < numChannels; i++ {
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
bob, alice, lntemp.OpenChannelParams{Amt: 500000},
|
bob, alice, lntest.OpenChannelParams{Amt: 500000},
|
||||||
)
|
)
|
||||||
defer ht.CloseChannel(bob, chanPoint)
|
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{
|
initialRequest := &lnrpc.InvoiceSubscription{
|
||||||
AddIndex: 1, SettleIndex: 1,
|
AddIndex: 1, SettleIndex: 1,
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,6 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/funding"
|
"github.com/lightningnetwork/lnd/funding"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -21,7 +20,7 @@ import (
|
|||||||
// testRevokedCloseRetribution tests that Carol is able carry out
|
// testRevokedCloseRetribution tests that Carol is able carry out
|
||||||
// retribution in the event that she fails immediately after detecting Bob's
|
// retribution in the event that she fails immediately after detecting Bob's
|
||||||
// breach txn in the mempool.
|
// breach txn in the mempool.
|
||||||
func testRevokedCloseRetribution(ht *lntemp.HarnessTest) {
|
func testRevokedCloseRetribution(ht *lntest.HarnessTest) {
|
||||||
const (
|
const (
|
||||||
chanAmt = funding.MaxBtcFundingAmount
|
chanAmt = funding.MaxBtcFundingAmount
|
||||||
paymentAmt = 10000
|
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
|
// closure by Bob, we'll first open up a channel between them with a
|
||||||
// 0.5 BTC value.
|
// 0.5 BTC value.
|
||||||
chanPoint := ht.OpenChannel(
|
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
|
// 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
|
// 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
|
// included the justice tx we only need to mine extra DefaultCSV-2
|
||||||
// blocks to unlock it.
|
// blocks to unlock it.
|
||||||
ht.MineBlocks(lntest.DefaultCSV - 2)
|
ht.MineBlocks(defaultCSV - 2)
|
||||||
|
|
||||||
ht.AssertNumPendingForceClose(bob, 0)
|
ht.AssertNumPendingForceClose(bob, 0)
|
||||||
}
|
}
|
||||||
@@ -166,7 +165,7 @@ func testRevokedCloseRetribution(ht *lntemp.HarnessTest) {
|
|||||||
// testRevokedCloseRetributionZeroValueRemoteOutput tests that Dave is able
|
// testRevokedCloseRetributionZeroValueRemoteOutput tests that Dave is able
|
||||||
// carry out retribution in the event that he fails in state where the remote
|
// carry out retribution in the event that he fails in state where the remote
|
||||||
// commitment output has zero-value.
|
// commitment output has zero-value.
|
||||||
func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntemp.HarnessTest) {
|
func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntest.HarnessTest) {
|
||||||
const (
|
const (
|
||||||
chanAmt = funding.MaxBtcFundingAmount
|
chanAmt = funding.MaxBtcFundingAmount
|
||||||
paymentAmt = 10000
|
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
|
// closure by Carol, we'll first open up a channel between them with a
|
||||||
// 0.5 BTC value.
|
// 0.5 BTC value.
|
||||||
chanPoint := ht.OpenChannel(
|
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
|
// With the channel open, we'll create a few invoices for Carol that
|
||||||
@@ -224,6 +223,9 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntemp.HarnessTest) {
|
|||||||
// backup.
|
// backup.
|
||||||
ht.EnsureConnected(dave, carol)
|
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
|
// Finally, send payments from Dave to Carol, consuming Carol's
|
||||||
// remaining payment hashes.
|
// remaining payment hashes.
|
||||||
ht.CompletePaymentRequestsNoWait(dave, carolPayReqs, chanPoint)
|
ht.CompletePaymentRequestsNoWait(dave, carolPayReqs, chanPoint)
|
||||||
@@ -298,7 +300,7 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntemp.HarnessTest) {
|
|||||||
// testRevokedCloseRetributionRemoteHodl tests that Dave properly responds to a
|
// testRevokedCloseRetributionRemoteHodl tests that Dave properly responds to a
|
||||||
// channel breach made by the remote party, specifically in the case that the
|
// channel breach made by the remote party, specifically in the case that the
|
||||||
// remote party breaches before settling extended HTLCs.
|
// remote party breaches before settling extended HTLCs.
|
||||||
func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
|
func testRevokedCloseRetributionRemoteHodl(ht *lntest.HarnessTest) {
|
||||||
const (
|
const (
|
||||||
chanAmt = funding.MaxBtcFundingAmount
|
chanAmt = funding.MaxBtcFundingAmount
|
||||||
pushAmt = 200000
|
pushAmt = 200000
|
||||||
@@ -333,7 +335,7 @@ func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
|
|||||||
// by Carol, we'll first open up a channel between them with a
|
// by Carol, we'll first open up a channel between them with a
|
||||||
// funding.MaxBtcFundingAmount (2^24) satoshis value.
|
// funding.MaxBtcFundingAmount (2^24) satoshis value.
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
dave, carol, lntemp.OpenChannelParams{
|
dave, carol, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
},
|
},
|
||||||
@@ -401,6 +403,9 @@ func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
|
|||||||
// backup.
|
// backup.
|
||||||
ht.EnsureConnected(dave, carol)
|
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
|
// Finally, send payments from Dave to Carol, consuming Carol's
|
||||||
// remaining payment hashes.
|
// remaining payment hashes.
|
||||||
ht.CompletePaymentRequestsNoWait(
|
ht.CompletePaymentRequestsNoWait(
|
||||||
@@ -472,7 +477,14 @@ func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
|
|||||||
for _, txid := range mempool {
|
for _, txid := range mempool {
|
||||||
// Check that the justice tx has the appropriate number
|
// Check that the justice tx has the appropriate number
|
||||||
// of inputs.
|
// 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
|
exNumInputs := 2 + numInvoices
|
||||||
if len(tx.MsgTx().TxIn) == exNumInputs {
|
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
|
// trigger a breach. Carol is kept offline throughout the process and the test
|
||||||
// asserts that Willy responds by broadcasting the justice transaction on
|
// asserts that Willy responds by broadcasting the justice transaction on
|
||||||
// Carol's behalf sweeping her funds without a reward.
|
// Carol's behalf sweeping her funds without a reward.
|
||||||
func testRevokedCloseRetributionAltruistWatchtower(ht *lntemp.HarnessTest) {
|
func testRevokedCloseRetributionAltruistWatchtower(ht *lntest.HarnessTest) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
anchors bool
|
anchors bool
|
||||||
@@ -592,7 +604,7 @@ func testRevokedCloseRetributionAltruistWatchtower(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
testFunc := func(ht *lntemp.HarnessTest) {
|
testFunc := func(ht *lntest.HarnessTest) {
|
||||||
testRevokedCloseRetributionAltruistWatchtowerCase(
|
testRevokedCloseRetributionAltruistWatchtowerCase(
|
||||||
ht, tc.anchors,
|
ht, tc.anchors,
|
||||||
)
|
)
|
||||||
@@ -601,7 +613,7 @@ func testRevokedCloseRetributionAltruistWatchtower(ht *lntemp.HarnessTest) {
|
|||||||
success := ht.Run(tc.name, func(tt *testing.T) {
|
success := ht.Run(tc.name, func(tt *testing.T) {
|
||||||
st := ht.Subtest(tt)
|
st := ht.Subtest(tt)
|
||||||
|
|
||||||
st.RunTestCase(&lntemp.TestCase{
|
st.RunTestCase(&lntest.TestCase{
|
||||||
Name: tc.name,
|
Name: tc.name,
|
||||||
TestFunc: testFunc,
|
TestFunc: testFunc,
|
||||||
})
|
})
|
||||||
@@ -619,7 +631,7 @@ func testRevokedCloseRetributionAltruistWatchtower(ht *lntemp.HarnessTest) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntemp.HarnessTest,
|
func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest,
|
||||||
anchors bool) {
|
anchors bool) {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -696,7 +708,7 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntemp.HarnessTest,
|
|||||||
// In order to test Dave's response to an uncooperative channel
|
// 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
|
// closure by Carol, we'll first open up a channel between them with a
|
||||||
// 0.5 BTC value.
|
// 0.5 BTC value.
|
||||||
params := lntemp.OpenChannelParams{
|
params := lntest.OpenChannelParams{
|
||||||
Amt: 3 * (chanAmt / 4),
|
Amt: 3 * (chanAmt / 4),
|
||||||
PushAmt: chanAmt / 4,
|
PushAmt: chanAmt / 4,
|
||||||
}
|
}
|
||||||
@@ -727,6 +739,9 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntemp.HarnessTest,
|
|||||||
// backup.
|
// backup.
|
||||||
ht.EnsureConnected(dave, carol)
|
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
|
// Finally, send payments from Dave to Carol, consuming Carol's
|
||||||
// remaining payment hashes.
|
// remaining payment hashes.
|
||||||
ht.CompletePaymentRequestsNoWait(dave, carolPayReqs, chanPoint)
|
ht.CompletePaymentRequestsNoWait(dave, carolPayReqs, chanPoint)
|
||||||
@@ -10,8 +10,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainreg"
|
"github.com/lightningnetwork/lnd/chainreg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/stretchr/testify/require"
|
"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
|
// 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
|
// test all three SendToRoute endpoints, forcing each to perform both a regular
|
||||||
// payment and an MPP payment.
|
// payment and an MPP payment.
|
||||||
func testSingleHopSendToRoute(ht *lntemp.HarnessTest) {
|
func testSingleHopSendToRoute(ht *lntest.HarnessTest) {
|
||||||
for _, test := range singleHopSendToRouteCases {
|
for _, test := range singleHopSendToRouteCases {
|
||||||
test := test
|
test := test
|
||||||
|
|
||||||
@@ -76,7 +76,7 @@ func testSingleHopSendToRoute(ht *lntemp.HarnessTest) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSingleHopSendToRouteCase(ht *lntemp.HarnessTest,
|
func testSingleHopSendToRouteCase(ht *lntest.HarnessTest,
|
||||||
test singleHopSendToRouteCase) {
|
test singleHopSendToRouteCase) {
|
||||||
|
|
||||||
const chanAmt = btcutil.Amount(100000)
|
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
|
// Open a channel with 100k satoshis between Carol and Dave with Carol
|
||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
chanPointCarol := ht.OpenChannel(
|
chanPointCarol := ht.OpenChannel(
|
||||||
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
|
carol, dave, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
defer ht.CloseChannel(carol, chanPointCarol)
|
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
|
// We'll query the daemon for routes from Alice to Carol and then
|
||||||
// send payments through the routes.
|
// send payments through the routes.
|
||||||
func testMultiHopSendToRoute(ht *lntemp.HarnessTest) {
|
func testMultiHopSendToRoute(ht *lntest.HarnessTest) {
|
||||||
ht.Run("with cache", func(tt *testing.T) {
|
ht.Run("with cache", func(tt *testing.T) {
|
||||||
st := ht.Subtest(tt)
|
st := ht.Subtest(tt)
|
||||||
runMultiHopSendToRoute(st, true)
|
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
|
// We'll query the daemon for routes from Alice to Carol and then
|
||||||
// send payments through the routes.
|
// send payments through the routes.
|
||||||
func runMultiHopSendToRoute(ht *lntemp.HarnessTest, useGraphCache bool) {
|
func runMultiHopSendToRoute(ht *lntest.HarnessTest, useGraphCache bool) {
|
||||||
var opts []string
|
var opts []string
|
||||||
if !useGraphCache {
|
if !useGraphCache {
|
||||||
opts = append(opts, "--db.no-graph-cache")
|
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
|
// Open a channel with 100k satoshis between Alice and Bob with Alice
|
||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
chanPointAlice := ht.OpenChannel(
|
chanPointAlice := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
defer ht.CloseChannel(alice, chanPointAlice)
|
defer ht.CloseChannel(alice, chanPointAlice)
|
||||||
|
|
||||||
@@ -337,10 +337,13 @@ func runMultiHopSendToRoute(ht *lntemp.HarnessTest, useGraphCache bool) {
|
|||||||
ht.ConnectNodes(carol, bob)
|
ht.ConnectNodes(carol, bob)
|
||||||
|
|
||||||
chanPointBob := ht.OpenChannel(
|
chanPointBob := ht.OpenChannel(
|
||||||
bob, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
bob, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
defer ht.CloseChannel(carol, chanPointBob)
|
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
|
// Create 5 invoices for Carol, which expect a payment from Alice for
|
||||||
// 1k satoshis with a different preimage each time.
|
// 1k satoshis with a different preimage each time.
|
||||||
const (
|
const (
|
||||||
@@ -407,14 +410,14 @@ func runMultiHopSendToRoute(ht *lntemp.HarnessTest, useGraphCache bool) {
|
|||||||
|
|
||||||
// testSendToRouteErrorPropagation tests propagation of errors that occur
|
// testSendToRouteErrorPropagation tests propagation of errors that occur
|
||||||
// while processing a multi-hop payment through an unknown route.
|
// 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)
|
const chanAmt = btcutil.Amount(100000)
|
||||||
|
|
||||||
// Open a channel with 100k satoshis between Alice and Bob with Alice
|
// Open a channel with 100k satoshis between Alice and Bob with Alice
|
||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
chanPointAlice := ht.OpenChannel(
|
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,
|
// 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.FundCoins(btcutil.SatoshiPerBitcoin, charlie)
|
||||||
|
|
||||||
ht.ConnectNodes(carol, 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
|
// Query routes from Carol to Charlie which will be an invalid route
|
||||||
// for Alice -> Bob.
|
// for Alice -> Bob.
|
||||||
@@ -476,7 +479,9 @@ func testSendToRouteErrorPropagation(ht *lntemp.HarnessTest) {
|
|||||||
// testPrivateChannels tests that a private channel can be used for
|
// testPrivateChannels tests that a private channel can be used for
|
||||||
// routing by the two endpoints of the channel, but is not known by
|
// routing by the two endpoints of the channel, but is not known by
|
||||||
// the rest of the nodes in the graph.
|
// 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)
|
const chanAmt = btcutil.Amount(100000)
|
||||||
|
|
||||||
// We create the following topology:
|
// We create the following topology:
|
||||||
@@ -493,7 +498,7 @@ func testPrivateChannels(ht *lntemp.HarnessTest) {
|
|||||||
// Open a channel with 200k satoshis between Alice and Bob.
|
// Open a channel with 200k satoshis between Alice and Bob.
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
chanPointAlice := ht.OpenChannel(
|
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.
|
// Create Dave, and a channel to Alice of 100k.
|
||||||
@@ -502,7 +507,7 @@ func testPrivateChannels(ht *lntemp.HarnessTest) {
|
|||||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, dave)
|
ht.FundCoins(btcutil.SatoshiPerBitcoin, dave)
|
||||||
|
|
||||||
chanPointDave := ht.OpenChannel(
|
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
|
// 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)
|
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||||
|
|
||||||
chanPointCarol := ht.OpenChannel(
|
chanPointCarol := ht.OpenChannel(
|
||||||
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
|
carol, dave, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Now create a _private_ channel directly between Carol and
|
// Now create a _private_ channel directly between Carol and
|
||||||
// Alice of 100k.
|
// Alice of 100k.
|
||||||
ht.ConnectNodes(carol, alice)
|
ht.ConnectNodes(carol, alice)
|
||||||
chanPointPrivate := ht.OpenChannel(
|
chanPointPrivate := ht.OpenChannel(
|
||||||
carol, alice, lntemp.OpenChannelParams{
|
carol, alice, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
Private: true,
|
Private: true,
|
||||||
},
|
},
|
||||||
@@ -602,7 +607,7 @@ func testPrivateChannels(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// testInvoiceRoutingHints tests that the routing hints for an invoice are
|
// testInvoiceRoutingHints tests that the routing hints for an invoice are
|
||||||
// created properly.
|
// created properly.
|
||||||
func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
func testInvoiceRoutingHints(ht *lntest.HarnessTest) {
|
||||||
const chanAmt = btcutil.Amount(100000)
|
const chanAmt = btcutil.Amount(100000)
|
||||||
|
|
||||||
// Throughout this test, we'll be opening a channel between Alice and
|
// Throughout this test, we'll be opening a channel between Alice and
|
||||||
@@ -615,7 +620,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
|||||||
// invoice's payment.
|
// invoice's payment.
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
chanPointBob := ht.OpenChannel(
|
chanPointBob := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: chanAmt / 2,
|
PushAmt: chanAmt / 2,
|
||||||
Private: true,
|
Private: true,
|
||||||
@@ -629,7 +634,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
ht.ConnectNodes(alice, carol)
|
ht.ConnectNodes(alice, carol)
|
||||||
chanPointCarol := ht.OpenChannel(
|
chanPointCarol := ht.OpenChannel(
|
||||||
alice, carol, lntemp.OpenChannelParams{
|
alice, carol, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: chanAmt / 2,
|
PushAmt: chanAmt / 2,
|
||||||
},
|
},
|
||||||
@@ -642,7 +647,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
|||||||
// that wish to stay unadvertised.
|
// that wish to stay unadvertised.
|
||||||
ht.ConnectNodes(bob, carol)
|
ht.ConnectNodes(bob, carol)
|
||||||
chanPointBobCarol := ht.OpenChannel(
|
chanPointBobCarol := ht.OpenChannel(
|
||||||
bob, carol, lntemp.OpenChannelParams{
|
bob, carol, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: chanAmt / 2,
|
PushAmt: chanAmt / 2,
|
||||||
},
|
},
|
||||||
@@ -656,7 +661,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
ht.ConnectNodes(alice, dave)
|
ht.ConnectNodes(alice, dave)
|
||||||
chanPointDave := ht.OpenChannel(
|
chanPointDave := ht.OpenChannel(
|
||||||
alice, dave, lntemp.OpenChannelParams{
|
alice, dave, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
Private: true,
|
Private: true,
|
||||||
},
|
},
|
||||||
@@ -669,7 +674,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
|||||||
eve := ht.NewNode("Eve", nil)
|
eve := ht.NewNode("Eve", nil)
|
||||||
ht.ConnectNodes(alice, eve)
|
ht.ConnectNodes(alice, eve)
|
||||||
chanPointEve := ht.OpenChannel(
|
chanPointEve := ht.OpenChannel(
|
||||||
alice, eve, lntemp.OpenChannelParams{
|
alice, eve, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: chanAmt / 2,
|
PushAmt: chanAmt / 2,
|
||||||
Private: true,
|
Private: true,
|
||||||
@@ -744,7 +749,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// testMultiHopOverPrivateChannels tests that private channels can be used as
|
// testMultiHopOverPrivateChannels tests that private channels can be used as
|
||||||
// intermediate hops in a route for payments.
|
// 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
|
// We'll test that multi-hop payments over private channels work as
|
||||||
// intended. To do so, we'll create the following topology:
|
// intended. To do so, we'll create the following topology:
|
||||||
// private public private
|
// private public private
|
||||||
@@ -755,7 +760,7 @@ func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
|
|||||||
// being the funder.
|
// being the funder.
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
chanPointAlice := ht.OpenChannel(
|
chanPointAlice := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
Private: true,
|
Private: true,
|
||||||
},
|
},
|
||||||
@@ -766,7 +771,7 @@ func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
|
|||||||
carol := ht.NewNode("Carol", nil)
|
carol := ht.NewNode("Carol", nil)
|
||||||
ht.ConnectNodes(bob, carol)
|
ht.ConnectNodes(bob, carol)
|
||||||
chanPointBob := ht.OpenChannel(
|
chanPointBob := ht.OpenChannel(
|
||||||
bob, carol, lntemp.OpenChannelParams{
|
bob, carol, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -781,7 +786,7 @@ func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
|
|||||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||||
|
|
||||||
chanPointCarol := ht.OpenChannel(
|
chanPointCarol := ht.OpenChannel(
|
||||||
carol, dave, lntemp.OpenChannelParams{
|
carol, dave, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
Private: true,
|
Private: true,
|
||||||
},
|
},
|
||||||
@@ -851,7 +856,7 @@ func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
|
|||||||
// Alice --> Bob --> Carol --> Dave
|
// Alice --> Bob --> Carol --> Dave
|
||||||
//
|
//
|
||||||
// and query the daemon for routes from Alice to 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)
|
const chanAmt = btcutil.Amount(100000)
|
||||||
|
|
||||||
// Grab Alice and Bob from the standby nodes.
|
// Grab Alice and Bob from the standby nodes.
|
||||||
@@ -869,8 +874,8 @@ func testQueryRoutes(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// We now proceed to open channels:
|
// We now proceed to open channels:
|
||||||
// Alice=>Bob, Bob=>Carol and Carol=>Dave.
|
// Alice=>Bob, Bob=>Carol and Carol=>Dave.
|
||||||
p := lntemp.OpenChannelParams{Amt: chanAmt}
|
p := lntest.OpenChannelParams{Amt: chanAmt}
|
||||||
reqs := []*lntemp.OpenChannelRequest{
|
reqs := []*lntest.OpenChannelRequest{
|
||||||
{Local: alice, Remote: bob, Param: p},
|
{Local: alice, Remote: bob, Param: p},
|
||||||
{Local: bob, Remote: carol, Param: p},
|
{Local: bob, Remote: carol, Param: p},
|
||||||
{Local: carol, Remote: dave, 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
|
// testMissionControlImport tests import of mission control results from an
|
||||||
// external source.
|
// external source.
|
||||||
func testMissionControlImport(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
func testMissionControlImport(ht *lntest.HarnessTest, hn *node.HarnessNode,
|
||||||
fromNode, toNode []byte) {
|
fromNode, toNode []byte) {
|
||||||
|
|
||||||
// Reset mission control so that our query will return the default
|
// 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
|
// testRouteFeeCutoff tests that we are able to prevent querying routes and
|
||||||
// sending payments that incur a fee higher than the fee limit.
|
// 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:
|
// For this test, we'll create the following topology:
|
||||||
//
|
//
|
||||||
// --- Bob ---
|
// --- Bob ---
|
||||||
@@ -1155,7 +1160,7 @@ func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
|
|||||||
// Open a channel between Alice and Bob.
|
// Open a channel between Alice and Bob.
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
chanPointAliceBob := ht.OpenChannel(
|
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
|
// 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)
|
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||||
|
|
||||||
chanPointAliceCarol := ht.OpenChannel(
|
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
|
// 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)
|
dave := ht.NewNode("Dave", nil)
|
||||||
ht.ConnectNodes(dave, bob)
|
ht.ConnectNodes(dave, bob)
|
||||||
chanPointBobDave := ht.OpenChannel(
|
chanPointBobDave := ht.OpenChannel(
|
||||||
bob, dave, lntemp.OpenChannelParams{Amt: chanAmt},
|
bob, dave, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Open a channel between Carol and Dave.
|
// Open a channel between Carol and Dave.
|
||||||
ht.ConnectNodes(carol, dave)
|
ht.ConnectNodes(carol, dave)
|
||||||
chanPointCarolDave := ht.OpenChannel(
|
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
|
// 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)
|
baseFee := int64(10000)
|
||||||
feeRate := int64(5)
|
feeRate := int64(5)
|
||||||
timeLockDelta := uint32(chainreg.DefaultBitcoinTimeLockDelta)
|
timeLockDelta := uint32(chainreg.DefaultBitcoinTimeLockDelta)
|
||||||
maxHtlc := calculateMaxHtlc(chanAmt)
|
maxHtlc := lntest.CalculateMaxHtlc(chanAmt)
|
||||||
|
|
||||||
expectedPolicy := &lnrpc.RoutingPolicy{
|
expectedPolicy := &lnrpc.RoutingPolicy{
|
||||||
FeeBaseMsat: baseFee,
|
FeeBaseMsat: baseFee,
|
||||||
@@ -1285,7 +1290,8 @@ func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
|
|||||||
case *lnrpc.FeeLimit_Fixed:
|
case *lnrpc.FeeLimit_Fixed:
|
||||||
sendReq.FeeLimitMsat = 1000 * limit.Fixed
|
sendReq.FeeLimitMsat = 1000 * limit.Fixed
|
||||||
case *lnrpc.FeeLimit_Percent:
|
case *lnrpc.FeeLimit_Percent:
|
||||||
sendReq.FeeLimitMsat = 1000 * paymentAmt * limit.Percent / 100
|
sendReq.FeeLimitMsat = 1000 * paymentAmt *
|
||||||
|
limit.Percent / 100
|
||||||
}
|
}
|
||||||
|
|
||||||
result := ht.SendPaymentAssertSettled(alice, sendReq)
|
result := ht.SendPaymentAssertSettled(alice, sendReq)
|
||||||
+5
-5
@@ -8,8 +8,8 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/macaroons"
|
"github.com/lightningnetwork/lnd/macaroons"
|
||||||
"github.com/lightningnetwork/lnd/zpay32"
|
"github.com/lightningnetwork/lnd/zpay32"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -19,7 +19,7 @@ import (
|
|||||||
|
|
||||||
// testRPCMiddlewareInterceptor tests that the RPC middleware interceptor can
|
// testRPCMiddlewareInterceptor tests that the RPC middleware interceptor can
|
||||||
// be used correctly and in a safe way.
|
// 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.
|
// Let's first enable the middleware interceptor.
|
||||||
//
|
//
|
||||||
// NOTE: we cannot use standby nodes here as the test messes with
|
// 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.
|
// data to inspect when doing RPC calls to Alice later.
|
||||||
ht.EnsureConnected(alice, bob)
|
ht.EnsureConnected(alice, bob)
|
||||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, alice)
|
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
|
// Load or bake the macaroons that the simulated users will use to
|
||||||
// access the RPC.
|
// 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
|
// middlewareMandatoryTest tests that all RPC requests are blocked if there is
|
||||||
// a mandatory middleware declared that's currently not registered.
|
// 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
|
// 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
|
// it just yet. That should cause all RPC requests to fail, except for
|
||||||
// the registration itself.
|
// the registration itself.
|
||||||
+2
-2
@@ -6,13 +6,13 @@ import (
|
|||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// testSendMultiPathPayment tests that we are able to successfully route a
|
// testSendMultiPathPayment tests that we are able to successfully route a
|
||||||
// payment using multiple shards across different paths.
|
// payment using multiple shards across different paths.
|
||||||
func testSendMultiPathPayment(ht *lntemp.HarnessTest) {
|
func testSendMultiPathPayment(ht *lntest.HarnessTest) {
|
||||||
mts := newMppTestScenario(ht)
|
mts := newMppTestScenario(ht)
|
||||||
|
|
||||||
const paymentAmt = btcutil.Amount(300000)
|
const paymentAmt = btcutil.Amount(300000)
|
||||||
@@ -13,8 +13,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
// DeriveSharedKey. It creates an ephemeral private key, performing an ECDH with
|
// 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
|
// the node's pubkey and a customized public key to check the validity of the
|
||||||
// result.
|
// result.
|
||||||
func testDeriveSharedKey(ht *lntemp.HarnessTest) {
|
func testDeriveSharedKey(ht *lntest.HarnessTest) {
|
||||||
runDeriveSharedKey(ht, ht.Alice)
|
runDeriveSharedKey(ht, ht.Alice)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -30,7 +30,7 @@ func testDeriveSharedKey(ht *lntemp.HarnessTest) {
|
|||||||
// DeriveSharedKey. It creates an ephemeral private key, performing an ECDH with
|
// 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
|
// the node's pubkey and a customized public key to check the validity of the
|
||||||
// result.
|
// 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
|
// Create an ephemeral key, extracts its public key, and make a
|
||||||
// PrivKeyECDH using the ephemeral key.
|
// PrivKeyECDH using the ephemeral key.
|
||||||
ephemeralPriv, err := btcec.NewPrivateKey()
|
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
|
// testSignOutputRaw makes sure that the SignOutputRaw RPC can be used with all
|
||||||
// custom ways of specifying the signing key in the key descriptor/locator.
|
// 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(ht, ht.Alice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// runSignOutputRaw makes sure that the SignOutputRaw RPC can be used with all
|
// runSignOutputRaw makes sure that the SignOutputRaw RPC can be used with all
|
||||||
// custom ways of specifying the signing key in the key descriptor/locator.
|
// 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 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.
|
// for this. We want this to be an index of zero.
|
||||||
const testCustomKeyFamily = 44
|
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
|
// 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
|
// target public key and then tries to spend that output again by invoking the
|
||||||
// SignOutputRaw RPC with the key descriptor provided.
|
// SignOutputRaw RPC with the key descriptor provided.
|
||||||
func assertSignOutputRaw(ht *lntemp.HarnessTest,
|
func assertSignOutputRaw(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode, targetPubKey *btcec.PublicKey,
|
alice *node.HarnessNode, targetPubKey *btcec.PublicKey,
|
||||||
keyDesc *signrpc.KeyDescriptor,
|
keyDesc *signrpc.KeyDescriptor,
|
||||||
sigHash txscript.SigHashType) {
|
sigHash txscript.SigHashType) {
|
||||||
@@ -373,14 +373,14 @@ func assertSignOutputRaw(ht *lntemp.HarnessTest,
|
|||||||
// testSignVerifyMessage makes sure that the SignMessage RPC can be used with
|
// testSignVerifyMessage makes sure that the SignMessage RPC can be used with
|
||||||
// all custom flags by verifying with VerifyMessage. Tests both ECDSA and
|
// all custom flags by verifying with VerifyMessage. Tests both ECDSA and
|
||||||
// Schnorr signatures.
|
// Schnorr signatures.
|
||||||
func testSignVerifyMessage(ht *lntemp.HarnessTest) {
|
func testSignVerifyMessage(ht *lntest.HarnessTest) {
|
||||||
runSignVerifyMessage(ht, ht.Alice)
|
runSignVerifyMessage(ht, ht.Alice)
|
||||||
}
|
}
|
||||||
|
|
||||||
// runSignVerifyMessage makes sure that the SignMessage RPC can be used with
|
// runSignVerifyMessage makes sure that the SignMessage RPC can be used with
|
||||||
// all custom flags by verifying with VerifyMessage. Tests both ECDSA and
|
// all custom flags by verifying with VerifyMessage. Tests both ECDSA and
|
||||||
// Schnorr signatures.
|
// Schnorr signatures.
|
||||||
func runSignVerifyMessage(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
func runSignVerifyMessage(ht *lntest.HarnessTest, alice *node.HarnessNode) {
|
||||||
aliceMsg := []byte("alice msg")
|
aliceMsg := []byte("alice msg")
|
||||||
keyLoc := &signrpc.KeyLocator{
|
keyLoc := &signrpc.KeyLocator{
|
||||||
KeyFamily: int32(keychain.KeyFamilyNodeKey),
|
KeyFamily: int32(keychain.KeyFamilyNodeKey),
|
||||||
@@ -7,20 +7,20 @@ import (
|
|||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"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/lntypes"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/record"
|
"github.com/lightningnetwork/lnd/record"
|
||||||
"github.com/stretchr/testify/require"
|
"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
|
// Open a channel with 100k satoshis between Alice and Bob with Alice
|
||||||
// being the sole funder of the channel.
|
// being the sole funder of the channel.
|
||||||
chanAmt := btcutil.Amount(100000)
|
chanAmt := btcutil.Amount(100000)
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
cp := ht.OpenChannel(
|
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
|
// assertAmountPaid is a helper closure that asserts the amount paid by
|
||||||
@@ -3,8 +3,8 @@ package itest
|
|||||||
import (
|
import (
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -21,11 +21,11 @@ const (
|
|||||||
//
|
//
|
||||||
// The general flow of this test:
|
// The general flow of this test:
|
||||||
// 1. Carol --> Dave --> Alice --> Bob forward payment
|
// 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
|
// 3. Carol <-- Dave <-- Alice <-- Bob expect settle to propagate
|
||||||
//
|
//
|
||||||
//nolint:dupword
|
//nolint:dupword
|
||||||
func testSwitchCircuitPersistence(ht *lntemp.HarnessTest) {
|
func testSwitchCircuitPersistence(ht *lntest.HarnessTest) {
|
||||||
// Setup our test scenario. We should now have four nodes running with
|
// Setup our test scenario. We should now have four nodes running with
|
||||||
// three channels.
|
// three channels.
|
||||||
s := setupScenarioFourNodes(ht)
|
s := setupScenarioFourNodes(ht)
|
||||||
@@ -95,7 +95,7 @@ func testSwitchCircuitPersistence(ht *lntemp.HarnessTest) {
|
|||||||
// 2. Carol --- Dave X Alice --- Bob disconnect intermediaries
|
// 2. Carol --- Dave X Alice --- Bob disconnect intermediaries
|
||||||
// 3. Carol --- Dave X Alice <-- Bob settle last hop
|
// 3. Carol --- Dave X Alice <-- Bob settle last hop
|
||||||
// 4. Carol <-- Dave <-- Alice --- Bob reconnect, expect settle to propagate
|
// 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
|
// Setup our test scenario. We should now have four nodes running with
|
||||||
// three channels.
|
// three channels.
|
||||||
s := setupScenarioFourNodes(ht)
|
s := setupScenarioFourNodes(ht)
|
||||||
@@ -131,11 +131,6 @@ func testSwitchOfflineDelivery(ht *lntemp.HarnessTest) {
|
|||||||
// Wait until all outstanding htlcs in the network have been settled.
|
// Wait until all outstanding htlcs in the network have been settled.
|
||||||
s.assertHTLCs(ht, 0)
|
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
|
// 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
|
// shifted by 5k satoshis in the direction of Carol, the sink within the
|
||||||
// payment flow generated above. The order of asserts corresponds to
|
// 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
|
// 3. Carol --- Dave X Alice <-- Bob settle last hop
|
||||||
// 4. Carol --- Dave X X Bob restart Alice
|
// 4. Carol --- Dave X X Bob restart Alice
|
||||||
// 5. Carol <-- Dave <-- Alice --- Bob expect settle to propagate
|
// 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
|
// Setup our test scenario. We should now have four nodes running with
|
||||||
// three channels.
|
// three channels.
|
||||||
s := setupScenarioFourNodes(ht)
|
s := setupScenarioFourNodes(ht)
|
||||||
@@ -260,7 +257,9 @@ func testSwitchOfflineDeliveryPersistence(ht *lntemp.HarnessTest) {
|
|||||||
// 3. Carol --- Dave X Alice <-- Bob settle last hop
|
// 3. Carol --- Dave X Alice <-- Bob settle last hop
|
||||||
// 4. Carol --- Dave X X shutdown Bob, restart Alice
|
// 4. Carol --- Dave X X shutdown Bob, restart Alice
|
||||||
// 5. Carol <-- Dave <-- Alice X expect settle to propagate
|
// 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
|
// 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
|
// three channels. Note that we won't call the cleanUp function here as
|
||||||
// we will manually stop the node Carol and her channel.
|
// 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
|
// NOTE: caller needs to call cleanUp to clean the nodes and channels created
|
||||||
// from this setup.
|
// from this setup.
|
||||||
func setupScenarioFourNodes(ht *lntemp.HarnessTest) *scenarioFourNodes {
|
func setupScenarioFourNodes(ht *lntest.HarnessTest) *scenarioFourNodes {
|
||||||
const (
|
const (
|
||||||
chanAmt = btcutil.Amount(1000000)
|
chanAmt = btcutil.Amount(1000000)
|
||||||
pushAmt = btcutil.Amount(900000)
|
pushAmt = btcutil.Amount(900000)
|
||||||
)
|
)
|
||||||
|
|
||||||
params := lntemp.OpenChannelParams{
|
params := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
}
|
}
|
||||||
@@ -404,7 +403,7 @@ func setupScenarioFourNodes(ht *lntemp.HarnessTest) *scenarioFourNodes {
|
|||||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||||
|
|
||||||
// Open channels in batch to save blocks mined.
|
// Open channels in batch to save blocks mined.
|
||||||
reqs := []*lntemp.OpenChannelRequest{
|
reqs := []*lntest.OpenChannelRequest{
|
||||||
{Local: alice, Remote: bob, Param: params},
|
{Local: alice, Remote: bob, Param: params},
|
||||||
{Local: dave, Remote: alice, Param: params},
|
{Local: dave, Remote: alice, Param: params},
|
||||||
{Local: carol, Remote: dave, 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
|
// assertHTLCs is a helper function which asserts the desired num of
|
||||||
// HTLCs has been seen in the nodes.
|
// 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
|
// Alice should have both the same number of outgoing and
|
||||||
// incoming HTLCs.
|
// incoming HTLCs.
|
||||||
ht.AssertNumActiveHtlcs(s.alice, num*2)
|
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
|
// assertAmoutPaid is a helper method which takes a given paid amount
|
||||||
// and number of payments and asserts the desired payments are made in
|
// and number of payments and asserts the desired payments are made in
|
||||||
// the four nodes.
|
// the four nodes.
|
||||||
func (s *scenarioFourNodes) assertAmoutPaid(ht *lntemp.HarnessTest,
|
func (s *scenarioFourNodes) assertAmoutPaid(ht *lntest.HarnessTest,
|
||||||
amt int64, num int64) {
|
amt int64, num int64) {
|
||||||
|
|
||||||
ht.AssertAmountPaid(
|
ht.AssertAmountPaid(
|
||||||
@@ -20,8 +20,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -47,7 +47,7 @@ var (
|
|||||||
|
|
||||||
// testTaproot ensures that the daemon can send to and spend from taproot (p2tr)
|
// testTaproot ensures that the daemon can send to and spend from taproot (p2tr)
|
||||||
// outputs.
|
// outputs.
|
||||||
func testTaproot(ht *lntemp.HarnessTest) {
|
func testTaproot(ht *lntest.HarnessTest) {
|
||||||
testTaprootSendCoinsKeySpendBip86(ht, ht.Alice)
|
testTaprootSendCoinsKeySpendBip86(ht, ht.Alice)
|
||||||
testTaprootComputeInputScriptKeySpendBip86(ht, ht.Alice)
|
testTaprootComputeInputScriptKeySpendBip86(ht, ht.Alice)
|
||||||
testTaprootSignOutputRawScriptSpend(ht, ht.Alice)
|
testTaprootSignOutputRawScriptSpend(ht, ht.Alice)
|
||||||
@@ -81,7 +81,7 @@ func testTaproot(ht *lntemp.HarnessTest) {
|
|||||||
// testTaprootSendCoinsKeySpendBip86 tests sending to and spending from
|
// testTaprootSendCoinsKeySpendBip86 tests sending to and spending from
|
||||||
// p2tr key spend only (BIP-0086) addresses through the SendCoins RPC which
|
// p2tr key spend only (BIP-0086) addresses through the SendCoins RPC which
|
||||||
// internally uses the ComputeInputScript method for signing.
|
// internally uses the ComputeInputScript method for signing.
|
||||||
func testTaprootSendCoinsKeySpendBip86(ht *lntemp.HarnessTest,
|
func testTaprootSendCoinsKeySpendBip86(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode) {
|
alice *node.HarnessNode) {
|
||||||
|
|
||||||
// We'll start the test by sending Alice some coins, which she'll use to
|
// 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
|
// testTaprootComputeInputScriptKeySpendBip86 tests sending to and spending from
|
||||||
// p2tr key spend only (BIP-0086) addresses through the SendCoins RPC which
|
// p2tr key spend only (BIP-0086) addresses through the SendCoins RPC which
|
||||||
// internally uses the ComputeInputScript method for signing.
|
// internally uses the ComputeInputScript method for signing.
|
||||||
func testTaprootComputeInputScriptKeySpendBip86(ht *lntemp.HarnessTest,
|
func testTaprootComputeInputScriptKeySpendBip86(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode) {
|
alice *node.HarnessNode) {
|
||||||
|
|
||||||
// We'll start the test by sending Alice some coins, which she'll use
|
// 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
|
// testTaprootSignOutputRawScriptSpend tests sending to and spending from p2tr
|
||||||
// script addresses using the script path with the SignOutputRaw RPC.
|
// 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) {
|
alice *node.HarnessNode, sigHashType ...txscript.SigHashType) {
|
||||||
|
|
||||||
// For the next step, we need a public key. Let's use a special family
|
// 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)
|
require.NoError(ht, err)
|
||||||
|
|
||||||
// Send some coins to the generated tapscript address.
|
// Send some coins to the generated tapscript address.
|
||||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||||
ht, alice, taprootKey, testAmount,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Spend the output again, this time back to a p2wkh address.
|
// Spend the output again, this time back to a p2wkh address.
|
||||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||||
@@ -392,7 +390,7 @@ func testTaprootSignOutputRawScriptSpend(ht *lntemp.HarnessTest,
|
|||||||
// testTaprootSignOutputRawKeySpendBip86 tests that a tapscript address can
|
// testTaprootSignOutputRawKeySpendBip86 tests that a tapscript address can
|
||||||
// also be spent using the key spend path through the SignOutputRaw RPC using a
|
// also be spent using the key spend path through the SignOutputRaw RPC using a
|
||||||
// BIP0086 key spend only commitment.
|
// BIP0086 key spend only commitment.
|
||||||
func testTaprootSignOutputRawKeySpendBip86(ht *lntemp.HarnessTest,
|
func testTaprootSignOutputRawKeySpendBip86(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode, sigHashType ...txscript.SigHashType) {
|
alice *node.HarnessNode, sigHashType ...txscript.SigHashType) {
|
||||||
|
|
||||||
// For the next step, we need a public key. Let's use a special family
|
// 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)
|
taprootKey := txscript.ComputeTaprootKeyNoScript(internalKey)
|
||||||
|
|
||||||
// Send some coins to the generated tapscript address.
|
// Send some coins to the generated tapscript address.
|
||||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||||
ht, alice, taprootKey, testAmount,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Spend the output again, this time back to a p2wkh address.
|
// Spend the output again, this time back to a p2wkh address.
|
||||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||||
@@ -490,7 +486,7 @@ func testTaprootSignOutputRawKeySpendBip86(ht *lntemp.HarnessTest,
|
|||||||
// testTaprootSignOutputRawKeySpendRootHash tests that a tapscript address can
|
// testTaprootSignOutputRawKeySpendRootHash tests that a tapscript address can
|
||||||
// also be spent using the key spend path through the SignOutputRaw RPC using a
|
// also be spent using the key spend path through the SignOutputRaw RPC using a
|
||||||
// tapscript root hash.
|
// tapscript root hash.
|
||||||
func testTaprootSignOutputRawKeySpendRootHash(ht *lntemp.HarnessTest,
|
func testTaprootSignOutputRawKeySpendRootHash(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode) {
|
alice *node.HarnessNode) {
|
||||||
|
|
||||||
// For the next step, we need a public key. Let's use a special family
|
// 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[:])
|
taprootKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash[:])
|
||||||
|
|
||||||
// Send some coins to the generated tapscript address.
|
// Send some coins to the generated tapscript address.
|
||||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||||
ht, alice, taprootKey, testAmount,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Spend the output again, this time back to a p2wkh address.
|
// Spend the output again, this time back to a p2wkh address.
|
||||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||||
@@ -583,7 +577,7 @@ func testTaprootSignOutputRawKeySpendRootHash(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// testTaprootMuSig2KeySpendBip86 tests that a combined MuSig2 key can also be
|
// testTaprootMuSig2KeySpendBip86 tests that a combined MuSig2 key can also be
|
||||||
// used as a BIP-0086 key spend only key.
|
// 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) {
|
alice *node.HarnessNode, version signrpc.MuSig2Version) {
|
||||||
|
|
||||||
// We're not going to commit to a script. So our taproot tweak will be
|
// 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.
|
// Send some coins to the generated tapscript address.
|
||||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||||
ht, alice, taprootKey, testAmount,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Spend the output again, this time back to a p2wkh address.
|
// Spend the output again, this time back to a p2wkh address.
|
||||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||||
@@ -711,7 +703,7 @@ func testTaprootMuSig2KeySpendBip86(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// testTaprootMuSig2KeySpendRootHash tests that a tapscript address can also be
|
// testTaprootMuSig2KeySpendRootHash tests that a tapscript address can also be
|
||||||
// spent using a MuSig2 combined key.
|
// spent using a MuSig2 combined key.
|
||||||
func testTaprootMuSig2KeySpendRootHash(ht *lntemp.HarnessTest,
|
func testTaprootMuSig2KeySpendRootHash(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode, version signrpc.MuSig2Version) {
|
alice *node.HarnessNode, version signrpc.MuSig2Version) {
|
||||||
|
|
||||||
// We're going to commit to a script as well. This is a hash lock with a
|
// 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.
|
// Send some coins to the generated tapscript address.
|
||||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||||
ht, alice, taprootKey, testAmount,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Spend the output again, this time back to a p2wkh address.
|
// Spend the output again, this time back to a p2wkh address.
|
||||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||||
@@ -843,7 +833,7 @@ func testTaprootMuSig2KeySpendRootHash(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// testTaprootMuSig2ScriptSpend tests that a tapscript address with an internal
|
// testTaprootMuSig2ScriptSpend tests that a tapscript address with an internal
|
||||||
// key that is a MuSig2 combined key can also be spent using the script path.
|
// 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) {
|
alice *node.HarnessNode, version signrpc.MuSig2Version) {
|
||||||
|
|
||||||
// We're going to commit to a script and spend the output using the
|
// 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)
|
tapscript := input.TapscriptFullTree(internalKey, leaf1)
|
||||||
|
|
||||||
// Send some coins to the generated tapscript address.
|
// Send some coins to the generated tapscript address.
|
||||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||||
ht, alice, taprootKey, testAmount,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Spend the output again, this time back to a p2wkh address.
|
// Spend the output again, this time back to a p2wkh address.
|
||||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||||
@@ -926,7 +914,7 @@ func testTaprootMuSig2ScriptSpend(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// testTaprootMuSig2CombinedLeafKeySpend tests that a MuSig2 combined key can be
|
// testTaprootMuSig2CombinedLeafKeySpend tests that a MuSig2 combined key can be
|
||||||
// used for an OP_CHECKSIG inside a tap script leaf spend.
|
// 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) {
|
alice *node.HarnessNode, version signrpc.MuSig2Version) {
|
||||||
|
|
||||||
// We're using the combined MuSig2 key in a script leaf. So we need to
|
// 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)
|
require.NoError(ht, err)
|
||||||
|
|
||||||
// Send some coins to the generated tapscript address.
|
// Send some coins to the generated tapscript address.
|
||||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||||
ht, alice, taprootKey, testAmount,
|
|
||||||
)
|
|
||||||
|
|
||||||
// Spend the output again, this time back to a p2wkh address.
|
// Spend the output again, this time back to a p2wkh address.
|
||||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||||
@@ -1102,7 +1088,7 @@ func testTaprootMuSig2CombinedLeafKeySpend(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// testTaprootImportTapscriptScriptSpend tests importing p2tr script addresses
|
// testTaprootImportTapscriptScriptSpend tests importing p2tr script addresses
|
||||||
// using the script path with the full tree known.
|
// using the script path with the full tree known.
|
||||||
func testTaprootImportTapscriptFullTree(ht *lntemp.HarnessTest,
|
func testTaprootImportTapscriptFullTree(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode) {
|
alice *node.HarnessNode) {
|
||||||
|
|
||||||
// For the next step, we need a public key. Let's use a special family
|
// 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)
|
require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
|
||||||
|
|
||||||
// Send some coins to the generated tapscript address.
|
// Send some coins to the generated tapscript address.
|
||||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||||
ht, alice, taprootKey, testAmount,
|
|
||||||
)
|
|
||||||
p2trOutputRPC := &lnrpc.OutPoint{
|
p2trOutputRPC := &lnrpc.OutPoint{
|
||||||
TxidBytes: p2trOutpoint.Hash[:],
|
TxidBytes: p2trOutpoint.Hash[:],
|
||||||
OutputIndex: p2trOutpoint.Index,
|
OutputIndex: p2trOutpoint.Index,
|
||||||
@@ -1176,7 +1160,7 @@ func testTaprootImportTapscriptFullTree(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// testTaprootImportTapscriptPartialReveal tests importing p2tr script addresses
|
// testTaprootImportTapscriptPartialReveal tests importing p2tr script addresses
|
||||||
// for which we only know part of the tree.
|
// for which we only know part of the tree.
|
||||||
func testTaprootImportTapscriptPartialReveal(ht *lntemp.HarnessTest,
|
func testTaprootImportTapscriptPartialReveal(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode) {
|
alice *node.HarnessNode) {
|
||||||
|
|
||||||
// For the next step, we need a public key. Let's use a special family
|
// 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)
|
require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
|
||||||
|
|
||||||
// Send some coins to the generated tapscript address.
|
// Send some coins to the generated tapscript address.
|
||||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||||
ht, alice, taprootKey, testAmount,
|
|
||||||
)
|
|
||||||
|
|
||||||
p2trOutputRPC := &lnrpc.OutPoint{
|
p2trOutputRPC := &lnrpc.OutPoint{
|
||||||
TxidBytes: p2trOutpoint.Hash[:],
|
TxidBytes: p2trOutpoint.Hash[:],
|
||||||
@@ -1247,7 +1229,7 @@ func testTaprootImportTapscriptPartialReveal(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// testTaprootImportTapscriptRootHashOnly tests importing p2tr script addresses
|
// testTaprootImportTapscriptRootHashOnly tests importing p2tr script addresses
|
||||||
// for which we only know the root hash.
|
// for which we only know the root hash.
|
||||||
func testTaprootImportTapscriptRootHashOnly(ht *lntemp.HarnessTest,
|
func testTaprootImportTapscriptRootHashOnly(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode) {
|
alice *node.HarnessNode) {
|
||||||
|
|
||||||
// For the next step, we need a public key. Let's use a special family
|
// 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)
|
require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
|
||||||
|
|
||||||
// Send some coins to the generated tapscript address.
|
// Send some coins to the generated tapscript address.
|
||||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||||
ht, alice, taprootKey, testAmount,
|
|
||||||
)
|
|
||||||
|
|
||||||
p2trOutputRPC := &lnrpc.OutPoint{
|
p2trOutputRPC := &lnrpc.OutPoint{
|
||||||
TxidBytes: p2trOutpoint.Hash[:],
|
TxidBytes: p2trOutpoint.Hash[:],
|
||||||
@@ -1306,7 +1286,7 @@ func testTaprootImportTapscriptRootHashOnly(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// testTaprootImportTapscriptFullKey tests importing p2tr script addresses for
|
// testTaprootImportTapscriptFullKey tests importing p2tr script addresses for
|
||||||
// which we only know the full Taproot key.
|
// which we only know the full Taproot key.
|
||||||
func testTaprootImportTapscriptFullKey(ht *lntemp.HarnessTest,
|
func testTaprootImportTapscriptFullKey(ht *lntest.HarnessTest,
|
||||||
alice *node.HarnessNode) {
|
alice *node.HarnessNode) {
|
||||||
|
|
||||||
// For the next step, we need a public key. Let's use a special family
|
// 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)
|
require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
|
||||||
|
|
||||||
// Send some coins to the generated tapscript address.
|
// Send some coins to the generated tapscript address.
|
||||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||||
ht, alice, taprootKey, testAmount,
|
|
||||||
)
|
|
||||||
|
|
||||||
p2trOutputRPC := &lnrpc.OutPoint{
|
p2trOutputRPC := &lnrpc.OutPoint{
|
||||||
TxidBytes: p2trOutpoint.Hash[:],
|
TxidBytes: p2trOutpoint.Hash[:],
|
||||||
@@ -1365,7 +1343,7 @@ func testTaprootImportTapscriptFullKey(ht *lntemp.HarnessTest,
|
|||||||
|
|
||||||
// clearWalletImportedTapscriptBalance manually assembles and then attempts to
|
// clearWalletImportedTapscriptBalance manually assembles and then attempts to
|
||||||
// sign a TX to sweep funds from an imported tapscript address.
|
// 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,
|
hn *node.HarnessNode, utxo *wire.TxOut, outPoint wire.OutPoint,
|
||||||
internalKey *btcec.PublicKey, derivationPath []uint32,
|
internalKey *btcec.PublicKey, derivationPath []uint32,
|
||||||
rootHash []byte) {
|
rootHash []byte) {
|
||||||
@@ -1460,7 +1438,7 @@ func testScriptSchnorrSig(t *testing.T,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// newAddrWithScript returns a new address and its pkScript.
|
// 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) {
|
addrType lnrpc.AddressType) (btcutil.Address, []byte) {
|
||||||
|
|
||||||
p2wkhResp := node.RPC.NewAddress(&lnrpc.NewAddressRequest{
|
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
|
// sendToTaprootOutput sends coins to a p2tr output of the given taproot key and
|
||||||
// mines a block to confirm the coins.
|
// mines a block to confirm the coins.
|
||||||
func sendToTaprootOutput(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
func sendToTaprootOutput(ht *lntest.HarnessTest, hn *node.HarnessNode,
|
||||||
taprootKey *btcec.PublicKey, amt int64) (wire.OutPoint, []byte) {
|
taprootKey *btcec.PublicKey) (wire.OutPoint, []byte) {
|
||||||
|
|
||||||
tapScriptAddr, err := btcutil.NewAddressTaproot(
|
tapScriptAddr, err := btcutil.NewAddressTaproot(
|
||||||
schnorr.SerializePubKey(taprootKey), harnessNetParams,
|
schnorr.SerializePubKey(taprootKey), harnessNetParams,
|
||||||
@@ -1492,7 +1470,7 @@ func sendToTaprootOutput(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
|||||||
// Send some coins to the generated tapscript address.
|
// Send some coins to the generated tapscript address.
|
||||||
req := &lnrpc.SendCoinsRequest{
|
req := &lnrpc.SendCoinsRequest{
|
||||||
Addr: tapScriptAddr.String(),
|
Addr: tapScriptAddr.String(),
|
||||||
Amount: amt,
|
Amount: testAmount,
|
||||||
}
|
}
|
||||||
hn.RPC.SendCoins(req)
|
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
|
// after checking its weight against an estimate. After asserting the given
|
||||||
// spend request, the given sweep address' balance is verified to be seen as
|
// spend request, the given sweep address' balance is verified to be seen as
|
||||||
// funds belonging to the wallet.
|
// 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,
|
tx *wire.MsgTx, estimatedWeight int64,
|
||||||
spendRequest *chainrpc.SpendRequest, sweepAddr string) {
|
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
|
// confirmAddress makes sure that a transaction in the mempool spends funds to
|
||||||
// the given address. It also checks that a confirmation notification for the
|
// the given address. It also checks that a confirmation notification for the
|
||||||
// address is triggered when the transaction is mined.
|
// 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) {
|
addrString string) {
|
||||||
|
|
||||||
// Wait until the tx that sends to the address is found.
|
// 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,
|
// deriveSigningKeys derives three signing keys and returns their descriptors,
|
||||||
// as well as the public keys in the Schnorr serialized format.
|
// 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,
|
version signrpc.MuSig2Version) (*signrpc.KeyDescriptor,
|
||||||
*signrpc.KeyDescriptor, *signrpc.KeyDescriptor, [][]byte) {
|
*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
|
// 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
|
// participants but a separate key is generated for each session. So the result
|
||||||
// should be the same as if it were three different nodes.
|
// 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,
|
taprootTweak *signrpc.TaprootTweakDesc,
|
||||||
keyDesc1, keyDesc2, keyDesc3 *signrpc.KeyDescriptor,
|
keyDesc1, keyDesc2, keyDesc3 *signrpc.KeyDescriptor,
|
||||||
allPubKeys [][]byte, version signrpc.MuSig2Version) (*btcec.PublicKey,
|
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,
|
// testTaprootCoopClose asserts that if both peers signal ShutdownAnySegwit,
|
||||||
// then a taproot closing addr is used. Otherwise, we shouldn't expect one to
|
// then a taproot closing addr is used. Otherwise, we shouldn't expect one to
|
||||||
// be used.
|
// 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
|
// We'll start by making two new nodes, and funding a channel between
|
||||||
// them.
|
// them.
|
||||||
carol := ht.NewNode("Carol", nil)
|
carol := ht.NewNode("Carol", nil)
|
||||||
@@ -1853,7 +1831,7 @@ func testTaprootCoopClose(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// We'll now open a channel between Carol and Dave.
|
// We'll now open a channel between Carol and Dave.
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
carol, dave, lntemp.OpenChannelParams{
|
carol, dave, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
SatPerVByte: satPerVbyte,
|
SatPerVByte: satPerVbyte,
|
||||||
@@ -1888,7 +1866,7 @@ func testTaprootCoopClose(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// We'll now open up a chanel again between Carol and Eve.
|
// We'll now open up a chanel again between Carol and Eve.
|
||||||
chanPoint = ht.OpenChannel(
|
chanPoint = ht.OpenChannel(
|
||||||
carol, eve, lntemp.OpenChannelParams{
|
carol, eve, lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: pushAmt,
|
PushAmt: pushAmt,
|
||||||
SatPerVByte: satPerVbyte,
|
SatPerVByte: satPerVbyte,
|
||||||
@@ -1904,7 +1882,7 @@ func testTaprootCoopClose(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// testMuSig2CombineKey makes sure that combining a key with MuSig2 returns the
|
// testMuSig2CombineKey makes sure that combining a key with MuSig2 returns the
|
||||||
// correct result according to the MuSig2 version specified.
|
// 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) {
|
version signrpc.MuSig2Version) {
|
||||||
|
|
||||||
testVector040Key1 := hexDecode(
|
testVector040Key1 := hexDecode(
|
||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"math"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
@@ -11,9 +12,12 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/btcsuite/btcd/integration/rpctest"
|
"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"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
"google.golang.org/grpc/grpclog"
|
"google.golang.org/grpc/grpclog"
|
||||||
)
|
)
|
||||||
@@ -26,9 +30,25 @@ const (
|
|||||||
// defaultRunTranche is the default index of the test cases tranche that
|
// defaultRunTranche is the default index of the test cases tranche that
|
||||||
// we run.
|
// we run.
|
||||||
defaultRunTranche uint = 0
|
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 (
|
var (
|
||||||
|
harnessNetParams = &chaincfg.RegressionNetParams
|
||||||
|
|
||||||
// testCasesSplitParts is the number of tranches the test cases should
|
// testCasesSplitParts is the number of tranches the test cases should
|
||||||
// be split into. By default this is set to 1, so no splitting happens.
|
// 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
|
// If this value is increased, then the -runtranche flag must be
|
||||||
@@ -49,31 +69,32 @@ var (
|
|||||||
|
|
||||||
// dbBackendFlag specifies the backend to use.
|
// dbBackendFlag specifies the backend to use.
|
||||||
dbBackendFlag = flag.String("dbbackend", "bbolt", "Database backend "+
|
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
|
// TestLightningNetworkDaemon performs a series of integration tests amongst a
|
||||||
// amongst a programmatically driven network of lnd nodes.
|
// programmatically driven network of lnd nodes.
|
||||||
func TestLightningNetworkDaemonTemp(t *testing.T) {
|
func TestLightningNetworkDaemon(t *testing.T) {
|
||||||
if !*tempTest {
|
|
||||||
t.Skip("Running old tests, new tests are skipped")
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no tests are registered, then we can exit early.
|
// If no tests are registered, then we can exit early.
|
||||||
if len(allTestCasesTemp) == 0 {
|
if len(allTestCases) == 0 {
|
||||||
t.Skip("integration tests not selected with flag 'rpctest'")
|
t.Skip("integration tests not selected with flag 'integration'")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the test cases to be run in this tranche.
|
// Get the test cases to be run in this tranche.
|
||||||
testCases, trancheIndex, trancheOffset := getTestCaseSplitTranche()
|
testCases, trancheIndex, trancheOffset := getTestCaseSplitTranche()
|
||||||
lntest.ApplyPortOffset(uint32(trancheIndex) * 1000)
|
node.ApplyPortOffset(uint32(trancheIndex) * 1000)
|
||||||
|
|
||||||
// Create a simple fee service.
|
// Create a simple fee service.
|
||||||
feeService := lntemp.NewFeeService(t)
|
feeService := lntest.NewFeeService(t)
|
||||||
|
|
||||||
// Get the binary path and setup the harness test.
|
// Get the binary path and setup the harness test.
|
||||||
binary := getLndBinary(t)
|
binary := getLndBinary(t)
|
||||||
harnessTest := lntemp.SetupHarness(
|
harnessTest := lntest.SetupHarness(
|
||||||
t, binary, *dbBackendFlag, feeService,
|
t, binary, *dbBackendFlag, feeService,
|
||||||
)
|
)
|
||||||
defer harnessTest.Stop()
|
defer harnessTest.Stop()
|
||||||
@@ -126,12 +147,16 @@ func TestLightningNetworkDaemonTemp(t *testing.T) {
|
|||||||
break
|
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
|
// 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
|
// be run as the current split tranche as well as the index and slice offset of
|
||||||
// the tranche.
|
// the tranche.
|
||||||
func getTestCaseSplitTranche() ([]*lntemp.TestCase, uint, uint) {
|
func getTestCaseSplitTranche() ([]*lntest.TestCase, uint, uint) {
|
||||||
numTranches := defaultSplitTranches
|
numTranches := defaultSplitTranches
|
||||||
if testCasesSplitTranches != nil {
|
if testCasesSplitTranches != nil {
|
||||||
numTranches = *testCasesSplitTranches
|
numTranches = *testCasesSplitTranches
|
||||||
@@ -150,7 +175,7 @@ func getTestCaseSplitTranche() ([]*lntemp.TestCase, uint, uint) {
|
|||||||
runTranche = 0
|
runTranche = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
numCases := uint(len(allTestCasesTemp))
|
numCases := uint(len(allTestCases))
|
||||||
testsPerTranche := numCases / numTranches
|
testsPerTranche := numCases / numTranches
|
||||||
trancheOffset := runTranche * testsPerTranche
|
trancheOffset := runTranche * testsPerTranche
|
||||||
trancheEnd := trancheOffset + testsPerTranche
|
trancheEnd := trancheOffset + testsPerTranche
|
||||||
@@ -158,7 +183,7 @@ func getTestCaseSplitTranche() ([]*lntemp.TestCase, uint, uint) {
|
|||||||
trancheEnd = numCases
|
trancheEnd = numCases
|
||||||
}
|
}
|
||||||
|
|
||||||
return allTestCasesTemp[trancheOffset:trancheEnd], threadID,
|
return allTestCases[trancheOffset:trancheEnd], threadID,
|
||||||
trancheOffset
|
trancheOffset
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,7 +213,7 @@ func init() {
|
|||||||
// Before we start any node, we need to make sure that any btcd node
|
// 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
|
// that is started through the RPC harness uses a unique port as well
|
||||||
// to avoid any port collisions.
|
// 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
|
// Swap out grpc's default logger with out fake logger which drops the
|
||||||
// statements on the floor.
|
// statements on the floor.
|
||||||
@@ -7,17 +7,17 @@ import (
|
|||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
// testTrackPayments tests whether a client that calls the TrackPayments api
|
// testTrackPayments tests whether a client that calls the TrackPayments api
|
||||||
// receives payment updates.
|
// receives payment updates.
|
||||||
func testTrackPayments(ht *lntemp.HarnessTest) {
|
func testTrackPayments(ht *lntest.HarnessTest) {
|
||||||
// Open a channel between alice and bob.
|
// Open a channel between alice and bob.
|
||||||
alice, bob := ht.Alice, ht.Bob
|
alice, bob := ht.Alice, ht.Bob
|
||||||
channel := ht.OpenChannel(
|
channel := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{
|
alice, bob, lntest.OpenChannelParams{
|
||||||
Amt: btcutil.Amount(300000),
|
Amt: btcutil.Amount(300000),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -16,8 +16,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/funding"
|
"github.com/lightningnetwork/lnd/funding"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/stretchr/testify/require"
|
"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
|
// 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.
|
// 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 {
|
importedAccount string, addrType walletrpc.AddressType) string {
|
||||||
|
|
||||||
// We'll generate a new address for Carol from Dave's node to receive
|
// 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
|
// psbtSendFromImportedAccount attempts to fund a PSBT from the given imported
|
||||||
// account, originating from the source node to the destination.
|
// 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,
|
signer *node.HarnessNode, account string,
|
||||||
accountAddrType walletrpc.AddressType) {
|
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
|
// 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
|
// is made. Several balance assertions are made along the way for the sake of
|
||||||
// correctness.
|
// correctness.
|
||||||
func fundChanAndCloseFromImportedAccount(ht *lntemp.HarnessTest, srcNode,
|
func fundChanAndCloseFromImportedAccount(ht *lntest.HarnessTest, srcNode,
|
||||||
destNode, signer *node.HarnessNode, account string,
|
destNode, signer *node.HarnessNode, account string,
|
||||||
accountAddrType walletrpc.AddressType, utxoAmt, chanSize int64) {
|
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.
|
// The source node will then fund the channel through a PSBT shim.
|
||||||
pendingChanID := ht.Random32Bytes()
|
pendingChanID := ht.Random32Bytes()
|
||||||
chanUpdates, rawPsbt := ht.OpenChannelPsbt(
|
chanUpdates, rawPsbt := ht.OpenChannelPsbt(
|
||||||
srcNode, destNode, lntemp.OpenChannelParams{
|
srcNode, destNode, lntest.OpenChannelParams{
|
||||||
Amt: btcutil.Amount(chanSize),
|
Amt: btcutil.Amount(chanSize),
|
||||||
FundingShim: &lnrpc.FundingShim{
|
FundingShim: &lnrpc.FundingShim{
|
||||||
Shim: &lnrpc.FundingShim_PsbtShim{
|
Shim: &lnrpc.FundingShim_PsbtShim{
|
||||||
@@ -463,7 +463,7 @@ func fundChanAndCloseFromImportedAccount(ht *lntemp.HarnessTest, srcNode,
|
|||||||
// testWalletImportAccount tests that an imported account can fund transactions
|
// testWalletImportAccount tests that an imported account can fund transactions
|
||||||
// and channels through PSBTs, by having one node (the one with the imported
|
// and channels through PSBTs, by having one node (the one with the imported
|
||||||
// account) craft the transactions and another node act as the signer.
|
// account) craft the transactions and another node act as the signer.
|
||||||
func testWalletImportAccount(ht *lntemp.HarnessTest) {
|
func testWalletImportAccount(ht *lntest.HarnessTest) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
addrType walletrpc.AddressType
|
addrType walletrpc.AddressType
|
||||||
@@ -491,7 +491,7 @@ func testWalletImportAccount(ht *lntemp.HarnessTest) {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
success := ht.Run(tc.name, func(tt *testing.T) {
|
success := ht.Run(tc.name, func(tt *testing.T) {
|
||||||
testFunc := func(ht *lntemp.HarnessTest) {
|
testFunc := func(ht *lntest.HarnessTest) {
|
||||||
testWalletImportAccountScenario(
|
testWalletImportAccountScenario(
|
||||||
ht, tc.addrType,
|
ht, tc.addrType,
|
||||||
)
|
)
|
||||||
@@ -499,7 +499,7 @@ func testWalletImportAccount(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
st := ht.Subtest(tt)
|
st := ht.Subtest(tt)
|
||||||
|
|
||||||
st.RunTestCase(&lntemp.TestCase{
|
st.RunTestCase(&lntest.TestCase{
|
||||||
Name: tc.name,
|
Name: tc.name,
|
||||||
TestFunc: testFunc,
|
TestFunc: testFunc,
|
||||||
})
|
})
|
||||||
@@ -515,7 +515,7 @@ func testWalletImportAccount(ht *lntemp.HarnessTest) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testWalletImportAccountScenario(ht *lntemp.HarnessTest,
|
func testWalletImportAccountScenario(ht *lntest.HarnessTest,
|
||||||
addrType walletrpc.AddressType) {
|
addrType walletrpc.AddressType) {
|
||||||
|
|
||||||
// We'll start our test by having two nodes, Carol and Dave. Carol's
|
// 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)
|
runWalletImportAccountScenario(ht, addrType, carol, dave)
|
||||||
}
|
}
|
||||||
|
|
||||||
func runWalletImportAccountScenario(ht *lntemp.HarnessTest,
|
func runWalletImportAccountScenario(ht *lntest.HarnessTest,
|
||||||
addrType walletrpc.AddressType, carol, dave *node.HarnessNode) {
|
addrType walletrpc.AddressType, carol, dave *node.HarnessNode) {
|
||||||
|
|
||||||
const utxoAmt int64 = btcutil.SatoshiPerBitcoin
|
const utxoAmt int64 = btcutil.SatoshiPerBitcoin
|
||||||
@@ -619,7 +619,7 @@ func runWalletImportAccountScenario(ht *lntemp.HarnessTest,
|
|||||||
// testWalletImportPubKey tests that an imported public keys can fund
|
// testWalletImportPubKey tests that an imported public keys can fund
|
||||||
// transactions and channels through PSBTs, by having one node (the one with the
|
// 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.
|
// imported account) craft the transactions and another node act as the signer.
|
||||||
func testWalletImportPubKey(ht *lntemp.HarnessTest) {
|
func testWalletImportPubKey(ht *lntest.HarnessTest) {
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
addrType walletrpc.AddressType
|
addrType walletrpc.AddressType
|
||||||
@@ -642,7 +642,7 @@ func testWalletImportPubKey(ht *lntemp.HarnessTest) {
|
|||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
tc := tc
|
tc := tc
|
||||||
success := ht.Run(tc.name, func(tt *testing.T) {
|
success := ht.Run(tc.name, func(tt *testing.T) {
|
||||||
testFunc := func(ht *lntemp.HarnessTest) {
|
testFunc := func(ht *lntest.HarnessTest) {
|
||||||
testWalletImportPubKeyScenario(
|
testWalletImportPubKeyScenario(
|
||||||
ht, tc.addrType,
|
ht, tc.addrType,
|
||||||
)
|
)
|
||||||
@@ -650,7 +650,7 @@ func testWalletImportPubKey(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
st := ht.Subtest(tt)
|
st := ht.Subtest(tt)
|
||||||
|
|
||||||
st.RunTestCase(&lntemp.TestCase{
|
st.RunTestCase(&lntest.TestCase{
|
||||||
Name: tc.name,
|
Name: tc.name,
|
||||||
TestFunc: testFunc,
|
TestFunc: testFunc,
|
||||||
})
|
})
|
||||||
@@ -666,7 +666,7 @@ func testWalletImportPubKey(ht *lntemp.HarnessTest) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testWalletImportPubKeyScenario(ht *lntemp.HarnessTest,
|
func testWalletImportPubKeyScenario(ht *lntest.HarnessTest,
|
||||||
addrType walletrpc.AddressType) {
|
addrType walletrpc.AddressType) {
|
||||||
|
|
||||||
const utxoAmt int64 = btcutil.SatoshiPerBitcoin
|
const utxoAmt int64 = btcutil.SatoshiPerBitcoin
|
||||||
@@ -5,12 +5,10 @@ import (
|
|||||||
|
|
||||||
"github.com/lightningnetwork/lnd/chainreg"
|
"github.com/lightningnetwork/lnd/chainreg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
type pendingChan *lnrpc.PendingChannelsResponse_PendingChannel
|
|
||||||
|
|
||||||
// testWipeForwardingPackagesLocal tests that when a channel is closed, either
|
// testWipeForwardingPackagesLocal tests that when a channel is closed, either
|
||||||
// through local force close, remote close, or coop close, all the forwarding
|
// through local force close, remote close, or coop close, all the forwarding
|
||||||
// packages of that particular channel are deleted. The test creates a
|
// packages of that particular channel are deleted. The test creates a
|
||||||
@@ -21,7 +19,7 @@ type pendingChan *lnrpc.PendingChannelsResponse_PendingChannel
|
|||||||
// packages are wiped.
|
// packages are wiped.
|
||||||
// - Bob coop closes the channel Bob->Carol, and checks from both Bob PoVs
|
// - Bob coop closes the channel Bob->Carol, and checks from both Bob PoVs
|
||||||
// that the forwarding packages are wiped.
|
// that the forwarding packages are wiped.
|
||||||
func testWipeForwardingPackages(ht *lntemp.HarnessTest) {
|
func testWipeForwardingPackages(ht *lntest.HarnessTest) {
|
||||||
const (
|
const (
|
||||||
chanAmt = 10e6
|
chanAmt = 10e6
|
||||||
paymentAmt = 10e4
|
paymentAmt = 10e4
|
||||||
@@ -41,12 +39,12 @@ func testWipeForwardingPackages(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// Open a channel between Alice and Bob.
|
// Open a channel between Alice and Bob.
|
||||||
chanPointAB := ht.OpenChannel(
|
chanPointAB := ht.OpenChannel(
|
||||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
|
|
||||||
// Open a channel between Bob and Carol.
|
// Open a channel between Bob and Carol.
|
||||||
chanPointBC := ht.OpenChannel(
|
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
|
// Before we continue, make sure Alice has seen the channel between Bob
|
||||||
@@ -3,7 +3,7 @@ package itest
|
|||||||
import (
|
import (
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/funding"
|
"github.com/lightningnetwork/lnd/funding"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ import (
|
|||||||
// acceptances will allow a wumbo channel to be created. Additionally, if a
|
// 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
|
// node is running with mini channels only enabled, then they should reject any
|
||||||
// inbound wumbo channel requests.
|
// 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
|
// With all the channel types exercised, we'll now make sure the wumbo
|
||||||
// signalling support works properly.
|
// 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
|
// The test should indicate a failure due to the channel being too
|
||||||
// large.
|
// large.
|
||||||
ht.OpenChannelAssertErr(
|
ht.OpenChannelAssertErr(
|
||||||
wumboNode, miniNode, lntemp.OpenChannelParams{Amt: chanAmt},
|
wumboNode, miniNode, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
lnwallet.ErrChanTooLarge(chanAmt, funding.MaxBtcFundingAmount),
|
lnwallet.ErrChanTooLarge(chanAmt, funding.MaxBtcFundingAmount),
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ func testWumboChannels(ht *lntemp.HarnessTest) {
|
|||||||
// Creating a wumbo channel between these two nodes should succeed.
|
// Creating a wumbo channel between these two nodes should succeed.
|
||||||
ht.EnsureConnected(wumboNode, wumboNode2)
|
ht.EnsureConnected(wumboNode, wumboNode2)
|
||||||
chanPoint := ht.OpenChannel(
|
chanPoint := ht.OpenChannel(
|
||||||
wumboNode, wumboNode2, lntemp.OpenChannelParams{Amt: chanAmt},
|
wumboNode, wumboNode2, lntest.OpenChannelParams{Amt: chanAmt},
|
||||||
)
|
)
|
||||||
ht.CloseChannel(wumboNode, chanPoint)
|
ht.CloseChannel(wumboNode, chanPoint)
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -13,10 +13,9 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chainreg"
|
"github.com/lightningnetwork/lnd/chainreg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"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"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -24,7 +23,7 @@ import (
|
|||||||
|
|
||||||
// testZeroConfChannelOpen tests that opening a zero-conf channel works and
|
// testZeroConfChannelOpen tests that opening a zero-conf channel works and
|
||||||
// sending payments also works.
|
// 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
|
// 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
|
// not have the feature bit set. Also need to set anchors as those are
|
||||||
// default-off in itests.
|
// 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.
|
// We'll open a regular public channel between Bob and Carol here.
|
||||||
chanAmt := btcutil.Amount(1_000_000)
|
chanAmt := btcutil.Amount(1_000_000)
|
||||||
p := lntemp.OpenChannelParams{
|
p := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
}
|
}
|
||||||
chanPoint := ht.OpenChannel(bob, carol, p)
|
chanPoint := ht.OpenChannel(bob, carol, p)
|
||||||
@@ -59,7 +58,7 @@ func testZeroConfChannelOpen(ht *lntemp.HarnessTest) {
|
|||||||
go acceptChannel(ht.T, true, acceptStream)
|
go acceptChannel(ht.T, true, acceptStream)
|
||||||
|
|
||||||
// Open a private zero-conf anchors channel of 1M satoshis.
|
// Open a private zero-conf anchors channel of 1M satoshis.
|
||||||
params := lntemp.OpenChannelParams{
|
params := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
Private: true,
|
Private: true,
|
||||||
CommitmentType: lnrpc.CommitmentType_ANCHORS,
|
CommitmentType: lnrpc.CommitmentType_ANCHORS,
|
||||||
@@ -192,7 +191,7 @@ func testZeroConfChannelOpen(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// testOptionScidAlias checks that opening an option_scid_alias channel-type
|
// testOptionScidAlias checks that opening an option_scid_alias channel-type
|
||||||
// channel or w/o the channel-type works properly.
|
// channel or w/o the channel-type works properly.
|
||||||
func testOptionScidAlias(ht *lntemp.HarnessTest) {
|
func testOptionScidAlias(ht *lntest.HarnessTest) {
|
||||||
type scidTestCase struct {
|
type scidTestCase struct {
|
||||||
name string
|
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.
|
// Option-scid-alias is opt-in, as is anchors.
|
||||||
scidAliasArgs := []string{
|
scidAliasArgs := []string{
|
||||||
"--protocol.option-scid-alias",
|
"--protocol.option-scid-alias",
|
||||||
@@ -257,7 +256,7 @@ func optionScidAliasScenario(ht *lntemp.HarnessTest, chantype, private bool) {
|
|||||||
|
|
||||||
chanAmt := btcutil.Amount(1_000_000)
|
chanAmt := btcutil.Amount(1_000_000)
|
||||||
|
|
||||||
params := lntemp.OpenChannelParams{
|
params := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
Private: private,
|
Private: private,
|
||||||
CommitmentType: lnrpc.CommitmentType_ANCHORS,
|
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
|
// 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
|
// assert that Bob can pay Dave. We'll also assert that the invoice
|
||||||
// Dave issues has the startingAlias as a hop hint.
|
// Dave issues has the startingAlias as a hop hint.
|
||||||
p := lntemp.OpenChannelParams{
|
p := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
}
|
}
|
||||||
fundingPoint2 := ht.OpenChannel(bob, carol, p)
|
fundingPoint2 := ht.OpenChannel(bob, carol, p)
|
||||||
@@ -313,6 +312,7 @@ func optionScidAliasScenario(ht *lntemp.HarnessTest, chantype, private bool) {
|
|||||||
require.Len(ht, decodedReq.RouteHints, 0)
|
require.Len(ht, decodedReq.RouteHints, 0)
|
||||||
payReq := daveInvoiceResp2.PaymentRequest
|
payReq := daveInvoiceResp2.PaymentRequest
|
||||||
ht.CompletePaymentRequests(bob, []string{payReq})
|
ht.CompletePaymentRequests(bob, []string{payReq})
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,7 +410,7 @@ func waitForZeroConfGraphChange(hn *node.HarnessNode,
|
|||||||
// testUpdateChannelPolicyScidAlias checks that option-scid-alias, zero-conf
|
// testUpdateChannelPolicyScidAlias checks that option-scid-alias, zero-conf
|
||||||
// channel-types, and option-scid-alias feature-bit-only channels have the
|
// channel-types, and option-scid-alias feature-bit-only channels have the
|
||||||
// expected graph and that payments work when updating the channel policy.
|
// expected graph and that payments work when updating the channel policy.
|
||||||
func testUpdateChannelPolicyScidAlias(ht *lntemp.HarnessTest) {
|
func testUpdateChannelPolicyScidAlias(ht *lntest.HarnessTest) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
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) {
|
zeroConf, scidAliasType, private bool) {
|
||||||
|
|
||||||
// We'll create a new node Eve that will not have option-scid-alias
|
// 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)
|
chanAmt := btcutil.Amount(1_000_000)
|
||||||
|
|
||||||
p := lntemp.OpenChannelParams{
|
p := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: chanAmt / 2,
|
PushAmt: chanAmt / 2,
|
||||||
}
|
}
|
||||||
@@ -509,7 +509,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
|||||||
go acceptChannel(ht.T, zeroConf, acceptStream)
|
go acceptChannel(ht.T, zeroConf, acceptStream)
|
||||||
|
|
||||||
// Open a private channel, optionally specifying a channel-type.
|
// Open a private channel, optionally specifying a channel-type.
|
||||||
params := lntemp.OpenChannelParams{
|
params := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
Private: private,
|
Private: private,
|
||||||
CommitmentType: lnrpc.CommitmentType_ANCHORS,
|
CommitmentType: lnrpc.CommitmentType_ANCHORS,
|
||||||
@@ -542,7 +542,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
|||||||
FeeRateMilliMsat: testFeeBase * feeRate,
|
FeeRateMilliMsat: testFeeBase * feeRate,
|
||||||
TimeLockDelta: timeLockDelta,
|
TimeLockDelta: timeLockDelta,
|
||||||
MinHtlc: 1000, // default value
|
MinHtlc: 1000, // default value
|
||||||
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
|
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert that Dave receives Carol's policy update.
|
// Assert that Dave receives Carol's policy update.
|
||||||
@@ -568,7 +568,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
|||||||
FeeRateMilliMsat: testFeeBase * feeRate,
|
FeeRateMilliMsat: testFeeBase * feeRate,
|
||||||
TimeLockDelta: timeLockDelta,
|
TimeLockDelta: timeLockDelta,
|
||||||
MinHtlc: 1000,
|
MinHtlc: 1000,
|
||||||
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
|
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert that Carol receives Dave's policy update.
|
// Assert that Carol receives Dave's policy update.
|
||||||
@@ -655,7 +655,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
|||||||
FeeRateMilliMsat: testFeeBase * feeRate,
|
FeeRateMilliMsat: testFeeBase * feeRate,
|
||||||
TimeLockDelta: timeLockDelta,
|
TimeLockDelta: timeLockDelta,
|
||||||
MinHtlc: 1000,
|
MinHtlc: 1000,
|
||||||
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
|
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert Dave receives Carol's policy update.
|
// Assert Dave receives Carol's policy update.
|
||||||
@@ -744,7 +744,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
|||||||
FeeRateMilliMsat: testFeeBase * feeRate,
|
FeeRateMilliMsat: testFeeBase * feeRate,
|
||||||
TimeLockDelta: timeLockDelta,
|
TimeLockDelta: timeLockDelta,
|
||||||
MinHtlc: 1000,
|
MinHtlc: 1000,
|
||||||
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
|
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Assert Dave and optionally Eve receives Carol's update.
|
// 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
|
// testOptionScidUpgrade tests that toggling the option-scid-alias feature bit
|
||||||
// correctly upgrades existing channels.
|
// correctly upgrades existing channels.
|
||||||
func testOptionScidUpgrade(ht *lntemp.HarnessTest) {
|
func testOptionScidUpgrade(ht *lntest.HarnessTest) {
|
||||||
bob := ht.Bob
|
bob := ht.Bob
|
||||||
|
|
||||||
// Start carol with anchors only.
|
// Start carol with anchors only.
|
||||||
@@ -788,7 +788,7 @@ func testOptionScidUpgrade(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
chanAmt := btcutil.Amount(1_000_000)
|
chanAmt := btcutil.Amount(1_000_000)
|
||||||
|
|
||||||
p := lntemp.OpenChannelParams{
|
p := lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
PushAmt: chanAmt / 2,
|
PushAmt: chanAmt / 2,
|
||||||
Private: true,
|
Private: true,
|
||||||
@@ -798,7 +798,7 @@ func testOptionScidUpgrade(ht *lntemp.HarnessTest) {
|
|||||||
// Bob will open a channel to Carol now.
|
// Bob will open a channel to Carol now.
|
||||||
ht.EnsureConnected(bob, carol)
|
ht.EnsureConnected(bob, carol)
|
||||||
|
|
||||||
p = lntemp.OpenChannelParams{
|
p = lntest.OpenChannelParams{
|
||||||
Amt: chanAmt,
|
Amt: chanAmt,
|
||||||
}
|
}
|
||||||
fundingPoint2 := ht.OpenChannel(bob, carol, p)
|
fundingPoint2 := ht.OpenChannel(bob, carol, p)
|
||||||
@@ -822,25 +822,34 @@ func testOptionScidUpgrade(ht *lntemp.HarnessTest) {
|
|||||||
var startingAlias lnwire.ShortChannelID
|
var startingAlias lnwire.ShortChannelID
|
||||||
startingAlias.BlockHeight = 16_000_000
|
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)
|
invoiceResp := dave.RPC.AddInvoice(daveParams)
|
||||||
decodedReq := dave.RPC.DecodePayReq(invoiceResp.PaymentRequest)
|
decodedReq := dave.RPC.DecodePayReq(invoiceResp.PaymentRequest)
|
||||||
|
|
||||||
if len(decodedReq.RouteHints) != 1 {
|
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 {
|
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
|
hopHint := decodedReq.RouteHints[0].HopHints[0].ChanId
|
||||||
if startingAlias.ToUint64() == hopHint {
|
if startingAlias.ToUint64() == hopHint {
|
||||||
daveInvoice = invoiceResp
|
daveInvoice = invoiceResp
|
||||||
return true
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return fmt.Errorf("unmatched alias, expected %v, got %v",
|
||||||
|
startingAlias.ToUint64(), hopHint)
|
||||||
}, defaultTimeout)
|
}, defaultTimeout)
|
||||||
require.NoError(ht, err)
|
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
|
// 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
|
// be deleted from the channel graph. This was previously the case due to logic
|
||||||
// in the function DisconnectBlockAtHeight.
|
// in the function DisconnectBlockAtHeight.
|
||||||
func testZeroConfReorg(ht *lntemp.HarnessTest) {
|
func testZeroConfReorg(ht *lntest.HarnessTest) {
|
||||||
if ht.ChainBackendName() == lntest.NeutrinoBackendName {
|
if ht.IsNeutrinoBackend() {
|
||||||
ht.Skipf("skipping zero-conf reorg test for neutrino backend")
|
ht.Skipf("skipping zero-conf reorg test for neutrino backend")
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var temp = "temp"
|
||||||
ctxb = context.Background()
|
|
||||||
temp = "temp"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Since zero-conf is opt in, the harness nodes provided won't be able
|
// 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.
|
// 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)
|
go acceptChannel(ht.T, true, acceptStream)
|
||||||
|
|
||||||
// Open a private zero-conf anchors channel of 1M satoshis.
|
// Open a private zero-conf anchors channel of 1M satoshis.
|
||||||
params := lntemp.OpenChannelParams{
|
params := lntest.OpenChannelParams{
|
||||||
Amt: btcutil.Amount(1_000_000),
|
Amt: btcutil.Amount(1_000_000),
|
||||||
CommitmentType: lnrpc.CommitmentType_ANCHORS,
|
CommitmentType: lnrpc.CommitmentType_ANCHORS,
|
||||||
ZeroConf: true,
|
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 now attempt to query for the alias SCID in Carol's graph.
|
||||||
// We will query for the starting alias, which is exported by the
|
// We will query for the starting alias, which is exported by the
|
||||||
// aliasmgr package.
|
// aliasmgr package.
|
||||||
_, err := carol.RPC.LN.GetChanInfo(ctxb, &lnrpc.ChanInfoRequest{
|
carol.RPC.GetChanInfo(&lnrpc.ChanInfoRequest{
|
||||||
ChanId: aliasmgr.StartingAlias.ToUint64(),
|
ChanId: aliasmgr.StartingAlias.ToUint64(),
|
||||||
})
|
})
|
||||||
require.NoError(ht.T, err)
|
|
||||||
|
|
||||||
// Now we will trigger a reorg and we'll assert that the edge still
|
// Now we will trigger a reorg and we'll assert that the edge still
|
||||||
// exists in the graph.
|
// 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.
|
// First, we'll setup a new miner that we can use to cause a reorg.
|
||||||
tempLogDir := ".tempminerlogs"
|
tempLogDir := ".tempminerlogs"
|
||||||
logFilename := "output-open_channel_reorg-temp_miner.log"
|
logFilename := "output-open_channel_reorg-temp_miner.log"
|
||||||
tempMiner := lntemp.NewTempMiner(
|
tempMiner := lntest.NewTempMiner(
|
||||||
ht.Context(), ht.T, tempLogDir, logFilename,
|
ht.Context(), ht.T, tempLogDir, logFilename,
|
||||||
)
|
)
|
||||||
defer tempMiner.Stop()
|
defer tempMiner.Stop()
|
||||||
@@ -971,7 +976,7 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
// We start by connecting the new miner to our original miner, such
|
// We start by connecting the new miner to our original miner, such
|
||||||
// that it will sync to our original chain.
|
// that it will sync to our original chain.
|
||||||
err = ht.Miner.Client.Node(
|
err := ht.Miner.Client.Node(
|
||||||
btcjson.NConnect, tempMiner.P2PAddress(), &temp,
|
btcjson.NConnect, tempMiner.P2PAddress(), &temp,
|
||||||
)
|
)
|
||||||
require.NoError(ht.T, err, "unable to connect node")
|
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")
|
require.NoError(ht.T, err, "unable to remove node")
|
||||||
|
|
||||||
// We now cause a fork, by letting our original miner mine 1 block and
|
// We now cause a fork, by letting our original miner mine 1 block and
|
||||||
// our new miner will mine 2.
|
// our new miner will mine 2. We also expect the funding transition to
|
||||||
ht.MineBlocks(1)
|
// be mined.
|
||||||
_, err = tempMiner.Client.Generate(2)
|
ht.MineBlocksAndAssertNumTxes(1, 1)
|
||||||
require.NoError(ht.T, err, "unable to generate blocks")
|
tempMiner.MineEmptyBlocks(2)
|
||||||
|
|
||||||
// Ensure the temp miner is one block ahead.
|
// Ensure the temp miner is one block ahead.
|
||||||
assertMinerBlockHeightDelta(ht, ht.Miner, tempMiner, 1)
|
assertMinerBlockHeightDelta(ht, ht.Miner, tempMiner, 1)
|
||||||
|
|
||||||
// Wait for Carol to sync to the original miner's chain.
|
// Wait for Carol to sync to the original miner's chain.
|
||||||
_, minerHeight, err := ht.Miner.Client.GetBestBlock()
|
_, minerHeight := ht.Miner.GetBestBlock()
|
||||||
require.NoError(ht.T, err, "unable to get current blockheight")
|
|
||||||
|
|
||||||
ht.WaitForNodeBlockHeight(carol, minerHeight)
|
ht.WaitForNodeBlockHeight(carol, minerHeight)
|
||||||
|
|
||||||
// Now we'll disconnect Carol's chain backend from the original miner
|
// Now we'll disconnect Carol's chain backend from the original miner
|
||||||
@@ -1033,24 +1036,19 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
|
|||||||
|
|
||||||
ht.ConnectMiner()
|
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.
|
// chain.
|
||||||
_, tempMinerHeight, err := tempMiner.Client.GetBestBlock()
|
_, tempMinerHeight := tempMiner.GetBestBlock()
|
||||||
require.NoError(ht.T, err, "unable to get current blockheight")
|
|
||||||
|
|
||||||
ht.WaitForNodeBlockHeight(carol, tempMinerHeight)
|
ht.WaitForNodeBlockHeight(carol, tempMinerHeight)
|
||||||
|
|
||||||
err = wait.Predicate(func() bool {
|
// Make sure all active nodes are synced.
|
||||||
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
|
ht.AssertActiveNodesSynced()
|
||||||
|
|
||||||
_, err = carol.RPC.LN.GetChanInfo(ctxt, &lnrpc.ChanInfoRequest{
|
// Carol should have the channel once synced.
|
||||||
ChanId: aliasmgr.StartingAlias.ToUint64(),
|
carol.RPC.GetChanInfo(&lnrpc.ChanInfoRequest{
|
||||||
})
|
ChanId: aliasmgr.StartingAlias.ToUint64(),
|
||||||
|
})
|
||||||
return err == nil
|
|
||||||
}, defaultTimeout)
|
|
||||||
require.NoError(ht.T, err, "carol doesn't have zero-conf edge")
|
|
||||||
|
|
||||||
// Mine the zero-conf funding transaction so the test doesn't fail.
|
// Mine the zero-conf funding transaction so the test doesn't fail.
|
||||||
ht.MineBlocks(1)
|
ht.MineBlocksAndAssertNumTxes(1, 1)
|
||||||
}
|
}
|
||||||
File renamed without changes.
File renamed without changes.
@@ -1,6 +1,3 @@
|
|||||||
//go:build !rpctest
|
|
||||||
// +build !rpctest
|
|
||||||
|
|
||||||
package lncfg
|
package lncfg
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|||||||
+1
-2
@@ -1,5 +1,4 @@
|
|||||||
//go:build !rpctest
|
//go:build !integration
|
||||||
// +build !rpctest
|
|
||||||
|
|
||||||
package lncfg
|
package lncfg
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
//go:build rpctest
|
//go:build integration
|
||||||
// +build rpctest
|
|
||||||
|
|
||||||
package lncfg
|
package lncfg
|
||||||
|
|
||||||
@@ -7,6 +6,8 @@ package lncfg
|
|||||||
// compatibility of protocol additions, while defaulting to the latest within
|
// compatibility of protocol additions, while defaulting to the latest within
|
||||||
// lnd, or to enable experimental protocol changes.
|
// lnd, or to enable experimental protocol changes.
|
||||||
//
|
//
|
||||||
|
// TODO(yy): delete this build flag to unify with `lncfg/protocol.go`.
|
||||||
|
//
|
||||||
//nolint:lll
|
//nolint:lll
|
||||||
type ProtocolOptions struct {
|
type ProtocolOptions struct {
|
||||||
// LegacyProtocol is a sub-config that houses all the legacy protocol
|
// LegacyProtocol is a sub-config that houses all the legacy protocol
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
@@ -93,3 +93,24 @@ making a new test case using `Subtest`, there’s a cleanup function which
|
|||||||
further validates the current test case has no dangling uncleaned states, such
|
further validates the current test case has no dangling uncleaned states, such
|
||||||
as transactions left in mempool, open channels, etc.
|
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.
|
||||||
@@ -14,6 +14,7 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/btcsuite/btcd/rpcclient"
|
"github.com/btcsuite/btcd/rpcclient"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
)
|
)
|
||||||
|
|
||||||
// logDirPattern is the pattern of the name of the temporary log directory.
|
// 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
|
// A compile time assertion to ensure BitcoindBackendConfig meets the
|
||||||
// BackendConfig interface.
|
// BackendConfig interface.
|
||||||
var _ BackendConfig = (*BitcoindBackendConfig)(nil)
|
var _ node.BackendConfig = (*BitcoindBackendConfig)(nil)
|
||||||
|
|
||||||
// GenArgs returns the arguments needed to be passed to LND at startup for
|
// GenArgs returns the arguments needed to be passed to LND at startup for
|
||||||
// using this node as a chain backend.
|
// 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,
|
func newBackend(miner string, netParams *chaincfg.Params, extraArgs []string,
|
||||||
rpcPolling bool) (*BitcoindBackendConfig, func() error, error) {
|
rpcPolling bool) (*BitcoindBackendConfig, func() error, error) {
|
||||||
|
|
||||||
baseLogDir := fmt.Sprintf(logDirPattern, GetLogDir())
|
baseLogDir := fmt.Sprintf(logDirPattern, node.GetLogDir())
|
||||||
if netParams != &chaincfg.RegressionNetParams {
|
if netParams != &chaincfg.RegressionNetParams {
|
||||||
return nil, nil, fmt.Errorf("only regtest supported")
|
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)
|
fmt.Errorf("unable to create temp directory: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
zmqBlockAddr := fmt.Sprintf("tcp://127.0.0.1:%d", NextAvailablePort())
|
zmqBlockAddr := fmt.Sprintf("tcp://127.0.0.1:%d",
|
||||||
zmqTxAddr := fmt.Sprintf("tcp://127.0.0.1:%d", NextAvailablePort())
|
node.NextAvailablePort())
|
||||||
rpcPort := NextAvailablePort()
|
zmqTxAddr := fmt.Sprintf("tcp://127.0.0.1:%d",
|
||||||
p2pPort := NextAvailablePort()
|
node.NextAvailablePort())
|
||||||
|
rpcPort := node.NextAvailablePort()
|
||||||
|
p2pPort := node.NextAvailablePort()
|
||||||
|
|
||||||
cmdArgs := []string{
|
cmdArgs := []string{
|
||||||
"-datadir=" + tempBitcoindDir,
|
"-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
|
// After shutting down the chain backend, we'll make a copy of
|
||||||
// the log file before deleting the temporary log dir.
|
// the log file before deleting the temporary log dir.
|
||||||
logDestination := fmt.Sprintf(
|
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 {
|
if err != nil {
|
||||||
errStr += fmt.Sprintf("unable to copy file: %v\n", err)
|
errStr += fmt.Sprintf("unable to copy file: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-11
@@ -15,6 +15,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/btcsuite/btcd/integration/rpctest"
|
"github.com/btcsuite/btcd/integration/rpctest"
|
||||||
"github.com/btcsuite/btcd/rpcclient"
|
"github.com/btcsuite/btcd/rpcclient"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
)
|
)
|
||||||
|
|
||||||
// logDirPattern is the pattern of the name of the temporary log directory.
|
// 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
|
// A compile time assertion to ensure BtcdBackendConfig meets the BackendConfig
|
||||||
// interface.
|
// interface.
|
||||||
var _ BackendConfig = (*BtcdBackendConfig)(nil)
|
var _ node.BackendConfig = (*BtcdBackendConfig)(nil)
|
||||||
|
|
||||||
// GenArgs returns the arguments needed to be passed to LND at startup for
|
// GenArgs returns the arguments needed to be passed to LND at startup for
|
||||||
// using this node as a chain backend.
|
// using this node as a chain backend.
|
||||||
@@ -83,7 +84,7 @@ func (b BtcdBackendConfig) Name() string {
|
|||||||
func NewBackend(miner string, netParams *chaincfg.Params) (
|
func NewBackend(miner string, netParams *chaincfg.Params) (
|
||||||
*BtcdBackendConfig, func() error, error) {
|
*BtcdBackendConfig, func() error, error) {
|
||||||
|
|
||||||
baseLogDir := fmt.Sprintf(logDirPattern, GetLogDir())
|
baseLogDir := fmt.Sprintf(logDirPattern, node.GetLogDir())
|
||||||
args := []string{
|
args := []string{
|
||||||
"--rejectnonstd",
|
"--rejectnonstd",
|
||||||
"--txindex",
|
"--txindex",
|
||||||
@@ -98,9 +99,12 @@ func NewBackend(miner string, netParams *chaincfg.Params) (
|
|||||||
// Don't disconnect if a reply takes too long.
|
// Don't disconnect if a reply takes too long.
|
||||||
"--nostalldetect",
|
"--nostalldetect",
|
||||||
}
|
}
|
||||||
chainBackend, err := rpctest.New(netParams, nil, args, GetBtcdBinary())
|
chainBackend, err := rpctest.New(
|
||||||
|
netParams, nil, args, node.GetBtcdBinary(),
|
||||||
|
)
|
||||||
if err != nil {
|
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
|
// 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
|
// are already blocks present, which will take a bit longer than the
|
||||||
// 1 second the default settings amount to. Doubling both values will
|
// 1 second the default settings amount to. Doubling both values will
|
||||||
// give us retries up to 4 seconds.
|
// give us retries up to 4 seconds.
|
||||||
chainBackend.MaxConnRetries = rpctest.DefaultMaxConnectionRetries * 2
|
const (
|
||||||
chainBackend.ConnectionRetryTimeout = rpctest.DefaultConnectionRetryTimeout * 2
|
maxConnRetries = rpctest.DefaultMaxConnectionRetries * 2
|
||||||
|
connRetryTimeout = rpctest.DefaultConnectionRetryTimeout * 2
|
||||||
|
)
|
||||||
|
|
||||||
|
chainBackend.MaxConnRetries = maxConnRetries
|
||||||
|
chainBackend.ConnectionRetryTimeout = connRetryTimeout
|
||||||
|
|
||||||
if err := chainBackend.SetUp(false, 0); err != nil {
|
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{
|
bd := &BtcdBackendConfig{
|
||||||
@@ -141,14 +151,16 @@ func NewBackend(miner string, netParams *chaincfg.Params) (
|
|||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
logFile := fmt.Sprintf("%s/%s", logDir, file.Name())
|
logFile := fmt.Sprintf("%s/%s", logDir, file.Name())
|
||||||
newFilename := strings.Replace(
|
newFilename := strings.Replace(
|
||||||
file.Name(), "btcd.log", "output_btcd_chainbackend.log", 1,
|
file.Name(), "btcd.log",
|
||||||
|
"output_btcd_chainbackend.log", 1,
|
||||||
)
|
)
|
||||||
logDestination := fmt.Sprintf(
|
logDestination := fmt.Sprintf(
|
||||||
"%s/%s", GetLogDir(), newFilename,
|
"%s/%s", node.GetLogDir(), newFilename,
|
||||||
)
|
)
|
||||||
err := CopyFile(logDestination, logFile)
|
err := node.CopyFile(logDestination, logFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errStr += fmt.Sprintf("unable to copy file: %v\n", err)
|
errStr += fmt.Sprintf("unable to copy file: "+
|
||||||
|
"%v\n", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+76
-46
@@ -9,45 +9,72 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"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 (
|
const (
|
||||||
// feeServiceTarget is the confirmation target for which a fee estimate
|
// feeServiceTarget is the confirmation target for which a fee estimate
|
||||||
// is returned. Requests for higher confirmation targets will fall back
|
// is returned. Requests for higher confirmation targets will fall back
|
||||||
// to this.
|
// to this.
|
||||||
feeServiceTarget = 1
|
feeServiceTarget = 1
|
||||||
|
|
||||||
|
// DefaultFeeRateSatPerKw specifies the default fee rate used in the
|
||||||
|
// tests.
|
||||||
|
DefaultFeeRateSatPerKw = 12500
|
||||||
)
|
)
|
||||||
|
|
||||||
// feeService runs a web service that provides fee estimation information.
|
// FeeService runs a web service that provides fee estimation information.
|
||||||
type feeService struct {
|
type FeeService struct {
|
||||||
feeEstimates
|
*testing.T
|
||||||
|
|
||||||
t *testing.T
|
feeRateMap map[uint32]uint32
|
||||||
|
url string
|
||||||
srv *http.Server
|
|
||||||
wg sync.WaitGroup
|
|
||||||
|
|
||||||
url string
|
|
||||||
|
|
||||||
|
srv *http.Server
|
||||||
|
wg sync.WaitGroup
|
||||||
lock sync.Mutex
|
lock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
// feeEstimates contains the current fee estimates.
|
// Compile-time check for the WebFeeService interface.
|
||||||
type feeEstimates struct {
|
var _ WebFeeService = (*FeeService)(nil)
|
||||||
Fees map[uint32]uint32 `json:"fee_by_block_target"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// startFeeService spins up a go-routine to serve fee estimates.
|
// Start spins up a go-routine to serve fee estimates.
|
||||||
func startFeeService(t *testing.T) *feeService {
|
func NewFeeService(t *testing.T) *FeeService {
|
||||||
port := NextAvailablePort()
|
t.Helper()
|
||||||
f := feeService{
|
|
||||||
t: t,
|
port := node.NextAvailablePort()
|
||||||
url: fmt.Sprintf("http://localhost:%v/fee-estimates.json", port),
|
f := FeeService{
|
||||||
|
T: t,
|
||||||
|
url: fmt.Sprintf(
|
||||||
|
"http://localhost:%v/fee-estimates.json", port,
|
||||||
|
),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize default fee estimate.
|
// Initialize default fee estimate.
|
||||||
f.Fees = map[uint32]uint32{feeServiceTarget: 50000}
|
f.feeRateMap = map[uint32]uint32{
|
||||||
|
feeServiceTarget: DefaultFeeRateSatPerKw,
|
||||||
|
}
|
||||||
|
|
||||||
listenAddr := fmt.Sprintf(":%v", port)
|
listenAddr := fmt.Sprintf(":%v", port)
|
||||||
mux := http.NewServeMux()
|
mux := http.NewServeMux()
|
||||||
@@ -58,57 +85,60 @@ func startFeeService(t *testing.T) *feeService {
|
|||||||
Handler: mux,
|
Handler: mux,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return &f
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start starts the web server.
|
||||||
|
func (f *FeeService) Start() error {
|
||||||
f.wg.Add(1)
|
f.wg.Add(1)
|
||||||
go func() {
|
go func() {
|
||||||
defer f.wg.Done()
|
defer f.wg.Done()
|
||||||
|
|
||||||
if err := f.srv.ListenAndServe(); err != http.ErrServerClosed {
|
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.
|
// 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()
|
f.lock.Lock()
|
||||||
defer f.lock.Unlock()
|
defer f.lock.Unlock()
|
||||||
|
|
||||||
bytes, err := json.Marshal(f.feeEstimates)
|
bytes, err := json.Marshal(
|
||||||
if err != nil {
|
struct {
|
||||||
f.t.Errorf("error: cannot serialize estimates: %v", err)
|
Fees map[uint32]uint32 `json:"fee_by_block_target"`
|
||||||
|
}{
|
||||||
return
|
Fees: f.feeRateMap,
|
||||||
}
|
},
|
||||||
|
)
|
||||||
|
require.NoErrorf(f, err, "cannot serialize estimates")
|
||||||
|
|
||||||
_, err = io.WriteString(w, string(bytes))
|
_, err = io.WriteString(w, string(bytes))
|
||||||
if err != nil {
|
require.NoError(f, err, "cannot send estimates")
|
||||||
f.t.Errorf("error: cannot send estimates: %v", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// stop stops the web server.
|
// Stop stops the web server.
|
||||||
func (f *feeService) stop() {
|
func (f *FeeService) Stop() error {
|
||||||
if err := f.srv.Shutdown(context.Background()); err != nil {
|
err := f.srv.Shutdown(context.Background())
|
||||||
f.t.Errorf("error: cannot stop fee api: %v", err)
|
require.NoError(f, err, "cannot stop fee api")
|
||||||
}
|
|
||||||
|
|
||||||
f.wg.Wait()
|
f.wg.Wait()
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// setFee changes the current fee estimate for the fixed confirmation target.
|
// SetFeeRate sets a fee for the given confirmation target.
|
||||||
func (f *feeService) setFee(fee chainfee.SatPerKWeight) {
|
func (f *FeeService) SetFeeRate(fee chainfee.SatPerKWeight, conf uint32) {
|
||||||
f.lock.Lock()
|
f.lock.Lock()
|
||||||
defer f.lock.Unlock()
|
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.
|
// URL returns the service endpoint.
|
||||||
func (f *feeService) setFeeWithConf(fee chainfee.SatPerKWeight, conf uint32) {
|
func (f *FeeService) URL() string {
|
||||||
f.lock.Lock()
|
return f.url
|
||||||
defer f.lock.Unlock()
|
|
||||||
|
|
||||||
f.Fees[conf] = uint32(fee.FeePerKVByte())
|
|
||||||
}
|
}
|
||||||
@@ -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),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package lntemp
|
package lntest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -17,9 +17,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@@ -38,6 +37,10 @@ const (
|
|||||||
// numBlocksOpenChannel specifies the number of blocks mined when
|
// numBlocksOpenChannel specifies the number of blocks mined when
|
||||||
// opening a channel.
|
// opening a channel.
|
||||||
numBlocksOpenChannel = 6
|
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.
|
// 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
|
// 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
|
// node needs to quit, and used as the parent context when spawning
|
||||||
// children contexts for RPC requests.
|
// children contexts for RPC requests.
|
||||||
runCtx context.Context
|
runCtx context.Context //nolint:containedctx
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
|
||||||
// stopChainBackend points to the cleanup function returned by the
|
// 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
|
// NewHarnessTest creates a new instance of a harnessTest from a regular
|
||||||
// testing.T instance.
|
// testing.T instance.
|
||||||
func NewHarnessTest(t *testing.T, lndBinary string, feeService WebFeeService,
|
func NewHarnessTest(t *testing.T, lndBinary string, feeService WebFeeService,
|
||||||
dbBackend lntest.DatabaseBackend) *HarnessTest {
|
dbBackend node.DatabaseBackend) *HarnessTest {
|
||||||
|
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
// Create the run context.
|
// Create the run context.
|
||||||
ctxt, cancel := context.WithCancel(context.Background())
|
ctxt, cancel := context.WithCancel(context.Background())
|
||||||
|
|
||||||
manager := newNodeManager(lndBinary, dbBackend)
|
manager := newNodeManager(lndBinary, dbBackend)
|
||||||
|
|
||||||
return &HarnessTest{
|
return &HarnessTest{
|
||||||
T: t,
|
T: t,
|
||||||
manager: manager,
|
manager: manager,
|
||||||
@@ -114,7 +120,7 @@ func NewHarnessTest(t *testing.T, lndBinary string, feeService WebFeeService,
|
|||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
// We need to use buffered channel here as we don't want to
|
// We need to use buffered channel here as we don't want to
|
||||||
// block sending errors.
|
// 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.Alice = h.NewNode("Alice", lndArgs)
|
||||||
h.Bob = h.NewNode("Bob", 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{
|
addrReq := &lnrpc.NewAddressRequest{
|
||||||
Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH,
|
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.
|
// each.
|
||||||
nodes := []*node.HarnessNode{h.Alice, h.Bob}
|
nodes := []*node.HarnessNode{h.Alice, h.Bob}
|
||||||
for _, hn := range nodes {
|
for _, hn := range nodes {
|
||||||
h.manager.standbyNodes[hn.Cfg.NodeID] = hn
|
h.manager.standbyNodes[hn.Cfg.NodeID] = hn
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 100; i++ {
|
||||||
resp := hn.RPC.NewAddress(addrReq)
|
resp := hn.RPC.NewAddress(addrReq)
|
||||||
|
|
||||||
addr, err := btcutil.DecodeAddress(
|
addr, err := btcutil.DecodeAddress(
|
||||||
@@ -207,7 +210,7 @@ func (h *HarnessTest) SetupStandbyNodes() {
|
|||||||
|
|
||||||
output := &wire.TxOut{
|
output := &wire.TxOut{
|
||||||
PkScript: addrScript,
|
PkScript: addrScript,
|
||||||
Value: 10 * btcutil.SatoshiPerBitcoin,
|
Value: initialFund,
|
||||||
}
|
}
|
||||||
h.Miner.SendOutput(output, defaultMinerFeeRate)
|
h.Miner.SendOutput(output, defaultMinerFeeRate)
|
||||||
}
|
}
|
||||||
@@ -215,7 +218,7 @@ func (h *HarnessTest) SetupStandbyNodes() {
|
|||||||
|
|
||||||
// We generate several blocks in order to give the outputs created
|
// We generate several blocks in order to give the outputs created
|
||||||
// above a good number of confirmations.
|
// above a good number of confirmations.
|
||||||
const totalTxes = 20
|
const totalTxes = 200
|
||||||
h.MineBlocksAndAssertNumTxes(numBlocksSendOutput, totalTxes)
|
h.MineBlocksAndAssertNumTxes(numBlocksSendOutput, totalTxes)
|
||||||
|
|
||||||
// Now we want to wait for the nodes to catch up.
|
// Now we want to wait for the nodes to catch up.
|
||||||
@@ -223,7 +226,7 @@ func (h *HarnessTest) SetupStandbyNodes() {
|
|||||||
h.WaitForBlockchainSync(h.Bob)
|
h.WaitForBlockchainSync(h.Bob)
|
||||||
|
|
||||||
// Now block until both wallets have fully synced up.
|
// Now block until both wallets have fully synced up.
|
||||||
expectedBalance := int64(btcutil.SatoshiPerBitcoin * 100)
|
const expectedBalance = 100 * initialFund
|
||||||
err := wait.NoError(func() error {
|
err := wait.NoError(func() error {
|
||||||
aliceResp := h.Alice.RPC.WalletBalance()
|
aliceResp := h.Alice.RPC.WalletBalance()
|
||||||
bobResp := h.Bob.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
|
// resetStandbyNodes resets all standby nodes by attaching the new testing.T
|
||||||
// and restarting them with the original config.
|
// and restarting them with the original config.
|
||||||
func (h *HarnessTest) resetStandbyNodes(t *testing.T) {
|
func (h *HarnessTest) resetStandbyNodes(t *testing.T) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
for _, hn := range h.manager.standbyNodes {
|
for _, hn := range h.manager.standbyNodes {
|
||||||
// Inherit the testing.T.
|
// Inherit the testing.T.
|
||||||
h.T = t
|
h.T = t
|
||||||
@@ -313,7 +318,7 @@ func (h *HarnessTest) Subtest(t *testing.T) *HarnessTest {
|
|||||||
Miner: h.Miner,
|
Miner: h.Miner,
|
||||||
standbyNodes: h.standbyNodes,
|
standbyNodes: h.standbyNodes,
|
||||||
feeService: h.feeService,
|
feeService: h.feeService,
|
||||||
lndErrorChan: make(chan error, 10),
|
lndErrorChan: make(chan error, lndErrorChanSize),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inherit context from the main test.
|
// 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.
|
// Don't bother run the cleanups if the test is failed.
|
||||||
if st.Failed() {
|
if st.Failed() {
|
||||||
st.Log("test failed, skipped cleanup")
|
st.Log("test failed, skipped cleanup")
|
||||||
|
st.shutdownAllNodes()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -381,10 +387,21 @@ func (h *HarnessTest) Subtest(t *testing.T) *HarnessTest {
|
|||||||
|
|
||||||
// shutdownNonStandbyNodes will shutdown any non-standby nodes.
|
// shutdownNonStandbyNodes will shutdown any non-standby nodes.
|
||||||
func (h *HarnessTest) shutdownNonStandbyNodes() {
|
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 {
|
for nid, node := range h.manager.activeNodes {
|
||||||
// If it's a standby node, skip.
|
// If it's a standby node, skip.
|
||||||
_, ok := h.manager.standbyNodes[nid]
|
_, ok := h.manager.standbyNodes[nid]
|
||||||
if ok {
|
if ok && skipStandby {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -394,7 +411,11 @@ func (h *HarnessTest) shutdownNonStandbyNodes() {
|
|||||||
err := wait.NoError(func() error {
|
err := wait.NoError(func() error {
|
||||||
return h.manager.shutdownNode(node)
|
return h.manager.shutdownNode(node)
|
||||||
}, DefaultTimeout)
|
}, 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 {
|
leaderSessionTTL int) *node.HarnessNode {
|
||||||
|
|
||||||
// We don't want to use the embedded etcd instance.
|
// We don't want to use the embedded etcd instance.
|
||||||
h.manager.dbBackend = lntest.BackendBbolt
|
h.manager.dbBackend = node.BackendBbolt
|
||||||
|
|
||||||
extraArgs := node.ExtraArgsEtcd(
|
extraArgs := node.ExtraArgsEtcd(
|
||||||
etcdCfg, name, cluster, leaderSessionTTL,
|
etcdCfg, name, cluster, leaderSessionTTL,
|
||||||
@@ -659,7 +680,7 @@ func (h *HarnessTest) NewNodeWithSeedEtcd(name string, etcdCfg *etcd.Config,
|
|||||||
leaderSessionTTL int) (*node.HarnessNode, []string, []byte) {
|
leaderSessionTTL int) (*node.HarnessNode, []string, []byte) {
|
||||||
|
|
||||||
// We don't want to use the embedded etcd instance.
|
// 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
|
// Create a request to generate a new aezeed. The new seed will have
|
||||||
// the same password as the internal wallet.
|
// 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
|
// transaction to be broadcast, then wait for the closing tx to be seen
|
||||||
// within the network.
|
// within the network.
|
||||||
event, err := h.ReceiveCloseChannelUpdate(stream)
|
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)
|
pendingClose, ok := event.Update.(*lnrpc.CloseStatusUpdate_ClosePending)
|
||||||
require.Truef(h, ok, "expected channel close update, instead got %v",
|
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) {
|
send := func(payReq string) {
|
||||||
req := &routerrpc.SendPaymentRequest{
|
req := &routerrpc.SendPaymentRequest{
|
||||||
PaymentRequest: payReq,
|
PaymentRequest: payReq,
|
||||||
TimeoutSeconds: defaultPaymentTimeout,
|
TimeoutSeconds: int32(wait.PaymentTimeout.Seconds()),
|
||||||
FeeLimitMsat: noFeeLimitMsat,
|
FeeLimitMsat: noFeeLimitMsat,
|
||||||
}
|
}
|
||||||
stream := hn.RPC.SendPayment(req)
|
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.
|
// Wait for all payments to report the expected status.
|
||||||
timer := time.After(DefaultTimeout)
|
timer := time.After(wait.PaymentTimeout)
|
||||||
select {
|
select {
|
||||||
case stream := <-results:
|
case stream := <-results:
|
||||||
h.AssertPaymentStatusFromStream(stream, status)
|
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
|
// The commit sweep resolver is able to broadcast the sweep tx up to
|
||||||
// one block before the CSV elapses, so wait until defaulCSV-1.
|
// 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
|
// The node should now sweep the funds, clean up by mining the sweeping
|
||||||
// tx.
|
// tx.
|
||||||
@@ -1686,7 +1719,7 @@ func (h *HarnessTest) OpenMultiChannelsAsync(
|
|||||||
case cp := <-r.result:
|
case cp := <-r.result:
|
||||||
channelPoints = append(channelPoints, cp)
|
channelPoints = append(channelPoints, cp)
|
||||||
|
|
||||||
case <-time.After(lntest.ChannelOpenTimeout):
|
case <-time.After(wait.ChannelOpenTimeout):
|
||||||
require.Failf(h, "timeout", "wait channel point "+
|
require.Failf(h, "timeout", "wait channel point "+
|
||||||
"timeout for channel %s=>%s", r.Local.Name(),
|
"timeout for channel %s=>%s", r.Local.Name(),
|
||||||
r.Remote.Name())
|
r.Remote.Name())
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package lntemp
|
package lntest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -23,8 +23,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lntypes"
|
"github.com/lightningnetwork/lnd/lntypes"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -38,6 +38,7 @@ func (h *HarnessTest) WaitForBlockchainSync(hn *node.HarnessNode) {
|
|||||||
if resp.SyncedToChain {
|
if resp.SyncedToChain {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Errorf("%s is not synced to chain", hn.Name())
|
return fmt.Errorf("%s is not synced to chain", hn.Name())
|
||||||
}, DefaultTimeout)
|
}, DefaultTimeout)
|
||||||
|
|
||||||
@@ -145,6 +146,12 @@ func (h *HarnessTest) EnsureConnected(a, b *node.HarnessNode) {
|
|||||||
// connected to the peer.
|
// connected to the peer.
|
||||||
errConnectionRequested := "connection request in progress"
|
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 {
|
tryConnect := func(a, b *node.HarnessNode) error {
|
||||||
bInfo := b.RPC.GetInfo()
|
bInfo := b.RPC.GetInfo()
|
||||||
|
|
||||||
@@ -165,17 +172,21 @@ func (h *HarnessTest) EnsureConnected(a, b *node.HarnessNode) {
|
|||||||
return nil
|
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
|
// If the two are already connected, we return early with no
|
||||||
// error.
|
// error.
|
||||||
if strings.Contains(err.Error(), "already connected to peer") {
|
if strings.Contains(err.Error(), "already connected to peer") {
|
||||||
return nil
|
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
|
// We may get connection refused error if we happens to be in
|
||||||
// the middle of a previous node disconnection, e.g., a restart
|
// the middle of a previous node disconnection, e.g., a restart
|
||||||
// from one of the nodes.
|
// from one of the nodes.
|
||||||
@@ -183,6 +194,16 @@ func (h *HarnessTest) EnsureConnected(a, b *node.HarnessNode) {
|
|||||||
return nil
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,8 +252,10 @@ func (h *HarnessTest) AssertNumEdges(hn *node.HarnessNode,
|
|||||||
// slice.
|
// slice.
|
||||||
edges = chanGraph.Edges[old:]
|
edges = chanGraph.Edges[old:]
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return errNumNotMatched(hn.Name(), "num of channel edges",
|
return errNumNotMatched(hn.Name(), "num of channel edges",
|
||||||
expected, total-old, total, old)
|
expected, total-old, total, old)
|
||||||
}, DefaultTimeout)
|
}, DefaultTimeout)
|
||||||
@@ -925,7 +948,9 @@ func (h *HarnessTest) AssertNodesNumPendingOpenChannels(a, b *node.HarnessNode,
|
|||||||
func (h *HarnessTest) AssertPaymentStatusFromStream(stream rpc.PaymentClient,
|
func (h *HarnessTest) AssertPaymentStatusFromStream(stream rpc.PaymentClient,
|
||||||
status lnrpc.Payment_PaymentStatus) *lnrpc.Payment {
|
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
|
// AssertPaymentSucceedWithTimeout asserts that a payment is succeeded within
|
||||||
@@ -1166,7 +1191,9 @@ func (h *HarnessTest) AssertActiveHtlcs(hn *node.HarnessNode,
|
|||||||
h := hex.EncodeToString(htlc.HashLock)
|
h := hex.EncodeToString(htlc.HashLock)
|
||||||
_, ok := htlcHashes[h]
|
_, ok := htlcHashes[h]
|
||||||
if ok {
|
if ok {
|
||||||
return fmt.Errorf("duplicate HashLock")
|
return fmt.Errorf("duplicate HashLock "+
|
||||||
|
"in PendingHtlcs: %v",
|
||||||
|
ch.PendingHtlcs)
|
||||||
}
|
}
|
||||||
htlcHashes[h] = struct{}{}
|
htlcHashes[h] = struct{}{}
|
||||||
}
|
}
|
||||||
@@ -1732,7 +1759,8 @@ func (h *HarnessTest) AssertNumPayments(hn *node.HarnessNode,
|
|||||||
return errNumNotMatched(hn.Name(), "num of payments",
|
return errNumNotMatched(hn.Name(), "num of payments",
|
||||||
num, len(payments), have+len(payments), have)
|
num, len(payments), have+len(payments), have)
|
||||||
}, DefaultTimeout)
|
}, DefaultTimeout)
|
||||||
require.NoError(h, err, "timeout checking num of payments")
|
require.NoError(h, err, "%s: timeout checking num of payments",
|
||||||
|
hn.Name())
|
||||||
|
|
||||||
return payments
|
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
|
// We will get the current number of channel updates first and add it
|
||||||
// to our expected number of newly created channel updates.
|
// to our expected number of newly created channel updates.
|
||||||
anns, err := hn.Watcher.WaitForNumNodeUpdates(pubkey, num)
|
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
|
return anns
|
||||||
}
|
}
|
||||||
@@ -1757,7 +1786,8 @@ func (h *HarnessTest) AssertNumChannelUpdates(hn *node.HarnessNode,
|
|||||||
|
|
||||||
op := h.OutPointFromChannelPoint(chanPoint)
|
op := h.OutPointFromChannelPoint(chanPoint)
|
||||||
err := hn.Watcher.WaitForNumChannelUpdates(op, num)
|
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.
|
// CreateBurnAddr creates a random burn address of the given type.
|
||||||
+350
-56
@@ -1,18 +1,26 @@
|
|||||||
package lntest
|
package lntest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/btcjson"
|
||||||
|
"github.com/btcsuite/btcd/btcutil"
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/integration/rpctest"
|
"github.com/btcsuite/btcd/integration/rpctest"
|
||||||
"github.com/btcsuite/btcd/rpcclient"
|
"github.com/btcsuite/btcd/rpcclient"
|
||||||
|
"github.com/btcsuite/btcd/wire"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -21,16 +29,21 @@ const (
|
|||||||
|
|
||||||
// minerLogDir is the default log dir for the miner node.
|
// minerLogDir is the default log dir for the miner node.
|
||||||
minerLogDir = ".minerlogs"
|
minerLogDir = ".minerlogs"
|
||||||
|
|
||||||
|
// slowMineDelay defines a wait period between mining new blocks.
|
||||||
|
slowMineDelay = 100 * time.Millisecond
|
||||||
)
|
)
|
||||||
|
|
||||||
var harnessNetParams = &chaincfg.RegressionNetParams
|
var harnessNetParams = &chaincfg.RegressionNetParams
|
||||||
|
|
||||||
type HarnessMiner struct {
|
type HarnessMiner struct {
|
||||||
|
*testing.T
|
||||||
*rpctest.Harness
|
*rpctest.Harness
|
||||||
|
|
||||||
// runCtx is a context with cancel method. It's used to signal when the
|
// 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
|
// 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
|
cancel context.CancelFunc
|
||||||
|
|
||||||
// logPath is the directory path of the miner's logs.
|
// 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
|
// NewMiner creates a new miner using btcd backend with the default log file
|
||||||
// dir and name.
|
// dir and name.
|
||||||
func NewMiner() (*HarnessMiner, error) {
|
func NewMiner(ctxt context.Context, t *testing.T) *HarnessMiner {
|
||||||
return newMiner(minerLogDir, minerLogFilename)
|
t.Helper()
|
||||||
|
return newMiner(ctxt, t, minerLogDir, minerLogFilename)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewTempMiner creates a new miner using btcd backend with the specified log
|
// NewTempMiner creates a new miner using btcd backend with the specified log
|
||||||
// file dir and name.
|
// file dir and name.
|
||||||
func NewTempMiner(tempDir, tempLogFilename string) (*HarnessMiner, error) {
|
func NewTempMiner(ctxt context.Context, t *testing.T,
|
||||||
return newMiner(tempDir, tempLogFilename)
|
tempDir, tempLogFilename string) *HarnessMiner {
|
||||||
|
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
return newMiner(ctxt, t, tempDir, tempLogFilename)
|
||||||
}
|
}
|
||||||
|
|
||||||
// newMiner creates a new miner using btcd's rpctest.
|
// 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{}
|
handler := &rpcclient.NotificationHandlers{}
|
||||||
btcdBinary := GetBtcdBinary()
|
btcdBinary := node.GetBtcdBinary()
|
||||||
baseLogPath := fmt.Sprintf("%s/%s", GetLogDir(), minerDirName)
|
baseLogPath := fmt.Sprintf("%s/%s", node.GetLogDir(), minerDirName)
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"--rejectnonstd",
|
"--rejectnonstd",
|
||||||
@@ -71,42 +93,28 @@ func newMiner(minerDirName, logFilename string) (*HarnessMiner, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
miner, err := rpctest.New(harnessNetParams, handler, args, btcdBinary)
|
miner, err := rpctest.New(harnessNetParams, handler, args, btcdBinary)
|
||||||
if err != nil {
|
require.NoError(t, err, "unable to create mining node")
|
||||||
return nil, fmt.Errorf("unable to create mining node: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctxt, cancel := context.WithCancel(context.Background())
|
ctxt, cancel := context.WithCancel(ctxb)
|
||||||
m := &HarnessMiner{
|
|
||||||
|
return &HarnessMiner{
|
||||||
|
T: t,
|
||||||
Harness: miner,
|
Harness: miner,
|
||||||
runCtx: ctxt,
|
runCtx: ctxt,
|
||||||
cancel: cancel,
|
cancel: cancel,
|
||||||
logPath: baseLogPath,
|
logPath: baseLogPath,
|
||||||
logFilename: logFilename,
|
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
|
// saveLogs copies the node logs and save it to the file specified by
|
||||||
// h.logFilename.
|
// 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
|
// After shutting down the miner, we'll make a copy of the log files
|
||||||
// before deleting the temporary log dir.
|
// before deleting the temporary log dir.
|
||||||
path := fmt.Sprintf("%s/%s", h.logPath, harnessNetParams.Name)
|
path := fmt.Sprintf("%s/%s", h.logPath, harnessNetParams.Name)
|
||||||
files, err := ioutil.ReadDir(path)
|
files, err := ioutil.ReadDir(path)
|
||||||
if err != nil {
|
require.NoError(h, err, "unable to read log directory")
|
||||||
return fmt.Errorf("unable to read log directory: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, file := range files {
|
for _, file := range files {
|
||||||
newFilename := strings.Replace(
|
newFilename := strings.Replace(
|
||||||
@@ -116,46 +124,332 @@ func (h *HarnessMiner) saveLogs() error {
|
|||||||
|
|
||||||
logFile := fmt.Sprintf("%s/%s", path, file.Name())
|
logFile := fmt.Sprintf("%s/%s", path, file.Name())
|
||||||
err := CopyFile(filepath.Clean(copyPath), logFile)
|
err := CopyFile(filepath.Clean(copyPath), logFile)
|
||||||
if err != nil {
|
require.NoError(h, err, "unable to copy file")
|
||||||
return fmt.Errorf("unable to copy file: %v", err)
|
}
|
||||||
|
|
||||||
|
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 {
|
require.Failf(h, "tx was not included in block", "tx:%v, block has:%v",
|
||||||
return fmt.Errorf("cannot remove dir %s: %v", h.logPath, err)
|
txid, blockTxes)
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// waitForTxInMempool blocks until the target txid is seen in the mempool. If
|
// MineBlocksAndAssertNumTxes mine 'num' of blocks and check that blocks are
|
||||||
// the transaction isn't seen within the network before the passed timeout,
|
// present in node blockchain. numTxs should be set to the number of
|
||||||
// then an error is returned.
|
// transactions (excluding the coinbase) we expect to be included in the first
|
||||||
func (h *HarnessMiner) waitForTxInMempool(txid chainhash.Hash) error {
|
// mined block.
|
||||||
ticker := time.NewTicker(50 * time.Millisecond)
|
func (h *HarnessMiner) MineBlocksAndAssertNumTxes(num uint32,
|
||||||
defer ticker.Stop()
|
numTxs int) []*wire.MsgBlock {
|
||||||
|
|
||||||
var mempool []*chainhash.Hash
|
// If we expect transactions to be included in the blocks we'll mine,
|
||||||
for {
|
// we wait here until they are seen in the miner's mempool.
|
||||||
select {
|
txids := h.AssertNumTxsInMempool(numTxs)
|
||||||
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)
|
|
||||||
|
|
||||||
case <-ticker.C:
|
// Mine blocks.
|
||||||
var err error
|
blocks := h.MineBlocks(num)
|
||||||
mempool, err = h.Client.GetRawMempool()
|
|
||||||
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, mempoolTx := range mempool {
|
msgTx = tx.MsgTx()
|
||||||
if *mempoolTx == txid {
|
for _, txIn := range msgTx.TxIn {
|
||||||
|
if txIn.PreviousOutPoint == op {
|
||||||
return nil
|
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
@@ -1,4 +1,4 @@
|
|||||||
package lntemp
|
package lntest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -8,8 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,7 +29,7 @@ type nodeManager struct {
|
|||||||
lndBinary string
|
lndBinary string
|
||||||
|
|
||||||
// dbBackend sets the database backend to use.
|
// dbBackend sets the database backend to use.
|
||||||
dbBackend lntest.DatabaseBackend
|
dbBackend node.DatabaseBackend
|
||||||
|
|
||||||
// activeNodes is a map of all running nodes, format:
|
// activeNodes is a map of all running nodes, format:
|
||||||
// {pubkey: *HarnessNode}.
|
// {pubkey: *HarnessNode}.
|
||||||
@@ -50,7 +49,7 @@ type nodeManager struct {
|
|||||||
|
|
||||||
// newNodeManager creates a new node manager instance.
|
// newNodeManager creates a new node manager instance.
|
||||||
func newNodeManager(lndBinary string,
|
func newNodeManager(lndBinary string,
|
||||||
dbBackend lntest.DatabaseBackend) *nodeManager {
|
dbBackend node.DatabaseBackend) *nodeManager {
|
||||||
|
|
||||||
return &nodeManager{
|
return &nodeManager{
|
||||||
lndBinary: lndBinary,
|
lndBinary: lndBinary,
|
||||||
@@ -80,7 +79,7 @@ func (nm *nodeManager) newNode(t *testing.T, name string, extraArgs []string,
|
|||||||
BackendCfg: nm.chainBackend,
|
BackendCfg: nm.chainBackend,
|
||||||
ExtraArgs: extraArgs,
|
ExtraArgs: extraArgs,
|
||||||
FeeURL: nm.feeServiceURL,
|
FeeURL: nm.feeServiceURL,
|
||||||
DbBackend: nm.dbBackend,
|
DBBackend: nm.dbBackend,
|
||||||
NodeID: nm.nextNodeID(),
|
NodeID: nm.nextNodeID(),
|
||||||
LndBinary: nm.lndBinary,
|
LndBinary: nm.lndBinary,
|
||||||
NetParams: harnessNetParams,
|
NetParams: harnessNetParams,
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package lntemp
|
package lntest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/integration/rpctest"
|
"github.com/btcsuite/btcd/integration/rpctest"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -23,11 +23,11 @@ func SetupHarness(t *testing.T, binaryPath, dbBackendName string,
|
|||||||
t.Log("Setting up HarnessTest...")
|
t.Log("Setting up HarnessTest...")
|
||||||
|
|
||||||
// Parse testing flags that influence our test execution.
|
// 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")
|
require.NoError(t, os.MkdirAll(logDir, 0700), "create log dir failed")
|
||||||
|
|
||||||
// Parse database backend
|
// Parse database backend
|
||||||
dbBackend := prepareDbBackend(t, dbBackendName)
|
dbBackend := prepareDBBackend(t, dbBackendName)
|
||||||
|
|
||||||
// Create a new HarnessTest.
|
// Create a new HarnessTest.
|
||||||
ht := NewHarnessTest(t, binaryPath, feeService, dbBackend)
|
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.
|
// prepareChainBackend creates a new chain backend.
|
||||||
func prepareChainBackend(t *testing.T,
|
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,
|
minerAddr, harnessNetParams,
|
||||||
)
|
)
|
||||||
require.NoError(t, err, "new backend")
|
require.NoError(t, err, "new backend")
|
||||||
@@ -94,23 +94,23 @@ func prepareChainBackend(t *testing.T,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepareDbBackend parses a DatabaseBackend based on the name given.
|
// prepareDBBackend parses a DatabaseBackend based on the name given.
|
||||||
func prepareDbBackend(t *testing.T,
|
func prepareDBBackend(t *testing.T,
|
||||||
dbBackendName string) lntest.DatabaseBackend {
|
dbBackendName string) node.DatabaseBackend {
|
||||||
|
|
||||||
var dbBackend lntest.DatabaseBackend
|
var dbBackend node.DatabaseBackend
|
||||||
switch dbBackendName {
|
switch dbBackendName {
|
||||||
case "bbolt":
|
case "bbolt":
|
||||||
dbBackend = lntest.BackendBbolt
|
dbBackend = node.BackendBbolt
|
||||||
|
|
||||||
case "etcd":
|
case "etcd":
|
||||||
dbBackend = lntest.BackendEtcd
|
dbBackend = node.BackendEtcd
|
||||||
|
|
||||||
case "postgres":
|
case "postgres":
|
||||||
dbBackend = lntest.BackendPostgres
|
dbBackend = node.BackendPostgres
|
||||||
|
|
||||||
case "sqlite":
|
case "sqlite":
|
||||||
dbBackend = lntest.BackendSqlite
|
dbBackend = node.BackendSqlite
|
||||||
|
|
||||||
default:
|
default:
|
||||||
require.Fail(t, "unknown db backend")
|
require.Fail(t, "unknown db backend")
|
||||||
File diff suppressed because it is too large.
Load diff
@@ -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{}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
//go:build !rpctest
|
|
||||||
// +build !rpctest
|
|
||||||
|
|
||||||
package itest
|
|
||||||
|
|
||||||
var allTestCases = []*testCase{}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
//go:build rpctest
|
|
||||||
// +build rpctest
|
|
||||||
|
|
||||||
package itest
|
|
||||||
|
|
||||||
var allTestCases = []*testCase{
|
|
||||||
{
|
|
||||||
name: "async bidirectional payments",
|
|
||||||
test: testBidirectionalAsyncPayments,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
@@ -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)
|
|
||||||
}
|
|
||||||
@@ -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
|
|
||||||
}
|
|
||||||
+2
-1
@@ -7,6 +7,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
|
"github.com/lightningnetwork/lnd/lntest/node"
|
||||||
)
|
)
|
||||||
|
|
||||||
// NeutrinoBackendConfig is an implementation of the BackendConfig interface
|
// NeutrinoBackendConfig is an implementation of the BackendConfig interface
|
||||||
@@ -17,7 +18,7 @@ type NeutrinoBackendConfig struct {
|
|||||||
|
|
||||||
// A compile time assertion to ensure NeutrinoBackendConfig meets the
|
// A compile time assertion to ensure NeutrinoBackendConfig meets the
|
||||||
// BackendConfig interface.
|
// BackendConfig interface.
|
||||||
var _ BackendConfig = (*NeutrinoBackendConfig)(nil)
|
var _ node.BackendConfig = (*NeutrinoBackendConfig)(nil)
|
||||||
|
|
||||||
// GenArgs returns the arguments needed to be passed to LND at startup for
|
// GenArgs returns the arguments needed to be passed to LND at startup for
|
||||||
// using this node as a chain backend.
|
// using this node as a chain backend.
|
||||||
|
|||||||
@@ -1,20 +1,63 @@
|
|||||||
package node
|
package node
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/chaincfg"
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
"github.com/lightningnetwork/lnd/chanbackup"
|
"github.com/lightningnetwork/lnd/chanbackup"
|
||||||
"github.com/lightningnetwork/lnd/kvdb/etcd"
|
"github.com/lightningnetwork/lnd/kvdb/etcd"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// ListenerFormat is the format string that is used to generate local
|
// ListenerFormat is the format string that is used to generate local
|
||||||
// listener addresses.
|
// listener addresses.
|
||||||
ListenerFormat = "127.0.0.1:%d"
|
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.
|
// Option is a function for updating a node's configuration.
|
||||||
@@ -73,7 +116,7 @@ type BaseNodeConfig struct {
|
|||||||
|
|
||||||
FeeURL string
|
FeeURL string
|
||||||
|
|
||||||
DbBackend lntest.DatabaseBackend
|
DBBackend DatabaseBackend
|
||||||
PostgresDsn string
|
PostgresDsn string
|
||||||
|
|
||||||
// NodeID is a unique ID used to identify the node.
|
// NodeID is a unique ID used to identify the node.
|
||||||
@@ -83,12 +126,12 @@ type BaseNodeConfig struct {
|
|||||||
// compiled with all required itest flags.
|
// compiled with all required itest flags.
|
||||||
LndBinary string
|
LndBinary string
|
||||||
|
|
||||||
// backupDbDir is the path where a database backup is stored, if any.
|
// backupDBDir is the path where a database backup is stored, if any.
|
||||||
backupDbDir string
|
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.
|
// is stored in.
|
||||||
postgresDbName string
|
postgresDBName string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cfg BaseNodeConfig) P2PAddr() string {
|
func (cfg BaseNodeConfig) P2PAddr() string {
|
||||||
@@ -126,16 +169,16 @@ func (cfg BaseNodeConfig) ChanBackupPath() string {
|
|||||||
// current lightning network test.
|
// current lightning network test.
|
||||||
func (cfg *BaseNodeConfig) GenerateListeningPorts() {
|
func (cfg *BaseNodeConfig) GenerateListeningPorts() {
|
||||||
if cfg.P2PPort == 0 {
|
if cfg.P2PPort == 0 {
|
||||||
cfg.P2PPort = lntest.NextAvailablePort()
|
cfg.P2PPort = NextAvailablePort()
|
||||||
}
|
}
|
||||||
if cfg.RPCPort == 0 {
|
if cfg.RPCPort == 0 {
|
||||||
cfg.RPCPort = lntest.NextAvailablePort()
|
cfg.RPCPort = NextAvailablePort()
|
||||||
}
|
}
|
||||||
if cfg.RESTPort == 0 {
|
if cfg.RESTPort == 0 {
|
||||||
cfg.RESTPort = lntest.NextAvailablePort()
|
cfg.RESTPort = NextAvailablePort()
|
||||||
}
|
}
|
||||||
if cfg.ProfilePort == 0 {
|
if cfg.ProfilePort == 0 {
|
||||||
cfg.ProfilePort = lntest.NextAvailablePort()
|
cfg.ProfilePort = NextAvailablePort()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -169,8 +212,7 @@ func (cfg *BaseNodeConfig) GenArgs() []string {
|
|||||||
"--accept-keysend",
|
"--accept-keysend",
|
||||||
"--keep-failed-payment-attempts",
|
"--keep-failed-payment-attempts",
|
||||||
fmt.Sprintf("--db.batch-commit-interval=%v", commitInterval),
|
fmt.Sprintf("--db.batch-commit-interval=%v", commitInterval),
|
||||||
fmt.Sprintf("--bitcoin.defaultremotedelay=%v",
|
fmt.Sprintf("--bitcoin.defaultremotedelay=%v", DefaultCSV),
|
||||||
lntest.DefaultCSV),
|
|
||||||
fmt.Sprintf("--rpclisten=%v", cfg.RPCAddr()),
|
fmt.Sprintf("--rpclisten=%v", cfg.RPCAddr()),
|
||||||
fmt.Sprintf("--restlisten=%v", cfg.RESTAddr()),
|
fmt.Sprintf("--restlisten=%v", cfg.RESTAddr()),
|
||||||
fmt.Sprintf("--restcors=https://%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("--invoicemacaroonpath=%v", cfg.InvoiceMacPath),
|
||||||
fmt.Sprintf("--trickledelay=%v", trickleDelay),
|
fmt.Sprintf("--trickledelay=%v", trickleDelay),
|
||||||
fmt.Sprintf("--profile=%d", cfg.ProfilePort),
|
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
|
// Use a small batch window so we can broadcast our sweep
|
||||||
// transactions faster.
|
// transactions faster.
|
||||||
@@ -191,27 +232,32 @@ func (cfg *BaseNodeConfig) GenArgs() []string {
|
|||||||
// Use a small batch delay so we can broadcast the
|
// Use a small batch delay so we can broadcast the
|
||||||
// announcements quickly in the tests.
|
// announcements quickly in the tests.
|
||||||
"--gossip.sub-batch-delay=5ms",
|
"--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...)
|
args = append(args, nodeArgs...)
|
||||||
|
|
||||||
if cfg.Password == nil {
|
if cfg.Password == nil {
|
||||||
args = append(args, "--noseedbackup")
|
args = append(args, "--noseedbackup")
|
||||||
}
|
}
|
||||||
|
|
||||||
switch cfg.DbBackend {
|
switch cfg.DBBackend {
|
||||||
case lntest.BackendEtcd:
|
case BackendEtcd:
|
||||||
args = append(args, "--db.backend=etcd")
|
args = append(args, "--db.backend=etcd")
|
||||||
args = append(args, "--db.etcd.embedded")
|
args = append(args, "--db.etcd.embedded")
|
||||||
args = append(
|
args = append(
|
||||||
args, fmt.Sprintf(
|
args, fmt.Sprintf(
|
||||||
"--db.etcd.embedded_client_port=%v",
|
"--db.etcd.embedded_client_port=%v",
|
||||||
lntest.NextAvailablePort(),
|
NextAvailablePort(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
args = append(
|
args = append(
|
||||||
args, fmt.Sprintf(
|
args, fmt.Sprintf(
|
||||||
"--db.etcd.embedded_peer_port=%v",
|
"--db.etcd.embedded_peer_port=%v",
|
||||||
lntest.NextAvailablePort(),
|
NextAvailablePort(),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
args = append(
|
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.backend=postgres")
|
||||||
args = append(args, "--db.postgres.dsn="+cfg.PostgresDsn)
|
args = append(args, "--db.postgres.dsn="+cfg.PostgresDsn)
|
||||||
|
|
||||||
case lntest.BackendSqlite:
|
case BackendSqlite:
|
||||||
args = append(args, "--db.backend=sqlite")
|
args = append(args, "--db.backend=sqlite")
|
||||||
args = append(args, fmt.Sprintf("--db.sqlite.busytimeout=%v",
|
args = append(args, fmt.Sprintf("--db.sqlite.busytimeout=%v",
|
||||||
lntest.SqliteBusyTimeout))
|
wait.SqliteBusyTimeout))
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.FeeURL != "" {
|
if cfg.FeeURL != "" {
|
||||||
@@ -272,3 +318,86 @@ func ExtraArgsEtcd(etcdCfg *etcd.Config, name string, cluster bool,
|
|||||||
|
|
||||||
return extraArgs
|
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)
|
||||||
|
}
|
||||||
@@ -18,8 +18,7 @@ import (
|
|||||||
|
|
||||||
"github.com/jackc/pgx/v4/pgxpool"
|
"github.com/jackc/pgx/v4/pgxpool"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/macaroons"
|
"github.com/lightningnetwork/lnd/macaroons"
|
||||||
"google.golang.org/grpc"
|
"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
|
// 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
|
// node needs to quit, and used as the parent context when spawning
|
||||||
// children contexts for RPC requests.
|
// children contexts for RPC requests.
|
||||||
runCtx context.Context
|
runCtx context.Context //nolint:containedctx
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
|
||||||
// filename is the log file's name.
|
// filename is the log file's name.
|
||||||
@@ -117,9 +116,9 @@ func NewHarnessNode(t *testing.T, cfg *BaseNodeConfig) (*HarnessNode, error) {
|
|||||||
|
|
||||||
// Create temporary database.
|
// Create temporary database.
|
||||||
var dbName string
|
var dbName string
|
||||||
if cfg.DbBackend == lntest.BackendPostgres {
|
if cfg.DBBackend == BackendPostgres {
|
||||||
var err error
|
var err error
|
||||||
dbName, err = createTempPgDb()
|
dbName, err = createTempPgDB()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -127,7 +126,7 @@ func NewHarnessNode(t *testing.T, cfg *BaseNodeConfig) (*HarnessNode, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cfg.OriginalExtraArgs = cfg.ExtraArgs
|
cfg.OriginalExtraArgs = cfg.ExtraArgs
|
||||||
cfg.postgresDbName = dbName
|
cfg.postgresDBName = dbName
|
||||||
|
|
||||||
return &HarnessNode{
|
return &HarnessNode{
|
||||||
T: t,
|
T: t,
|
||||||
@@ -324,7 +323,7 @@ func (hn *HarnessNode) ConnectRPCWithMacaroon(mac *macaroon.Macaroon) (
|
|||||||
hn.Cfg.TLSCertPath, "",
|
hn.Cfg.TLSCertPath, "",
|
||||||
)
|
)
|
||||||
return err
|
return err
|
||||||
}, DefaultTimeout)
|
}, wait.DefaultTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("error reading TLS cert: %v", err)
|
return nil, fmt.Errorf("error reading TLS cert: %v", err)
|
||||||
}
|
}
|
||||||
@@ -334,7 +333,7 @@ func (hn *HarnessNode) ConnectRPCWithMacaroon(mac *macaroon.Macaroon) (
|
|||||||
grpc.WithTransportCredentials(tlsCreds),
|
grpc.WithTransportCredentials(tlsCreds),
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx, cancel := context.WithTimeout(hn.runCtx, DefaultTimeout)
|
ctx, cancel := context.WithTimeout(hn.runCtx, wait.DefaultTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if mac == nil {
|
if mac == nil {
|
||||||
@@ -354,7 +353,7 @@ func (hn *HarnessNode) ConnectRPCWithMacaroon(mac *macaroon.Macaroon) (
|
|||||||
func (hn *HarnessNode) ConnectRPC() (*grpc.ClientConn, error) {
|
func (hn *HarnessNode) ConnectRPC() (*grpc.ClientConn, error) {
|
||||||
// If we should use a macaroon, always take the admin macaroon as a
|
// If we should use a macaroon, always take the admin macaroon as a
|
||||||
// default.
|
// default.
|
||||||
mac, err := hn.ReadMacaroon(hn.Cfg.AdminMacPath, DefaultTimeout)
|
mac, err := hn.ReadMacaroon(hn.Cfg.AdminMacPath, wait.DefaultTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -375,7 +374,7 @@ func (hn *HarnessNode) StartLndCmd(ctxb context.Context) error {
|
|||||||
hn.runCtx, hn.cancel = context.WithCancel(ctxb)
|
hn.runCtx, hn.cancel = context.WithCancel(ctxb)
|
||||||
|
|
||||||
args := hn.Cfg.GenArgs()
|
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
|
// Redirect stderr output to buffer
|
||||||
var errb bytes.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
|
// If the logoutput flag is passed, redirect output from the nodes to
|
||||||
// log files.
|
// log files.
|
||||||
if *lntest.LogOutput {
|
if *logOutput {
|
||||||
err := addLogFile(hn)
|
err := addLogFile(hn)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -540,7 +539,7 @@ func (hn *HarnessNode) waitTillServerState(
|
|||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-time.After(lntest.NodeStartTimeout):
|
case <-time.After(wait.NodeStartTimeout):
|
||||||
return fmt.Errorf("timeout waiting for server state")
|
return fmt.Errorf("timeout waiting for server state")
|
||||||
case err := <-errChan:
|
case err := <-errChan:
|
||||||
return fmt.Errorf("receive server state err: %v", err)
|
return fmt.Errorf("receive server state err: %v", err)
|
||||||
@@ -581,7 +580,7 @@ func (hn *HarnessNode) initLightningClient() error {
|
|||||||
"got err: %v", err)
|
"got err: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
case <-time.After(DefaultTimeout):
|
case <-time.After(wait.DefaultTimeout):
|
||||||
return fmt.Errorf("timeout creating topology client stream")
|
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.
|
// cleanup cleans up all the temporary files created by the node's process.
|
||||||
func (hn *HarnessNode) cleanup() error {
|
func (hn *HarnessNode) cleanup() error {
|
||||||
if hn.Cfg.backupDbDir != "" {
|
if hn.Cfg.backupDBDir != "" {
|
||||||
err := os.RemoveAll(hn.Cfg.backupDbDir)
|
err := os.RemoveAll(hn.Cfg.backupDBDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to remove backup dir: %v",
|
return fmt.Errorf("unable to remove backup dir: %v",
|
||||||
err)
|
err)
|
||||||
@@ -650,9 +649,10 @@ func (hn *HarnessNode) waitForProcessExit() {
|
|||||||
// Otherwise, we print the error, break the select and save
|
// Otherwise, we print the error, break the select and save
|
||||||
// logs.
|
// logs.
|
||||||
hn.printErrf("wait process exit got err: %v", err)
|
hn.printErrf("wait process exit got err: %v", err)
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
case <-time.After(DefaultTimeout * 2):
|
case <-time.After(wait.DefaultTimeout):
|
||||||
hn.printErrf("timeout waiting for process to exit")
|
hn.printErrf("timeout waiting for process to exit")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -705,7 +705,7 @@ func (hn *HarnessNode) Stop() error {
|
|||||||
default:
|
default:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}, DefaultTimeout)
|
}, wait.DefaultTimeout)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -720,7 +720,7 @@ func (hn *HarnessNode) Stop() error {
|
|||||||
// If the goroutines fail to finish before timeout, we'll print
|
// If the goroutines fail to finish before timeout, we'll print
|
||||||
// the error to console and continue.
|
// the error to console and continue.
|
||||||
select {
|
select {
|
||||||
case <-time.After(DefaultTimeout):
|
case <-time.After(wait.DefaultTimeout):
|
||||||
hn.printErrf("timeout on wait group")
|
hn.printErrf("timeout on wait group")
|
||||||
case <-done:
|
case <-done:
|
||||||
}
|
}
|
||||||
@@ -784,23 +784,23 @@ func (hn *HarnessNode) Kill() error {
|
|||||||
|
|
||||||
// printErrf prints an error to the console.
|
// printErrf prints an error to the console.
|
||||||
func (hn *HarnessNode) printErrf(format string, a ...interface{}) {
|
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,
|
hn.Cfg.LogFilenamePrefix, hn.Cfg.Name,
|
||||||
fmt.Sprintf(format, a...))
|
fmt.Sprintf(format, a...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// BackupDB creates a backup of the current database.
|
// BackupDB creates a backup of the current database.
|
||||||
func (hn *HarnessNode) BackupDB() error {
|
func (hn *HarnessNode) BackupDB() error {
|
||||||
if hn.Cfg.backupDbDir != "" {
|
if hn.Cfg.backupDBDir != "" {
|
||||||
return fmt.Errorf("backup already created")
|
return fmt.Errorf("backup already created")
|
||||||
}
|
}
|
||||||
|
|
||||||
if hn.Cfg.postgresDbName != "" {
|
if hn.Cfg.postgresDBName != "" {
|
||||||
// Backup database.
|
// Backup database.
|
||||||
backupDBName := hn.Cfg.postgresDbName + "_backup"
|
backupDBName := hn.Cfg.postgresDBName + "_backup"
|
||||||
err := executePgQuery(
|
err := executePgQuery(
|
||||||
"CREATE DATABASE " + backupDBName + " WITH TEMPLATE " +
|
"CREATE DATABASE " + backupDBName + " WITH TEMPLATE " +
|
||||||
hn.Cfg.postgresDbName,
|
hn.Cfg.postgresDBName,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -818,7 +818,7 @@ func (hn *HarnessNode) BackupDB() error {
|
|||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
|
|
||||||
hn.Cfg.backupDbDir = tempDir
|
hn.Cfg.backupDBDir = tempDir
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -826,39 +826,39 @@ func (hn *HarnessNode) BackupDB() error {
|
|||||||
|
|
||||||
// RestoreDB restores a database backup.
|
// RestoreDB restores a database backup.
|
||||||
func (hn *HarnessNode) RestoreDB() error {
|
func (hn *HarnessNode) RestoreDB() error {
|
||||||
if hn.Cfg.postgresDbName != "" {
|
if hn.Cfg.postgresDBName != "" {
|
||||||
// Restore database.
|
// Restore database.
|
||||||
backupDBName := hn.Cfg.postgresDbName + "_backup"
|
backupDBName := hn.Cfg.postgresDBName + "_backup"
|
||||||
err := executePgQuery(
|
err := executePgQuery(
|
||||||
"DROP DATABASE " + hn.Cfg.postgresDbName,
|
"DROP DATABASE " + hn.Cfg.postgresDBName,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = executePgQuery(
|
err = executePgQuery(
|
||||||
"ALTER DATABASE " + backupDBName + " RENAME TO " +
|
"ALTER DATABASE " + backupDBName + " RENAME TO " +
|
||||||
hn.Cfg.postgresDbName,
|
hn.Cfg.postgresDBName,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Restore files.
|
// Restore files.
|
||||||
if hn.Cfg.backupDbDir == "" {
|
if hn.Cfg.backupDBDir == "" {
|
||||||
return fmt.Errorf("no database backup created")
|
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 {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to copy database files: %w",
|
return fmt.Errorf("unable to copy database files: %w",
|
||||||
err)
|
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",
|
return fmt.Errorf("unable to remove backup dir: %w",
|
||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
hn.Cfg.backupDbDir = ""
|
hn.Cfg.backupDBDir = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -868,8 +868,8 @@ func postgresDatabaseDsn(dbName string) string {
|
|||||||
return fmt.Sprintf(postgresDsn, dbName)
|
return fmt.Sprintf(postgresDsn, dbName)
|
||||||
}
|
}
|
||||||
|
|
||||||
// createTempPgDb creates a temp postgres database.
|
// createTempPgDB creates a temp postgres database.
|
||||||
func createTempPgDb() (string, error) {
|
func createTempPgDB() (string, error) {
|
||||||
// Create random database name.
|
// Create random database name.
|
||||||
randBytes := make([]byte, 8)
|
randBytes := make([]byte, 8)
|
||||||
_, err := rand.Read(randBytes)
|
_, err := rand.Read(randBytes)
|
||||||
@@ -918,10 +918,8 @@ func getFinalizedLogFilePrefix(hn *HarnessNode) string {
|
|||||||
hn.PubKey[:logPubKeyBytes],
|
hn.PubKey[:logPubKeyBytes],
|
||||||
)
|
)
|
||||||
|
|
||||||
return fmt.Sprintf("%s/%d-%s-%s-%s",
|
return fmt.Sprintf("%s/%d-%s-%s-%s", GetLogDir(), hn.Cfg.NodeID,
|
||||||
lntest.GetLogDir(), hn.Cfg.NodeID,
|
hn.Cfg.LogFilenamePrefix, hn.Cfg.Name, pubKeyHex)
|
||||||
hn.Cfg.LogFilenamePrefix,
|
|
||||||
hn.Cfg.Name, pubKeyHex)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// finalizeLogfile makes sure the log file cleanup function is initialized,
|
// finalizeLogfile makes sure the log file cleanup function is initialized,
|
||||||
@@ -935,7 +933,7 @@ func finalizeLogfile(hn *HarnessNode) {
|
|||||||
hn.logFile.Close()
|
hn.logFile.Close()
|
||||||
|
|
||||||
// If logoutput flag is not set, return early.
|
// If logoutput flag is not set, return early.
|
||||||
if !*lntest.LogOutput {
|
if !*logOutput {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -948,7 +946,7 @@ func finalizeLogfile(hn *HarnessNode) {
|
|||||||
// finalizeEtcdLog saves the etcd log files when test ends.
|
// finalizeEtcdLog saves the etcd log files when test ends.
|
||||||
func finalizeEtcdLog(hn *HarnessNode) {
|
func finalizeEtcdLog(hn *HarnessNode) {
|
||||||
// Exit early if this is not etcd backend.
|
// Exit early if this is not etcd backend.
|
||||||
if hn.Cfg.DbBackend != lntest.BackendEtcd {
|
if hn.Cfg.DBBackend != BackendEtcd {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -964,7 +962,7 @@ func finalizeEtcdLog(hn *HarnessNode) {
|
|||||||
func addLogFile(hn *HarnessNode) error {
|
func addLogFile(hn *HarnessNode) error {
|
||||||
var fileName string
|
var fileName string
|
||||||
|
|
||||||
dir := lntest.GetLogDir()
|
dir := GetLogDir()
|
||||||
fileName = fmt.Sprintf("%s/%d-%s-%s-%s.log", dir, hn.Cfg.NodeID,
|
fileName = fmt.Sprintf("%s/%d-%s-%s-%s.log", dir, hn.Cfg.NodeID,
|
||||||
hn.Cfg.LogFilenamePrefix, hn.Cfg.Name,
|
hn.Cfg.LogFilenamePrefix, hn.Cfg.Name,
|
||||||
hex.EncodeToString(hn.PubKey[:logPubKeyBytes]))
|
hex.EncodeToString(hn.PubKey[:logPubKeyBytes]))
|
||||||
@@ -1028,7 +1026,7 @@ func copyAll(dstDir, srcDir string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if err := lntest.CopyFile(dstPath, srcPath); err != nil {
|
} else if err := CopyFile(dstPath, srcPath); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||||
"github.com/lightningnetwork/lnd/lnutils"
|
"github.com/lightningnetwork/lnd/lnutils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -11,8 +11,7 @@ import (
|
|||||||
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/lightningnetwork/lnd/lnutils"
|
"github.com/lightningnetwork/lnd/lnutils"
|
||||||
)
|
)
|
||||||
@@ -31,9 +30,6 @@ const (
|
|||||||
// watchPolicyUpdate specifies that this is a request to watch a policy
|
// watchPolicyUpdate specifies that this is a request to watch a policy
|
||||||
// update event.
|
// update event.
|
||||||
watchPolicyUpdate
|
watchPolicyUpdate
|
||||||
|
|
||||||
// TODO(yy): remove once temp tests is finished.
|
|
||||||
DefaultTimeout = lntest.DefaultTimeout
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// chanWatchRequest is a request to the lightningNetworkWatcher to be notified
|
// 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)
|
"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
|
// 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, "+
|
return fmt.Errorf("timeout waiting for num node updates, "+
|
||||||
"want %d, got %d", expected, num)
|
"want %d, got %d", expected, num)
|
||||||
}
|
}
|
||||||
|
err := wait.NoError(checkNumUpdates, wait.DefaultTimeout)
|
||||||
err := wait.NoError(checkNumUpdates, DefaultTimeout)
|
|
||||||
|
|
||||||
return updates, err
|
return updates, err
|
||||||
}
|
}
|
||||||
@@ -161,7 +156,7 @@ func (nw *nodeWatcher) WaitForChannelOpen(chanPoint *lnrpc.ChannelPoint) error {
|
|||||||
chanWatchType: watchOpenChannel,
|
chanWatchType: watchOpenChannel,
|
||||||
}
|
}
|
||||||
|
|
||||||
timer := time.After(DefaultTimeout)
|
timer := time.After(wait.DefaultTimeout)
|
||||||
select {
|
select {
|
||||||
case <-eventChan:
|
case <-eventChan:
|
||||||
return nil
|
return nil
|
||||||
@@ -192,7 +187,7 @@ func (nw *nodeWatcher) WaitForChannelClose(
|
|||||||
chanWatchType: watchCloseChannel,
|
chanWatchType: watchCloseChannel,
|
||||||
}
|
}
|
||||||
|
|
||||||
timer := time.After(DefaultTimeout)
|
timer := time.After(wait.DefaultTimeout)
|
||||||
select {
|
select {
|
||||||
case <-eventChan:
|
case <-eventChan:
|
||||||
closedChan, ok := nw.state.closedChans.Load(op)
|
closedChan, ok := nw.state.closedChans.Load(op)
|
||||||
@@ -218,7 +213,7 @@ func (nw *nodeWatcher) WaitForChannelPolicyUpdate(
|
|||||||
op := nw.rpc.MakeOutpoint(chanPoint)
|
op := nw.rpc.MakeOutpoint(chanPoint)
|
||||||
|
|
||||||
ticker := time.NewTicker(wait.PollInterval)
|
ticker := time.NewTicker(wait.PollInterval)
|
||||||
timer := time.After(DefaultTimeout)
|
timer := time.After(wait.DefaultTimeout)
|
||||||
defer ticker.Stop()
|
defer ticker.Stop()
|
||||||
|
|
||||||
eventChan := make(chan struct{})
|
eventChan := make(chan struct{})
|
||||||
Loaded 100 of 134 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user