mirror of
https://github.com/lightningnetwork/lnd.git
synced 2026-08-16 13:00:19 +02:00
Merge pull request #6825 from yyforyongyu/6-new-itest
itest: fix previously known test flakes
This commit is contained in:
commit
cfc19a9ac4
134 changed files with 2162 additions and 8844 deletions
108
.github/workflows/main.yml
vendored
108
.github/workflows/main.yml
vendored
|
|
@ -186,10 +186,10 @@ jobs:
|
|||
parallel: true
|
||||
|
||||
########################
|
||||
# run integration tests
|
||||
# run ubuntu integration tests
|
||||
########################
|
||||
integration-test:
|
||||
name: run itests
|
||||
ubuntu-integration-test:
|
||||
name: run ubuntu itests
|
||||
runs-on: ubuntu-latest
|
||||
if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')'
|
||||
strategy:
|
||||
|
|
@ -230,17 +230,18 @@ jobs:
|
|||
|
||||
- name: Zip log files on failure
|
||||
if: ${{ failure() }}
|
||||
timeout-minutes: 1 # timeout after 1 minute
|
||||
run: 7z a logs-itest-${{ matrix.name }}.zip lntest/itest/**/*.log
|
||||
timeout-minutes: 5 # timeout after 5 minute
|
||||
run: 7z a logs-itest-${{ matrix.name }}.zip itest/**/*.log
|
||||
|
||||
- name: Upload log files on failure
|
||||
uses: actions/upload-artifact@v2.2.4
|
||||
uses: actions/upload-artifact@v3
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: logs-itest-${{ matrix.name }}
|
||||
path: logs-itest-${{ matrix.name }}.zip
|
||||
retention-days: 5
|
||||
|
||||
|
||||
########################
|
||||
# run windows integration test
|
||||
########################
|
||||
|
|
@ -258,102 +259,15 @@ jobs:
|
|||
go-version: '${{ env.GO_VERSION }}'
|
||||
|
||||
- name: run itest
|
||||
run: make itest-parallel windows=1 tranches=2 parallel=2
|
||||
run: make itest-parallel windows=1
|
||||
|
||||
- name: Zip log files on failure
|
||||
if: ${{ failure() }}
|
||||
run: 7z a logs-itest-windows.zip lntest/itest/**/*.log
|
||||
timeout-minutes: 5 # timeout after 5 minute
|
||||
run: 7z a logs-itest-windows.zip itest/**/*.log
|
||||
|
||||
- name: Upload log files on failure
|
||||
uses: actions/upload-artifact@v2
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: logs-itest-windows
|
||||
path: logs-itest-windows.zip
|
||||
retention-days: 5
|
||||
|
||||
########################
|
||||
# run new integration tests
|
||||
########################
|
||||
new-integration-test:
|
||||
name: run new itests
|
||||
runs-on: ubuntu-latest
|
||||
if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')'
|
||||
strategy:
|
||||
# Allow other tests in the matrix to continue if one fails.
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- name: btcd
|
||||
args: backend=btcd
|
||||
- name: bitcoind
|
||||
args: backend=bitcoind
|
||||
- name: bitcoind-notxindex
|
||||
args: backend="bitcoind notxindex"
|
||||
- name: bitcoind-rpcpolling
|
||||
args: backend="bitcoind rpcpolling"
|
||||
- name: bitcoind-etcd
|
||||
args: backend=bitcoind dbbackend=etcd
|
||||
- name: bitcoind-postgres
|
||||
args: backend=bitcoind dbbackend=postgres
|
||||
- name: bitcoind-sqlite
|
||||
args: backend=bitcoind dbbackend=sqlite
|
||||
- name: neutrino
|
||||
args: backend=neutrino
|
||||
steps:
|
||||
- name: git checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: setup go ${{ env.GO_VERSION }}
|
||||
uses: ./.github/actions/setup-go
|
||||
with:
|
||||
go-version: '${{ env.GO_VERSION }}'
|
||||
|
||||
- name: install bitcoind
|
||||
run: ./scripts/install_bitcoind.sh
|
||||
|
||||
- name: run new ${{ matrix.name }}
|
||||
run: make itest-parallel temptest=true ${{ matrix.args }}
|
||||
|
||||
- name: Zip log files on failure
|
||||
if: ${{ failure() }}
|
||||
timeout-minutes: 1 # timeout after 1 minute
|
||||
run: 7z a logs-itest-${{ matrix.name }}.zip lntest/itest/**/*.log
|
||||
|
||||
- name: Upload log files on failure
|
||||
uses: actions/upload-artifact@v2.2.4
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: logs-itest-${{ matrix.name }}
|
||||
path: logs-itest-${{ matrix.name }}.zip
|
||||
retention-days: 5
|
||||
|
||||
########################
|
||||
# run new windows integration test
|
||||
########################
|
||||
new-windows-integration-test:
|
||||
name: run new windows itest
|
||||
runs-on: windows-latest
|
||||
if: '!contains(github.event.pull_request.labels.*.name, ''no-itest'')'
|
||||
steps:
|
||||
- name: git checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: setup go ${{ env.GO_VERSION }}
|
||||
uses: ./.github/actions/setup-go
|
||||
with:
|
||||
go-version: '${{ env.GO_VERSION }}'
|
||||
|
||||
- name: run new itest
|
||||
run: make itest-parallel temptest=true windows=1 tranches=2 parallel=2
|
||||
|
||||
- name: Zip log files on failure
|
||||
if: ${{ failure() }}
|
||||
timeout-minutes: 1 # timeout after 1 minute
|
||||
run: 7z a logs-itest-windows.zip lntest/itest/**/*.log
|
||||
|
||||
- name: Upload log files on failure
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
if: ${{ failure() }}
|
||||
with:
|
||||
name: logs-itest-windows
|
||||
|
|
|
|||
12
.gitignore
vendored
12
.gitignore
vendored
|
|
@ -32,12 +32,12 @@ _testmain.go
|
|||
/lncli-itest
|
||||
|
||||
# Integration test log files
|
||||
lntest/itest/*.log
|
||||
lntest/itest/.backendlogs
|
||||
lntest/itest/.minerlogs
|
||||
lntest/itest/lnd-itest
|
||||
lntest/itest/btcd-itest
|
||||
lntest/itest/.logs-*
|
||||
itest/*.log
|
||||
itest/.backendlogs
|
||||
itest/.minerlogs
|
||||
itest/lnd-itest
|
||||
itest/btcd-itest
|
||||
itest/.logs-*
|
||||
|
||||
cmd/cmd
|
||||
*.key
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ run:
|
|||
- kvdb_etcd
|
||||
- kvdb_postgres
|
||||
- kvdb_sqlite
|
||||
- integration
|
||||
|
||||
linters-settings:
|
||||
govet:
|
||||
|
|
@ -96,6 +97,7 @@ linters-settings:
|
|||
ignored-functions:
|
||||
- 'math.*'
|
||||
- 'strconv.ParseInt'
|
||||
- 'errors.Wrap'
|
||||
|
||||
|
||||
linters:
|
||||
|
|
@ -237,14 +239,9 @@ issues:
|
|||
linters:
|
||||
- forbidigo
|
||||
|
||||
# Fix false positives because of build flags in itest directory.
|
||||
- path: lntest/itest/.*
|
||||
- path: itest/.*
|
||||
linters:
|
||||
- unused
|
||||
- unparam
|
||||
- govet
|
||||
# itest case can be very long so we disable long function check.
|
||||
- funlen
|
||||
- paralleltest
|
||||
|
||||
- path: lnmock/*
|
||||
linters:
|
||||
|
|
|
|||
20
.travis.yml
20
.travis.yml
|
|
@ -32,31 +32,15 @@ sudo: required
|
|||
|
||||
jobs:
|
||||
include:
|
||||
- stage: Sanity Check
|
||||
name: Lint and compile
|
||||
script:
|
||||
# Step 1: Make sure no diff is produced when compiling with the correct
|
||||
# version.
|
||||
- make rpc-check
|
||||
|
||||
# Step 2: Make sure the unit tests compile, but don't run them. They run
|
||||
# in a GitHub Workflow.
|
||||
- make unit pkg=... case=_NONE_
|
||||
|
||||
# Step 3: Lint go code. Invoke GC more often to reduce memory usage.
|
||||
- GOGC=30 make lint
|
||||
|
||||
- stage: Integration Test
|
||||
name: Bitcoind Integration ARM
|
||||
script:
|
||||
- bash ./scripts/install_bitcoind.sh
|
||||
- GOARM=7 GOARCH=arm GOOS=linux make itest-parallel backend=bitcoind tranches=3 parallel=3
|
||||
- GOMEMLIMIT=500MiB GOARM=7 GOARCH=arm GOOS=linux travis_wait 30 make itest-parallel backend=bitcoind
|
||||
arch: arm64
|
||||
services:
|
||||
- docker
|
||||
|
||||
after_failure:
|
||||
- |-
|
||||
LOG_FILES=$(find ./lntest/itest -name '*.log')
|
||||
LOG_FILES=$(find ./itest -name '*.log')
|
||||
echo "Uploading to termbin.com..." && for f in $LOG_FILES; do echo -n $f; cat $f | nc termbin.com 9999 | xargs -r0 printf ' uploaded to %s'; done
|
||||
echo "Uploading to file.io..." && tar -zcvO $LOG_FILES | curl -s -F 'file=@-;filename=logs.tar.gz' https://file.io | xargs -r0 printf 'logs.tar.gz uploaded to %s\n'
|
||||
|
|
|
|||
16
Makefile
16
Makefile
|
|
@ -93,19 +93,19 @@ build:
|
|||
|
||||
build-itest:
|
||||
@$(call print, "Building itest btcd and lnd.")
|
||||
CGO_ENABLED=0 $(GOBUILD) -tags="rpctest" -o lntest/itest/btcd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(BTCD_PKG)
|
||||
CGO_ENABLED=0 $(GOBUILD) -tags="$(ITEST_TAGS)" -o lntest/itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd
|
||||
CGO_ENABLED=0 $(GOBUILD) -tags="integration" -o itest/btcd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(BTCD_PKG)
|
||||
CGO_ENABLED=0 $(GOBUILD) -tags="$(ITEST_TAGS)" -o itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd
|
||||
|
||||
@$(call print, "Building itest binary for ${backend} backend.")
|
||||
CGO_ENABLED=0 $(GOTEST) -v ./lntest/itest -tags="$(DEV_TAGS) $(RPC_TAGS) rpctest $(backend)" -c -o lntest/itest/itest.test$(EXEC_SUFFIX)
|
||||
CGO_ENABLED=0 $(GOTEST) -v ./itest -tags="$(DEV_TAGS) $(RPC_TAGS) integration $(backend)" -c -o itest/itest.test$(EXEC_SUFFIX)
|
||||
|
||||
build-itest-race:
|
||||
@$(call print, "Building itest btcd and lnd with race detector.")
|
||||
CGO_ENABLED=0 $(GOBUILD) -tags="rpctest" -o lntest/itest/btcd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(BTCD_PKG)
|
||||
CGO_ENABLED=1 $(GOBUILD) -race -tags="$(ITEST_TAGS)" -o lntest/itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd
|
||||
CGO_ENABLED=0 $(GOBUILD) -tags="integration" -o itest/btcd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(BTCD_PKG)
|
||||
CGO_ENABLED=1 $(GOBUILD) -race -tags="$(ITEST_TAGS)" -o itest/lnd-itest$(EXEC_SUFFIX) $(DEV_LDFLAGS) $(PKG)/cmd/lnd
|
||||
|
||||
@$(call print, "Building itest binary for ${backend} backend.")
|
||||
CGO_ENABLED=0 $(GOTEST) -v ./lntest/itest -tags="$(DEV_TAGS) $(RPC_TAGS) rpctest $(backend)" -c -o lntest/itest/itest.test$(EXEC_SUFFIX)
|
||||
CGO_ENABLED=0 $(GOTEST) -v ./itest -tags="$(DEV_TAGS) $(RPC_TAGS) integration $(backend)" -c -o itest/itest.test$(EXEC_SUFFIX)
|
||||
|
||||
install:
|
||||
@$(call print, "Installing lnd and lncli.")
|
||||
|
|
@ -164,7 +164,7 @@ endif
|
|||
|
||||
itest-only: db-instance
|
||||
@$(call print, "Running integration tests with ${backend} backend.")
|
||||
rm -rf lntest/itest/*.log lntest/itest/.logs-*; date
|
||||
rm -rf itest/*.log itest/.logs-*; date
|
||||
EXEC_SUFFIX=$(EXEC_SUFFIX) scripts/itest_part.sh 0 1 $(TEST_FLAGS) $(ITEST_FLAGS)
|
||||
|
||||
itest: build-itest itest-only
|
||||
|
|
@ -173,7 +173,7 @@ itest-race: build-itest-race itest-only
|
|||
|
||||
itest-parallel: build-itest db-instance
|
||||
@$(call print, "Running tests")
|
||||
rm -rf lntest/itest/*.log lntest/itest/.logs-*; date
|
||||
rm -rf itest/*.log itest/.logs-*; date
|
||||
EXEC_SUFFIX=$(EXEC_SUFFIX) echo "$$(seq 0 $$(expr $(ITEST_PARALLELISM) - 1))" | xargs -P $(ITEST_PARALLELISM) -n 1 -I {} scripts/itest_part.sh {} $(NUM_ITEST_TRANCHES) $(TEST_FLAGS) $(ITEST_FLAGS)
|
||||
|
||||
itest-clean:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//go:build rpctest
|
||||
// +build rpctest
|
||||
//go:build integration
|
||||
|
||||
package aezeed
|
||||
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
//go:build !rpctest
|
||||
// +build !rpctest
|
||||
|
||||
package contractcourt
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -497,10 +497,10 @@ func newChainSet(chanState *channeldb.OpenChannel) (*chainSet, error) {
|
|||
"chan_point=%v", chanState.FundingOutpoint)
|
||||
}
|
||||
|
||||
log.Debugf("ChannelPoint(%v): local_commit_type=%v, local_commit=%v",
|
||||
log.Tracef("ChannelPoint(%v): local_commit_type=%v, local_commit=%v",
|
||||
chanState.FundingOutpoint, chanState.ChanType,
|
||||
spew.Sdump(localCommit))
|
||||
log.Debugf("ChannelPoint(%v): remote_commit_type=%v, remote_commit=%v",
|
||||
log.Tracef("ChannelPoint(%v): remote_commit_type=%v, remote_commit=%v",
|
||||
chanState.FundingOutpoint, chanState.ChanType,
|
||||
spew.Sdump(remoteCommit))
|
||||
|
||||
|
|
@ -527,7 +527,7 @@ func newChainSet(chanState *channeldb.OpenChannel) (*chainSet, error) {
|
|||
var remotePendingCommit *channeldb.ChannelCommitment
|
||||
if remoteChainTip != nil {
|
||||
remotePendingCommit = &remoteChainTip.Commitment
|
||||
log.Debugf("ChannelPoint(%v): remote_pending_commit_type=%v, "+
|
||||
log.Tracef("ChannelPoint(%v): remote_pending_commit_type=%v, "+
|
||||
"remote_pending_commit=%v", chanState.FundingOutpoint,
|
||||
chanState.ChanType,
|
||||
spew.Sdump(remoteChainTip.Commitment))
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
//go:build !rpctest
|
||||
// +build !rpctest
|
||||
|
||||
package contractcourt
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
//go:build !rpctest
|
||||
// +build !rpctest
|
||||
|
||||
package contractcourt
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -316,6 +316,11 @@ type Config struct {
|
|||
// ChannelID. This is used to sign updates for them if the channel has
|
||||
// no AuthProof and the option-scid-alias feature bit was negotiated.
|
||||
GetAlias func(lnwire.ChannelID) (lnwire.ShortChannelID, error)
|
||||
|
||||
// FindChannel allows the gossiper to find a channel that we're party
|
||||
// to without iterating over the entire set of open channels.
|
||||
FindChannel func(node *btcec.PublicKey, chanID lnwire.ChannelID) (
|
||||
*channeldb.OpenChannel, error)
|
||||
}
|
||||
|
||||
// processedNetworkMsg is a wrapper around networkMsg and a boolean. It is
|
||||
|
|
@ -3016,6 +3021,16 @@ func (d *AuthenticatedGossiper) handleAnnSig(nMsg *networkMsg,
|
|||
ann.ShortChannelID,
|
||||
)
|
||||
if err != nil {
|
||||
_, err = d.cfg.FindChannel(nMsg.source, ann.ChannelID)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("unable to store the proof for "+
|
||||
"short_chan_id=%v: %v", shortChanID, err)
|
||||
log.Error(err)
|
||||
nMsg.err <- err
|
||||
|
||||
return nil, false
|
||||
}
|
||||
|
||||
proof := channeldb.NewWaitingProof(nMsg.isRemote, ann)
|
||||
err := d.cfg.WaitingProofStore.Add(proof)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -697,6 +697,12 @@ func createChannelAnnouncement(blockHeight uint32, key1, key2 *btcec.PrivateKey,
|
|||
return a, nil
|
||||
}
|
||||
|
||||
func mockFindChannel(node *btcec.PublicKey, chanID lnwire.ChannelID) (
|
||||
*channeldb.OpenChannel, error) {
|
||||
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type testCtx struct {
|
||||
gossiper *AuthenticatedGossiper
|
||||
router *mockGraphSource
|
||||
|
|
@ -792,6 +798,7 @@ func createTestCtx(t *testing.T, startHeight uint32) (*testCtx, error) {
|
|||
SignAliasUpdate: signAliasUpdate,
|
||||
FindBaseByAlias: findBaseByAlias,
|
||||
GetAlias: getAlias,
|
||||
FindChannel: mockFindChannel,
|
||||
}, selfKeyDesc)
|
||||
|
||||
if err := gossiper.Start(); err != nil {
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ A quick summary of test practices follows:
|
|||
or RPC's will need to be accompanied by integration tests which use the
|
||||
[`networkHarness`framework](https://github.com/lightningnetwork/lnd/blob/master/lntest/harness.go)
|
||||
contained within `lnd`. For example integration tests, see
|
||||
[`lnd_test.go`](https://github.com/lightningnetwork/lnd/blob/master/lntest/itest/lnd_test.go).
|
||||
[`lnd_test.go`](https://github.com/lightningnetwork/lnd/blob/master/itest/lnd_test.go).
|
||||
- The itest log files are automatically scanned for `[ERR]` lines. There
|
||||
shouldn't be any of those in the logs, see [Use of Log Levels](#use-of-log-levels).
|
||||
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ to test the RPCs and to showcase the different use cases.
|
|||
### 3-of-3 Taproot key spend path (BIP-0086)
|
||||
|
||||
See `testTaprootMuSig2KeySpendBip86` in
|
||||
[`lntest/itest/lnd_taproot_test.go`](../lntest/itest/lnd_taproot_test.go) to see
|
||||
[`itest/lnd_taproot_test.go`](../itest/lnd_taproot_test.go) to see
|
||||
the full code.
|
||||
|
||||
This example uses combines the public keys of 3 participants into a shared
|
||||
|
|
@ -73,7 +73,7 @@ the `MuSig2CreateSession` RPC call:
|
|||
### 3-of-3 Taproot key spend path with root hash commitment
|
||||
|
||||
See `testTaprootMuSig2KeySpendRootHash` in
|
||||
[`lntest/itest/lnd_taproot_test.go`](../lntest/itest/lnd_taproot_test.go) to see
|
||||
[`itest/lnd_taproot_test.go`](../itest/lnd_taproot_test.go) to see
|
||||
the full code.
|
||||
|
||||
This is very similar to the above example but with the main difference that the
|
||||
|
|
@ -101,7 +101,7 @@ the `MuSig2CreateSession` RPC call:
|
|||
### 3-of-3 `OP_CHECKSIG` in Taproot script spend path
|
||||
|
||||
See `testTaprootMuSig2CombinedLeafKeySpend` in
|
||||
[`lntest/itest/lnd_taproot_test.go`](../lntest/itest/lnd_taproot_test.go) to see
|
||||
[`itest/lnd_taproot_test.go`](../itest/lnd_taproot_test.go) to see
|
||||
the full code.
|
||||
|
||||
This example is definitely the most involved one. To be able to use a MuSig2
|
||||
|
|
|
|||
|
|
@ -487,7 +487,8 @@ PRs([6776](https://github.com/lightningnetwork/lnd/pull/6776),
|
|||
[7242](https://github.com/lightningnetwork/lnd/pull/7242),
|
||||
[7245](https://github.com/lightningnetwork/lnd/pull/7245)),
|
||||
[6823](https://github.com/lightningnetwork/lnd/pull/6823),
|
||||
[6824](https://github.com/lightningnetwork/lnd/pull/6824),) have been made to
|
||||
[6824](https://github.com/lightningnetwork/lnd/pull/6824),
|
||||
[6825](https://github.com/lightningnetwork/lnd/pull/6825)) have been made to
|
||||
refactor the itest for code health and maintenance.
|
||||
|
||||
# Contributors (Alphabetical Order)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
//go:build rpctest
|
||||
//go:build integration
|
||||
|
||||
package funding
|
||||
|
||||
|
|
@ -108,6 +108,11 @@ const (
|
|||
// for the funding transaction to be confirmed before forgetting
|
||||
// channels that aren't initiated by us. 2016 blocks is ~2 weeks.
|
||||
maxWaitNumBlocksFundingConf = 2016
|
||||
|
||||
// pendingChansLimit is the maximum number of pending channels that we
|
||||
// can have. After this point, pending channel opens will start to be
|
||||
// rejected.
|
||||
pendingChansLimit = 1_000
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -1320,6 +1325,25 @@ func (f *Manager) handleFundingOpen(peer lnpeer.Peer,
|
|||
return
|
||||
}
|
||||
|
||||
// Ensure that the pendingChansLimit is respected.
|
||||
pendingChans, err := f.cfg.Wallet.Cfg.Database.FetchPendingChannels()
|
||||
if err != nil {
|
||||
f.failFundingFlow(
|
||||
peer, msg.PendingChannelID, err,
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if len(pendingChans) > pendingChansLimit {
|
||||
f.failFundingFlow(
|
||||
peer, msg.PendingChannelID,
|
||||
lnwire.ErrMaxPendingChannels,
|
||||
)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// We'll also reject any requests to create channels until we're fully
|
||||
// synced to the network as we won't be able to properly validate the
|
||||
// confirmation of the funding transaction.
|
||||
|
|
|
|||
|
|
@ -1,6 +1,3 @@
|
|||
//go:build !rpctest
|
||||
// +build !rpctest
|
||||
|
||||
package funding
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -2743,6 +2743,15 @@ func (l *channelLink) handleSwitchPacket(pkt *htlcPacket) error {
|
|||
//
|
||||
// NOTE: Part of the ChannelLink interface.
|
||||
func (l *channelLink) HandleChannelUpdate(message lnwire.Message) {
|
||||
select {
|
||||
case <-l.quit:
|
||||
// Return early if the link is already in the process of
|
||||
// quitting. It doesn't make sense to hand the message to the
|
||||
// mailbox here.
|
||||
return
|
||||
default:
|
||||
}
|
||||
|
||||
l.mailBox.AddMessage(message)
|
||||
}
|
||||
|
||||
|
|
|
|||
106
itest/README.md
Normal file
106
itest/README.md
Normal file
|
|
@ -0,0 +1,106 @@
|
|||
# Integration Test
|
||||
|
||||
`itest` is a package that houses the integration tests made for `lnd`. This
|
||||
package builds test cases using the test framework `lntest`.
|
||||
|
||||
## Add New Tests
|
||||
|
||||
To add a new test case, create a `TestFunc` and add it in `list_on_test.go`.
|
||||
Ideally, the `Name` should just be the snake case of the name used in
|
||||
`TestFunc` without the leading `test` and underscores. For instance, to test
|
||||
`lnd`'s exporting channel backup, we have,
|
||||
|
||||
```go
|
||||
{
|
||||
Name: "export channel backup",
|
||||
TestFunc: testExportChannelBackup,
|
||||
}
|
||||
```
|
||||
|
||||
The place to put the code of the `TestFunc` is case-specific. `itest` package
|
||||
has loosely defined a list of files to test different functionalities of `lnd`.
|
||||
The new test needs to be put into one of these files, otherwise, a new file
|
||||
needs to be created.
|
||||
|
||||
## Run Tests
|
||||
|
||||
#### Run a single test case
|
||||
|
||||
To run a single test case, use `make itest icase=$case`, where `case` is the
|
||||
name defined in `list_on_test.go`, with spaces replaced with underscores(`_`).
|
||||
|
||||
```shell
|
||||
# Run `testListChannels`.
|
||||
make itest icase=list_channels
|
||||
```
|
||||
|
||||
#### Run multiple test cases
|
||||
|
||||
There are two ways to run multiple test cases. One way is to use `make itest
|
||||
icase=$cases`, where `cases` has the format `cases='(case|case|...)'`. The
|
||||
`case` is the name defined in `list_on_test.go`, with spaces replaced with
|
||||
underscores(`_`).
|
||||
|
||||
```shell
|
||||
# Run `testListChannels` and `testListAddresses` together.
|
||||
make itest icase='(list_channels|list_addresses)'
|
||||
```
|
||||
|
||||
Another way to run multiple cases is similar to how Go runs its tests - by
|
||||
simple regex matching. For instance, the following command will run three cases
|
||||
since they all start with the word `list`,
|
||||
|
||||
```shell
|
||||
# Run `testListChannels`, `testListAddresses`, and `testListPayments` together.
|
||||
make itest icase=list
|
||||
```
|
||||
|
||||
#### Run all tests
|
||||
|
||||
To run all tests, use `make itest` without `icase` flag.
|
||||
|
||||
```shell
|
||||
# Run all test cases.
|
||||
make itest
|
||||
```
|
||||
|
||||
#### Run tests in parallel
|
||||
|
||||
To run tests in parallel, use `make itest-parallel`. This command takes two
|
||||
special arguments,
|
||||
- `tranches`, specifies the number of parts the test cases will be split into.
|
||||
- `parallel`, specifies the number of threads to run in parallel. This value
|
||||
must be smaller than or equal to `tranches`.
|
||||
|
||||
```shell
|
||||
# Split the tests into 4 parts, and run them using 2 threads.
|
||||
make itest-parallel tranches=4 parallel=2
|
||||
```
|
||||
|
||||
By default, `itest-parallel` splits the tests into 4 parts and uses 4 threads
|
||||
to run each of them.
|
||||
|
||||
#### Additional arguments
|
||||
|
||||
For both `make itest` and `make itest-parallel`, the following arguments are
|
||||
allowed,
|
||||
- `timeout`, specifies the timeout value used in testing.
|
||||
- `dbbackend`, specifies the database backend. Must be `bbolt`, `etcd`, or
|
||||
`postgres`, default to `bbolt`.
|
||||
- `backend`, specifies the chain backend to be used. Must be one of,
|
||||
- `btcd`, the default value.
|
||||
- `neutrino`
|
||||
- `bitcoind`
|
||||
- `bitcoind notxindex`
|
||||
- `bitcoind rpcpolling`
|
||||
|
||||
```shell
|
||||
# Run a single test case using bitcoind as the chain backend and etcd as the
|
||||
# database backend, with a timeout of 5 minutes.
|
||||
make itest icase=list_channels backend=bitcoind dbbackend=etcd timeout=5m
|
||||
|
||||
# Run all test cases in parallel, using bitcoind notxindex as the chain backend
|
||||
# and etcd as the database backend, with a timeout of 60 minutes for each
|
||||
# parallel.
|
||||
make itest-parallel backend="bitcoind notxindex" dbbackend=etcd timeout=60m
|
||||
```
|
||||
7
itest/list_off_test.go
Normal file
7
itest/list_off_test.go
Normal file
|
|
@ -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
|
||||
// +build rpctest
|
||||
//go:build integration
|
||||
|
||||
package itest
|
||||
|
||||
import "github.com/lightningnetwork/lnd/lntemp"
|
||||
import "github.com/lightningnetwork/lnd/lntest"
|
||||
|
||||
// TODO(yy): remove the temp.
|
||||
var allTestCasesTemp = []*lntemp.TestCase{
|
||||
var allTestCases = []*lntest.TestCase{
|
||||
{
|
||||
Name: "update channel status",
|
||||
TestFunc: testUpdateChanStatus,
|
||||
|
|
@ -509,4 +507,8 @@ var allTestCasesTemp = []*lntemp.TestCase{
|
|||
Name: "zero conf reorg edge existence",
|
||||
TestFunc: testZeroConfReorg,
|
||||
},
|
||||
{
|
||||
Name: "async bidirectional payments",
|
||||
TestFunc: testBidirectionalAsyncPayments,
|
||||
},
|
||||
}
|
||||
|
|
@ -11,15 +11,15 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// testSendPaymentAMPInvoice tests that we can send an AMP payment to a
|
||||
// specified AMP invoice using SendPaymentV2.
|
||||
func testSendPaymentAMPInvoice(ht *lntemp.HarnessTest) {
|
||||
func testSendPaymentAMPInvoice(ht *lntest.HarnessTest) {
|
||||
succeed := ht.Run("native payaddr", func(t *testing.T) {
|
||||
tt := ht.Subtest(t)
|
||||
testSendPaymentAMPInvoiceCase(tt, false)
|
||||
|
|
@ -36,7 +36,7 @@ func testSendPaymentAMPInvoice(ht *lntemp.HarnessTest) {
|
|||
})
|
||||
}
|
||||
|
||||
func testSendPaymentAMPInvoiceCase(ht *lntemp.HarnessTest,
|
||||
func testSendPaymentAMPInvoiceCase(ht *lntest.HarnessTest,
|
||||
useExternalPayAddr bool) {
|
||||
|
||||
mts := newMppTestScenario(ht)
|
||||
|
|
@ -196,7 +196,7 @@ func testSendPaymentAMPInvoiceCase(ht *lntemp.HarnessTest,
|
|||
|
||||
// testSendPaymentAMPInvoiceRepeat tests that it's possible to pay an AMP
|
||||
// invoice multiple times by having the client generate a new setID each time.
|
||||
func testSendPaymentAMPInvoiceRepeat(ht *lntemp.HarnessTest) {
|
||||
func testSendPaymentAMPInvoiceRepeat(ht *lntest.HarnessTest) {
|
||||
// In this basic test, we'll only need two nodes as we want to
|
||||
// primarily test the recurring payment feature. So we'll re-use the
|
||||
carol := ht.NewNode("Carol", nil)
|
||||
|
|
@ -218,7 +218,7 @@ func testSendPaymentAMPInvoiceRepeat(ht *lntemp.HarnessTest) {
|
|||
// Establish a channel between Carol and Dave.
|
||||
chanAmt := btcutil.Amount(100_000)
|
||||
ht.OpenChannel(
|
||||
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
carol, dave, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Create an AMP invoice of a trivial amount, that we'll pay repeatedly
|
||||
|
|
@ -353,7 +353,7 @@ func testSendPaymentAMPInvoiceRepeat(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testSendPaymentAMP tests that we can send an AMP payment to a specified
|
||||
// destination using SendPaymentV2.
|
||||
func testSendPaymentAMP(ht *lntemp.HarnessTest) {
|
||||
func testSendPaymentAMP(ht *lntest.HarnessTest) {
|
||||
mts := newMppTestScenario(ht)
|
||||
const paymentAmt = btcutil.Amount(300000)
|
||||
|
||||
|
|
@ -460,7 +460,7 @@ func testSendPaymentAMP(ht *lntemp.HarnessTest) {
|
|||
mts.closeChannels()
|
||||
}
|
||||
|
||||
func testSendToRouteAMP(ht *lntemp.HarnessTest) {
|
||||
func testSendToRouteAMP(ht *lntest.HarnessTest) {
|
||||
mts := newMppTestScenario(ht)
|
||||
const (
|
||||
paymentAmt = btcutil.Amount(300000)
|
||||
|
|
@ -18,8 +18,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/funding"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -34,7 +34,7 @@ type (
|
|||
// that'll return the same node, but with its state restored via a
|
||||
// custom method. We use this to abstract away _how_ a node is restored
|
||||
// from our assertions once the node has been fully restored itself.
|
||||
restoreMethodType func(ht *lntemp.HarnessTest,
|
||||
restoreMethodType func(ht *lntest.HarnessTest,
|
||||
oldNode *node.HarnessNode, backupFilePath string,
|
||||
password []byte, mnemonic []string) nodeRestorer
|
||||
)
|
||||
|
|
@ -50,12 +50,12 @@ type chanRestoreScenario struct {
|
|||
dave *node.HarnessNode
|
||||
password []byte
|
||||
mnemonic []string
|
||||
params lntemp.OpenChannelParams
|
||||
params lntest.OpenChannelParams
|
||||
}
|
||||
|
||||
// newChanRestoreScenario creates a new scenario that has two nodes, Carol and
|
||||
// Dave, connected and funded.
|
||||
func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
|
||||
func newChanRestoreScenario(ht *lntest.HarnessTest, ct lnrpc.CommitmentType,
|
||||
zeroConf bool) *chanRestoreScenario {
|
||||
|
||||
const (
|
||||
|
|
@ -70,7 +70,7 @@ func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
|
|||
}
|
||||
|
||||
if ct != lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE {
|
||||
args := nodeArgsForCommitType(ct)
|
||||
args := lntest.NodeArgsForCommitType(ct)
|
||||
nodeArgs = append(nodeArgs, args...)
|
||||
}
|
||||
|
||||
|
|
@ -99,7 +99,7 @@ func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
|
|||
|
||||
// For the anchor output case we need two UTXOs for Carol so she can
|
||||
// sweep both the local and remote anchor.
|
||||
if commitTypeHasAnchors(ct) {
|
||||
if lntest.CommitTypeHasAnchors(ct) {
|
||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||
}
|
||||
|
||||
|
|
@ -112,7 +112,7 @@ func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
|
|||
dave: dave,
|
||||
mnemonic: mnemonic,
|
||||
password: password,
|
||||
params: lntemp.OpenChannelParams{
|
||||
params: lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
ZeroConf: zeroConf,
|
||||
|
|
@ -123,7 +123,7 @@ func newChanRestoreScenario(ht *lntemp.HarnessTest, ct lnrpc.CommitmentType,
|
|||
|
||||
// restoreDave will call the `nodeRestorer` and asserts Dave is restored by
|
||||
// checking his wallet balance against zero.
|
||||
func (c *chanRestoreScenario) restoreDave(ht *lntemp.HarnessTest,
|
||||
func (c *chanRestoreScenario) restoreDave(ht *lntest.HarnessTest,
|
||||
restoredNodeFunc nodeRestorer) *node.HarnessNode {
|
||||
|
||||
// Next, we'll make a new Dave and start the bulk of our recovery
|
||||
|
|
@ -154,7 +154,7 @@ func (c *chanRestoreScenario) restoreDave(ht *lntemp.HarnessTest,
|
|||
// 4. validate pending channel state and check we cannot force close it.
|
||||
// 5. validate Carol's UTXOs.
|
||||
// 6. assert DLP is executed.
|
||||
func (c *chanRestoreScenario) testScenario(ht *lntemp.HarnessTest,
|
||||
func (c *chanRestoreScenario) testScenario(ht *lntest.HarnessTest,
|
||||
restoredNodeFunc nodeRestorer) {
|
||||
|
||||
carol, dave := c.carol, c.dave
|
||||
|
|
@ -212,7 +212,7 @@ func (c *chanRestoreScenario) testScenario(ht *lntemp.HarnessTest,
|
|||
// let's start up Carol again.
|
||||
require.NoError(ht, restartCarol(), "restart carol failed")
|
||||
|
||||
if commitTypeHasAnchors(c.params.CommitmentType) {
|
||||
if lntest.CommitTypeHasAnchors(c.params.CommitmentType) {
|
||||
ht.AssertNumUTXOs(carol, 2)
|
||||
} else {
|
||||
ht.AssertNumUTXOs(carol, 1)
|
||||
|
|
@ -232,7 +232,7 @@ func (c *chanRestoreScenario) testScenario(ht *lntemp.HarnessTest,
|
|||
// restoring from initial wallet creation. We'll also alternate between
|
||||
// restoring form the on disk file, and restoring from the exported RPC command
|
||||
// as well.
|
||||
func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
||||
func testChannelBackupRestoreBasic(ht *lntest.HarnessTest) {
|
||||
var testCases = []struct {
|
||||
name string
|
||||
restoreMethod restoreMethodType
|
||||
|
|
@ -241,7 +241,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||
// was the initiator, of the non-advertised channel.
|
||||
{
|
||||
name: "restore from RPC backup",
|
||||
restoreMethod: func(st *lntemp.HarnessTest,
|
||||
restoreMethod: func(st *lntest.HarnessTest,
|
||||
oldNode *node.HarnessNode,
|
||||
backupFilePath string,
|
||||
password []byte,
|
||||
|
|
@ -269,7 +269,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||
// interface.
|
||||
{
|
||||
name: "restore from backup file",
|
||||
restoreMethod: func(st *lntemp.HarnessTest,
|
||||
restoreMethod: func(st *lntest.HarnessTest,
|
||||
oldNode *node.HarnessNode,
|
||||
backupFilePath string,
|
||||
password []byte,
|
||||
|
|
@ -293,7 +293,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||
// prior mnemonic and new backup seed.
|
||||
{
|
||||
name: "restore during creation",
|
||||
restoreMethod: func(st *lntemp.HarnessTest,
|
||||
restoreMethod: func(st *lntest.HarnessTest,
|
||||
oldNode *node.HarnessNode,
|
||||
backupFilePath string,
|
||||
password []byte,
|
||||
|
|
@ -325,7 +325,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||
// re-created, using the Unlock call.
|
||||
{
|
||||
name: "restore during unlock",
|
||||
restoreMethod: func(st *lntemp.HarnessTest,
|
||||
restoreMethod: func(st *lntest.HarnessTest,
|
||||
oldNode *node.HarnessNode,
|
||||
backupFilePath string,
|
||||
password []byte,
|
||||
|
|
@ -362,7 +362,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||
// make sure imports can be canceled and later resumed.
|
||||
{
|
||||
name: "restore from backup file twice",
|
||||
restoreMethod: func(st *lntemp.HarnessTest,
|
||||
restoreMethod: func(st *lntest.HarnessTest,
|
||||
oldNode *node.HarnessNode,
|
||||
backupFilePath string,
|
||||
password []byte,
|
||||
|
|
@ -376,6 +376,8 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||
// Now that we have Dave's backup file, we'll
|
||||
// create a new nodeRestorer that will restore
|
||||
// using the on-disk channel.backup.
|
||||
//
|
||||
//nolint:lll
|
||||
backup := &lnrpc.RestoreChanBackupRequest_MultiChanBackup{
|
||||
MultiChanBackup: multi,
|
||||
}
|
||||
|
|
@ -420,7 +422,7 @@ func testChannelBackupRestoreBasic(ht *lntemp.HarnessTest) {
|
|||
// ensuring that after Dave restores his channel state according to the
|
||||
// testCase, the DLP protocol is executed properly and both nodes are made
|
||||
// whole.
|
||||
func runChanRestoreScenarioBasic(ht *lntemp.HarnessTest,
|
||||
func runChanRestoreScenarioBasic(ht *lntest.HarnessTest,
|
||||
restoreMethod restoreMethodType) {
|
||||
|
||||
// Create a new retore scenario.
|
||||
|
|
@ -445,7 +447,7 @@ func runChanRestoreScenarioBasic(ht *lntemp.HarnessTest,
|
|||
|
||||
// testChannelBackupRestoreUnconfirmed tests that we're able to restore from
|
||||
// disk file and the exported RPC command for unconfirmed channel.
|
||||
func testChannelBackupRestoreUnconfirmed(ht *lntemp.HarnessTest) {
|
||||
func testChannelBackupRestoreUnconfirmed(ht *lntest.HarnessTest) {
|
||||
// Use the channel backup file that contains an unconfirmed channel and
|
||||
// make sure recovery works as well.
|
||||
ht.Run("restore unconfirmed channel file", func(t *testing.T) {
|
||||
|
|
@ -463,7 +465,7 @@ func testChannelBackupRestoreUnconfirmed(ht *lntemp.HarnessTest) {
|
|||
|
||||
// runChanRestoreScenarioUnConfirmed checks that Dave is able to restore for an
|
||||
// unconfirmed channel.
|
||||
func runChanRestoreScenarioUnConfirmed(ht *lntemp.HarnessTest, useFile bool) {
|
||||
func runChanRestoreScenarioUnConfirmed(ht *lntest.HarnessTest, useFile bool) {
|
||||
// Create a new retore scenario.
|
||||
crs := newChanRestoreScenario(
|
||||
ht, lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE, false,
|
||||
|
|
@ -527,7 +529,7 @@ func runChanRestoreScenarioUnConfirmed(ht *lntemp.HarnessTest, useFile bool) {
|
|||
// testChannelBackupRestoreCommitTypes tests that we're able to recover from,
|
||||
// and initiate the DLP protocol for different channel commitment types and
|
||||
// zero-conf channel.
|
||||
func testChannelBackupRestoreCommitTypes(ht *lntemp.HarnessTest) {
|
||||
func testChannelBackupRestoreCommitTypes(ht *lntest.HarnessTest) {
|
||||
var testCases = []struct {
|
||||
name string
|
||||
ct lnrpc.CommitmentType
|
||||
|
|
@ -584,7 +586,7 @@ func testChannelBackupRestoreCommitTypes(ht *lntemp.HarnessTest) {
|
|||
|
||||
// runChanRestoreScenarioCommitTypes tests that the DLP is applied for
|
||||
// different channel commitment types and zero-conf channel.
|
||||
func runChanRestoreScenarioCommitTypes(ht *lntemp.HarnessTest,
|
||||
func runChanRestoreScenarioCommitTypes(ht *lntest.HarnessTest,
|
||||
ct lnrpc.CommitmentType, zeroConf bool) {
|
||||
|
||||
// Create a new retore scenario.
|
||||
|
|
@ -606,7 +608,7 @@ func runChanRestoreScenarioCommitTypes(ht *lntemp.HarnessTest,
|
|||
_, minerHeight := ht.Miner.GetBestBlock()
|
||||
thawHeight := uint32(minerHeight + thawHeightDelta)
|
||||
|
||||
fundingShim, _, _ = deriveFundingShim(
|
||||
fundingShim, _ = deriveFundingShim(
|
||||
ht, dave, carol, crs.params.Amt, thawHeight, true,
|
||||
)
|
||||
crs.params.FundingShim = fundingShim
|
||||
|
|
@ -639,7 +641,7 @@ func runChanRestoreScenarioCommitTypes(ht *lntemp.HarnessTest,
|
|||
|
||||
// testChannelBackupRestoreLegacy checks a channel with the legacy revocation
|
||||
// producer format and makes sure old SCBs can still be recovered.
|
||||
func testChannelBackupRestoreLegacy(ht *lntemp.HarnessTest) {
|
||||
func testChannelBackupRestoreLegacy(ht *lntest.HarnessTest) {
|
||||
// Create a new retore scenario.
|
||||
crs := newChanRestoreScenario(
|
||||
ht, lnrpc.CommitmentType_UNKNOWN_COMMITMENT_TYPE, false,
|
||||
|
|
@ -668,7 +670,7 @@ func testChannelBackupRestoreLegacy(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testChannelBackupRestoreForceClose checks that Dave can restore from force
|
||||
// closed channels.
|
||||
func testChannelBackupRestoreForceClose(ht *lntemp.HarnessTest) {
|
||||
func testChannelBackupRestoreForceClose(ht *lntest.HarnessTest) {
|
||||
// Restore a channel that was force closed by dave just before going
|
||||
// offline.
|
||||
success := ht.Run("from backup file anchors", func(t *testing.T) {
|
||||
|
|
@ -691,7 +693,7 @@ func testChannelBackupRestoreForceClose(ht *lntemp.HarnessTest) {
|
|||
|
||||
// runChanRestoreScenarioForceClose creates anchor-enabled force close channels
|
||||
// and checks that Dave is able to restore from them.
|
||||
func runChanRestoreScenarioForceClose(ht *lntemp.HarnessTest, zeroConf bool) {
|
||||
func runChanRestoreScenarioForceClose(ht *lntest.HarnessTest, zeroConf bool) {
|
||||
crs := newChanRestoreScenario(
|
||||
ht, lnrpc.CommitmentType_ANCHORS, zeroConf,
|
||||
)
|
||||
|
|
@ -792,7 +794,7 @@ func runChanRestoreScenarioForceClose(ht *lntemp.HarnessTest, zeroConf bool) {
|
|||
// testChannelBackupUpdates tests that both the streaming channel update RPC,
|
||||
// and the on-disk channel.backup are updated each time a channel is
|
||||
// opened/closed.
|
||||
func testChannelBackupUpdates(ht *lntemp.HarnessTest) {
|
||||
func testChannelBackupUpdates(ht *lntest.HarnessTest) {
|
||||
alice := ht.Alice
|
||||
|
||||
// First, we'll make a temp directory that we'll use to store our
|
||||
|
|
@ -850,7 +852,7 @@ func testChannelBackupUpdates(ht *lntemp.HarnessTest) {
|
|||
chanAmt := btcutil.Amount(1000000)
|
||||
for i := 0; i < numChans; i++ {
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
chanPoints = append(chanPoints, chanPoint)
|
||||
}
|
||||
|
|
@ -962,7 +964,7 @@ func testChannelBackupUpdates(ht *lntemp.HarnessTest) {
|
|||
// testExportChannelBackup tests that we're able to properly export either a
|
||||
// targeted channel's backup, or export backups of all the currents open
|
||||
// channels.
|
||||
func testExportChannelBackup(ht *lntemp.HarnessTest) {
|
||||
func testExportChannelBackup(ht *lntest.HarnessTest) {
|
||||
// First, we'll create our primary test node: Carol. We'll use Carol to
|
||||
// open channels and also export backups that we'll examine throughout
|
||||
// the test.
|
||||
|
|
@ -979,7 +981,7 @@ func testExportChannelBackup(ht *lntemp.HarnessTest) {
|
|||
chanAmt := btcutil.Amount(1000000)
|
||||
for i := 0; i < numChans; i++ {
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
chanPoints = append(chanPoints, chanPoint)
|
||||
}
|
||||
|
|
@ -1022,17 +1024,20 @@ func testExportChannelBackup(ht *lntemp.HarnessTest) {
|
|||
require.NoError(ht, err, "timeout checking num single backup")
|
||||
}
|
||||
|
||||
assertMultiBackupFound := func() func(bool, map[wire.OutPoint]struct{}) {
|
||||
assertMultiBackupFound := func() func(bool,
|
||||
map[wire.OutPoint]struct{}) {
|
||||
|
||||
chanSnapshot := carol.RPC.ExportAllChanBackups()
|
||||
|
||||
return func(found bool, chanPoints map[wire.OutPoint]struct{}) {
|
||||
num := len(chanSnapshot.MultiChanBackup.MultiChanBackup)
|
||||
|
||||
switch {
|
||||
case found && chanSnapshot.MultiChanBackup == nil:
|
||||
require.Fail(ht, "multi-backup not present")
|
||||
|
||||
case !found && chanSnapshot.MultiChanBackup != nil &&
|
||||
(len(chanSnapshot.MultiChanBackup.MultiChanBackup) !=
|
||||
chanbackup.NilMultiSizePacked):
|
||||
num != chanbackup.NilMultiSizePacked:
|
||||
|
||||
require.Fail(ht, "found multi-backup when "+
|
||||
"non should be found")
|
||||
|
|
@ -1086,7 +1091,7 @@ func testExportChannelBackup(ht *lntemp.HarnessTest) {
|
|||
// relationship lost state, they will detect this during channel sync, and the
|
||||
// up-to-date party will force close the channel, giving the outdated party the
|
||||
// opportunity to sweep its output.
|
||||
func testDataLossProtection(ht *lntemp.HarnessTest) {
|
||||
func testDataLossProtection(ht *lntest.HarnessTest) {
|
||||
const (
|
||||
chanAmt = funding.MaxBtcFundingAmount
|
||||
paymentAmt = 10000
|
||||
|
|
@ -1107,22 +1112,20 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
|
|||
// directly from the miner.
|
||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||
|
||||
// timeTravel is a method that will make Carol open a channel to the
|
||||
// passed node, settle a series of payments, then reset the node back
|
||||
// to the state before the payments happened. When this method returns
|
||||
// the node will be unaware of the new state updates. The returned
|
||||
// function can be used to restart the node in this state.
|
||||
timeTravel := func(node *node.HarnessNode) (func() error,
|
||||
*lnrpc.ChannelPoint, int64) {
|
||||
|
||||
// timeTravelDave is a method that will make Carol open a channel to
|
||||
// Dave, settle a series of payments, then Dave back to the state
|
||||
// before the payments happened. When this method returns Dave will
|
||||
// be unaware of the new state updates. The returned function can be
|
||||
// used to restart Dave in this state.
|
||||
timeTravelDave := func() (func() error, *lnrpc.ChannelPoint, int64) {
|
||||
// We must let the node communicate with Carol before they are
|
||||
// able to open channel, so we connect them.
|
||||
ht.EnsureConnected(carol, node)
|
||||
ht.EnsureConnected(carol, dave)
|
||||
|
||||
// We'll first open up a channel between them with a 0.5 BTC
|
||||
// value.
|
||||
chanPoint := ht.OpenChannel(
|
||||
carol, node, lntemp.OpenChannelParams{
|
||||
carol, dave, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
},
|
||||
)
|
||||
|
|
@ -1132,17 +1135,17 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
|
|||
// the channel.
|
||||
// TODO(halseth): have dangling HTLCs on the commitment, able to
|
||||
// retrieve funds?
|
||||
payReqs, _, _ := ht.CreatePayReqs(node, paymentAmt, numInvoices)
|
||||
payReqs, _, _ := ht.CreatePayReqs(dave, paymentAmt, numInvoices)
|
||||
|
||||
// Send payments from Carol using 3 of the payment hashes
|
||||
// generated above.
|
||||
ht.CompletePaymentRequests(carol, payReqs[:numInvoices/2])
|
||||
|
||||
// Next query for the node's channel state, as we sent 3
|
||||
// payments of 10k satoshis each, it should now see his balance
|
||||
// as being 30k satoshis.
|
||||
// Next query for Dave's channel state, as we sent 3 payments
|
||||
// of 10k satoshis each, it should now see his balance as being
|
||||
// 30k satoshis.
|
||||
nodeChan := ht.AssertChannelLocalBalance(
|
||||
node, chanPoint, 30_000,
|
||||
dave, chanPoint, 30_000,
|
||||
)
|
||||
|
||||
// Grab the current commitment height (update number), we'll
|
||||
|
|
@ -1153,39 +1156,46 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
|
|||
// With the temporary file created, copy the current state into
|
||||
// the temporary file we created above. Later after more
|
||||
// updates, we'll restore this state.
|
||||
ht.BackupDB(node)
|
||||
ht.BackupDB(dave)
|
||||
|
||||
// Reconnect the peers after the restart that was needed for
|
||||
// the db backup.
|
||||
ht.EnsureConnected(carol, node)
|
||||
ht.EnsureConnected(carol, dave)
|
||||
|
||||
// Finally, send more payments from , using the remaining
|
||||
// Finally, send more payments from Carol, using the remaining
|
||||
// payment hashes.
|
||||
ht.CompletePaymentRequests(carol, payReqs[numInvoices/2:])
|
||||
|
||||
// Now we shutdown the node, copying over the its temporary
|
||||
// TODO(yy): remove the sleep once the following bug is fixed.
|
||||
//
|
||||
// While the payment is reported as settled, the commitment
|
||||
// dance may not be finished, which leaves several HTLCs in the
|
||||
// commitment. Later on, when Carol force closes this channel,
|
||||
// she would have HTLCs there and the test won't pass.
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Now we shutdown Dave, copying over the its temporary
|
||||
// database state which has the *prior* channel state over his
|
||||
// current most up to date state. With this, we essentially
|
||||
// force the node to travel back in time within the channel's
|
||||
// force Dave to travel back in time within the channel's
|
||||
// history.
|
||||
ht.RestartNodeAndRestoreDB(node)
|
||||
ht.RestartNodeAndRestoreDB(dave)
|
||||
|
||||
// Make sure the channel is still there from the PoV of the
|
||||
// node.
|
||||
ht.AssertNodeNumChannels(node, 1)
|
||||
// Make sure the channel is still there from the PoV of Dave.
|
||||
ht.AssertNodeNumChannels(dave, 1)
|
||||
|
||||
// Now query for the channel state, it should show that it's at
|
||||
// a state number in the past, not the *latest* state.
|
||||
ht.AssertChannelNumUpdates(node, stateNumPreCopy, chanPoint)
|
||||
ht.AssertChannelNumUpdates(dave, stateNumPreCopy, chanPoint)
|
||||
|
||||
balResp := node.RPC.WalletBalance()
|
||||
restart := ht.SuspendNode(node)
|
||||
balResp := dave.RPC.WalletBalance()
|
||||
restart := ht.SuspendNode(dave)
|
||||
|
||||
return restart, chanPoint, balResp.ConfirmedBalance
|
||||
}
|
||||
|
||||
// Reset Dave to a state where he has an outdated channel state.
|
||||
restartDave, _, daveStartingBalance := timeTravel(dave)
|
||||
restartDave, _, daveStartingBalance := timeTravelDave()
|
||||
|
||||
// We make a note of the nodes' current on-chain balances, to make sure
|
||||
// they are able to retrieve the channel funds eventually,
|
||||
|
|
@ -1209,7 +1219,7 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
|
|||
// closed channel, such that Dave can retrieve his funds.
|
||||
//
|
||||
// We start by letting Dave time travel back to an outdated state.
|
||||
restartDave, chanPoint2, daveStartingBalance := timeTravel(dave)
|
||||
restartDave, chanPoint2, daveStartingBalance := timeTravelDave()
|
||||
|
||||
carolBalResp = carol.RPC.WalletBalance()
|
||||
carolStartingBalance = carolBalResp.ConfirmedBalance
|
||||
|
|
@ -1255,7 +1265,7 @@ func testDataLossProtection(ht *lntemp.HarnessTest) {
|
|||
// createLegacyRevocationChannel creates a single channel using the legacy
|
||||
// revocation producer format by using PSBT to signal a special pending channel
|
||||
// ID.
|
||||
func createLegacyRevocationChannel(ht *lntemp.HarnessTest,
|
||||
func createLegacyRevocationChannel(ht *lntest.HarnessTest,
|
||||
chanAmt, pushAmt btcutil.Amount, from, to *node.HarnessNode) {
|
||||
|
||||
// We'll signal to the wallet that we also want to create a channel
|
||||
|
|
@ -1277,7 +1287,7 @@ func createLegacyRevocationChannel(ht *lntemp.HarnessTest,
|
|||
},
|
||||
},
|
||||
}
|
||||
openChannelReq := lntemp.OpenChannelParams{
|
||||
openChannelReq := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
FundingShim: shim,
|
||||
|
|
@ -1295,8 +1305,9 @@ func createLegacyRevocationChannel(ht *lntemp.HarnessTest,
|
|||
}
|
||||
fundResp := from.RPC.FundPsbt(fundReq)
|
||||
|
||||
// We have a PSBT that has no witness data yet, which is exactly what we
|
||||
// need for the next step of verifying the PSBT with the funding intents.
|
||||
// We have a PSBT that has no witness data yet, which is exactly what
|
||||
// we need for the next step of verifying the PSBT with the funding
|
||||
// intents.
|
||||
msg := &lnrpc.FundingTransitionMsg{
|
||||
Trigger: &lnrpc.FundingTransitionMsg_PsbtVerify{
|
||||
PsbtVerify: &lnrpc.FundingPsbtVerify{
|
||||
|
|
@ -1345,7 +1356,7 @@ func createLegacyRevocationChannel(ht *lntemp.HarnessTest,
|
|||
// chanRestoreViaRPC is a helper test method that returns a nodeRestorer
|
||||
// instance which will restore the target node from a password+seed, then
|
||||
// trigger a SCB restore using the RPC interface.
|
||||
func chanRestoreViaRPC(ht *lntemp.HarnessTest, password []byte,
|
||||
func chanRestoreViaRPC(ht *lntest.HarnessTest, password []byte,
|
||||
mnemonic []string, multi []byte,
|
||||
oldNode *node.HarnessNode) nodeRestorer {
|
||||
|
||||
|
|
@ -1382,7 +1393,7 @@ func copyPorts(oldNode *node.HarnessNode) node.Option {
|
|||
//
|
||||
// Note: this function is only used in this test file and has been made
|
||||
// specifically for testChanRestoreScenario.
|
||||
func assertTimeLockSwept(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode,
|
||||
func assertTimeLockSwept(ht *lntest.HarnessTest, carol, dave *node.HarnessNode,
|
||||
carolStartingBalance, daveStartingBalance int64) {
|
||||
|
||||
// We expect Carol to sweep her funds and also the anchor tx.
|
||||
|
|
@ -1450,11 +1461,13 @@ func assertTimeLockSwept(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode,
|
|||
// funds immediately, and Carol sweeping her fund after her CSV delay is up. If
|
||||
// the blankSlate value is true, then this means that Dave won't need to sweep
|
||||
// on chain as he has no funds in the channel.
|
||||
func assertDLPExecuted(ht *lntemp.HarnessTest,
|
||||
func assertDLPExecuted(ht *lntest.HarnessTest,
|
||||
carol *node.HarnessNode, carolStartingBalance int64,
|
||||
dave *node.HarnessNode, daveStartingBalance int64,
|
||||
commitType lnrpc.CommitmentType) {
|
||||
|
||||
ht.Helper()
|
||||
|
||||
// Increase the fee estimate so that the following force close tx will
|
||||
// be cpfp'ed.
|
||||
ht.SetFeeEstimate(30000)
|
||||
|
|
@ -1467,7 +1480,7 @@ func assertDLPExecuted(ht *lntemp.HarnessTest,
|
|||
// Upon reconnection, the nodes should detect that Dave is out of sync.
|
||||
// Carol should force close the channel using her latest commitment.
|
||||
expectedTxes := 1
|
||||
if commitTypeHasAnchors(commitType) {
|
||||
if lntest.CommitTypeHasAnchors(commitType) {
|
||||
expectedTxes = 2
|
||||
}
|
||||
ht.Miner.AssertNumTxsInMempool(expectedTxes)
|
||||
|
|
@ -7,8 +7,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/funding"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -16,7 +16,7 @@ import (
|
|||
|
||||
// testChannelBalance creates a new channel between Alice and Bob, then checks
|
||||
// channel balance to be equal amount specified while creation of channel.
|
||||
func testChannelBalance(ht *lntemp.HarnessTest) {
|
||||
func testChannelBalance(ht *lntest.HarnessTest) {
|
||||
// Open a channel with 0.16 BTC between Alice and Bob, ensuring the
|
||||
// channel has been opened properly.
|
||||
amount := funding.MaxBtcFundingAmount
|
||||
|
|
@ -52,16 +52,16 @@ func testChannelBalance(ht *lntemp.HarnessTest) {
|
|||
ht.EnsureConnected(alice, bob)
|
||||
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: amount},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: amount},
|
||||
)
|
||||
cType := ht.GetChannelCommitType(alice, chanPoint)
|
||||
|
||||
// As this is a single funder channel, Alice's balance should be
|
||||
// exactly 0.5 BTC since now state transitions have taken place yet.
|
||||
checkChannelBalance(alice, amount-calcStaticFee(cType, 0), 0)
|
||||
checkChannelBalance(alice, amount-lntest.CalcStaticFee(cType, 0), 0)
|
||||
|
||||
// Ensure Bob currently has no available balance within the channel.
|
||||
checkChannelBalance(bob, 0, amount-calcStaticFee(cType, 0))
|
||||
checkChannelBalance(bob, 0, amount-lntest.CalcStaticFee(cType, 0))
|
||||
|
||||
// Finally close the channel between Alice and Bob, asserting that the
|
||||
// channel has been properly closed on-chain.
|
||||
|
|
@ -73,7 +73,7 @@ func testChannelBalance(ht *lntemp.HarnessTest) {
|
|||
// Alice will send Htlcs to Carol while she is in hodl mode. This will result
|
||||
// in a build of pending Htlcs. We expect the channels unsettled balance to
|
||||
// equal the sum of all the Pending Htlcs.
|
||||
func testChannelUnsettledBalance(ht *lntemp.HarnessTest) {
|
||||
func testChannelUnsettledBalance(ht *lntest.HarnessTest) {
|
||||
const chanAmt = btcutil.Amount(1000000)
|
||||
|
||||
// Creates a helper closure to be used below which asserts the proper
|
||||
|
|
@ -123,17 +123,21 @@ func testChannelUnsettledBalance(ht *lntemp.HarnessTest) {
|
|||
|
||||
// Open a channel between Alice and Carol.
|
||||
chanPointAlice := ht.OpenChannel(
|
||||
alice, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
cType := ht.GetChannelCommitType(alice, chanPointAlice)
|
||||
|
||||
// Check alice's channel balance, which should have zero remote and zero
|
||||
// pending balance.
|
||||
checkChannelBalance(alice, chanAmt-calcStaticFee(cType, 0), 0, 0, 0)
|
||||
checkChannelBalance(
|
||||
alice, chanAmt-lntest.CalcStaticFee(cType, 0), 0, 0, 0,
|
||||
)
|
||||
|
||||
// Check carol's channel balance, which should have zero local and zero
|
||||
// pending balance.
|
||||
checkChannelBalance(carol, 0, chanAmt-calcStaticFee(cType, 0), 0, 0)
|
||||
checkChannelBalance(
|
||||
carol, 0, chanAmt-lntest.CalcStaticFee(cType, 0), 0, 0,
|
||||
)
|
||||
|
||||
// Channel should be ready for payments.
|
||||
const (
|
||||
|
|
@ -195,7 +199,8 @@ func testChannelUnsettledBalance(ht *lntemp.HarnessTest) {
|
|||
// Check alice's channel balance, which should have a remote unsettled
|
||||
// balance that equals to the amount of invoices * payAmt. The remote
|
||||
// balance remains zero.
|
||||
aliceLocal := chanAmt - calcStaticFee(cType, 0) - numInvoices*payAmt
|
||||
fee := lntest.CalcStaticFee(cType, 0)
|
||||
aliceLocal := chanAmt - fee - numInvoices*payAmt
|
||||
checkChannelBalance(alice, aliceLocal, 0, 0, numInvoices*payAmt)
|
||||
|
||||
// Check carol's channel balance, which should have a local unsettled
|
||||
|
|
@ -13,8 +13,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/chainreg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
|
|
@ -30,7 +30,7 @@ import (
|
|||
//
|
||||
// Note that whether the deadline is used or not is implicitly checked by its
|
||||
// corresponding fee rates.
|
||||
func testCommitmentTransactionDeadline(ht *lntemp.HarnessTest) {
|
||||
func testCommitmentTransactionDeadline(ht *lntest.HarnessTest) {
|
||||
// Get the default max fee rate used in sweeping the commitment
|
||||
// transaction.
|
||||
defaultMax := lnwallet.DefaultAnchorsCommitMaxFeeRateSatPerVByte
|
||||
|
|
@ -72,7 +72,7 @@ func testCommitmentTransactionDeadline(ht *lntemp.HarnessTest) {
|
|||
setupNode := func(name string) *node.HarnessNode {
|
||||
// Create the node.
|
||||
args := []string{"--hodl.exit-settle"}
|
||||
args = append(args, nodeArgsForCommitType(
|
||||
args = append(args, lntest.NodeArgsForCommitType(
|
||||
lnrpc.CommitmentType_ANCHORS)...,
|
||||
)
|
||||
node := ht.NewNode(name, args)
|
||||
|
|
@ -104,7 +104,7 @@ func testCommitmentTransactionDeadline(ht *lntemp.HarnessTest) {
|
|||
|
||||
// Open a channel between Alice and Bob.
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: 10e6,
|
||||
PushAmt: 5e6,
|
||||
},
|
||||
|
|
@ -194,7 +194,7 @@ func testCommitmentTransactionDeadline(ht *lntemp.HarnessTest) {
|
|||
// process.
|
||||
//
|
||||
// TODO(roasbeef): also add an unsettled HTLC before force closing.
|
||||
func testChannelForceClosure(ht *lntemp.HarnessTest) {
|
||||
func testChannelForceClosure(ht *lntest.HarnessTest) {
|
||||
// We'll test the scenario for some of the commitment types, to ensure
|
||||
// outputs can be swept.
|
||||
commitTypes := []lnrpc.CommitmentType{
|
||||
|
|
@ -209,7 +209,7 @@ func testChannelForceClosure(ht *lntemp.HarnessTest) {
|
|||
success := ht.Run(testName, func(t *testing.T) {
|
||||
st := ht.Subtest(t)
|
||||
|
||||
args := nodeArgsForCommitType(channelType)
|
||||
args := lntest.NodeArgsForCommitType(channelType)
|
||||
alice := st.NewNode("Alice", args)
|
||||
defer st.Shutdown(alice)
|
||||
|
||||
|
|
@ -237,7 +237,7 @@ func testChannelForceClosure(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func channelForceClosureTest(ht *lntemp.HarnessTest,
|
||||
func channelForceClosureTest(ht *lntest.HarnessTest,
|
||||
alice, carol *node.HarnessNode, channelType lnrpc.CommitmentType) {
|
||||
|
||||
const (
|
||||
|
|
@ -268,7 +268,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||
carolStartingBalance := carolBalResp.ConfirmedBalance
|
||||
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, carol, lntemp.OpenChannelParams{
|
||||
alice, carol, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
},
|
||||
|
|
@ -600,6 +600,20 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||
// Update current height
|
||||
_, curHeight = ht.Miner.GetBestBlock()
|
||||
|
||||
// checkForceClosedChannelNumHtlcs verifies that a force closed channel
|
||||
// has the proper number of htlcs.
|
||||
checkPendingChannelNumHtlcs := func(
|
||||
forceClose lntest.PendingForceClose) error {
|
||||
|
||||
if len(forceClose.PendingHtlcs) != numInvoices {
|
||||
return fmt.Errorf("expected force closed channel to "+
|
||||
"have %d pending htlcs, found %d instead",
|
||||
numInvoices, len(forceClose.PendingHtlcs))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
err = wait.NoError(func() error {
|
||||
// Now that the commit output has been fully swept, check to
|
||||
// see that the channel remains open for the pending htlc
|
||||
|
|
@ -611,7 +625,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||
// The commitment funds will have been recovered after the
|
||||
// commit txn was included in the last block. The htlc funds
|
||||
// will be shown in limbo.
|
||||
err := checkPendingChannelNumHtlcs(forceClose, numInvoices)
|
||||
err := checkPendingChannelNumHtlcs(forceClose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -659,7 +673,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||
|
||||
// We should now be at the block just before the utxo nursery
|
||||
// will attempt to broadcast the htlc timeout transactions.
|
||||
err = checkPendingChannelNumHtlcs(forceClose, numInvoices)
|
||||
err = checkPendingChannelNumHtlcs(forceClose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -702,9 +716,9 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||
|
||||
// Retrieve each htlc timeout txn from the mempool, and ensure it is
|
||||
// well-formed. This entails verifying that each only spends from
|
||||
// output, and that that output is from the commitment txn. In case
|
||||
// this is an anchor channel, the transactions are aggregated by the
|
||||
// sweeper into one.
|
||||
// output, and that output is from the commitment txn. In case this is
|
||||
// an anchor channel, the transactions are aggregated by the sweeper
|
||||
// into one.
|
||||
numInputs := 1
|
||||
if channelType == lnrpc.CommitmentType_ANCHORS {
|
||||
numInputs = numInvoices + 1
|
||||
|
|
@ -796,7 +810,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||
|
||||
// We record the htlc amount less fees here, so that we know
|
||||
// what value to expect for the second stage of our htlc
|
||||
// htlc resolution.
|
||||
// resolution.
|
||||
htlcLessFees = uint64(outputs[0].Value)
|
||||
}
|
||||
|
||||
|
|
@ -838,7 +852,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||
return fmt.Errorf("htlc funds should still be in limbo")
|
||||
}
|
||||
|
||||
return checkPendingChannelNumHtlcs(forceClose, numInvoices)
|
||||
return checkPendingChannelNumHtlcs(forceClose)
|
||||
}, defaultTimeout)
|
||||
require.NoError(ht, err, "timeout while checking force closed channel")
|
||||
|
||||
|
|
@ -913,7 +927,7 @@ func channelForceClosureTest(ht *lntemp.HarnessTest,
|
|||
forceClose := ht.AssertChannelPendingForceClose(
|
||||
alice, chanPoint,
|
||||
)
|
||||
err := checkPendingChannelNumHtlcs(forceClose, numInvoices)
|
||||
err := checkPendingChannelNumHtlcs(forceClose)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -986,7 +1000,7 @@ func padCLTV(cltv uint32) uint32 {
|
|||
// testFailingChannel tests that we will fail the channel by force closing it
|
||||
// in the case where a counterparty tries to settle an HTLC with the wrong
|
||||
// preimage.
|
||||
func testFailingChannel(ht *lntemp.HarnessTest) {
|
||||
func testFailingChannel(ht *lntest.HarnessTest) {
|
||||
const paymentAmt = 10000
|
||||
|
||||
chanAmt := lnd.MaxFundingAmount
|
||||
|
|
@ -999,7 +1013,7 @@ func testFailingChannel(ht *lntemp.HarnessTest) {
|
|||
ht.ConnectNodes(alice, carol)
|
||||
|
||||
// Let Alice connect and open a channel to Carol,
|
||||
ht.OpenChannel(alice, carol, lntemp.OpenChannelParams{Amt: chanAmt})
|
||||
ht.OpenChannel(alice, carol, lntest.OpenChannelParams{Amt: chanAmt})
|
||||
|
||||
// With the channel open, we'll create a invoice for Carol that Alice
|
||||
// will attempt to pay.
|
||||
|
|
@ -1058,7 +1072,7 @@ func testFailingChannel(ht *lntemp.HarnessTest) {
|
|||
// type matches a set of expected resolutions.
|
||||
//
|
||||
// NOTE: only used in current test file.
|
||||
func assertReports(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
||||
func assertReports(ht *lntest.HarnessTest, hn *node.HarnessNode,
|
||||
chanPoint *lnrpc.ChannelPoint, expected map[string]*lnrpc.Resolution) {
|
||||
|
||||
op := ht.OutPointFromChannelPoint(chanPoint)
|
||||
|
|
@ -1087,3 +1101,54 @@ func assertReports(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
|||
require.Equal(ht, expected, res)
|
||||
}
|
||||
}
|
||||
|
||||
// checkCommitmentMaturity checks that both the maturity height and blocks
|
||||
// maturity height are as expected.
|
||||
//
|
||||
// NOTE: only used in current test file.
|
||||
func checkCommitmentMaturity(forceClose lntest.PendingForceClose,
|
||||
maturityHeight uint32, blocksTilMaturity int32) error {
|
||||
|
||||
if forceClose.MaturityHeight != maturityHeight {
|
||||
return fmt.Errorf("expected commitment maturity height to be "+
|
||||
"%d, found %d instead", maturityHeight,
|
||||
forceClose.MaturityHeight)
|
||||
}
|
||||
if forceClose.BlocksTilMaturity != blocksTilMaturity {
|
||||
return fmt.Errorf("expected commitment blocks til maturity to "+
|
||||
"be %d, found %d instead", blocksTilMaturity,
|
||||
forceClose.BlocksTilMaturity)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// checkPendingHtlcStageAndMaturity uniformly tests all pending htlc's belonging
|
||||
// to a force closed channel, testing for the expected stage number, blocks till
|
||||
// maturity, and the maturity height.
|
||||
//
|
||||
// NOTE: only used in current test file.
|
||||
func checkPendingHtlcStageAndMaturity(
|
||||
forceClose *lnrpc.PendingChannelsResponse_ForceClosedChannel,
|
||||
stage, maturityHeight uint32, blocksTillMaturity int32) error {
|
||||
|
||||
for _, pendingHtlc := range forceClose.PendingHtlcs {
|
||||
if pendingHtlc.Stage != stage {
|
||||
return fmt.Errorf("expected pending htlc to be stage "+
|
||||
"%d, found %d", stage, pendingHtlc.Stage)
|
||||
}
|
||||
if pendingHtlc.MaturityHeight != maturityHeight {
|
||||
return fmt.Errorf("expected pending htlc maturity "+
|
||||
"height to be %d, instead has %d",
|
||||
maturityHeight, pendingHtlc.MaturityHeight)
|
||||
}
|
||||
if pendingHtlc.BlocksTilMaturity != blocksTillMaturity {
|
||||
return fmt.Errorf("expected pending htlc blocks til "+
|
||||
"maturity to be %d, instead has %d",
|
||||
blocksTillMaturity,
|
||||
pendingHtlc.BlocksTilMaturity)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
@ -11,8 +11,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/peersrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -40,7 +40,7 @@ import (
|
|||
// take more than 5 seconds to finish, the channel will be marked as disabled,
|
||||
// thus a following operation will fail if it relies on the channel being
|
||||
// enabled.
|
||||
func testUpdateChanStatus(ht *lntemp.HarnessTest) {
|
||||
func testUpdateChanStatus(ht *lntest.HarnessTest) {
|
||||
// Create two fresh nodes and open a channel between them.
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
args := []string{
|
||||
|
|
@ -57,7 +57,7 @@ func testUpdateChanStatus(ht *lntemp.HarnessTest) {
|
|||
// being the sole funder of the channel.
|
||||
chanAmt := btcutil.Amount(100000)
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
defer ht.CloseChannel(alice, chanPoint)
|
||||
|
||||
|
|
@ -141,7 +141,7 @@ func testUpdateChanStatus(ht *lntemp.HarnessTest) {
|
|||
FeeRateMilliMsat: int64(chainreg.DefaultBitcoinFeeRate),
|
||||
TimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta,
|
||||
MinHtlc: 1000, // default value
|
||||
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
|
||||
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
|
||||
}
|
||||
|
||||
// Manually disable the channel and ensure that a "Disabled = true"
|
||||
|
|
@ -217,14 +217,14 @@ func testUpdateChanStatus(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testUnannouncedChannels checks unannounced channels are not returned by
|
||||
// describeGraph RPC request unless explicitly asked for.
|
||||
func testUnannouncedChannels(ht *lntemp.HarnessTest) {
|
||||
func testUnannouncedChannels(ht *lntest.HarnessTest) {
|
||||
amount := funding.MaxBtcFundingAmount
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
|
||||
// Open a channel between Alice and Bob, ensuring the
|
||||
// channel has been opened properly.
|
||||
chanOpenUpdate := ht.OpenChannelAssertStream(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: amount},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: amount},
|
||||
)
|
||||
|
||||
// Mine 2 blocks, and check that the channel is opened but not yet
|
||||
|
|
@ -252,7 +252,7 @@ func testUnannouncedChannels(ht *lntemp.HarnessTest) {
|
|||
ht.CloseChannel(alice, fundingChanPoint)
|
||||
}
|
||||
|
||||
func testGraphTopologyNotifications(ht *lntemp.HarnessTest) {
|
||||
func testGraphTopologyNotifications(ht *lntest.HarnessTest) {
|
||||
ht.Run("pinned", func(t *testing.T) {
|
||||
subT := ht.Subtest(t)
|
||||
testGraphTopologyNtfns(subT, true)
|
||||
|
|
@ -263,7 +263,7 @@ func testGraphTopologyNotifications(ht *lntemp.HarnessTest) {
|
|||
})
|
||||
}
|
||||
|
||||
func testGraphTopologyNtfns(ht *lntemp.HarnessTest, pinned bool) {
|
||||
func testGraphTopologyNtfns(ht *lntest.HarnessTest, pinned bool) {
|
||||
const chanAmt = funding.MaxBtcFundingAmount
|
||||
|
||||
// Spin up Bob first, since we will need to grab his pubkey when
|
||||
|
|
@ -305,7 +305,7 @@ func testGraphTopologyNtfns(ht *lntemp.HarnessTest, pinned bool) {
|
|||
|
||||
// Open a new channel between Alice and Bob.
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// The channel opening above should have triggered a few notifications
|
||||
|
|
@ -335,17 +335,30 @@ func testGraphTopologyNtfns(ht *lntemp.HarnessTest, pinned bool) {
|
|||
|
||||
// For the final portion of the test, we'll ensure that once a new node
|
||||
// appears in the network, the proper notification is dispatched. Note
|
||||
// that a node that does not have any channels open is ignored, so first
|
||||
// we disconnect Alice and Bob, open a channel between Bob and Carol,
|
||||
// and finally connect Alice to Bob again.
|
||||
ht.DisconnectNodes(alice, bob)
|
||||
// that a node that does not have any channels open is ignored, so
|
||||
// first we disconnect Alice and Bob, open a channel between Bob and
|
||||
// Carol, and finally connect Alice to Bob again.
|
||||
ht.DisconnectNodes(bob, alice)
|
||||
|
||||
// Since Alice and Bob has a permanent connection, the above
|
||||
// disconnection won't be enough as Alice will try to reconnect to Bob
|
||||
// again. Atm, it seems nothing is stopping the reconnection. So we
|
||||
// need to shutdown Alice here.
|
||||
//
|
||||
// TODO(yy): clearly define what `disconnectpeer` rpc is responsible
|
||||
// for and its effect. If we disconnect a peer, we shouldn't allow the
|
||||
// peer to connect to us again.
|
||||
restartAlice := ht.SuspendNode(alice)
|
||||
|
||||
carol := ht.NewNode("Carol", nil)
|
||||
ht.ConnectNodes(bob, carol)
|
||||
chanPoint = ht.OpenChannel(
|
||||
bob, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
bob, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Restart Alice so she can receive the channel updates from Bob.
|
||||
require.NoError(ht, restartAlice(), "failed to restart Alice")
|
||||
|
||||
// Reconnect Alice and Bob. This should result in the nodes syncing up
|
||||
// their respective graph state, with the new addition being the
|
||||
// existence of Carol in the graph, and also the channel between Bob
|
||||
|
|
@ -366,7 +379,7 @@ func testGraphTopologyNtfns(ht *lntemp.HarnessTest, pinned bool) {
|
|||
// testNodeAnnouncement ensures that when a node is started with one or more
|
||||
// external IP addresses specified on the command line, that those addresses
|
||||
// announced to the network and reported in the network graph.
|
||||
func testNodeAnnouncement(ht *lntemp.HarnessTest) {
|
||||
func testNodeAnnouncement(ht *lntest.HarnessTest) {
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
|
||||
advertisedAddrs := []string{
|
||||
|
|
@ -392,7 +405,7 @@ func testNodeAnnouncement(ht *lntemp.HarnessTest) {
|
|||
// ensures that Alice receives the node announcement from Bob as part of
|
||||
// the announcement broadcast.
|
||||
chanPoint := ht.OpenChannel(
|
||||
bob, dave, lntemp.OpenChannelParams{Amt: 1000000},
|
||||
bob, dave, lntest.OpenChannelParams{Amt: 1000000},
|
||||
)
|
||||
|
||||
assertAddrs := func(addrsFound []string, targetAddrs ...string) {
|
||||
|
|
@ -421,7 +434,7 @@ func testNodeAnnouncement(ht *lntemp.HarnessTest) {
|
|||
// testUpdateNodeAnnouncement ensures that the RPC endpoint validates
|
||||
// the requests correctly and that the new node announcement is brodcasted
|
||||
// with the right information after updating our node.
|
||||
func testUpdateNodeAnnouncement(ht *lntemp.HarnessTest) {
|
||||
func testUpdateNodeAnnouncement(ht *lntest.HarnessTest) {
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
|
||||
var lndArgs []string
|
||||
|
|
@ -500,7 +513,7 @@ func testUpdateNodeAnnouncement(ht *lntemp.HarnessTest) {
|
|||
// ensures that Alice receives the node announcement from Bob as part of
|
||||
// the announcement broadcast.
|
||||
chanPoint := ht.OpenChannel(
|
||||
bob, dave, lntemp.OpenChannelParams{
|
||||
bob, dave, lntest.OpenChannelParams{
|
||||
Amt: 1000000,
|
||||
},
|
||||
)
|
||||
|
|
@ -637,7 +650,7 @@ func testUpdateNodeAnnouncement(ht *lntemp.HarnessTest) {
|
|||
// assertSyncType asserts that the peer has an expected syncType.
|
||||
//
|
||||
// NOTE: only made for tests in this file.
|
||||
func assertSyncType(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
||||
func assertSyncType(ht *lntest.HarnessTest, hn *node.HarnessNode,
|
||||
peer string, syncType lnrpc.Peer_SyncType) {
|
||||
|
||||
resp := hn.RPC.ListPeers()
|
||||
|
|
@ -693,7 +706,7 @@ func compareNodeAnns(n1, n2 *lnrpc.NodeUpdate) error {
|
|||
// the response expected values.
|
||||
//
|
||||
// NOTE: only used for tests in this file.
|
||||
func assertUpdateNodeAnnouncementResponse(ht *lntemp.HarnessTest,
|
||||
func assertUpdateNodeAnnouncementResponse(ht *lntest.HarnessTest,
|
||||
response *peersrpc.NodeAnnouncementUpdateResponse,
|
||||
expectedOps map[string]int) {
|
||||
|
||||
|
|
@ -10,37 +10,22 @@ import (
|
|||
"github.com/lightningnetwork/lnd/funding"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// assertPolicyUpdate checks that a given policy update has been received by a
|
||||
// list of given nodes.
|
||||
// TODO(yy): delete.
|
||||
func assertPolicyUpdate(t *harnessTest, nodes []*lntest.HarnessNode,
|
||||
advertisingNode string, policy *lnrpc.RoutingPolicy,
|
||||
chanPoint *lnrpc.ChannelPoint) {
|
||||
|
||||
for _, node := range nodes {
|
||||
assertChannelPolicyUpdate(
|
||||
t.t, node, advertisingNode, policy, chanPoint, false,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// testUpdateChannelPolicy tests that policy updates made to a channel
|
||||
// gets propagated to other nodes in the network.
|
||||
func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
||||
func testUpdateChannelPolicy(ht *lntest.HarnessTest) {
|
||||
const (
|
||||
defaultFeeBase = 1000
|
||||
defaultFeeRate = 1
|
||||
defaultTimeLockDelta = chainreg.DefaultBitcoinTimeLockDelta
|
||||
defaultMinHtlc = 1000
|
||||
)
|
||||
defaultMaxHtlc := calculateMaxHtlc(funding.MaxBtcFundingAmount)
|
||||
defaultMaxHtlc := lntest.CalculateMaxHtlc(funding.MaxBtcFundingAmount)
|
||||
|
||||
chanAmt := funding.MaxBtcFundingAmount
|
||||
pushAmt := chanAmt / 2
|
||||
|
|
@ -49,7 +34,7 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
|||
|
||||
// Create a channel Alice->Bob.
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
},
|
||||
|
|
@ -102,7 +87,7 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
|||
// part of his ChannelUpdate.
|
||||
const customMinHtlc = 5000
|
||||
chanPoint2 := ht.OpenChannel(
|
||||
carol, bob, lntemp.OpenChannelParams{
|
||||
carol, bob, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
MinHtlc: customMinHtlc,
|
||||
|
|
@ -182,9 +167,9 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
|||
payAmt = btcutil.Amount(4)
|
||||
amtSat := int64(payAmt)
|
||||
amtMSat := int64(lnwire.NewMSatFromSatoshis(payAmt))
|
||||
routes.Routes[0].Hops[0].AmtToForward = amtSat // nolint:staticcheck
|
||||
routes.Routes[0].Hops[0].AmtToForward = amtSat
|
||||
routes.Routes[0].Hops[0].AmtToForwardMsat = amtMSat
|
||||
routes.Routes[0].Hops[1].AmtToForward = amtSat // nolint:staticcheck
|
||||
routes.Routes[0].Hops[1].AmtToForward = amtSat
|
||||
routes.Routes[0].Hops[1].AmtToForwardMsat = amtMSat
|
||||
|
||||
// Send the payment with the modified value.
|
||||
|
|
@ -215,9 +200,9 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
|||
payAmt = btcutil.Amount(5)
|
||||
amtSat = int64(payAmt)
|
||||
amtMSat = int64(lnwire.NewMSatFromSatoshis(payAmt))
|
||||
routes.Routes[0].Hops[0].AmtToForward = amtSat // nolint:staticcheck
|
||||
routes.Routes[0].Hops[0].AmtToForward = amtSat
|
||||
routes.Routes[0].Hops[0].AmtToForwardMsat = amtMSat
|
||||
routes.Routes[0].Hops[1].AmtToForward = amtSat // nolint:staticcheck
|
||||
routes.Routes[0].Hops[1].AmtToForward = amtSat
|
||||
routes.Routes[0].Hops[1].AmtToForwardMsat = amtMSat
|
||||
|
||||
// Manually set the MPP payload a new for each payment since
|
||||
|
|
@ -298,7 +283,7 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
|||
// We'll now open a channel from Alice directly to Carol.
|
||||
ht.ConnectNodes(alice, carol)
|
||||
chanPoint3 := ht.OpenChannel(
|
||||
alice, carol, lntemp.OpenChannelParams{
|
||||
alice, carol, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
},
|
||||
|
|
@ -439,7 +424,7 @@ func testUpdateChannelPolicy(ht *lntemp.HarnessTest) {
|
|||
// chan-disable-timeout flags here. For instance, if some operations take more
|
||||
// than 6 seconds to finish, the channel will be marked as disabled, thus a
|
||||
// following operation will fail if it relies on the channel being enabled.
|
||||
func testSendUpdateDisableChannel(ht *lntemp.HarnessTest) {
|
||||
func testSendUpdateDisableChannel(ht *lntest.HarnessTest) {
|
||||
const chanAmt = 100000
|
||||
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
|
|
@ -482,8 +467,8 @@ func testSendUpdateDisableChannel(ht *lntemp.HarnessTest) {
|
|||
|
||||
// We now proceed to open channels: Alice=>Bob, Alice=>Carol and
|
||||
// Eve=>Carol.
|
||||
p := lntemp.OpenChannelParams{Amt: chanAmt}
|
||||
reqs := []*lntemp.OpenChannelRequest{
|
||||
p := lntest.OpenChannelParams{Amt: chanAmt}
|
||||
reqs := []*lntest.OpenChannelRequest{
|
||||
{Local: alice, Remote: bob, Param: p},
|
||||
{Local: alice, Remote: carol, Param: p},
|
||||
{Local: eve, Remote: carol, Param: p},
|
||||
|
|
@ -528,7 +513,7 @@ func testSendUpdateDisableChannel(ht *lntemp.HarnessTest) {
|
|||
FeeRateMilliMsat: int64(chainreg.DefaultBitcoinFeeRate),
|
||||
TimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta,
|
||||
MinHtlc: 1000, // default value
|
||||
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
|
||||
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
|
||||
Disabled: true,
|
||||
}
|
||||
|
||||
|
|
@ -670,7 +655,7 @@ func testSendUpdateDisableChannel(ht *lntemp.HarnessTest) {
|
|||
// Bob will update the base fee via UpdateChannelPolicy, we will test that
|
||||
// Alice will not fail the payment and send it using the updated channel
|
||||
// policy.
|
||||
func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
|
||||
func testUpdateChannelPolicyForPrivateChannel(ht *lntest.HarnessTest) {
|
||||
const (
|
||||
chanAmt = btcutil.Amount(100000)
|
||||
paymentAmt = 20000
|
||||
|
|
@ -683,7 +668,7 @@ func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
|
|||
|
||||
// Open a channel with 100k satoshis between Alice and Bob.
|
||||
chanPointAliceBob := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
},
|
||||
)
|
||||
|
|
@ -696,7 +681,7 @@ func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
|
|||
|
||||
// Open a channel with 100k satoshis between Bob and Carol.
|
||||
chanPointBobCarol := ht.OpenChannel(
|
||||
bob, carol, lntemp.OpenChannelParams{
|
||||
bob, carol, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
Private: true,
|
||||
},
|
||||
|
|
@ -729,6 +714,19 @@ func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
|
|||
|
||||
// Alice pays the invoices. She will use the updated baseFeeMSat in the
|
||||
// payment
|
||||
//
|
||||
// TODO(yy): we may get a flake saying the timeout checking the
|
||||
// payment's state, which is due to slow round of HTLC settlement. An
|
||||
// example log is shown below, where Alice sent RevokeAndAck to Bob,
|
||||
// but it took Bob 7 seconds to reply back the final UpdateFulfillHTLC.
|
||||
//
|
||||
// 2022-11-14 06:23:59.774 PEER: Peer(Bob): Sending UpdateAddHTLC
|
||||
// 2022-11-14 06:24:00.635 PEER: Peer(Bob): Sending CommitSig
|
||||
// 2022-11-14 06:24:01.784 PEER: Peer(Bob): Sending RevokeAndAck
|
||||
// 2022-11-14 06:24:08.464 PEER: Peer(Bob): Received UpdateFulfillHTLC
|
||||
//
|
||||
// 7 seconds is too long for a local test and this needs more
|
||||
// investigation.
|
||||
payReqs := []string{resp.PaymentRequest}
|
||||
ht.CompletePaymentRequests(alice, payReqs)
|
||||
|
||||
|
|
@ -770,14 +768,14 @@ func testUpdateChannelPolicyForPrivateChannel(ht *lntemp.HarnessTest) {
|
|||
// testUpdateChannelPolicyFeeRateAccuracy tests that updating the channel policy
|
||||
// rounds fee rate values correctly as well as setting fee rate with ppm works
|
||||
// as expected.
|
||||
func testUpdateChannelPolicyFeeRateAccuracy(ht *lntemp.HarnessTest) {
|
||||
func testUpdateChannelPolicyFeeRateAccuracy(ht *lntest.HarnessTest) {
|
||||
chanAmt := funding.MaxBtcFundingAmount
|
||||
pushAmt := chanAmt / 2
|
||||
|
||||
// Create a channel Alice -> Bob.
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
},
|
||||
|
|
@ -841,7 +839,7 @@ func testUpdateChannelPolicyFeeRateAccuracy(ht *lntemp.HarnessTest) {
|
|||
|
||||
// assertNodesPolicyUpdate checks that a given policy update has been received
|
||||
// by a list of given nodes.
|
||||
func assertNodesPolicyUpdate(ht *lntemp.HarnessTest, nodes []*node.HarnessNode,
|
||||
func assertNodesPolicyUpdate(ht *lntest.HarnessTest, nodes []*node.HarnessNode,
|
||||
advertisingNode *node.HarnessNode, policy *lnrpc.RoutingPolicy,
|
||||
chanPoint *lnrpc.ChannelPoint) {
|
||||
|
||||
|
|
@ -5,7 +5,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -13,7 +13,7 @@ import (
|
|||
// testCustomMessage tests sending and receiving of overridden custom message
|
||||
// types (within the message type range usually reserved for protocol messages)
|
||||
// via the send and subscribe custom message APIs.
|
||||
func testCustomMessage(ht *lntemp.HarnessTest) {
|
||||
func testCustomMessage(ht *lntest.HarnessTest) {
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
|
||||
var (
|
||||
|
|
@ -82,7 +82,7 @@ func testCustomMessage(ht *lntemp.HarnessTest) {
|
|||
require.Equal(ht, bob.PubKey[:], msg.Peer, "first msg "+
|
||||
"peer wrong")
|
||||
|
||||
case <-time.After(defaultTimeout):
|
||||
case <-time.After(lntest.DefaultTimeout):
|
||||
ht.Fatalf("alice did not receive first custom message: %v",
|
||||
msgType)
|
||||
}
|
||||
|
|
@ -151,7 +151,7 @@ func testCustomMessage(ht *lntemp.HarnessTest) {
|
|||
require.Equal(ht, bob.PubKey[:], msg.Peer, "second "+
|
||||
"message peer")
|
||||
|
||||
case <-time.After(defaultTimeout):
|
||||
case <-time.After(lntest.DefaultTimeout):
|
||||
ht.Fatalf("alice did not receive second custom message")
|
||||
}
|
||||
}
|
||||
|
|
@ -12,12 +12,12 @@ import (
|
|||
"github.com/lightningnetwork/lnd/kvdb"
|
||||
"github.com/lightningnetwork/lnd/lncfg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func assertLeader(ht *lntemp.HarnessTest, observer cluster.LeaderElector,
|
||||
func assertLeader(ht *lntest.HarnessTest, observer cluster.LeaderElector,
|
||||
expected string) {
|
||||
|
||||
leader, err := observer.Leader(ht.Context())
|
||||
|
|
@ -29,7 +29,7 @@ func assertLeader(ht *lntemp.HarnessTest, observer cluster.LeaderElector,
|
|||
// testEtcdFailover tests that in a cluster setup where two LND nodes form a
|
||||
// single cluster (sharing the same identity) one can hand over the leader role
|
||||
// to the other (failing over after graceful shutdown or forceful abort).
|
||||
func testEtcdFailover(ht *lntemp.HarnessTest) {
|
||||
func testEtcdFailover(ht *lntest.HarnessTest) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
kill bool
|
||||
|
|
@ -54,10 +54,10 @@ func testEtcdFailover(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func testEtcdFailoverCase(ht *lntemp.HarnessTest, kill bool) {
|
||||
func testEtcdFailoverCase(ht *lntest.HarnessTest, kill bool) {
|
||||
etcdCfg, cleanup, err := kvdb.StartEtcdTestBackend(
|
||||
ht.T.TempDir(), uint16(lntest.NextAvailablePort()),
|
||||
uint16(lntest.NextAvailablePort()), "",
|
||||
ht.T.TempDir(), uint16(node.NextAvailablePort()),
|
||||
uint16(node.NextAvailablePort()), "",
|
||||
)
|
||||
require.NoError(ht, err, "Failed to start etcd instance")
|
||||
defer cleanup()
|
||||
|
|
@ -91,7 +91,7 @@ func testEtcdFailoverCase(ht *lntemp.HarnessTest, kill bool) {
|
|||
// Open a channel with 100k satoshis between Carol and Alice with Alice
|
||||
// being the sole funder of the channel.
|
||||
chanAmt := btcutil.Amount(100_000)
|
||||
ht.OpenChannel(alice, carol1, lntemp.OpenChannelParams{Amt: chanAmt})
|
||||
ht.OpenChannel(alice, carol1, lntest.OpenChannelParams{Amt: chanAmt})
|
||||
|
||||
// At this point Carol-1 is the elected leader, while Carol-2 will wait
|
||||
// to become the leader when Carol-1 stops.
|
||||
|
|
@ -9,8 +9,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/chainreg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
|
|
@ -34,7 +34,7 @@ type interceptorTestCase struct {
|
|||
|
||||
// testForwardInterceptorDedupHtlc tests that upon reconnection, duplicate
|
||||
// HTLCs aren't re-notified using the HTLC interceptor API.
|
||||
func testForwardInterceptorDedupHtlc(ht *lntemp.HarnessTest) {
|
||||
func testForwardInterceptorDedupHtlc(ht *lntest.HarnessTest) {
|
||||
// Initialize the test context with 3 connected nodes.
|
||||
ts := newInterceptorTestScenario(ht)
|
||||
|
||||
|
|
@ -42,8 +42,8 @@ func testForwardInterceptorDedupHtlc(ht *lntemp.HarnessTest) {
|
|||
|
||||
// Open and wait for channels.
|
||||
const chanAmt = btcutil.Amount(300000)
|
||||
p := lntemp.OpenChannelParams{Amt: chanAmt}
|
||||
reqs := []*lntemp.OpenChannelRequest{
|
||||
p := lntest.OpenChannelParams{Amt: chanAmt}
|
||||
reqs := []*lntest.OpenChannelRequest{
|
||||
{Local: alice, Remote: bob, Param: p},
|
||||
{Local: bob, Remote: carol, Param: p},
|
||||
}
|
||||
|
|
@ -106,6 +106,7 @@ func testForwardInterceptorDedupHtlc(ht *lntemp.HarnessTest) {
|
|||
ht.EnsureConnected(bob, alice)
|
||||
|
||||
// Here we wait for the channel to be active again.
|
||||
ht.AssertChannelExists(alice, cpAB)
|
||||
ht.AssertChannelExists(bob, cpAB)
|
||||
|
||||
// Now that the channel is active we make sure the test passes as
|
||||
|
|
@ -185,15 +186,15 @@ func testForwardInterceptorDedupHtlc(ht *lntemp.HarnessTest) {
|
|||
// 3. Intercepted held htlcs result in no payment (invoice is not settled).
|
||||
// 4. When Interceptor disconnects it resumes all held htlcs, which result in
|
||||
// valid payment (invoice is settled).
|
||||
func testForwardInterceptorBasic(ht *lntemp.HarnessTest) {
|
||||
func testForwardInterceptorBasic(ht *lntest.HarnessTest) {
|
||||
ts := newInterceptorTestScenario(ht)
|
||||
|
||||
alice, bob, carol := ts.alice, ts.bob, ts.carol
|
||||
|
||||
// Open and wait for channels.
|
||||
const chanAmt = btcutil.Amount(300000)
|
||||
p := lntemp.OpenChannelParams{Amt: chanAmt}
|
||||
reqs := []*lntemp.OpenChannelRequest{
|
||||
p := lntest.OpenChannelParams{Amt: chanAmt}
|
||||
reqs := []*lntest.OpenChannelRequest{
|
||||
{Local: alice, Remote: bob, Param: p},
|
||||
{Local: bob, Remote: carol, Param: p},
|
||||
}
|
||||
|
|
@ -296,7 +297,8 @@ func testForwardInterceptorBasic(ht *lntemp.HarnessTest) {
|
|||
restartAlice := ht.SuspendNode(alice)
|
||||
require.NoError(ht, restartAlice(), "failed to restart alice")
|
||||
|
||||
// Make sure the channel is active from Bob's PoV.
|
||||
// Make sure the channel is active from both Alice and Bob's PoV.
|
||||
ht.AssertChannelExists(alice, cpAB)
|
||||
ht.AssertChannelExists(bob, cpAB)
|
||||
|
||||
// Create a new interceptor as the old one has quit.
|
||||
|
|
@ -345,7 +347,7 @@ func testForwardInterceptorBasic(ht *lntemp.HarnessTest) {
|
|||
// interceptorTestScenario is a helper struct to hold the test context and
|
||||
// provide the needed functionality.
|
||||
type interceptorTestScenario struct {
|
||||
ht *lntemp.HarnessTest
|
||||
ht *lntest.HarnessTest
|
||||
alice, bob, carol *node.HarnessNode
|
||||
}
|
||||
|
||||
|
|
@ -356,7 +358,7 @@ type interceptorTestScenario struct {
|
|||
//
|
||||
// Among them, Alice and Bob are standby nodes and Carol is a new node.
|
||||
func newInterceptorTestScenario(
|
||||
ht *lntemp.HarnessTest) *interceptorTestScenario {
|
||||
ht *lntest.HarnessTest) *interceptorTestScenario {
|
||||
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
carol := ht.NewNode("carol", nil)
|
||||
|
|
@ -416,6 +418,7 @@ func (c *interceptorTestScenario) prepareTestCases() []*interceptorTestCase {
|
|||
t.invoice = invoice
|
||||
t.payAddr = payReq.PaymentAddr
|
||||
}
|
||||
|
||||
return cases
|
||||
}
|
||||
|
||||
|
|
@ -13,8 +13,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/labels"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -24,7 +24,7 @@ import (
|
|||
// Bob, then immediately closes the channel after asserting some expected post
|
||||
// conditions. Finally, the chain itself is checked to ensure the closing
|
||||
// transaction was mined.
|
||||
func testBasicChannelFunding(ht *lntemp.HarnessTest) {
|
||||
func testBasicChannelFunding(ht *lntest.HarnessTest) {
|
||||
// Run through the test with combinations of all the different
|
||||
// commitment types.
|
||||
allTypes := []lnrpc.CommitmentType{
|
||||
|
|
@ -35,20 +35,20 @@ func testBasicChannelFunding(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testFunding is a function closure that takes Carol and Dave's
|
||||
// commitment types and test the funding flow.
|
||||
testFunding := func(ht *lntemp.HarnessTest, carolCommitType,
|
||||
testFunding := func(ht *lntest.HarnessTest, carolCommitType,
|
||||
daveCommitType lnrpc.CommitmentType) {
|
||||
|
||||
// Based on the current tweak variable for Carol, we'll
|
||||
// preferentially signal the legacy commitment format. We do
|
||||
// the same for Dave shortly below.
|
||||
carolArgs := nodeArgsForCommitType(carolCommitType)
|
||||
carolArgs := lntest.NodeArgsForCommitType(carolCommitType)
|
||||
carol := ht.NewNode("Carol", carolArgs)
|
||||
|
||||
// Each time, we'll send Carol a new set of coins in order to
|
||||
// fund the channel.
|
||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||
|
||||
daveArgs := nodeArgsForCommitType(daveCommitType)
|
||||
daveArgs := lntest.NodeArgsForCommitType(daveCommitType)
|
||||
dave := ht.NewNode("Dave", daveArgs)
|
||||
|
||||
// Before we start the test, we'll ensure both sides are
|
||||
|
|
@ -140,7 +140,7 @@ test:
|
|||
// test. Given two nodes: Alice and Bob, it'll assert proper channel creation,
|
||||
// then return a function closure that should be called to assert proper
|
||||
// channel closure.
|
||||
func basicChannelFundingTest(ht *lntemp.HarnessTest,
|
||||
func basicChannelFundingTest(ht *lntest.HarnessTest,
|
||||
alice, bob *node.HarnessNode,
|
||||
fundingShim *lnrpc.FundingShim) (*lnrpc.Channel,
|
||||
*lnrpc.Channel, func()) {
|
||||
|
|
@ -181,7 +181,7 @@ func basicChannelFundingTest(ht *lntemp.HarnessTest,
|
|||
// assertions will be executed to ensure the funding process completed
|
||||
// successfully.
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
FundingShim: fundingShim,
|
||||
|
|
@ -193,7 +193,7 @@ func basicChannelFundingTest(ht *lntemp.HarnessTest,
|
|||
|
||||
// With the channel open, ensure that the amount specified above has
|
||||
// properly been pushed to Bob.
|
||||
aliceLocalBalance := chanAmt - pushAmt - calcStaticFee(cType, 0)
|
||||
aliceLocalBalance := chanAmt - pushAmt - lntest.CalcStaticFee(cType, 0)
|
||||
checkChannelBalance(
|
||||
alice, aliceChannelBalance, aliceLocalBalance, pushAmt,
|
||||
)
|
||||
|
|
@ -216,7 +216,7 @@ func basicChannelFundingTest(ht *lntemp.HarnessTest,
|
|||
|
||||
// testUnconfirmedChannelFunding tests that our unconfirmed change outputs can
|
||||
// be used to fund channels.
|
||||
func testUnconfirmedChannelFunding(ht *lntemp.HarnessTest) {
|
||||
func testUnconfirmedChannelFunding(ht *lntest.HarnessTest) {
|
||||
const (
|
||||
chanAmt = funding.MaxBtcFundingAmount
|
||||
pushAmt = btcutil.Amount(100000)
|
||||
|
|
@ -236,7 +236,7 @@ func testUnconfirmedChannelFunding(ht *lntemp.HarnessTest) {
|
|||
ht.ConnectNodes(carol, alice)
|
||||
|
||||
chanOpenUpdate := ht.OpenChannelAssertStream(
|
||||
carol, alice, lntemp.OpenChannelParams{
|
||||
carol, alice, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
SpendUnconfirmed: true,
|
||||
|
|
@ -289,7 +289,7 @@ func testUnconfirmedChannelFunding(ht *lntemp.HarnessTest) {
|
|||
// Note that atm we haven't obtained the chanPoint yet, so we use the
|
||||
// type directly.
|
||||
cType := lnrpc.CommitmentType_STATIC_REMOTE_KEY
|
||||
carolLocalBalance := chanAmt - pushAmt - calcStaticFee(cType, 0)
|
||||
carolLocalBalance := chanAmt - pushAmt - lntest.CalcStaticFee(cType, 0)
|
||||
checkChannelBalance(carol, 0, 0, carolLocalBalance, pushAmt)
|
||||
|
||||
// For Alice, her local/remote balances should be zero, and the
|
||||
|
|
@ -329,7 +329,12 @@ func testUnconfirmedChannelFunding(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testChannelFundingInputTypes tests that any type of supported input type can
|
||||
// be used to fund channels.
|
||||
func testChannelFundingInputTypes(ht *lntemp.HarnessTest) {
|
||||
func testChannelFundingInputTypes(ht *lntest.HarnessTest) {
|
||||
const (
|
||||
chanAmt = funding.MaxBtcFundingAmount
|
||||
burnAddr = "bcrt1qxsnqpdc842lu8c0xlllgvejt6rhy49u6fmpgyz"
|
||||
)
|
||||
|
||||
// We'll start off by creating a node for Carol.
|
||||
carol := ht.NewNode("Carol", nil)
|
||||
|
||||
|
|
@ -342,7 +347,7 @@ func testChannelFundingInputTypes(ht *lntemp.HarnessTest) {
|
|||
|
||||
// runChannelFundingInputTypes tests that any type of supported input type can
|
||||
// be used to fund channels.
|
||||
func runChannelFundingInputTypes(ht *lntemp.HarnessTest, alice,
|
||||
func runChannelFundingInputTypes(ht *lntest.HarnessTest, alice,
|
||||
carol *node.HarnessNode) {
|
||||
|
||||
const (
|
||||
|
|
@ -411,7 +416,7 @@ func runChannelFundingInputTypes(ht *lntemp.HarnessTest, alice,
|
|||
funder((chanAmt*11)/10, carol)
|
||||
|
||||
chanOpenUpdate := ht.OpenChannelAssertStream(
|
||||
carol, alice, lntemp.OpenChannelParams{
|
||||
carol, alice, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
},
|
||||
)
|
||||
|
|
@ -423,7 +428,7 @@ func runChannelFundingInputTypes(ht *lntemp.HarnessTest, alice,
|
|||
// Note that atm we haven't obtained the chanPoint yet, so we
|
||||
// use the type directly.
|
||||
cType := lnrpc.CommitmentType_STATIC_REMOTE_KEY
|
||||
carolLocalBalance := chanAmt - calcStaticFee(cType, 0)
|
||||
carolLocalBalance := chanAmt - lntest.CalcStaticFee(cType, 0)
|
||||
checkChannelBalance(carol, 0, 0, carolLocalBalance, 0)
|
||||
|
||||
// For Alice, her local/remote balances should be zero, and the
|
||||
|
|
@ -463,7 +468,7 @@ func runChannelFundingInputTypes(ht *lntemp.HarnessTest, alice,
|
|||
|
||||
// sendAllCoinsConfirm sends all coins of the node's wallet to the given address
|
||||
// and awaits one confirmation.
|
||||
func sendAllCoinsConfirm(ht *lntemp.HarnessTest, node *node.HarnessNode,
|
||||
func sendAllCoinsConfirm(ht *lntest.HarnessTest, node *node.HarnessNode,
|
||||
addr string) {
|
||||
|
||||
sweepReq := &lnrpc.SendCoinsRequest{
|
||||
|
|
@ -477,7 +482,7 @@ func sendAllCoinsConfirm(ht *lntemp.HarnessTest, node *node.HarnessNode,
|
|||
// testExternalFundingChanPoint tests that we're able to carry out a normal
|
||||
// channel funding workflow given a channel point that was constructed outside
|
||||
// the main daemon.
|
||||
func testExternalFundingChanPoint(ht *lntemp.HarnessTest) {
|
||||
func testExternalFundingChanPoint(ht *lntest.HarnessTest) {
|
||||
// First, we'll create two new nodes that we'll use to open channel
|
||||
// between for this test.
|
||||
carol := ht.NewNode("carol", nil)
|
||||
|
|
@ -496,11 +501,11 @@ func testExternalFundingChanPoint(ht *lntemp.HarnessTest) {
|
|||
// a transaction that will never be published.
|
||||
const thawHeight uint32 = 10
|
||||
const chanSize = funding.MaxBtcFundingAmount
|
||||
fundingShim1, chanPoint1, _ := deriveFundingShim(
|
||||
fundingShim1, chanPoint1 := deriveFundingShim(
|
||||
ht, carol, dave, chanSize, thawHeight, false,
|
||||
)
|
||||
ht.OpenChannelAssertPending(
|
||||
carol, dave, lntemp.OpenChannelParams{
|
||||
carol, dave, lntest.OpenChannelParams{
|
||||
Amt: chanSize,
|
||||
FundingShim: fundingShim1,
|
||||
},
|
||||
|
|
@ -512,7 +517,7 @@ func testExternalFundingChanPoint(ht *lntemp.HarnessTest) {
|
|||
// externally funded, we should still be able to open another one. Let's
|
||||
// do exactly that now. For this one we publish the transaction so we
|
||||
// can mine it later.
|
||||
fundingShim2, chanPoint2, _ := deriveFundingShim(
|
||||
fundingShim2, chanPoint2 := deriveFundingShim(
|
||||
ht, carol, dave, chanSize, thawHeight, true,
|
||||
)
|
||||
|
||||
|
|
@ -591,7 +596,7 @@ func testExternalFundingChanPoint(ht *lntemp.HarnessTest) {
|
|||
// representation of channels if the system is restarted or disconnected.
|
||||
// testFundingPersistence mirrors testBasicChannelFunding, but adds restarts
|
||||
// and checks for the state of channels with unconfirmed funding transactions.
|
||||
func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
|
||||
func testChannelFundingPersistence(ht *lntest.HarnessTest) {
|
||||
chanAmt := funding.MaxBtcFundingAmount
|
||||
pushAmt := btcutil.Amount(0)
|
||||
|
||||
|
|
@ -609,7 +614,7 @@ func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
|
|||
|
||||
// Create a new channel that requires 5 confs before it's considered
|
||||
// open, then broadcast the funding transaction
|
||||
param := lntemp.OpenChannelParams{
|
||||
param := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
}
|
||||
|
|
@ -676,7 +681,7 @@ func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
|
|||
|
||||
// The channel should be listed in the peer information returned by
|
||||
// both peers.
|
||||
chanPoint := lntemp.ChanPointFromPendingUpdate(update)
|
||||
chanPoint := lntest.ChanPointFromPendingUpdate(update)
|
||||
|
||||
// Re-lookup our transaction in the block that it confirmed in.
|
||||
tx = ht.AssertTxAtHeight(alice, height, fundingTxID)
|
||||
|
|
@ -685,6 +690,11 @@ func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
|
|||
chanAlice := ht.AssertChannelExists(alice, chanPoint)
|
||||
ht.AssertChannelExists(carol, chanPoint)
|
||||
|
||||
// Make sure Alice and Carol have seen the channel in their network
|
||||
// topology.
|
||||
ht.AssertTopologyChannelOpen(alice, chanPoint)
|
||||
ht.AssertTopologyChannelOpen(carol, chanPoint)
|
||||
|
||||
// Create an additional check for our channel assertion that will
|
||||
// check that our label is as expected.
|
||||
shortChanID := lnwire.NewShortChanIDFromInt(chanAlice.ChanId)
|
||||
|
|
@ -699,7 +709,7 @@ func testChannelFundingPersistence(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testBatchChanFunding makes sure multiple channels can be opened in one batch
|
||||
// transaction in an atomic way.
|
||||
func testBatchChanFunding(ht *lntemp.HarnessTest) {
|
||||
func testBatchChanFunding(ht *lntest.HarnessTest) {
|
||||
// First, we'll create two new nodes that we'll use to open channels
|
||||
// to during this test. Carol has a high minimum funding amount that
|
||||
// we'll use to trigger an error during the batch channel open.
|
||||
|
|
@ -793,10 +803,10 @@ func testBatchChanFunding(ht *lntemp.HarnessTest) {
|
|||
|
||||
// deriveFundingShim creates a channel funding shim by deriving the necessary
|
||||
// keys on both sides.
|
||||
func deriveFundingShim(ht *lntemp.HarnessTest,
|
||||
func deriveFundingShim(ht *lntest.HarnessTest,
|
||||
carol, dave *node.HarnessNode, chanSize btcutil.Amount,
|
||||
thawHeight uint32, publish bool) (*lnrpc.FundingShim,
|
||||
*lnrpc.ChannelPoint, *chainhash.Hash) {
|
||||
*lnrpc.ChannelPoint) {
|
||||
|
||||
keyLoc := &signrpc.KeyLocator{KeyFamily: 9999}
|
||||
carolFundingKey := carol.RPC.DeriveKey(keyLoc)
|
||||
|
|
@ -882,5 +892,5 @@ func deriveFundingShim(ht *lntemp.HarnessTest,
|
|||
}
|
||||
fundingShim.GetChanPointShim().RemoteKey = daveFundingKey.RawKeyBytes
|
||||
|
||||
return fundingShim, chanPoint, txid
|
||||
return fundingShim, chanPoint
|
||||
}
|
||||
|
|
@ -7,7 +7,7 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -15,11 +15,11 @@ import (
|
|||
|
||||
// testHoldInvoiceForceClose tests cancellation of accepted hold invoices which
|
||||
// would otherwise trigger force closes when they expire.
|
||||
func testHoldInvoiceForceClose(ht *lntemp.HarnessTest) {
|
||||
func testHoldInvoiceForceClose(ht *lntest.HarnessTest) {
|
||||
// Open a channel between alice and bob.
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: 300000},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: 300000},
|
||||
)
|
||||
|
||||
// Create a non-dust hold invoice for bob.
|
||||
|
|
@ -7,8 +7,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -17,7 +17,7 @@ import (
|
|||
// testHoldInvoicePersistence tests that a sender to a hold-invoice, can be
|
||||
// restarted before the payment gets settled, and still be able to receive the
|
||||
// preimage.
|
||||
func testHoldInvoicePersistence(ht *lntemp.HarnessTest) {
|
||||
func testHoldInvoicePersistence(ht *lntest.HarnessTest) {
|
||||
const (
|
||||
chanAmt = btcutil.Amount(1000000)
|
||||
numPayments = 10
|
||||
|
|
@ -34,7 +34,7 @@ func testHoldInvoicePersistence(ht *lntemp.HarnessTest) {
|
|||
// Open a channel between Alice and Carol which is private so that we
|
||||
// cover the addition of hop hints for hold invoices.
|
||||
chanPointAlice := ht.OpenChannel(
|
||||
alice, carol, lntemp.OpenChannelParams{
|
||||
alice, carol, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
Private: true,
|
||||
},
|
||||
|
|
@ -45,7 +45,7 @@ func testHoldInvoicePersistence(ht *lntemp.HarnessTest) {
|
|||
// has at least one public channel in the graph. We open a public
|
||||
// channel from Alice -> Bob and wait for Carol to see it.
|
||||
chanPointBob := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
},
|
||||
)
|
||||
|
|
@ -11,8 +11,8 @@ import (
|
|||
|
||||
"github.com/golang/protobuf/proto"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -23,7 +23,7 @@ import (
|
|||
// enabled on the gRPC interface, no requests with missing or invalid
|
||||
// macaroons are allowed. Further, the specific access rights (read/write,
|
||||
// entity based) and first-party caveats are tested as well.
|
||||
func testMacaroonAuthentication(ht *lntemp.HarnessTest) {
|
||||
func testMacaroonAuthentication(ht *lntest.HarnessTest) {
|
||||
var (
|
||||
infoReq = &lnrpc.GetInfoRequest{}
|
||||
newAddrReq = &lnrpc.NewAddressRequest{
|
||||
|
|
@ -294,7 +294,7 @@ func testMacaroonAuthentication(ht *lntemp.HarnessTest) {
|
|||
// testBakeMacaroon checks that when creating macaroons, the permissions param
|
||||
// in the request must be set correctly, and the baked macaroon has the intended
|
||||
// permissions.
|
||||
func testBakeMacaroon(ht *lntemp.HarnessTest) {
|
||||
func testBakeMacaroon(ht *lntest.HarnessTest) {
|
||||
var testNode = ht.Alice
|
||||
|
||||
testCases := []struct {
|
||||
|
|
@ -518,7 +518,7 @@ func testBakeMacaroon(ht *lntemp.HarnessTest) {
|
|||
// specified ID and invalidates all macaroons derived from the key with that ID.
|
||||
// Also, it checks deleting the reserved marcaroon ID, DefaultRootKeyID or is
|
||||
// forbidden.
|
||||
func testDeleteMacaroonID(ht *lntemp.HarnessTest) {
|
||||
func testDeleteMacaroonID(ht *lntest.HarnessTest) {
|
||||
var (
|
||||
ctxb = ht.Context()
|
||||
testNode = ht.Alice
|
||||
|
|
@ -610,7 +610,7 @@ func testDeleteMacaroonID(ht *lntemp.HarnessTest) {
|
|||
// does not write any macaroon files to the daemon's file system and returns
|
||||
// the admin macaroon in the response. It then checks that the password
|
||||
// change of the wallet can also happen stateless.
|
||||
func testStatelessInit(ht *lntemp.HarnessTest) {
|
||||
func testStatelessInit(ht *lntest.HarnessTest) {
|
||||
var (
|
||||
initPw = []byte("stateless")
|
||||
newPw = []byte("stateless-new")
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
//go:build rpctest
|
||||
// +build rpctest
|
||||
|
||||
package itest
|
||||
|
||||
import (
|
||||
|
|
@ -8,14 +5,14 @@ import (
|
|||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/funding"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
)
|
||||
|
||||
// testMaxChannelSize tests that lnd handles --maxchansize parameter correctly.
|
||||
// Wumbo nodes should enforce a default soft limit of 10 BTC by default. This
|
||||
// limit can be adjusted with --maxchansize config option.
|
||||
func testMaxChannelSize(ht *lntemp.HarnessTest) {
|
||||
func testMaxChannelSize(ht *lntest.HarnessTest) {
|
||||
// We'll make two new nodes, both wumbo but with the default limit on
|
||||
// maximum channel size (10 BTC)
|
||||
wumboNode := ht.NewNode(
|
||||
|
|
@ -42,7 +39,7 @@ func testMaxChannelSize(ht *lntemp.HarnessTest) {
|
|||
)
|
||||
ht.OpenChannelAssertErr(
|
||||
wumboNode, wumboNode2,
|
||||
lntemp.OpenChannelParams{Amt: chanAmt}, expectedErr,
|
||||
lntest.OpenChannelParams{Amt: chanAmt}, expectedErr,
|
||||
)
|
||||
|
||||
// We'll now make another wumbo node with appropriate maximum channel
|
||||
|
|
@ -60,7 +57,7 @@ func testMaxChannelSize(ht *lntemp.HarnessTest) {
|
|||
// Creating a wumbo channel between these two nodes should succeed.
|
||||
ht.EnsureConnected(wumboNode, wumboNode3)
|
||||
chanPoint := ht.OpenChannel(
|
||||
wumboNode, wumboNode3, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
wumboNode, wumboNode3, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
ht.CloseChannel(wumboNode, chanPoint)
|
||||
|
|
@ -4,8 +4,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -14,14 +14,14 @@ import (
|
|||
// channel where we have already reached the limit of the number of htlcs that
|
||||
// we may add to the remote party's commitment. This test asserts that we do
|
||||
// not attempt to use the full channel at all in our pathfinding.
|
||||
func testMaxHtlcPathfind(ht *lntemp.HarnessTest) {
|
||||
func testMaxHtlcPathfind(ht *lntest.HarnessTest) {
|
||||
// Setup a channel between Alice and Bob where Alice will only allow
|
||||
// Bob to add a maximum of 5 htlcs to her commitment.
|
||||
maxHtlcs := 5
|
||||
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: 1000000,
|
||||
PushAmt: 800000,
|
||||
RemoteMaxHtlcs: uint16(maxHtlcs),
|
||||
|
|
@ -84,7 +84,7 @@ type holdSubscription struct {
|
|||
|
||||
// cancel updates a hold invoice to cancel from the recipient and consumes
|
||||
// updates from the payer until it has reached a final, failed state.
|
||||
func (h *holdSubscription) cancel(ht *lntemp.HarnessTest) {
|
||||
func (h *holdSubscription) cancel(ht *lntest.HarnessTest) {
|
||||
h.recipient.RPC.CancelInvoice(h.hash[:])
|
||||
|
||||
invUpdate := ht.ReceiveSingleInvoice(h.invSubscription)
|
||||
|
|
@ -110,7 +110,7 @@ func (h *holdSubscription) cancel(ht *lntemp.HarnessTest) {
|
|||
// acceptHoldInvoice adds a hold invoice to the recipient node, pays it from
|
||||
// the sender and asserts that we have reached the accepted state where htlcs
|
||||
// are locked in for the payment.
|
||||
func acceptHoldInvoice(ht *lntemp.HarnessTest, idx int, sender,
|
||||
func acceptHoldInvoice(ht *lntest.HarnessTest, idx int, sender,
|
||||
receiver *node.HarnessNode) *holdSubscription {
|
||||
|
||||
hash := [lntypes.HashSize]byte{byte(idx + 1)}
|
||||
|
|
@ -15,8 +15,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
|
|
@ -28,7 +28,7 @@ import (
|
|||
// disconnect at any point.
|
||||
//
|
||||
// TODO(yy): move to lnd_network_test.
|
||||
func testDisconnectingTargetPeer(ht *lntemp.HarnessTest) {
|
||||
func testDisconnectingTargetPeer(ht *lntest.HarnessTest) {
|
||||
// We'll start both nodes with a high backoff so that they don't
|
||||
// reconnect automatically during our test.
|
||||
args := []string{
|
||||
|
|
@ -49,7 +49,7 @@ func testDisconnectingTargetPeer(ht *lntemp.HarnessTest) {
|
|||
// Create a new channel that requires 1 confs before it's considered
|
||||
// open, then broadcast the funding transaction
|
||||
const numConfs = 1
|
||||
p := lntemp.OpenChannelParams{
|
||||
p := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
}
|
||||
|
|
@ -119,7 +119,7 @@ func testDisconnectingTargetPeer(ht *lntemp.HarnessTest) {
|
|||
// configuration arguments to force Carol to replay the same sphinx packet
|
||||
// after reconnecting to Dave, and compare the returned failure message with
|
||||
// what we expect for replayed onion packets.
|
||||
func testSphinxReplayPersistence(ht *lntemp.HarnessTest) {
|
||||
func testSphinxReplayPersistence(ht *lntest.HarnessTest) {
|
||||
// Open a channel with 100k satoshis between Carol and Dave with Carol
|
||||
// being the sole funder of the channel.
|
||||
chanAmt := btcutil.Amount(100000)
|
||||
|
|
@ -135,7 +135,7 @@ func testSphinxReplayPersistence(ht *lntemp.HarnessTest) {
|
|||
|
||||
ht.ConnectNodes(carol, dave)
|
||||
chanPoint := ht.OpenChannel(
|
||||
carol, dave, lntemp.OpenChannelParams{
|
||||
carol, dave, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
},
|
||||
)
|
||||
|
|
@ -150,7 +150,7 @@ func testSphinxReplayPersistence(ht *lntemp.HarnessTest) {
|
|||
|
||||
ht.ConnectNodes(fred, carol)
|
||||
chanPointFC := ht.OpenChannel(
|
||||
fred, carol, lntemp.OpenChannelParams{
|
||||
fred, carol, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
},
|
||||
)
|
||||
|
|
@ -232,7 +232,7 @@ func testSphinxReplayPersistence(ht *lntemp.HarnessTest) {
|
|||
// tests the values in all ChannelConstraints are returned as expected. Once
|
||||
// ListChannels becomes mature, a test against all fields in ListChannels
|
||||
// should be performed.
|
||||
func testListChannels(ht *lntemp.HarnessTest) {
|
||||
func testListChannels(ht *lntest.HarnessTest) {
|
||||
const aliceRemoteMaxHtlcs = 50
|
||||
const bobRemoteMaxHtlcs = 100
|
||||
|
||||
|
|
@ -255,7 +255,7 @@ func testListChannels(ht *lntemp.HarnessTest) {
|
|||
|
||||
chanAmt := btcutil.Amount(100000)
|
||||
pushAmt := btcutil.Amount(1000)
|
||||
p := lntemp.OpenChannelParams{
|
||||
p := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
MinHtlc: customizedMinHtlc,
|
||||
|
|
@ -337,7 +337,7 @@ func testListChannels(ht *lntemp.HarnessTest) {
|
|||
// testMaxPendingChannels checks that error is returned from remote peer if
|
||||
// max pending channel number was exceeded and that '--maxpendingchannels' flag
|
||||
// exists and works properly.
|
||||
func testMaxPendingChannels(ht *lntemp.HarnessTest) {
|
||||
func testMaxPendingChannels(ht *lntest.HarnessTest) {
|
||||
maxPendingChannels := lncfg.DefaultMaxPendingChannels + 1
|
||||
amount := funding.MaxBtcFundingAmount
|
||||
|
||||
|
|
@ -362,7 +362,7 @@ func testMaxPendingChannels(ht *lntemp.HarnessTest) {
|
|||
)
|
||||
for i := 0; i < maxPendingChannels; i++ {
|
||||
stream := ht.OpenChannelAssertStream(
|
||||
alice, carol, lntemp.OpenChannelParams{
|
||||
alice, carol, lntest.OpenChannelParams{
|
||||
Amt: amount,
|
||||
},
|
||||
)
|
||||
|
|
@ -372,7 +372,7 @@ func testMaxPendingChannels(ht *lntemp.HarnessTest) {
|
|||
// Carol exhausted available amount of pending channels, next open
|
||||
// channel request should cause ErrorGeneric to be sent back to Alice.
|
||||
ht.OpenChannelAssertErr(
|
||||
alice, carol, lntemp.OpenChannelParams{
|
||||
alice, carol, lntest.OpenChannelParams{
|
||||
Amt: amount,
|
||||
}, lnwire.ErrMaxPendingChannels,
|
||||
)
|
||||
|
|
@ -415,7 +415,7 @@ func testMaxPendingChannels(ht *lntemp.HarnessTest) {
|
|||
// testGarbageCollectLinkNodes tests that we properly garbage collect link
|
||||
// nodes from the database and the set of persistent connections within the
|
||||
// server.
|
||||
func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
|
||||
func testGarbageCollectLinkNodes(ht *lntest.HarnessTest) {
|
||||
const chanAmt = 1000000
|
||||
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
|
|
@ -423,7 +423,7 @@ func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
|
|||
// Open a channel between Alice and Bob which will later be
|
||||
// cooperatively closed.
|
||||
coopChanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
},
|
||||
)
|
||||
|
|
@ -435,7 +435,7 @@ func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
|
|||
// Open a channel between Alice and Carol which will later be force
|
||||
// closed.
|
||||
forceCloseChanPoint := ht.OpenChannel(
|
||||
alice, carol, lntemp.OpenChannelParams{
|
||||
alice, carol, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
},
|
||||
)
|
||||
|
|
@ -447,7 +447,7 @@ func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
|
|||
|
||||
ht.ConnectNodes(alice, dave)
|
||||
persistentChanPoint := ht.OpenChannel(
|
||||
alice, dave, lntemp.OpenChannelParams{
|
||||
alice, dave, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
},
|
||||
)
|
||||
|
|
@ -527,7 +527,7 @@ func testGarbageCollectLinkNodes(ht *lntemp.HarnessTest) {
|
|||
// testRejectHTLC tests that a node can be created with the flag --rejecthtlc.
|
||||
// This means that the node will reject all forwarded HTLCs but can still
|
||||
// accept direct HTLCs as well as send HTLCs.
|
||||
func testRejectHTLC(ht *lntemp.HarnessTest) {
|
||||
func testRejectHTLC(ht *lntest.HarnessTest) {
|
||||
// RejectHTLC
|
||||
// Alice ------> Carol ------> Bob
|
||||
//
|
||||
|
|
@ -548,14 +548,14 @@ func testRejectHTLC(ht *lntemp.HarnessTest) {
|
|||
|
||||
// Open a channel between Alice and Carol.
|
||||
chanPointAlice := ht.OpenChannel(
|
||||
alice, carol, lntemp.OpenChannelParams{
|
||||
alice, carol, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
},
|
||||
)
|
||||
|
||||
// Open a channel between Carol and Bob.
|
||||
chanPointCarol := ht.OpenChannel(
|
||||
carol, bob, lntemp.OpenChannelParams{
|
||||
carol, bob, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
},
|
||||
)
|
||||
|
|
@ -623,14 +623,14 @@ func testRejectHTLC(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testNodeSignVerify checks that only connected nodes are allowed to perform
|
||||
// signing and verifying messages.
|
||||
func testNodeSignVerify(ht *lntemp.HarnessTest) {
|
||||
func testNodeSignVerify(ht *lntest.HarnessTest) {
|
||||
chanAmt := funding.MaxBtcFundingAmount
|
||||
pushAmt := btcutil.Amount(100000)
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
|
||||
// Create a channel between alice and bob.
|
||||
aliceBobCh := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
},
|
||||
|
|
@ -670,11 +670,11 @@ func testNodeSignVerify(ht *lntemp.HarnessTest) {
|
|||
// testAbandonChannel abandons a channel and asserts that it is no longer open
|
||||
// and not in one of the pending closure states. It also verifies that the
|
||||
// abandoned channel is reported as closed with close type 'abandoned'.
|
||||
func testAbandonChannel(ht *lntemp.HarnessTest) {
|
||||
func testAbandonChannel(ht *lntest.HarnessTest) {
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
|
||||
// First establish a channel between Alice and Bob.
|
||||
channelParam := lntemp.OpenChannelParams{
|
||||
channelParam := lntest.OpenChannelParams{
|
||||
Amt: funding.MaxBtcFundingAmount,
|
||||
PushAmt: btcutil.Amount(100000),
|
||||
}
|
||||
|
|
@ -741,7 +741,7 @@ func testAbandonChannel(ht *lntemp.HarnessTest) {
|
|||
// wallet into a single target address at the specified fee rate.
|
||||
//
|
||||
// TODO(yy): expand this test to also use P2TR.
|
||||
func testSweepAllCoins(ht *lntemp.HarnessTest) {
|
||||
func testSweepAllCoins(ht *lntest.HarnessTest) {
|
||||
// First, we'll make a new node, ainz who'll we'll use to test wallet
|
||||
// sweeping.
|
||||
//
|
||||
|
|
@ -917,7 +917,7 @@ func testSweepAllCoins(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testListAddresses tests that we get all the addresses and their
|
||||
// corresponding balance correctly.
|
||||
func testListAddresses(ht *lntemp.HarnessTest) {
|
||||
func testListAddresses(ht *lntest.HarnessTest) {
|
||||
// First, we'll make a new node - Alice, which will be generating
|
||||
// new addresses.
|
||||
alice := ht.NewNode("Alice", nil)
|
||||
|
|
@ -964,7 +964,8 @@ func testListAddresses(ht *lntemp.HarnessTest) {
|
|||
})
|
||||
generatedAddr[resp.Address] = addressDetails{
|
||||
Balance: 400_000,
|
||||
Type: walletrpc.AddressType_HYBRID_NESTED_WITNESS_PUBKEY_HASH,
|
||||
Type: walletrpc.
|
||||
AddressType_HYBRID_NESTED_WITNESS_PUBKEY_HASH,
|
||||
}
|
||||
|
||||
for addr, addressDetail := range generatedAddr {
|
||||
|
|
@ -985,7 +986,7 @@ func testListAddresses(ht *lntemp.HarnessTest) {
|
|||
foundAddresses := 0
|
||||
for _, addressList := range addressLists.AccountWithAddresses {
|
||||
addresses := addressList.Addresses
|
||||
derivationPath, err := lntemp.ParseDerivationPath(
|
||||
derivationPath, err := lntest.ParseDerivationPath(
|
||||
addressList.DerivationPath,
|
||||
)
|
||||
require.NoError(ht, err)
|
||||
|
|
@ -1023,7 +1024,7 @@ func testListAddresses(ht *lntemp.HarnessTest) {
|
|||
|
||||
for _, addressList := range addressLists.AccountWithAddresses {
|
||||
addresses := addressList.Addresses
|
||||
derivationPath, err := lntemp.ParseDerivationPath(
|
||||
derivationPath, err := lntest.ParseDerivationPath(
|
||||
addressList.DerivationPath,
|
||||
)
|
||||
require.NoError(ht, err)
|
||||
|
|
@ -1053,7 +1054,7 @@ func testListAddresses(ht *lntemp.HarnessTest) {
|
|||
require.Equal(ht, len(generatedAddr), foundAddresses)
|
||||
}
|
||||
|
||||
func assertChannelConstraintsEqual(ht *lntemp.HarnessTest,
|
||||
func assertChannelConstraintsEqual(ht *lntest.HarnessTest,
|
||||
want, got *lnrpc.ChannelConstraints) {
|
||||
|
||||
require.Equal(ht, want.CsvDelay, got.CsvDelay, "CsvDelay mismatched")
|
||||
|
|
@ -1076,7 +1077,7 @@ func assertChannelConstraintsEqual(ht *lntemp.HarnessTest,
|
|||
|
||||
// testSignVerifyMessageWithAddr tests signing and also verifying a signature
|
||||
// on a message with a provided address.
|
||||
func testSignVerifyMessageWithAddr(ht *lntemp.HarnessTest) {
|
||||
func testSignVerifyMessageWithAddr(ht *lntest.HarnessTest) {
|
||||
// Using different nodes to sign the message and verify the signature.
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
|
||||
|
|
@ -7,8 +7,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/chainreg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -16,7 +16,7 @@ import (
|
|||
|
||||
// testSendToRouteMultiPath tests that we are able to successfully route a
|
||||
// payment using multiple shards across different paths, by using SendToRoute.
|
||||
func testSendToRouteMultiPath(ht *lntemp.HarnessTest) {
|
||||
func testSendToRouteMultiPath(ht *lntest.HarnessTest) {
|
||||
mts := newMppTestScenario(ht)
|
||||
|
||||
// To ensure the payment goes through separate paths, we'll set a
|
||||
|
|
@ -162,7 +162,7 @@ func testSendToRouteMultiPath(ht *lntemp.HarnessTest) {
|
|||
// It has two standby nodes, alice and bob, and three new nodes, carol, dave,
|
||||
// and eve.
|
||||
type mppTestScenario struct {
|
||||
ht *lntemp.HarnessTest
|
||||
ht *lntest.HarnessTest
|
||||
|
||||
alice, bob, carol, dave, eve *node.HarnessNode
|
||||
nodes []*node.HarnessNode
|
||||
|
|
@ -179,7 +179,7 @@ type mppTestScenario struct {
|
|||
// Alice -- Carol ---- Bob
|
||||
// \ /
|
||||
// \__ Dave ____/
|
||||
func newMppTestScenario(ht *lntemp.HarnessTest) *mppTestScenario {
|
||||
func newMppTestScenario(ht *lntest.HarnessTest) *mppTestScenario {
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
ht.RestartNodeWithExtraArgs(bob, []string{
|
||||
"--maxpendingchannels=2",
|
||||
|
|
@ -256,36 +256,36 @@ type mppOpenChannelRequest struct {
|
|||
//
|
||||
// NOTE: all the channels are open together to save blocks mined.
|
||||
func (m *mppTestScenario) openChannels(r *mppOpenChannelRequest) {
|
||||
reqs := []*lntemp.OpenChannelRequest{
|
||||
reqs := []*lntest.OpenChannelRequest{
|
||||
{
|
||||
Local: m.alice,
|
||||
Remote: m.carol,
|
||||
Param: lntemp.OpenChannelParams{Amt: r.amtAliceCarol},
|
||||
Param: lntest.OpenChannelParams{Amt: r.amtAliceCarol},
|
||||
},
|
||||
{
|
||||
Local: m.alice,
|
||||
Remote: m.dave,
|
||||
Param: lntemp.OpenChannelParams{Amt: r.amtAliceDave},
|
||||
Param: lntest.OpenChannelParams{Amt: r.amtAliceDave},
|
||||
},
|
||||
{
|
||||
Local: m.carol,
|
||||
Remote: m.bob,
|
||||
Param: lntemp.OpenChannelParams{Amt: r.amtCarolBob},
|
||||
Param: lntest.OpenChannelParams{Amt: r.amtCarolBob},
|
||||
},
|
||||
{
|
||||
Local: m.carol,
|
||||
Remote: m.eve,
|
||||
Param: lntemp.OpenChannelParams{Amt: r.amtCarolEve},
|
||||
Param: lntest.OpenChannelParams{Amt: r.amtCarolEve},
|
||||
},
|
||||
{
|
||||
Local: m.dave,
|
||||
Remote: m.bob,
|
||||
Param: lntemp.OpenChannelParams{Amt: r.amtDaveBob},
|
||||
Param: lntest.OpenChannelParams{Amt: r.amtDaveBob},
|
||||
},
|
||||
{
|
||||
Local: m.eve,
|
||||
Remote: m.bob,
|
||||
Param: lntemp.OpenChannelParams{Amt: r.amtEveBob},
|
||||
Param: lntest.OpenChannelParams{Amt: r.amtEveBob},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -313,7 +313,7 @@ func (m *mppTestScenario) closeChannels() {
|
|||
// active htlcs` or `link failed to shutdown` if we close the channel.
|
||||
// We need to investigate the order of settling the payments and
|
||||
// updating commitments to understand and fix .
|
||||
time.Sleep(2 * time.Second)
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// Close all channels without mining the closing transactions.
|
||||
m.ht.CloseChannelAssertPending(m.alice, m.channelPoints[0], false)
|
||||
|
|
@ -6,12 +6,12 @@ import (
|
|||
"github.com/lightningnetwork/lnd/funding"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
||||
func testHtlcErrorPropagation(ht *lntest.HarnessTest) {
|
||||
// In this test we wish to exercise the daemon's correct parsing,
|
||||
// handling, and propagation of errors that occur while processing a
|
||||
// multi-hop payment.
|
||||
|
|
@ -39,23 +39,22 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
|||
// and Bob.
|
||||
chanPointAlice := ht.OpenChannel(
|
||||
alice, bob,
|
||||
lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Next, we'll create a connection from Bob to Carol, and open a
|
||||
// channel between them so we have the topology: Alice -> Bob -> Carol.
|
||||
// The channel created will be of lower capacity that the one created
|
||||
// above.
|
||||
const bobChanAmt = funding.MaxBtcFundingAmount
|
||||
chanPointBob := ht.OpenChannel(
|
||||
bob, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
bob, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Ensure that Alice has Carol in her routing table before proceeding.
|
||||
ht.AssertTopologyChannelOpen(alice, chanPointBob)
|
||||
|
||||
cType := ht.GetChannelCommitType(alice, chanPointAlice)
|
||||
commitFee := calcStaticFee(cType, 0)
|
||||
commitFee := lntest.CalcStaticFee(cType, 0)
|
||||
|
||||
assertBaseBalance := func() {
|
||||
// Alice has opened a channel with Bob with zero push amount,
|
||||
|
|
@ -153,24 +152,24 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
|||
assertAliceAndBob := func() {
|
||||
ht.AssertHtlcEventTypes(
|
||||
aliceEvents, routerrpc.HtlcEvent_SEND,
|
||||
lntemp.HtlcEventForward,
|
||||
lntest.HtlcEventForward,
|
||||
)
|
||||
ht.AssertHtlcEventTypes(
|
||||
aliceEvents, routerrpc.HtlcEvent_SEND,
|
||||
lntemp.HtlcEventForwardFail,
|
||||
lntest.HtlcEventForwardFail,
|
||||
)
|
||||
|
||||
ht.AssertHtlcEventTypes(
|
||||
bobEvents, routerrpc.HtlcEvent_FORWARD,
|
||||
lntemp.HtlcEventForward,
|
||||
lntest.HtlcEventForward,
|
||||
)
|
||||
ht.AssertHtlcEventTypes(
|
||||
bobEvents, routerrpc.HtlcEvent_FORWARD,
|
||||
lntemp.HtlcEventForwardFail,
|
||||
lntest.HtlcEventForwardFail,
|
||||
)
|
||||
ht.AssertHtlcEventTypes(
|
||||
bobEvents, routerrpc.HtlcEvent_UNKNOWN,
|
||||
lntemp.HtlcEventFinal,
|
||||
lntest.HtlcEventFinal,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +187,7 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
|||
// There's also a final htlc event that gives the final outcome of the
|
||||
// htlc.
|
||||
ht.AssertHtlcEventTypes(
|
||||
carolEvents, routerrpc.HtlcEvent_UNKNOWN, lntemp.HtlcEventFinal,
|
||||
carolEvents, routerrpc.HtlcEvent_UNKNOWN, lntest.HtlcEventFinal,
|
||||
)
|
||||
|
||||
// The balances of all parties should be the same as initially since
|
||||
|
|
@ -228,7 +227,7 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
|||
// There's also a final htlc event that gives the final outcome of the
|
||||
// htlc.
|
||||
ht.AssertHtlcEventTypes(
|
||||
carolEvents, routerrpc.HtlcEvent_UNKNOWN, lntemp.HtlcEventFinal,
|
||||
carolEvents, routerrpc.HtlcEvent_UNKNOWN, lntest.HtlcEventFinal,
|
||||
)
|
||||
|
||||
// The balances of all parties should be the same as initially since
|
||||
|
|
@ -273,19 +272,19 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
|||
// settle event and a final htlc event for her receive.
|
||||
ht.AssertHtlcEventTypes(
|
||||
bobEvents, routerrpc.HtlcEvent_SEND,
|
||||
lntemp.HtlcEventForward,
|
||||
lntest.HtlcEventForward,
|
||||
)
|
||||
ht.AssertHtlcEventTypes(
|
||||
bobEvents, routerrpc.HtlcEvent_SEND,
|
||||
lntemp.HtlcEventSettle,
|
||||
lntest.HtlcEventSettle,
|
||||
)
|
||||
ht.AssertHtlcEventTypes(
|
||||
carolEvents, routerrpc.HtlcEvent_RECEIVE,
|
||||
lntemp.HtlcEventSettle,
|
||||
lntest.HtlcEventSettle,
|
||||
)
|
||||
ht.AssertHtlcEventTypes(
|
||||
carolEvents, routerrpc.HtlcEvent_UNKNOWN,
|
||||
lntemp.HtlcEventFinal,
|
||||
lntest.HtlcEventFinal,
|
||||
)
|
||||
|
||||
amtSent += toSend
|
||||
|
|
@ -316,11 +315,11 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
|||
// Alice should have a forwarding event and a forwarding failure.
|
||||
ht.AssertHtlcEventTypes(
|
||||
aliceEvents, routerrpc.HtlcEvent_SEND,
|
||||
lntemp.HtlcEventForward,
|
||||
lntest.HtlcEventForward,
|
||||
)
|
||||
ht.AssertHtlcEventTypes(
|
||||
aliceEvents, routerrpc.HtlcEvent_SEND,
|
||||
lntemp.HtlcEventForwardFail,
|
||||
lntest.HtlcEventForwardFail,
|
||||
)
|
||||
|
||||
// Bob should have a link failure because the htlc failed on his
|
||||
|
|
@ -331,7 +330,7 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
|||
// There's also a final htlc event that gives the final outcome of the
|
||||
// htlc.
|
||||
ht.AssertHtlcEventTypes(
|
||||
bobEvents, routerrpc.HtlcEvent_UNKNOWN, lntemp.HtlcEventFinal,
|
||||
bobEvents, routerrpc.HtlcEvent_UNKNOWN, lntest.HtlcEventFinal,
|
||||
)
|
||||
|
||||
// Generate new invoice to not pay same invoice twice.
|
||||
|
|
@ -362,11 +361,11 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
|||
// Alice should have a forwarding event and subsequent fail.
|
||||
ht.AssertHtlcEventTypes(
|
||||
aliceEvents, routerrpc.HtlcEvent_SEND,
|
||||
lntemp.HtlcEventForward,
|
||||
lntest.HtlcEventForward,
|
||||
)
|
||||
ht.AssertHtlcEventTypes(
|
||||
aliceEvents, routerrpc.HtlcEvent_SEND,
|
||||
lntemp.HtlcEventForwardFail,
|
||||
lntest.HtlcEventForwardFail,
|
||||
)
|
||||
|
||||
// Bob should have a link failure because he could not find the next
|
||||
|
|
@ -377,7 +376,7 @@ func testHtlcErrorPropagation(ht *lntemp.HarnessTest) {
|
|||
// There's also a final htlc event that gives the final outcome of the
|
||||
// htlc.
|
||||
ht.AssertHtlcEventTypes(
|
||||
bobEvents, routerrpc.HtlcEvent_UNKNOWN, lntemp.HtlcEventFinal,
|
||||
bobEvents, routerrpc.HtlcEvent_UNKNOWN, lntest.HtlcEventFinal,
|
||||
)
|
||||
|
||||
// Finally, immediately close the channel. This function will also
|
||||
|
|
@ -5,12 +5,12 @@ import (
|
|||
"github.com/lightningnetwork/lnd/chainreg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testMultiHopPayments(ht *lntemp.HarnessTest) {
|
||||
func testMultiHopPayments(ht *lntest.HarnessTest) {
|
||||
const chanAmt = btcutil.Amount(100000)
|
||||
|
||||
// As preliminary setup, we'll create two new nodes: Carol and Dave,
|
||||
|
|
@ -43,21 +43,21 @@ func testMultiHopPayments(ht *lntemp.HarnessTest) {
|
|||
// Open a channel with 100k satoshis between Alice and Bob with Alice
|
||||
// being the sole funder of the channel.
|
||||
chanPointAlice := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// We'll create Dave and establish a channel to Alice. Dave will be
|
||||
// running an older node that requires the legacy onion payload.
|
||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, dave)
|
||||
chanPointDave := ht.OpenChannel(
|
||||
dave, alice, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
dave, alice, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Next, we'll create Carol and establish a channel to from her to
|
||||
// Dave.
|
||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||
chanPointCarol := ht.OpenChannel(
|
||||
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
carol, dave, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Create 5 invoices for Bob, which expect a payment from Carol for 1k
|
||||
|
|
@ -69,7 +69,7 @@ func testMultiHopPayments(ht *lntemp.HarnessTest) {
|
|||
// Set the fee policies of the Alice -> Bob and the Dave -> Alice
|
||||
// channel edges to relatively large non default values. This makes it
|
||||
// possible to pick up more subtle fee calculation errors.
|
||||
maxHtlc := calculateMaxHtlc(chanAmt)
|
||||
maxHtlc := lntest.CalculateMaxHtlc(chanAmt)
|
||||
const aliceBaseFeeSat = 1
|
||||
const aliceFeeRatePPM = 100000
|
||||
updateChannelPolicy(
|
||||
|
|
@ -222,7 +222,7 @@ func testMultiHopPayments(ht *lntemp.HarnessTest) {
|
|||
// policy update.
|
||||
//
|
||||
// NOTE: only used in current test.
|
||||
func updateChannelPolicy(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
||||
func updateChannelPolicy(ht *lntest.HarnessTest, hn *node.HarnessNode,
|
||||
chanPoint *lnrpc.ChannelPoint, baseFee int64,
|
||||
feeRate int64, timeLockDelta uint32,
|
||||
maxHtlc uint64, listenerNode *node.HarnessNode) {
|
||||
|
|
@ -12,10 +12,9 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -52,109 +51,13 @@ var commitWithZeroConf = []struct {
|
|||
},
|
||||
}
|
||||
|
||||
// waitForInvoiceAccepted waits until the specified invoice moved to the
|
||||
// accepted state by the node.
|
||||
func waitForInvoiceAccepted(t *harnessTest, node *lntest.HarnessNode,
|
||||
payHash lntypes.Hash) {
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
|
||||
defer cancel()
|
||||
invoiceUpdates, err := node.SubscribeSingleInvoice(ctx,
|
||||
&invoicesrpc.SubscribeSingleInvoiceRequest{
|
||||
RHash: payHash[:],
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("subscribe single invoice: %v", err)
|
||||
}
|
||||
|
||||
for {
|
||||
update, err := invoiceUpdates.Recv()
|
||||
if err != nil {
|
||||
t.Fatalf("invoice update err: %v", err)
|
||||
}
|
||||
if update.State == lnrpc.Invoice_ACCEPTED {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// checkPaymentStatus asserts that the given node list a payment with the given
|
||||
// preimage has the expected status.
|
||||
func checkPaymentStatus(node *lntest.HarnessNode, preimage lntypes.Preimage,
|
||||
status lnrpc.Payment_PaymentStatus) error {
|
||||
|
||||
ctxb := context.Background()
|
||||
ctxt, cancel := context.WithTimeout(ctxb, defaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
req := &lnrpc.ListPaymentsRequest{
|
||||
IncludeIncomplete: true,
|
||||
}
|
||||
paymentsResp, err := node.ListPayments(ctxt, req)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error when obtaining Alice payments: %v",
|
||||
err)
|
||||
}
|
||||
|
||||
payHash := preimage.Hash()
|
||||
var found bool
|
||||
for _, p := range paymentsResp.Payments {
|
||||
if p.PaymentHash != payHash.String() {
|
||||
continue
|
||||
}
|
||||
|
||||
found = true
|
||||
if p.Status != status {
|
||||
return fmt.Errorf("expected payment status "+
|
||||
"%v, got %v", status, p.Status)
|
||||
}
|
||||
|
||||
switch status {
|
||||
// If this expected status is SUCCEEDED, we expect the final preimage.
|
||||
case lnrpc.Payment_SUCCEEDED:
|
||||
if p.PaymentPreimage != preimage.String() {
|
||||
return fmt.Errorf("preimage doesn't match: %v vs %v",
|
||||
p.PaymentPreimage, preimage.String())
|
||||
}
|
||||
|
||||
// Otherwise we expect an all-zero preimage.
|
||||
default:
|
||||
if p.PaymentPreimage != (lntypes.Preimage{}).String() {
|
||||
return fmt.Errorf("expected zero preimage, got %v",
|
||||
p.PaymentPreimage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !found {
|
||||
return fmt.Errorf("payment with payment hash %v not found "+
|
||||
"in response", payHash)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// assertAllTxesSpendFrom asserts that all txes in the list spend from the given
|
||||
// tx.
|
||||
func assertAllTxesSpendFrom(t *harnessTest, txes []*wire.MsgTx,
|
||||
prevTxid chainhash.Hash) {
|
||||
|
||||
for _, tx := range txes {
|
||||
if tx.TxIn[0].PreviousOutPoint.Hash != prevTxid {
|
||||
t.Fatalf("tx %v did not spend from %v",
|
||||
tx.TxHash(), prevTxid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// caseRunner defines a single test case runner.
|
||||
type caseRunner func(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode,
|
||||
type caseRunner func(ht *lntest.HarnessTest, alice, bob *node.HarnessNode,
|
||||
c lnrpc.CommitmentType, zeroConf bool)
|
||||
|
||||
// runMultiHopHtlcClaimTest is a helper method to build test cases based on
|
||||
// different commitment types and zero-conf config and run them.
|
||||
func runMultiHopHtlcClaimTest(ht *lntemp.HarnessTest, tester caseRunner) {
|
||||
func runMultiHopHtlcClaimTest(ht *lntest.HarnessTest, tester caseRunner) {
|
||||
for _, typeAndConf := range commitWithZeroConf {
|
||||
typeAndConf := typeAndConf
|
||||
name := fmt.Sprintf("zeroconf=%v/committype=%v",
|
||||
|
|
@ -162,7 +65,7 @@ func runMultiHopHtlcClaimTest(ht *lntemp.HarnessTest, tester caseRunner) {
|
|||
|
||||
// Create the nodes here so that separate logs will be created
|
||||
// for Alice and Bob.
|
||||
args := nodeArgsForCommitType(typeAndConf.commitType)
|
||||
args := lntest.NodeArgsForCommitType(typeAndConf.commitType)
|
||||
if typeAndConf.zeroConf {
|
||||
args = append(
|
||||
args, "--protocol.option-scid-alias",
|
||||
|
|
@ -200,11 +103,11 @@ func runMultiHopHtlcClaimTest(ht *lntemp.HarnessTest, tester caseRunner) {
|
|||
// it using the HTLC timeout transaction. Any dust HTLC's should be immediately
|
||||
// canceled backwards. Once the timeout has been reached, then we should sweep
|
||||
// it on-chain, and cancel the HTLC backwards.
|
||||
func testMultiHopHtlcLocalTimeout(ht *lntemp.HarnessTest) {
|
||||
func testMultiHopHtlcLocalTimeout(ht *lntest.HarnessTest) {
|
||||
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcLocalTimeout)
|
||||
}
|
||||
|
||||
func runMultiHopHtlcLocalTimeout(ht *lntemp.HarnessTest,
|
||||
func runMultiHopHtlcLocalTimeout(ht *lntest.HarnessTest,
|
||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||
|
||||
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
|
||||
|
|
@ -268,7 +171,7 @@ func runMultiHopHtlcLocalTimeout(ht *lntemp.HarnessTest,
|
|||
// Bob's force close transaction should now be found in the mempool. If
|
||||
// there are anchors, we also expect Bob's anchor sweep.
|
||||
expectedTxes := 1
|
||||
hasAnchors := commitTypeHasAnchors(c)
|
||||
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||
if hasAnchors {
|
||||
expectedTxes = 2
|
||||
}
|
||||
|
|
@ -369,11 +272,11 @@ func runMultiHopHtlcLocalTimeout(ht *lntemp.HarnessTest,
|
|||
// transaction. In this scenario, the node that sent the outgoing HTLC should
|
||||
// extract the preimage from the sweep transaction, and finish settling the
|
||||
// HTLC backwards into the route.
|
||||
func testMultiHopReceiverChainClaim(ht *lntemp.HarnessTest) {
|
||||
func testMultiHopReceiverChainClaim(ht *lntest.HarnessTest) {
|
||||
runMultiHopHtlcClaimTest(ht, runMultiHopReceiverChainClaim)
|
||||
}
|
||||
|
||||
func runMultiHopReceiverChainClaim(ht *lntemp.HarnessTest,
|
||||
func runMultiHopReceiverChainClaim(ht *lntest.HarnessTest,
|
||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||
|
||||
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
|
||||
|
|
@ -445,7 +348,7 @@ func runMultiHopReceiverChainClaim(ht *lntemp.HarnessTest,
|
|||
// transaction in order to go to the chain and sweep her HTLC. If there
|
||||
// are anchors, Carol also sweeps hers.
|
||||
expectedTxes := 1
|
||||
hasAnchors := commitTypeHasAnchors(c)
|
||||
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||
if hasAnchors {
|
||||
expectedTxes = 2
|
||||
}
|
||||
|
|
@ -567,13 +470,13 @@ func runMultiHopReceiverChainClaim(ht *lntemp.HarnessTest,
|
|||
// commitment on-chain early, then it eventually recognizes this HTLC as one
|
||||
// that's timed out. At this point, the node should timeout the HTLC using the
|
||||
// HTLC timeout transaction, then cancel it backwards as normal.
|
||||
func testMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest) {
|
||||
func testMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest) {
|
||||
runMultiHopHtlcClaimTest(
|
||||
ht, runMultiHopLocalForceCloseOnChainHtlcTimeout,
|
||||
)
|
||||
}
|
||||
|
||||
func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
|
||||
func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest,
|
||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||
|
||||
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
|
||||
|
|
@ -614,7 +517,7 @@ func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
|
|||
// Now that all parties have the HTLC locked in, we'll immediately
|
||||
// force close the Bob -> Carol channel. This should trigger contract
|
||||
// resolution mode for both of them.
|
||||
hasAnchors := commitTypeHasAnchors(c)
|
||||
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||
stream, _ := ht.CloseChannelAssertPending(bob, bobChanPoint, true)
|
||||
closeTx := ht.AssertStreamChannelForceClosed(
|
||||
bob, bobChanPoint, hasAnchors, stream,
|
||||
|
|
@ -723,13 +626,13 @@ func runMultiHopLocalForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
|
|||
// channel, then we properly timeout the HTLC directly on *their* commitment
|
||||
// transaction once the timeout has expired. Once we sweep the transaction, we
|
||||
// should also cancel back the initial HTLC.
|
||||
func testMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest) {
|
||||
func testMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest) {
|
||||
runMultiHopHtlcClaimTest(
|
||||
ht, runMultiHopRemoteForceCloseOnChainHtlcTimeout,
|
||||
)
|
||||
}
|
||||
|
||||
func runMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
|
||||
func runMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntest.HarnessTest,
|
||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||
|
||||
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
|
||||
|
|
@ -779,7 +682,7 @@ func runMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
|
|||
// transaction. This will let us exercise that Bob is able to sweep the
|
||||
// expired HTLC on Carol's version of the commitment transaction. If
|
||||
// Carol has an anchor, it will be swept too.
|
||||
hasAnchors := commitTypeHasAnchors(c)
|
||||
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||
closeStream, _ := ht.CloseChannelAssertPending(
|
||||
carol, bobChanPoint, true,
|
||||
)
|
||||
|
|
@ -879,11 +782,11 @@ func runMultiHopRemoteForceCloseOnChainHtlcTimeout(ht *lntemp.HarnessTest,
|
|||
// we force close a channel with an incoming HTLC, and later find out the
|
||||
// preimage via the witness beacon, we properly settle the HTLC on-chain using
|
||||
// the HTLC success transaction in order to ensure we don't lose any funds.
|
||||
func testMultiHopHtlcLocalChainClaim(ht *lntemp.HarnessTest) {
|
||||
func testMultiHopHtlcLocalChainClaim(ht *lntest.HarnessTest) {
|
||||
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcLocalChainClaim)
|
||||
}
|
||||
|
||||
func runMultiHopHtlcLocalChainClaim(ht *lntemp.HarnessTest,
|
||||
func runMultiHopHtlcLocalChainClaim(ht *lntest.HarnessTest,
|
||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||
|
||||
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
|
||||
|
|
@ -937,7 +840,7 @@ func runMultiHopHtlcLocalChainClaim(ht *lntemp.HarnessTest,
|
|||
|
||||
// At this point, Bob decides that he wants to exit the channel
|
||||
// immediately, so he force closes his commitment transaction.
|
||||
hasAnchors := commitTypeHasAnchors(c)
|
||||
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||
closeStream, _ := ht.CloseChannelAssertPending(
|
||||
bob, aliceChanPoint, true,
|
||||
)
|
||||
|
|
@ -985,7 +888,7 @@ func runMultiHopHtlcLocalChainClaim(ht *lntemp.HarnessTest,
|
|||
|
||||
// Carol's commitment transaction should now be in the mempool. If
|
||||
// there is an anchor, Carol will sweep that too.
|
||||
if commitTypeHasAnchors(c) {
|
||||
if lntest.CommitTypeHasAnchors(c) {
|
||||
expectedTxes = 2
|
||||
}
|
||||
ht.Miner.AssertNumTxsInMempool(expectedTxes)
|
||||
|
|
@ -1173,11 +1076,11 @@ func runMultiHopHtlcLocalChainClaim(ht *lntemp.HarnessTest,
|
|||
// we found out the preimage via the witness beacon, we properly settle the
|
||||
// HTLC directly on-chain using the preimage in order to ensure that we don't
|
||||
// lose any funds.
|
||||
func testMultiHopHtlcRemoteChainClaim(ht *lntemp.HarnessTest) {
|
||||
func testMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest) {
|
||||
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcRemoteChainClaim)
|
||||
}
|
||||
|
||||
func runMultiHopHtlcRemoteChainClaim(ht *lntemp.HarnessTest,
|
||||
func runMultiHopHtlcRemoteChainClaim(ht *lntest.HarnessTest,
|
||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||
|
||||
// First, we'll create a three hop network: Alice -> Bob -> Carol, with
|
||||
|
|
@ -1232,7 +1135,7 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntemp.HarnessTest,
|
|||
// Next, Alice decides that she wants to exit the channel, so she'll
|
||||
// immediately force close the channel by broadcast her commitment
|
||||
// transaction.
|
||||
hasAnchors := commitTypeHasAnchors(c)
|
||||
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||
closeStream, _ := ht.CloseChannelAssertPending(
|
||||
alice, aliceChanPoint, true,
|
||||
)
|
||||
|
|
@ -1443,11 +1346,11 @@ func runMultiHopHtlcRemoteChainClaim(ht *lntemp.HarnessTest,
|
|||
// resolve them using the second level timeout and success transactions. In
|
||||
// case of anchor channels, the second-level spends can also be aggregated and
|
||||
// properly feebumped, so we'll check that as well.
|
||||
func testMultiHopHtlcAggregation(ht *lntemp.HarnessTest) {
|
||||
func testMultiHopHtlcAggregation(ht *lntest.HarnessTest) {
|
||||
runMultiHopHtlcClaimTest(ht, runMultiHopHtlcAggregation)
|
||||
}
|
||||
|
||||
func runMultiHopHtlcAggregation(ht *lntemp.HarnessTest,
|
||||
func runMultiHopHtlcAggregation(ht *lntest.HarnessTest,
|
||||
alice, bob *node.HarnessNode, c lnrpc.CommitmentType, zeroConf bool) {
|
||||
|
||||
// First, we'll create a three hop network: Alice -> Bob -> Carol.
|
||||
|
|
@ -1586,7 +1489,7 @@ func runMultiHopHtlcAggregation(ht *lntemp.HarnessTest,
|
|||
|
||||
// Bob's force close transaction should now be found in the mempool. If
|
||||
// there are anchors, we also expect Bob's anchor sweep.
|
||||
hasAnchors := commitTypeHasAnchors(c)
|
||||
hasAnchors := lntest.CommitTypeHasAnchors(c)
|
||||
expectedTxes := 1
|
||||
if hasAnchors {
|
||||
expectedTxes = 2
|
||||
|
|
@ -1825,7 +1728,7 @@ func runMultiHopHtlcAggregation(ht *lntemp.HarnessTest,
|
|||
}
|
||||
|
||||
// createThreeHopNetwork creates a topology of `Alice -> Bob -> Carol`.
|
||||
func createThreeHopNetwork(ht *lntemp.HarnessTest,
|
||||
func createThreeHopNetwork(ht *lntest.HarnessTest,
|
||||
alice, bob *node.HarnessNode, carolHodl bool, c lnrpc.CommitmentType,
|
||||
zeroConf bool) (*lnrpc.ChannelPoint,
|
||||
*lnrpc.ChannelPoint, *node.HarnessNode) {
|
||||
|
|
@ -1835,7 +1738,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
|
|||
// We'll create a new node "carol" and have Bob connect to her.
|
||||
// If the carolHodl flag is set, we'll make carol always hold onto the
|
||||
// HTLC, this way it'll force Bob to go to chain to resolve the HTLC.
|
||||
carolFlags := nodeArgsForCommitType(c)
|
||||
carolFlags := lntest.NodeArgsForCommitType(c)
|
||||
if carolHodl {
|
||||
carolFlags = append(carolFlags, "--hodl.exit-settle")
|
||||
}
|
||||
|
|
@ -1871,7 +1774,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
|
|||
if c == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE {
|
||||
_, minerHeight := ht.Miner.GetBestBlock()
|
||||
thawHeight = uint32(minerHeight + thawHeightDelta)
|
||||
aliceFundingShim, _, _ = deriveFundingShim(
|
||||
aliceFundingShim, _ = deriveFundingShim(
|
||||
ht, alice, bob, chanAmt, thawHeight, true,
|
||||
)
|
||||
}
|
||||
|
|
@ -1887,7 +1790,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
|
|||
go acceptChannel(ht.T, true, acceptStream)
|
||||
}
|
||||
|
||||
aliceParams := lntemp.OpenChannelParams{
|
||||
aliceParams := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
CommitmentType: c,
|
||||
FundingShim: aliceFundingShim,
|
||||
|
|
@ -1904,7 +1807,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
|
|||
// open, our topology looks like: A -> B -> C.
|
||||
var bobFundingShim *lnrpc.FundingShim
|
||||
if c == lnrpc.CommitmentType_SCRIPT_ENFORCED_LEASE {
|
||||
bobFundingShim, _, _ = deriveFundingShim(
|
||||
bobFundingShim, _ = deriveFundingShim(
|
||||
ht, bob, carol, chanAmt, thawHeight, true,
|
||||
)
|
||||
}
|
||||
|
|
@ -1916,7 +1819,7 @@ func createThreeHopNetwork(ht *lntemp.HarnessTest,
|
|||
go acceptChannel(ht.T, true, acceptStream)
|
||||
}
|
||||
|
||||
bobParams := lntemp.OpenChannelParams{
|
||||
bobParams := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
CommitmentType: c,
|
||||
FundingShim: bobFundingShim,
|
||||
|
|
@ -3,12 +3,12 @@ package itest
|
|||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/lightningnetwork/lnd/lncfg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -16,7 +16,7 @@ import (
|
|||
// testNetworkConnectionTimeout checks that the connectiontimeout is taking
|
||||
// effect. It creates a node with a small connection timeout value, and
|
||||
// connects it to a non-routable IP address.
|
||||
func testNetworkConnectionTimeout(ht *lntemp.HarnessTest) {
|
||||
func testNetworkConnectionTimeout(ht *lntest.HarnessTest) {
|
||||
var (
|
||||
// testPub is a random public key for testing only.
|
||||
testPub = "0332bda7da70fefe4b6ab92f53b3c4f4ee7999" +
|
||||
|
|
@ -75,7 +75,7 @@ func testNetworkConnectionTimeout(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testReconnectAfterIPChange verifies that if a persistent inbound node changes
|
||||
// its listening address then it's peer will still be able to reconnect to it.
|
||||
func testReconnectAfterIPChange(ht *lntemp.HarnessTest) {
|
||||
func testReconnectAfterIPChange(ht *lntest.HarnessTest) {
|
||||
// In this test, the following network will be set up. A single
|
||||
// dash line represents a peer connection and a double dash line
|
||||
// represents a channel.
|
||||
|
|
@ -105,7 +105,7 @@ func testReconnectAfterIPChange(ht *lntemp.HarnessTest) {
|
|||
|
||||
// We derive an extra port for Dave, and we initialise his node with
|
||||
// the port advertised as `--externalip` arguments.
|
||||
ip2 := lntest.NextAvailablePort()
|
||||
ip2 := node.NextAvailablePort()
|
||||
|
||||
// Create a new node, Dave, which will initialize a P2P port for him.
|
||||
daveArgs := []string{fmt.Sprintf("--externalip=127.0.0.1:%d", ip2)}
|
||||
|
|
@ -127,7 +127,7 @@ func testReconnectAfterIPChange(ht *lntemp.HarnessTest) {
|
|||
// ensures that Charlie receives the node announcement from Alice as
|
||||
// part of the announcement broadcast.
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, dave, lntemp.OpenChannelParams{Amt: 1000000},
|
||||
alice, dave, lntest.OpenChannelParams{Amt: 1000000},
|
||||
)
|
||||
|
||||
// waitForNodeAnnouncement is a closure used to wait on the given graph
|
||||
|
|
@ -184,7 +184,7 @@ func testReconnectAfterIPChange(ht *lntemp.HarnessTest) {
|
|||
// address.
|
||||
|
||||
// Change Dave's listening port and restart.
|
||||
dave.Cfg.P2PPort = lntest.NextAvailablePort()
|
||||
dave.Cfg.P2PPort = node.NextAvailablePort()
|
||||
dave.Cfg.ExtraArgs = []string{
|
||||
fmt.Sprintf(
|
||||
"--externalip=127.0.0.1:%d", dave.Cfg.P2PPort,
|
||||
|
|
@ -210,7 +210,7 @@ func testReconnectAfterIPChange(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testAddPeerConfig tests that the "--addpeer" config flag successfully adds
|
||||
// a new peer.
|
||||
func testAddPeerConfig(ht *lntemp.HarnessTest) {
|
||||
func testAddPeerConfig(ht *lntest.HarnessTest) {
|
||||
alice := ht.Alice
|
||||
info := alice.RPC.GetInfo()
|
||||
|
||||
|
|
@ -220,6 +220,9 @@ func testAddPeerConfig(ht *lntemp.HarnessTest) {
|
|||
args := []string{fmt.Sprintf("--addpeer=%v", alicePeerAddress)}
|
||||
carol := ht.NewNode("Carol", args)
|
||||
|
||||
// TODO(yy): remove this once the peer conn race is fixed.
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
ht.EnsureConnected(alice, carol)
|
||||
|
||||
// If we list Carol's peers, Alice should already be
|
||||
|
|
@ -2,15 +2,14 @@ package itest
|
|||
|
||||
import (
|
||||
"github.com/lightningnetwork/lnd/lnrpc/neutrinorpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// testNeutrino checks that the neutrino sub-server can fetch compact
|
||||
// block filters, server status and connect to a connected peer.
|
||||
func testNeutrino(ht *lntemp.HarnessTest) {
|
||||
if ht.ChainBackendName() != lntest.NeutrinoBackendName {
|
||||
func testNeutrino(ht *lntest.HarnessTest) {
|
||||
if !ht.IsNeutrinoBackend() {
|
||||
ht.Skipf("skipping test for non neutrino backends")
|
||||
}
|
||||
|
||||
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
package itest
|
||||
|
||||
import "github.com/lightningnetwork/lnd/lntemp"
|
||||
import "github.com/lightningnetwork/lnd/lntest"
|
||||
|
||||
// testEtcdFailover is an empty itest when LND is not compiled with etcd
|
||||
// support.
|
||||
func testEtcdFailover(ht *lntemp.HarnessTest) {}
|
||||
func testEtcdFailover(ht *lntest.HarnessTest) {}
|
||||
|
|
@ -5,11 +5,11 @@ import (
|
|||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testNonstdSweep(ht *lntemp.HarnessTest) {
|
||||
func testNonstdSweep(ht *lntest.HarnessTest) {
|
||||
p2shAddr, err := btcutil.NewAddressScriptHash(
|
||||
make([]byte, 1), harnessNetParams,
|
||||
)
|
||||
|
|
@ -74,7 +74,7 @@ func testNonstdSweep(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func testNonStdSweepInner(ht *lntemp.HarnessTest, address string) {
|
||||
func testNonStdSweepInner(ht *lntest.HarnessTest, address string) {
|
||||
carol := ht.NewNode("carol", nil)
|
||||
|
||||
// Give Carol a UTXO so SendCoins will behave as expected.
|
||||
|
|
@ -11,8 +11,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/sweep"
|
||||
|
|
@ -20,7 +20,7 @@ import (
|
|||
)
|
||||
|
||||
// testChainKit tests ChainKit RPC endpoints.
|
||||
func testChainKit(ht *lntemp.HarnessTest) {
|
||||
func testChainKit(ht *lntest.HarnessTest) {
|
||||
// Test functions registered as test cases spin up separate nodes
|
||||
// during execution. By calling sub-test functions as seen below we
|
||||
// avoid the need to start separate nodes.
|
||||
|
|
@ -30,7 +30,7 @@ func testChainKit(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testChainKitGetBlock ensures that given a block hash, the RPC endpoint
|
||||
// returns the correct target block.
|
||||
func testChainKitGetBlock(ht *lntemp.HarnessTest) {
|
||||
func testChainKitGetBlock(ht *lntest.HarnessTest) {
|
||||
// Get best block hash.
|
||||
bestBlockRes := ht.Alice.RPC.GetBestBlock(nil)
|
||||
|
||||
|
|
@ -58,7 +58,7 @@ func testChainKitGetBlock(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testChainKitGetBlockHash ensures that given a block height, the RPC endpoint
|
||||
// returns the correct target block hash.
|
||||
func testChainKitGetBlockHash(ht *lntemp.HarnessTest) {
|
||||
func testChainKitGetBlockHash(ht *lntest.HarnessTest) {
|
||||
// Get best block hash.
|
||||
bestBlockRes := ht.Alice.RPC.GetBestBlock(nil)
|
||||
|
||||
|
|
@ -78,13 +78,13 @@ func testChainKitGetBlockHash(ht *lntemp.HarnessTest) {
|
|||
// rate by broadcasting a Child-Pays-For-Parent (CPFP) transaction.
|
||||
//
|
||||
// TODO(wilmer): Add RBF case once btcd supports it.
|
||||
func testCPFP(ht *lntemp.HarnessTest) {
|
||||
func testCPFP(ht *lntest.HarnessTest) {
|
||||
runCPFP(ht, ht.Alice, ht.Bob)
|
||||
}
|
||||
|
||||
// runCPFP ensures that the daemon can bump an unconfirmed transaction's fee
|
||||
// rate by broadcasting a Child-Pays-For-Parent (CPFP) transaction.
|
||||
func runCPFP(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
|
||||
func runCPFP(ht *lntest.HarnessTest, alice, bob *node.HarnessNode) {
|
||||
// Skip this test for neutrino, as it's not aware of mempool
|
||||
// transactions.
|
||||
if ht.IsNeutrinoBackend() {
|
||||
|
|
@ -172,6 +172,7 @@ func runCPFP(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
|
|||
return fmt.Errorf("expected 0 pending sweeps, found %d",
|
||||
len(resp.PendingSweeps))
|
||||
}
|
||||
|
||||
return nil
|
||||
}, defaultTimeout)
|
||||
require.NoError(ht, err, "timeout checking bob's pending sweeps")
|
||||
|
|
@ -180,9 +181,9 @@ func runCPFP(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
|
|||
// testAnchorReservedValue tests that we won't allow sending transactions when
|
||||
// that would take the value we reserve for anchor fee bumping out of our
|
||||
// wallet.
|
||||
func testAnchorReservedValue(ht *lntemp.HarnessTest) {
|
||||
func testAnchorReservedValue(ht *lntest.HarnessTest) {
|
||||
// Start two nodes supporting anchor channels.
|
||||
args := nodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
|
||||
args := lntest.NodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
|
||||
|
||||
// NOTE: we cannot reuse the standby node here as the test requires the
|
||||
// node to start with no UTXOs.
|
||||
|
|
@ -203,7 +204,7 @@ func testAnchorReservedValue(ht *lntemp.HarnessTest) {
|
|||
|
||||
// wallet, without a change output. This should not be allowed.
|
||||
ht.OpenChannelAssertErr(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
}, lnwallet.ErrReservedValueInvalidated,
|
||||
)
|
||||
|
|
@ -211,13 +212,13 @@ func testAnchorReservedValue(ht *lntemp.HarnessTest) {
|
|||
// Alice opens a smaller channel. This works since it will have a
|
||||
// change output.
|
||||
chanPoint1 := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt / 4},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt / 4},
|
||||
)
|
||||
|
||||
// If Alice tries to open another anchor channel to Bob, Bob should not
|
||||
// reject it as he is not contributing any funds.
|
||||
chanPoint2 := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt / 4},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt / 4},
|
||||
)
|
||||
|
||||
// Similarly, if Alice tries to open a legacy channel to Bob, Bob
|
||||
|
|
@ -229,7 +230,7 @@ func testAnchorReservedValue(ht *lntemp.HarnessTest) {
|
|||
ht.EnsureConnected(alice, bob)
|
||||
|
||||
chanPoint3 := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt / 4},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt / 4},
|
||||
)
|
||||
chanPoints := []*lnrpc.ChannelPoint{chanPoint1, chanPoint2, chanPoint3}
|
||||
|
||||
|
|
@ -276,6 +277,7 @@ func testAnchorReservedValue(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
|
||||
balance = resp.TotalBalance
|
||||
|
||||
return nil
|
||||
}, defaultTimeout)
|
||||
require.NoError(ht, err, "timeout checking alice's balance")
|
||||
|
|
@ -347,18 +349,15 @@ func testAnchorReservedValue(ht *lntemp.HarnessTest) {
|
|||
// testAnchorThirdPartySpend tests that if we force close a channel, but then
|
||||
// don't sweep the anchor in time and a 3rd party spends it, that we remove any
|
||||
// transactions that are a descendent of that sweep.
|
||||
func testAnchorThirdPartySpend(ht *lntemp.HarnessTest) {
|
||||
func testAnchorThirdPartySpend(ht *lntest.HarnessTest) {
|
||||
// First, we'll create two new nodes that both default to anchor
|
||||
// channels.
|
||||
//
|
||||
// NOTE: The itests differ here as anchors is default off vs the normal
|
||||
// lnd binary.
|
||||
args := nodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
|
||||
args := lntest.NodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
|
||||
alice := ht.NewNode("Alice", args)
|
||||
defer ht.Shutdown(alice)
|
||||
|
||||
bob := ht.NewNode("Bob", args)
|
||||
defer ht.Shutdown(bob)
|
||||
|
||||
ht.EnsureConnected(alice, bob)
|
||||
|
||||
|
|
@ -374,7 +373,7 @@ func testAnchorThirdPartySpend(ht *lntemp.HarnessTest) {
|
|||
// Open the channel between the two nodes and wait for it to confirm
|
||||
// fully.
|
||||
aliceChanPoint1 := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: firstChanSize,
|
||||
},
|
||||
)
|
||||
|
|
@ -493,7 +492,7 @@ func testAnchorThirdPartySpend(ht *lntemp.HarnessTest) {
|
|||
|
||||
// assertAnchorOutputLost asserts that the anchor output for the given channel
|
||||
// has the state of being lost.
|
||||
func assertAnchorOutputLost(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
||||
func assertAnchorOutputLost(ht *lntest.HarnessTest, hn *node.HarnessNode,
|
||||
chanPoint *lnrpc.ChannelPoint) {
|
||||
|
||||
cp := ht.OutPointFromChannelPoint(chanPoint)
|
||||
|
|
@ -527,8 +526,8 @@ func assertAnchorOutputLost(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
|||
// genAnchorSweep generates a "3rd party" anchor sweeping from an existing one.
|
||||
// In practice, we just re-use the existing witness, and track on our own
|
||||
// output producing a 1-in-1-out transaction.
|
||||
func genAnchorSweep(ht *lntemp.HarnessTest,
|
||||
aliceAnchor *lntemp.SweptOutput, anchorCsv uint32) *btcutil.Tx {
|
||||
func genAnchorSweep(ht *lntest.HarnessTest,
|
||||
aliceAnchor *lntest.SweptOutput, anchorCsv uint32) *btcutil.Tx {
|
||||
|
||||
// At this point, we have the transaction that Alice used to try to
|
||||
// sweep her anchor. As this is actually just something anyone can
|
||||
|
|
@ -10,9 +10,9 @@ import (
|
|||
"github.com/lightningnetwork/lnd/chainreg"
|
||||
"github.com/lightningnetwork/lnd/funding"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -20,7 +20,7 @@ import (
|
|||
// testOpenChannelAfterReorg tests that in the case where we have an open
|
||||
// channel where the funding tx gets reorged out, the channel will no
|
||||
// longer be present in the node's routing table.
|
||||
func testOpenChannelAfterReorg(ht *lntemp.HarnessTest) {
|
||||
func testOpenChannelAfterReorg(ht *lntest.HarnessTest) {
|
||||
// Skip test for neutrino, as we cannot disconnect the miner at will.
|
||||
// TODO(halseth): remove when either can disconnect at will, or restart
|
||||
// node with connection to new miner.
|
||||
|
|
@ -33,7 +33,7 @@ func testOpenChannelAfterReorg(ht *lntemp.HarnessTest) {
|
|||
// Set up a new miner that we can use to cause a reorg.
|
||||
tempLogDir := ".tempminerlogs"
|
||||
logFilename := "output-open_channel_reorg-temp_miner.log"
|
||||
tempMiner := lntemp.NewTempMiner(
|
||||
tempMiner := lntest.NewTempMiner(
|
||||
ht.Context(), ht.T, tempLogDir, logFilename,
|
||||
)
|
||||
defer tempMiner.Stop()
|
||||
|
|
@ -68,7 +68,7 @@ func testOpenChannelAfterReorg(ht *lntemp.HarnessTest) {
|
|||
|
||||
// Create a new channel that requires 1 confs before it's considered
|
||||
// open, then broadcast the funding transaction
|
||||
params := lntemp.OpenChannelParams{
|
||||
params := lntest.OpenChannelParams{
|
||||
Amt: funding.MaxBtcFundingAmount,
|
||||
Private: true,
|
||||
}
|
||||
|
|
@ -172,7 +172,7 @@ func testOpenChannelAfterReorg(ht *lntemp.HarnessTest) {
|
|||
// ChannelUpdate --> defaultBaseFee, provided FeeRate
|
||||
// 4.) baseFee and feeRate provided to OpenChannelRequest
|
||||
// ChannelUpdate --> provided baseFee, provided feeRate.
|
||||
func testOpenChannelUpdateFeePolicy(ht *lntemp.HarnessTest) {
|
||||
func testOpenChannelUpdateFeePolicy(ht *lntest.HarnessTest) {
|
||||
const (
|
||||
defaultBaseFee = 1000
|
||||
defaultFeeRate = 1
|
||||
|
|
@ -182,12 +182,12 @@ func testOpenChannelUpdateFeePolicy(ht *lntemp.HarnessTest) {
|
|||
optionalFeeRate = 1337
|
||||
)
|
||||
|
||||
defaultMaxHtlc := calculateMaxHtlc(funding.MaxBtcFundingAmount)
|
||||
defaultMaxHtlc := lntest.CalculateMaxHtlc(funding.MaxBtcFundingAmount)
|
||||
|
||||
chanAmt := funding.MaxBtcFundingAmount
|
||||
pushAmt := chanAmt / 2
|
||||
|
||||
feeScenarios := []lntemp.OpenChannelParams{
|
||||
feeScenarios := []lntest.OpenChannelParams{
|
||||
{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
|
|
@ -259,8 +259,8 @@ func testOpenChannelUpdateFeePolicy(ht *lntemp.HarnessTest) {
|
|||
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
|
||||
runTestCase := func(ht *lntemp.HarnessTest,
|
||||
fs lntemp.OpenChannelParams,
|
||||
runTestCase := func(ht *lntest.HarnessTest,
|
||||
fs lntest.OpenChannelParams,
|
||||
alicePolicy, bobPolicy *lnrpc.RoutingPolicy) {
|
||||
|
||||
// Create a channel Alice->Bob.
|
||||
|
|
@ -305,14 +305,14 @@ func testOpenChannelUpdateFeePolicy(ht *lntemp.HarnessTest) {
|
|||
// testBasicChannelCreationAndUpdates tests multiple channel opening and
|
||||
// closing, and ensures that if a node is subscribed to channel updates they
|
||||
// will be received correctly for both cooperative and force closed channels.
|
||||
func testBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest) {
|
||||
func testBasicChannelCreationAndUpdates(ht *lntest.HarnessTest) {
|
||||
runBasicChannelCreationAndUpdates(ht, ht.Alice, ht.Bob)
|
||||
}
|
||||
|
||||
// runBasicChannelCreationAndUpdates tests multiple channel opening and closing,
|
||||
// and ensures that if a node is subscribed to channel updates they will be
|
||||
// received correctly for both cooperative and force closed channels.
|
||||
func runBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest,
|
||||
func runBasicChannelCreationAndUpdates(ht *lntest.HarnessTest,
|
||||
alice, bob *node.HarnessNode) {
|
||||
|
||||
const (
|
||||
|
|
@ -329,7 +329,7 @@ func runBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest,
|
|||
chanPoints := make([]*lnrpc.ChannelPoint, numChannels)
|
||||
for i := 0; i < numChannels; i++ {
|
||||
chanPoints[i] = ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: amount,
|
||||
},
|
||||
)
|
||||
|
|
@ -458,8 +458,8 @@ func runBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest,
|
|||
|
||||
// assertMinerBlockHeightDelta ensures that tempMiner is 'delta' blocks ahead
|
||||
// of miner.
|
||||
func assertMinerBlockHeightDelta(ht *lntemp.HarnessTest,
|
||||
miner, tempMiner *lntemp.HarnessMiner, delta int32) {
|
||||
func assertMinerBlockHeightDelta(ht *lntest.HarnessTest,
|
||||
miner, tempMiner *lntest.HarnessMiner, delta int32) {
|
||||
|
||||
// Ensure the chain lengths are what we expect.
|
||||
err := wait.NoError(func() error {
|
||||
|
|
@ -1,7 +1,6 @@
|
|||
package itest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
|
|
@ -11,14 +10,13 @@ import (
|
|||
"github.com/lightningnetwork/lnd/input"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testListPayments(ht *lntemp.HarnessTest) {
|
||||
func testListPayments(ht *lntest.HarnessTest) {
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
|
||||
// Check that there are no payments before test.
|
||||
|
|
@ -28,7 +26,7 @@ func testListPayments(ht *lntemp.HarnessTest) {
|
|||
// being the sole funder of the channel.
|
||||
chanAmt := btcutil.Amount(100000)
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Get the number of invoices Bob already has.
|
||||
|
|
@ -171,13 +169,13 @@ func testListPayments(ht *lntemp.HarnessTest) {
|
|||
// subsystems trying to update the channel state in the db. We follow this
|
||||
// transition with a payment that updates the commitment state and verify that
|
||||
// the pending state is up to date.
|
||||
func testPaymentFollowingChannelOpen(ht *lntemp.HarnessTest) {
|
||||
func testPaymentFollowingChannelOpen(ht *lntest.HarnessTest) {
|
||||
const paymentAmt = btcutil.Amount(100)
|
||||
channelCapacity := paymentAmt * 1000
|
||||
|
||||
// We first establish a channel between Alice and Bob.
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
p := lntemp.OpenChannelParams{
|
||||
p := lntest.OpenChannelParams{
|
||||
Amt: channelCapacity,
|
||||
}
|
||||
pendingUpdate := ht.OpenChannelAssertPending(alice, bob, p)
|
||||
|
|
@ -198,7 +196,7 @@ func testPaymentFollowingChannelOpen(ht *lntemp.HarnessTest) {
|
|||
ht.MineBlocksAndAssertNumTxes(6, 1)
|
||||
|
||||
// We verify that the channel is open from both nodes point of view.
|
||||
chanPoint := lntemp.ChanPointFromPendingUpdate(pendingUpdate)
|
||||
chanPoint := lntest.ChanPointFromPendingUpdate(pendingUpdate)
|
||||
ht.AssertNodesNumPendingOpenChannels(alice, bob, 0)
|
||||
ht.AssertChannelExists(alice, chanPoint)
|
||||
ht.AssertChannelExists(bob, chanPoint)
|
||||
|
|
@ -226,7 +224,7 @@ func testPaymentFollowingChannelOpen(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
|
||||
// testAsyncPayments tests the performance of the async payments.
|
||||
func testAsyncPayments(ht *lntemp.HarnessTest) {
|
||||
func testAsyncPayments(ht *lntest.HarnessTest) {
|
||||
// We use new nodes here as the benchmark test creates lots of data
|
||||
// which can be costly to be carried on.
|
||||
alice := ht.NewNode("Alice", []string{"--pending-commit-interval=3m"})
|
||||
|
|
@ -239,7 +237,7 @@ func testAsyncPayments(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
|
||||
// runAsyncPayments tests the performance of the async payments.
|
||||
func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
|
||||
func runAsyncPayments(ht *lntest.HarnessTest, alice, bob *node.HarnessNode) {
|
||||
const paymentAmt = 100
|
||||
|
||||
// First establish a channel with a capacity equals to the overall
|
||||
|
|
@ -247,7 +245,7 @@ func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
|
|||
// Alice should send all money from her side to Bob.
|
||||
channelCapacity := btcutil.Amount(paymentAmt * 2000)
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: channelCapacity},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: channelCapacity},
|
||||
)
|
||||
|
||||
info := ht.QueryChannelByChanPoint(alice, chanPoint)
|
||||
|
|
@ -273,7 +271,7 @@ func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
|
|||
settled := make(chan struct{})
|
||||
defer close(settled)
|
||||
|
||||
timeout := lntest.AsyncBenchmarkTimeout * 2
|
||||
timeout := wait.AsyncBenchmarkTimeout
|
||||
for i := 0; i < numInvoices; i++ {
|
||||
payReq := bobPayReqs[i]
|
||||
go func() {
|
||||
|
|
@ -304,46 +302,13 @@ func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
|
|||
// All payments have been sent, mark the finish time.
|
||||
timeTaken := time.Since(now)
|
||||
|
||||
// assertChannelState asserts the channel state by checking the values
|
||||
// in fields, LocalBalance, RemoteBalance and num of PendingHtlcs.
|
||||
assertChannelState := func(hn *node.HarnessNode, cp *lnrpc.ChannelPoint,
|
||||
localBalance, remoteBalance int64, numPendingHtlcs int) {
|
||||
|
||||
// Get the funding point.
|
||||
err := wait.NoError(func() error {
|
||||
// Find the target channel first.
|
||||
target := ht.GetChannelByChanPoint(hn, cp)
|
||||
|
||||
if len(target.PendingHtlcs) != numPendingHtlcs {
|
||||
return fmt.Errorf("pending htlcs is "+
|
||||
"incorrect, got %v, expected %v",
|
||||
len(target.PendingHtlcs), 0)
|
||||
}
|
||||
|
||||
if target.LocalBalance != localBalance {
|
||||
return fmt.Errorf("local balance is "+
|
||||
"incorrect, got %v, expected %v",
|
||||
target.LocalBalance, localBalance)
|
||||
}
|
||||
|
||||
if target.RemoteBalance != remoteBalance {
|
||||
return fmt.Errorf("remote balance is "+
|
||||
"incorrect, got %v, expected %v",
|
||||
target.RemoteBalance, remoteBalance)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, lntemp.DefaultTimeout)
|
||||
require.NoError(ht, err, "timeout while chekcing for balance")
|
||||
}
|
||||
|
||||
// Wait for the revocation to be received so alice no longer has
|
||||
// pending htlcs listed and has correct balances. This is needed due to
|
||||
// the fact that we now pipeline the settles.
|
||||
assertChannelState(alice, chanPoint, aliceAmt, bobAmt, 0)
|
||||
assertChannelState(ht, alice, chanPoint, aliceAmt, bobAmt)
|
||||
|
||||
// Wait for Bob to receive revocation from Alice.
|
||||
assertChannelState(bob, chanPoint, bobAmt, aliceAmt, 0)
|
||||
assertChannelState(ht, bob, chanPoint, bobAmt, aliceAmt)
|
||||
|
||||
ht.Log("\tBenchmark info: Elapsed time: ", timeTaken)
|
||||
ht.Log("\tBenchmark info: TPS: ",
|
||||
|
|
@ -357,28 +322,41 @@ func runAsyncPayments(ht *lntemp.HarnessTest, alice, bob *node.HarnessNode) {
|
|||
|
||||
// testBidirectionalAsyncPayments tests that nodes are able to send the
|
||||
// payments to each other in async manner without blocking.
|
||||
func testBidirectionalAsyncPayments(net *lntest.NetworkHarness, t *harnessTest) {
|
||||
ctxb := context.Background()
|
||||
func testBidirectionalAsyncPayments(ht *lntest.HarnessTest) {
|
||||
const paymentAmt = 1000
|
||||
|
||||
const (
|
||||
paymentAmt = 1000
|
||||
)
|
||||
// We use new nodes here as the benchmark test creates lots of data
|
||||
// which can be costly to be carried on.
|
||||
args := []string{
|
||||
// Increase the dust threshold to avoid the payments fail due
|
||||
// to threshold limit reached.
|
||||
"--dust-threshold=5000000",
|
||||
|
||||
// Increase the pending commit interval since there are lots of
|
||||
// commitment dances.
|
||||
"--pending-commit-interval=5m",
|
||||
|
||||
// Increase the mailbox delivery timeout as there are lots of
|
||||
// ADDs going on.
|
||||
"--htlcswitch.mailboxdeliverytimeout=2m",
|
||||
}
|
||||
alice := ht.NewNode("Alice", args)
|
||||
bob := ht.NewNode("Bob", args)
|
||||
|
||||
ht.EnsureConnected(alice, bob)
|
||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, alice)
|
||||
|
||||
// First establish a channel with a capacity equals to the overall
|
||||
// amount of payments, between Alice and Bob, at the end of the test
|
||||
// Alice should send all money from her side to Bob.
|
||||
chanPoint := openChannelAndAssert(
|
||||
t, net, net.Alice, net.Bob,
|
||||
lntest.OpenChannelParams{
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: paymentAmt * 2000,
|
||||
PushAmt: paymentAmt * 1000,
|
||||
},
|
||||
)
|
||||
|
||||
info, err := getChanInfo(net.Alice)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get alice channel info: %v", err)
|
||||
}
|
||||
info := ht.QueryChannelByChanPoint(alice, chanPoint)
|
||||
|
||||
// We'll create a number of invoices equal the max number of HTLCs that
|
||||
// can be carried in one direction. The number on the commitment will
|
||||
|
|
@ -394,158 +372,67 @@ func testBidirectionalAsyncPayments(net *lntest.NetworkHarness, t *harnessTest)
|
|||
|
||||
// With the channel open, we'll create invoices for Bob that Alice
|
||||
// will pay to in order to advance the state of the channel.
|
||||
bobPayReqs, _, _, err := createPayReqs(
|
||||
net.Bob, paymentAmt, numInvoices,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create pay reqs: %v", err)
|
||||
}
|
||||
bobPayReqs, _, _ := ht.CreatePayReqs(bob, paymentAmt, numInvoices)
|
||||
|
||||
// With the channel open, we'll create invoices for Alice that Bob
|
||||
// will pay to in order to advance the state of the channel.
|
||||
alicePayReqs, _, _, err := createPayReqs(
|
||||
net.Alice, paymentAmt, numInvoices,
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create pay reqs: %v", err)
|
||||
}
|
||||
|
||||
// Wait for Alice to receive the channel edge from the funding manager.
|
||||
if err = net.Alice.WaitForNetworkChannelOpen(chanPoint); err != nil {
|
||||
t.Fatalf("alice didn't see the alice->bob channel before "+
|
||||
"timeout: %v", err)
|
||||
}
|
||||
if err = net.Bob.WaitForNetworkChannelOpen(chanPoint); err != nil {
|
||||
t.Fatalf("bob didn't see the bob->alice channel before "+
|
||||
"timeout: %v", err)
|
||||
}
|
||||
alicePayReqs, _, _ := ht.CreatePayReqs(alice, paymentAmt, numInvoices)
|
||||
|
||||
// Reset mission control to prevent previous payment results from
|
||||
// interfering with this test. A new channel has been opened, but
|
||||
// mission control operates on node pairs.
|
||||
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
|
||||
_, err = net.Alice.RouterClient.ResetMissionControl(
|
||||
ctxt, &routerrpc.ResetMissionControlRequest{},
|
||||
)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to reset mc for alice: %v", err)
|
||||
}
|
||||
alice.RPC.ResetMissionControl()
|
||||
|
||||
// Send payments from Alice to Bob and from Bob to Alice in async
|
||||
// manner.
|
||||
errChan := make(chan error)
|
||||
statusChan := make(chan *lnrpc.Payment)
|
||||
settled := make(chan struct{})
|
||||
defer close(settled)
|
||||
|
||||
send := func(node *lntest.HarnessNode, payReq string) {
|
||||
go func() {
|
||||
ctxt, _ = context.WithTimeout(
|
||||
ctxb, lntest.AsyncBenchmarkTimeout,
|
||||
)
|
||||
stream, err := node.RouterClient.SendPaymentV2(
|
||||
ctxt,
|
||||
&routerrpc.SendPaymentRequest{
|
||||
PaymentRequest: payReq,
|
||||
TimeoutSeconds: 60,
|
||||
FeeLimitMsat: noFeeLimitMsat,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
}
|
||||
result, err := getPaymentResult(stream)
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
}
|
||||
timeout := wait.AsyncBenchmarkTimeout * 2
|
||||
send := func(node *node.HarnessNode, payReq string) {
|
||||
req := &routerrpc.SendPaymentRequest{
|
||||
PaymentRequest: payReq,
|
||||
TimeoutSeconds: int32(timeout.Seconds()),
|
||||
FeeLimitMsat: noFeeLimitMsat,
|
||||
}
|
||||
// AssertPaymentStatusWithTimeout will assert that the
|
||||
// payment is settled.
|
||||
stream := node.RPC.SendPayment(req)
|
||||
ht.AssertPaymentSucceedWithTimeout(stream, timeout)
|
||||
|
||||
statusChan <- result
|
||||
}()
|
||||
settled <- struct{}{}
|
||||
}
|
||||
|
||||
for i := 0; i < numInvoices; i++ {
|
||||
send(net.Bob, alicePayReqs[i])
|
||||
send(net.Alice, bobPayReqs[i])
|
||||
go send(bob, alicePayReqs[i])
|
||||
go send(alice, bobPayReqs[i])
|
||||
}
|
||||
|
||||
// Expect all payments to succeed.
|
||||
timer := time.After(timeout)
|
||||
for i := 0; i < 2*numInvoices; i++ {
|
||||
select {
|
||||
case result := <-statusChan:
|
||||
if result.Status != lnrpc.Payment_SUCCEEDED {
|
||||
t.Fatalf("payment error: %v", result.Status)
|
||||
}
|
||||
|
||||
case err := <-errChan:
|
||||
t.Fatalf("payment error: %v", err)
|
||||
case <-settled:
|
||||
case <-timer:
|
||||
require.Fail(ht, "timeout", "wait payment failed")
|
||||
}
|
||||
}
|
||||
|
||||
// Wait for Alice and Bob to receive revocations messages, and update
|
||||
// states, i.e. balance info.
|
||||
err = wait.NoError(func() error {
|
||||
aliceInfo, err := getChanInfo(net.Alice)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get alice's channel info: %v", err)
|
||||
}
|
||||
|
||||
if aliceInfo.RemoteBalance != bobAmt {
|
||||
return fmt.Errorf("alice's remote balance is incorrect, "+
|
||||
"got %v, expected %v", aliceInfo.RemoteBalance,
|
||||
bobAmt)
|
||||
}
|
||||
|
||||
if aliceInfo.LocalBalance != aliceAmt {
|
||||
return fmt.Errorf("alice's local balance is incorrect, "+
|
||||
"got %v, expected %v", aliceInfo.LocalBalance,
|
||||
aliceAmt)
|
||||
}
|
||||
|
||||
if len(aliceInfo.PendingHtlcs) != 0 {
|
||||
return fmt.Errorf("alice's pending htlcs is incorrect, "+
|
||||
"got %v expected %v",
|
||||
len(aliceInfo.PendingHtlcs), 0)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, defaultTimeout)
|
||||
require.NoError(t.t, err)
|
||||
assertChannelState(ht, alice, chanPoint, aliceAmt, bobAmt)
|
||||
|
||||
// Next query for Bob's and Alice's channel states, in order to confirm
|
||||
// that all payment have been successful transmitted.
|
||||
err = wait.NoError(func() error {
|
||||
bobInfo, err := getChanInfo(net.Bob)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get bob's channel info: %v", err)
|
||||
}
|
||||
|
||||
if bobInfo.LocalBalance != bobAmt {
|
||||
return fmt.Errorf("bob's local balance is incorrect, "+
|
||||
"got %v, expected %v", bobInfo.LocalBalance,
|
||||
bobAmt)
|
||||
}
|
||||
|
||||
if bobInfo.RemoteBalance != aliceAmt {
|
||||
return fmt.Errorf("bob's remote balance is incorrect, "+
|
||||
"got %v, expected %v", bobInfo.RemoteBalance,
|
||||
aliceAmt)
|
||||
}
|
||||
|
||||
if len(bobInfo.PendingHtlcs) != 0 {
|
||||
return fmt.Errorf("bob's pending htlcs is incorrect, "+
|
||||
"got %v, expected %v",
|
||||
len(bobInfo.PendingHtlcs), 0)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, defaultTimeout)
|
||||
require.NoError(t.t, err)
|
||||
assertChannelState(ht, bob, chanPoint, bobAmt, aliceAmt)
|
||||
|
||||
// Finally, immediately close the channel. This function will also
|
||||
// block until the channel is closed and will additionally assert the
|
||||
// relevant channel closing post conditions.
|
||||
closeChannelAndAssert(t, net, net.Alice, chanPoint, false)
|
||||
ht.CloseChannel(alice, chanPoint)
|
||||
}
|
||||
|
||||
func testInvoiceSubscriptions(ht *lntemp.HarnessTest) {
|
||||
func testInvoiceSubscriptions(ht *lntest.HarnessTest) {
|
||||
const chanAmt = btcutil.Amount(500000)
|
||||
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
|
|
@ -558,7 +445,7 @@ func testInvoiceSubscriptions(ht *lntemp.HarnessTest) {
|
|||
// Open a channel with 500k satoshis between Alice and Bob with Alice
|
||||
// being the sole funder of the channel.
|
||||
chanPoint := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Next create a new invoice for Bob requesting 1k satoshis.
|
||||
|
|
@ -672,3 +559,36 @@ func testInvoiceSubscriptions(ht *lntemp.HarnessTest) {
|
|||
|
||||
ht.CloseChannel(alice, chanPoint)
|
||||
}
|
||||
|
||||
// assertChannelState asserts the channel state by checking the values in
|
||||
// fields, LocalBalance, RemoteBalance and num of PendingHtlcs.
|
||||
func assertChannelState(ht *lntest.HarnessTest, hn *node.HarnessNode,
|
||||
cp *lnrpc.ChannelPoint, localBalance, remoteBalance int64) {
|
||||
|
||||
// Get the funding point.
|
||||
err := wait.NoError(func() error {
|
||||
// Find the target channel first.
|
||||
target := ht.GetChannelByChanPoint(hn, cp)
|
||||
|
||||
if len(target.PendingHtlcs) != 0 {
|
||||
return fmt.Errorf("pending htlcs is "+
|
||||
"incorrect, got %v, expected %v",
|
||||
len(target.PendingHtlcs), 0)
|
||||
}
|
||||
|
||||
if target.LocalBalance != localBalance {
|
||||
return fmt.Errorf("local balance is "+
|
||||
"incorrect, got %v, expected %v",
|
||||
target.LocalBalance, localBalance)
|
||||
}
|
||||
|
||||
if target.RemoteBalance != remoteBalance {
|
||||
return fmt.Errorf("remote balance is "+
|
||||
"incorrect, got %v, expected %v",
|
||||
target.RemoteBalance, remoteBalance)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, lntest.DefaultTimeout)
|
||||
require.NoError(ht, err, "timeout while chekcing for balance")
|
||||
}
|
||||
|
|
@ -2,8 +2,6 @@ package itest
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
|
|
@ -20,16 +18,15 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// testPsbtChanFunding makes sure a channel can be opened between carol and dave
|
||||
// by using a Partially Signed Bitcoin Transaction that funds the channel
|
||||
// multisig funding output.
|
||||
func testPsbtChanFunding(ht *lntemp.HarnessTest) {
|
||||
func testPsbtChanFunding(ht *lntest.HarnessTest) {
|
||||
// First, we'll create two new nodes that we'll use to open channels
|
||||
// between for this test. Dave gets some coins that will be used to
|
||||
// fund the PSBT, just to make sure that Carol has an empty wallet.
|
||||
|
|
@ -42,7 +39,7 @@ func testPsbtChanFunding(ht *lntemp.HarnessTest) {
|
|||
// runPsbtChanFunding makes sure a channel can be opened between carol and dave
|
||||
// by using a Partially Signed Bitcoin Transaction that funds the channel
|
||||
// multisig funding output.
|
||||
func runPsbtChanFunding(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode) {
|
||||
func runPsbtChanFunding(ht *lntest.HarnessTest, carol, dave *node.HarnessNode) {
|
||||
const chanSize = funding.MaxBtcFundingAmount
|
||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, dave)
|
||||
|
||||
|
|
@ -64,7 +61,7 @@ func runPsbtChanFunding(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode) {
|
|||
// by specifying a PSBT shim. We use the NoPublish flag here to avoid
|
||||
// publishing the whole batch TX too early.
|
||||
chanUpdates, tempPsbt := ht.OpenChannelPsbt(
|
||||
carol, dave, lntemp.OpenChannelParams{
|
||||
carol, dave, lntest.OpenChannelParams{
|
||||
Amt: chanSize,
|
||||
FundingShim: &lnrpc.FundingShim{
|
||||
Shim: &lnrpc.FundingShim_PsbtShim{
|
||||
|
|
@ -81,7 +78,7 @@ func runPsbtChanFunding(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode) {
|
|||
// Alice. We will publish the batch TX once this channel funding is
|
||||
// complete.
|
||||
chanUpdates2, psbtBytes2 := ht.OpenChannelPsbt(
|
||||
carol, alice, lntemp.OpenChannelParams{
|
||||
carol, alice, lntest.OpenChannelParams{
|
||||
Amt: chanSize,
|
||||
FundingShim: &lnrpc.FundingShim{
|
||||
Shim: &lnrpc.FundingShim_PsbtShim{
|
||||
|
|
@ -231,7 +228,7 @@ func runPsbtChanFunding(ht *lntemp.HarnessTest, carol, dave *node.HarnessNode) {
|
|||
// and dave by using a Partially Signed Bitcoin Transaction that funds the
|
||||
// channel multisig funding output and is fully funded by an external third
|
||||
// party.
|
||||
func testPsbtChanFundingExternal(ht *lntemp.HarnessTest) {
|
||||
func testPsbtChanFundingExternal(ht *lntest.HarnessTest) {
|
||||
const chanSize = funding.MaxBtcFundingAmount
|
||||
|
||||
// First, we'll create two new nodes that we'll use to open channels
|
||||
|
|
@ -258,7 +255,7 @@ func testPsbtChanFundingExternal(ht *lntemp.HarnessTest) {
|
|||
// by specifying a PSBT shim. We use the NoPublish flag here to avoid
|
||||
// publishing the whole batch TX too early.
|
||||
chanUpdates, tempPsbt := ht.OpenChannelPsbt(
|
||||
carol, dave, lntemp.OpenChannelParams{
|
||||
carol, dave, lntest.OpenChannelParams{
|
||||
Amt: chanSize,
|
||||
FundingShim: &lnrpc.FundingShim{
|
||||
Shim: &lnrpc.FundingShim_PsbtShim{
|
||||
|
|
@ -275,7 +272,7 @@ func testPsbtChanFundingExternal(ht *lntemp.HarnessTest) {
|
|||
// Alice. We will publish the batch TX once this channel funding is
|
||||
// complete.
|
||||
chanUpdates2, psbtBytes2 := ht.OpenChannelPsbt(
|
||||
carol, alice, lntemp.OpenChannelParams{
|
||||
carol, alice, lntest.OpenChannelParams{
|
||||
Amt: chanSize,
|
||||
FundingShim: &lnrpc.FundingShim{
|
||||
Shim: &lnrpc.FundingShim_PsbtShim{
|
||||
|
|
@ -413,19 +410,16 @@ func testPsbtChanFundingExternal(ht *lntemp.HarnessTest) {
|
|||
// the wallet of both nodes are empty and one of them uses PSBT and an external
|
||||
// wallet to fund the channel while creating reserve output in the same
|
||||
// transaction.
|
||||
func testPsbtChanFundingSingleStep(ht *lntemp.HarnessTest) {
|
||||
func testPsbtChanFundingSingleStep(ht *lntest.HarnessTest) {
|
||||
const chanSize = funding.MaxBtcFundingAmount
|
||||
|
||||
args := nodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
|
||||
args := lntest.NodeArgsForCommitType(lnrpc.CommitmentType_ANCHORS)
|
||||
|
||||
// First, we'll create two new nodes that we'll use to open channels
|
||||
// between for this test. But in this case both nodes have an empty
|
||||
// wallet.
|
||||
carol := ht.NewNode("carol", args)
|
||||
defer ht.Shutdown(carol)
|
||||
|
||||
dave := ht.NewNode("dave", args)
|
||||
defer ht.Shutdown(dave)
|
||||
|
||||
alice := ht.Alice
|
||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, alice)
|
||||
|
|
@ -454,7 +448,7 @@ func testPsbtChanFundingSingleStep(ht *lntemp.HarnessTest) {
|
|||
// Now that we have the pending channel ID, Carol will open the channel
|
||||
// by specifying a PSBT shim.
|
||||
chanUpdates, tempPsbt := ht.OpenChannelPsbt(
|
||||
carol, dave, lntemp.OpenChannelParams{
|
||||
carol, dave, lntest.OpenChannelParams{
|
||||
Amt: chanSize,
|
||||
FundingShim: &lnrpc.FundingShim{
|
||||
Shim: &lnrpc.FundingShim_PsbtShim{
|
||||
|
|
@ -576,7 +570,7 @@ func testPsbtChanFundingSingleStep(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
|
||||
// testSignPsbt tests that the SignPsbt RPC works correctly.
|
||||
func testSignPsbt(ht *lntemp.HarnessTest) {
|
||||
func testSignPsbt(ht *lntest.HarnessTest) {
|
||||
runSignPsbtSegWitV0P2WKH(ht, ht.Alice)
|
||||
runSignPsbtSegWitV0NP2WKH(ht, ht.Alice)
|
||||
runSignPsbtSegWitV1KeySpendBip86(ht, ht.Alice)
|
||||
|
|
@ -591,7 +585,7 @@ func testSignPsbt(ht *lntemp.HarnessTest) {
|
|||
|
||||
// runSignPsbtSegWitV0P2WKH tests that the SignPsbt RPC works correctly for a
|
||||
// SegWit v0 p2wkh input.
|
||||
func runSignPsbtSegWitV0P2WKH(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
||||
func runSignPsbtSegWitV0P2WKH(ht *lntest.HarnessTest, alice *node.HarnessNode) {
|
||||
// We test that we can sign a PSBT that spends funds from an input that
|
||||
// the wallet doesn't know about. To set up that test case, we first
|
||||
// derive an address manually that the wallet won't be watching on
|
||||
|
|
@ -670,7 +664,7 @@ func runSignPsbtSegWitV0P2WKH(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
|||
|
||||
// runSignPsbtSegWitV0NP2WKH tests that the SignPsbt RPC works correctly for a
|
||||
// SegWit v0 np2wkh input.
|
||||
func runSignPsbtSegWitV0NP2WKH(ht *lntemp.HarnessTest,
|
||||
func runSignPsbtSegWitV0NP2WKH(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode) {
|
||||
|
||||
// We test that we can sign a PSBT that spends funds from an input that
|
||||
|
|
@ -759,7 +753,7 @@ func runSignPsbtSegWitV0NP2WKH(ht *lntemp.HarnessTest,
|
|||
|
||||
// runSignPsbtSegWitV1KeySpendBip86 tests that the SignPsbt RPC works correctly
|
||||
// for a SegWit v1 p2tr key spend BIP-0086 input.
|
||||
func runSignPsbtSegWitV1KeySpendBip86(ht *lntemp.HarnessTest,
|
||||
func runSignPsbtSegWitV1KeySpendBip86(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode) {
|
||||
|
||||
// Derive a key we can use for signing.
|
||||
|
|
@ -803,7 +797,7 @@ func runSignPsbtSegWitV1KeySpendBip86(ht *lntemp.HarnessTest,
|
|||
// runSignPsbtSegWitV1KeySpendRootHash tests that the SignPsbt RPC works
|
||||
// correctly for a SegWit v1 p2tr key spend that also commits to a script tree
|
||||
// root hash.
|
||||
func runSignPsbtSegWitV1KeySpendRootHash(ht *lntemp.HarnessTest,
|
||||
func runSignPsbtSegWitV1KeySpendRootHash(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode) {
|
||||
|
||||
// Derive a key we can use for signing.
|
||||
|
|
@ -850,7 +844,7 @@ func runSignPsbtSegWitV1KeySpendRootHash(ht *lntemp.HarnessTest,
|
|||
|
||||
// runSignPsbtSegWitV1ScriptSpend tests that the SignPsbt RPC works correctly
|
||||
// for a SegWit v1 p2tr script spend.
|
||||
func runSignPsbtSegWitV1ScriptSpend(ht *lntemp.HarnessTest,
|
||||
func runSignPsbtSegWitV1ScriptSpend(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode) {
|
||||
|
||||
// Derive a key we can use for signing.
|
||||
|
|
@ -911,7 +905,7 @@ func runSignPsbtSegWitV1ScriptSpend(ht *lntemp.HarnessTest,
|
|||
|
||||
// runFundAndSignPsbt makes sure we can sign PSBTs that were funded by our
|
||||
// internal wallet.
|
||||
func runFundAndSignPsbt(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
||||
func runFundAndSignPsbt(ht *lntest.HarnessTest, alice *node.HarnessNode) {
|
||||
alice.AddToLogf("================ runFundAndSignPsbt ===============")
|
||||
|
||||
// We'll be using a "main" address where we send the funds to and from
|
||||
|
|
@ -965,7 +959,7 @@ func runFundAndSignPsbt(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
|||
// assertPsbtSpend creates an output with the given pkScript on chain and then
|
||||
// attempts to create a sweep transaction that is signed using the SignPsbt RPC
|
||||
// that spends that output again.
|
||||
func assertPsbtSpend(ht *lntemp.HarnessTest, alice *node.HarnessNode,
|
||||
func assertPsbtSpend(ht *lntest.HarnessTest, alice *node.HarnessNode,
|
||||
pkScript []byte, decorateUnsigned func(*psbt.Packet),
|
||||
verifySigned func(*psbt.Packet)) {
|
||||
|
||||
|
|
@ -1074,7 +1068,7 @@ func assertPsbtSpend(ht *lntemp.HarnessTest, alice *node.HarnessNode,
|
|||
|
||||
// assertPsbtFundSignSpend funds a PSBT from the internal wallet and then
|
||||
// attempts to sign it by using the SignPsbt or FinalizePsbt method.
|
||||
func assertPsbtFundSignSpend(ht *lntemp.HarnessTest, alice *node.HarnessNode,
|
||||
func assertPsbtFundSignSpend(ht *lntest.HarnessTest, alice *node.HarnessNode,
|
||||
fundOutputs map[string]uint64, changeType walletrpc.ChangeAddressType,
|
||||
useFinalize bool) {
|
||||
|
||||
|
|
@ -1149,7 +1143,7 @@ func assertPsbtFundSignSpend(ht *lntemp.HarnessTest, alice *node.HarnessNode,
|
|||
// assertChangeScriptType checks if the given script has the right type given
|
||||
// the change address type we used in FundPsbt. By default, the script should
|
||||
// be a P2WPKH one.
|
||||
func assertChangeScriptType(ht *lntemp.HarnessTest, script []byte,
|
||||
func assertChangeScriptType(ht *lntest.HarnessTest, script []byte,
|
||||
fundChangeType walletrpc.ChangeAddressType) {
|
||||
|
||||
switch fundChangeType {
|
||||
|
|
@ -1163,7 +1157,7 @@ func assertChangeScriptType(ht *lntemp.HarnessTest, script []byte,
|
|||
|
||||
// deriveInternalKey derives a signing key and returns its descriptor, full
|
||||
// derivation path and parsed public key.
|
||||
func deriveInternalKey(ht *lntemp.HarnessTest,
|
||||
func deriveInternalKey(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode) (*signrpc.KeyDescriptor, *btcec.PublicKey,
|
||||
[]uint32) {
|
||||
|
||||
|
|
@ -1187,96 +1181,9 @@ func deriveInternalKey(ht *lntemp.HarnessTest,
|
|||
return keyDesc, parsedPubKey, fullDerivationPath
|
||||
}
|
||||
|
||||
// openChannelPsbt attempts to open a channel between srcNode and destNode with
|
||||
// the passed channel funding parameters. If the passed context has a timeout,
|
||||
// then if the timeout is reached before the channel pending notification is
|
||||
// received, an error is returned. An error is returned if the expected step
|
||||
// of funding the PSBT is not received from the source node.
|
||||
func openChannelPsbt(ctx context.Context, srcNode, destNode *lntest.HarnessNode,
|
||||
p lntest.OpenChannelParams) (lnrpc.Lightning_OpenChannelClient, []byte,
|
||||
error) {
|
||||
|
||||
// Wait until srcNode and destNode have the latest chain synced.
|
||||
// Otherwise, we may run into a check within the funding manager that
|
||||
// prevents any funding workflows from being kicked off if the chain
|
||||
// isn't yet synced.
|
||||
if err := srcNode.WaitForBlockchainSync(); err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to sync srcNode chain: %v",
|
||||
err)
|
||||
}
|
||||
if err := destNode.WaitForBlockchainSync(); err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to sync destNode chain: %v",
|
||||
err)
|
||||
}
|
||||
|
||||
// Send the request to open a channel to the source node now. This will
|
||||
// open a long-lived stream where we'll receive status updates about the
|
||||
// progress of the channel.
|
||||
respStream, err := srcNode.OpenChannel(ctx, &lnrpc.OpenChannelRequest{
|
||||
NodePubkey: destNode.PubKey[:],
|
||||
LocalFundingAmount: int64(p.Amt),
|
||||
PushSat: int64(p.PushAmt),
|
||||
Private: p.Private,
|
||||
SpendUnconfirmed: p.SpendUnconfirmed,
|
||||
MinHtlcMsat: int64(p.MinHtlc),
|
||||
FundingShim: p.FundingShim,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to open channel between "+
|
||||
"source and dest: %v", err)
|
||||
}
|
||||
|
||||
// Consume the "PSBT funding ready" update. This waits until the node
|
||||
// notifies us that the PSBT can now be funded.
|
||||
resp, err := receiveChanUpdate(ctx, respStream)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to consume channel update "+
|
||||
"message: %v", err)
|
||||
}
|
||||
upd, ok := resp.Update.(*lnrpc.OpenStatusUpdate_PsbtFund)
|
||||
if !ok {
|
||||
return nil, nil, fmt.Errorf("expected PSBT funding update, "+
|
||||
"instead got %v", resp)
|
||||
}
|
||||
return respStream, upd.PsbtFund.Psbt, nil
|
||||
}
|
||||
|
||||
// receiveChanUpdate waits until a message is received on the stream or the
|
||||
// context is canceled. The context must have a timeout or must be canceled
|
||||
// in case no message is received, otherwise this function will block forever.
|
||||
func receiveChanUpdate(ctx context.Context,
|
||||
stream lnrpc.Lightning_OpenChannelClient) (*lnrpc.OpenStatusUpdate,
|
||||
error) {
|
||||
|
||||
chanMsg := make(chan *lnrpc.OpenStatusUpdate)
|
||||
errChan := make(chan error)
|
||||
go func() {
|
||||
// Consume one message. This will block until the message is
|
||||
// received.
|
||||
resp, err := stream.Recv()
|
||||
if err != nil {
|
||||
errChan <- err
|
||||
return
|
||||
}
|
||||
chanMsg <- resp
|
||||
}()
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil, fmt.Errorf("timeout reached before chan pending " +
|
||||
"update sent")
|
||||
|
||||
case err := <-errChan:
|
||||
return nil, err
|
||||
|
||||
case updateMsg := <-chanMsg:
|
||||
return updateMsg, nil
|
||||
}
|
||||
}
|
||||
|
||||
// sendAllCoinsToAddrType sweeps all coins from the wallet and sends them to a
|
||||
// new address of the given type.
|
||||
func sendAllCoinsToAddrType(ht *lntemp.HarnessTest,
|
||||
func sendAllCoinsToAddrType(ht *lntest.HarnessTest,
|
||||
hn *node.HarnessNode, addrType lnrpc.AddressType) {
|
||||
|
||||
resp := hn.RPC.NewAddress(&lnrpc.NewAddressRequest{
|
||||
|
|
@ -15,8 +15,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -24,7 +24,7 @@ import (
|
|||
|
||||
// testGetRecoveryInfo checks whether lnd gives the right information about
|
||||
// the wallet recovery process.
|
||||
func testGetRecoveryInfo(ht *lntemp.HarnessTest) {
|
||||
func testGetRecoveryInfo(ht *lntest.HarnessTest) {
|
||||
// First, create a new node with strong passphrase and grab the mnemonic
|
||||
// used for key derivation. This will bring up Carol with an empty
|
||||
// wallet, and such that she is synced up.
|
||||
|
|
@ -94,7 +94,7 @@ func testGetRecoveryInfo(ht *lntemp.HarnessTest) {
|
|||
// when providing a valid aezeed that owns outputs on the chain. This test
|
||||
// performs multiple restorations using the same seed and various recovery
|
||||
// windows to ensure we detect funds properly.
|
||||
func testOnchainFundRecovery(ht *lntemp.HarnessTest) {
|
||||
func testOnchainFundRecovery(ht *lntest.HarnessTest) {
|
||||
// First, create a new node with strong passphrase and grab the mnemonic
|
||||
// used for key derivation. This will bring up Carol with an empty
|
||||
// wallet, and such that she is synced up.
|
||||
|
|
@ -321,7 +321,7 @@ func testOnchainFundRecovery(ht *lntemp.HarnessTest) {
|
|||
// The fix in the wallet is simple: In step 6, don't detect addresses from
|
||||
// internal scopes while re-scanning to be in line with the logic in other areas
|
||||
// of the wallet code.
|
||||
func testRescanAddressDetection(ht *lntemp.HarnessTest) {
|
||||
func testRescanAddressDetection(ht *lntest.HarnessTest) {
|
||||
// We start off by creating a new node with the wallet re-scan flag
|
||||
// enabled. This won't have any effect on the first startup but will
|
||||
// come into effect after we re-start the node.
|
||||
|
|
@ -11,8 +11,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
|
@ -55,24 +55,24 @@ var (
|
|||
|
||||
// testRemoteSigner tests that a watch-only wallet can use a remote signing
|
||||
// wallet to perform any signing or ECDH operations.
|
||||
func testRemoteSigner(ht *lntemp.HarnessTest) {
|
||||
func testRemoteSigner(ht *lntest.HarnessTest) {
|
||||
type testCase struct {
|
||||
name string
|
||||
randomSeed bool
|
||||
sendCoins bool
|
||||
fn func(tt *lntemp.HarnessTest,
|
||||
fn func(tt *lntest.HarnessTest,
|
||||
wo, carol *node.HarnessNode)
|
||||
}
|
||||
|
||||
subTests := []testCase{{
|
||||
name: "random seed",
|
||||
randomSeed: true,
|
||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
// Nothing more to test here.
|
||||
},
|
||||
}, {
|
||||
name: "account import",
|
||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
runWalletImportAccountScenario(
|
||||
tt, walletrpc.AddressType_WITNESS_PUBKEY_HASH,
|
||||
carol, wo,
|
||||
|
|
@ -81,36 +81,36 @@ func testRemoteSigner(ht *lntemp.HarnessTest) {
|
|||
}, {
|
||||
name: "basic channel open close",
|
||||
sendCoins: true,
|
||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
runBasicChannelCreationAndUpdates(tt, wo, carol)
|
||||
},
|
||||
}, {
|
||||
name: "channel funding input types",
|
||||
sendCoins: false,
|
||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
runChannelFundingInputTypes(tt, carol, wo)
|
||||
},
|
||||
}, {
|
||||
name: "async payments",
|
||||
sendCoins: true,
|
||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
runAsyncPayments(tt, wo, carol)
|
||||
},
|
||||
}, {
|
||||
name: "shared key",
|
||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
runDeriveSharedKey(tt, wo)
|
||||
},
|
||||
}, {
|
||||
name: "cpfp",
|
||||
sendCoins: true,
|
||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
runCPFP(tt, wo, carol)
|
||||
},
|
||||
}, {
|
||||
name: "psbt",
|
||||
randomSeed: true,
|
||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
runPsbtChanFunding(tt, carol, wo)
|
||||
runSignPsbtSegWitV0P2WKH(tt, wo)
|
||||
runSignPsbtSegWitV1KeySpendBip86(tt, wo)
|
||||
|
|
@ -125,20 +125,20 @@ func testRemoteSigner(ht *lntemp.HarnessTest) {
|
|||
}, {
|
||||
name: "sign output raw",
|
||||
sendCoins: true,
|
||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
runSignOutputRaw(tt, wo)
|
||||
},
|
||||
}, {
|
||||
name: "sign verify msg",
|
||||
sendCoins: true,
|
||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
runSignVerifyMessage(tt, wo)
|
||||
},
|
||||
}, {
|
||||
name: "taproot",
|
||||
sendCoins: true,
|
||||
randomSeed: true,
|
||||
fn: func(tt *lntemp.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
fn: func(tt *lntest.HarnessTest, wo, carol *node.HarnessNode) {
|
||||
testTaprootSendCoinsKeySpendBip86(tt, wo)
|
||||
testTaprootComputeInputScriptKeySpendBip86(tt, wo)
|
||||
testTaprootSignOutputRawScriptSpend(tt, wo)
|
||||
|
|
@ -162,7 +162,7 @@ func testRemoteSigner(ht *lntemp.HarnessTest) {
|
|||
},
|
||||
}}
|
||||
|
||||
prepareTest := func(st *lntemp.HarnessTest,
|
||||
prepareTest := func(st *lntest.HarnessTest,
|
||||
subTest testCase) (*node.HarnessNode,
|
||||
*node.HarnessNode, *node.HarnessNode) {
|
||||
|
||||
|
|
@ -5,13 +5,13 @@ import (
|
|||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// testResHandoff tests that the contractcourt is able to properly hand-off
|
||||
// resolution messages to the switch.
|
||||
func testResHandoff(ht *lntemp.HarnessTest) {
|
||||
func testResHandoff(ht *lntest.HarnessTest) {
|
||||
const (
|
||||
chanAmt = btcutil.Amount(1000000)
|
||||
paymentAmt = 50000
|
||||
|
|
@ -22,14 +22,13 @@ func testResHandoff(ht *lntemp.HarnessTest) {
|
|||
// First we'll create a channel between Alice and Bob.
|
||||
ht.EnsureConnected(alice, bob)
|
||||
|
||||
params := lntemp.OpenChannelParams{Amt: chanAmt}
|
||||
params := lntest.OpenChannelParams{Amt: chanAmt}
|
||||
chanPointAlice := ht.OpenChannel(alice, bob, params)
|
||||
|
||||
// Create a new node Carol that will be in hodl mode. This is used to
|
||||
// trigger the behavior of checkRemoteDanglingActions in the
|
||||
// contractcourt. This will cause Bob to fail the HTLC back to Alice.
|
||||
carol := ht.NewNode("Carol", []string{"--hodl.commit"})
|
||||
defer ht.Shutdown(carol)
|
||||
|
||||
// Connect Bob to Carol.
|
||||
ht.ConnectNodes(bob, carol)
|
||||
|
|
@ -23,8 +23,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/verrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
|
@ -56,7 +56,7 @@ var (
|
|||
|
||||
// testRestAPI tests that the most important features of the REST API work
|
||||
// correctly.
|
||||
func testRestAPI(ht *lntemp.HarnessTest) {
|
||||
func testRestAPI(ht *lntest.HarnessTest) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
run func(*testing.T, *node.HarnessNode, *node.HarnessNode)
|
||||
|
|
@ -201,7 +201,7 @@ func testRestAPI(ht *lntemp.HarnessTest) {
|
|||
}}
|
||||
wsTestCases := []struct {
|
||||
name string
|
||||
run func(ht *lntemp.HarnessTest)
|
||||
run func(ht *lntest.HarnessTest)
|
||||
}{{
|
||||
name: "websocket subscription",
|
||||
run: wsTestCaseSubscription,
|
||||
|
|
@ -243,7 +243,7 @@ func testRestAPI(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func wsTestCaseSubscription(ht *lntemp.HarnessTest) {
|
||||
func wsTestCaseSubscription(ht *lntest.HarnessTest) {
|
||||
// Find out the current best block so we can subscribe to the next one.
|
||||
hash, height := ht.Miner.GetBestBlock()
|
||||
|
||||
|
|
@ -317,7 +317,7 @@ func wsTestCaseSubscription(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func wsTestCaseSubscriptionMacaroon(ht *lntemp.HarnessTest) {
|
||||
func wsTestCaseSubscriptionMacaroon(ht *lntest.HarnessTest) {
|
||||
// Find out the current best block so we can subscribe to the next one.
|
||||
hash, height := ht.Miner.GetBestBlock()
|
||||
|
||||
|
|
@ -407,7 +407,7 @@ func wsTestCaseSubscriptionMacaroon(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func wsTestCaseBiDirectionalSubscription(ht *lntemp.HarnessTest) {
|
||||
func wsTestCaseBiDirectionalSubscription(ht *lntest.HarnessTest) {
|
||||
initialRequest := &lnrpc.ChannelAcceptResponse{}
|
||||
url := "/v1/channels/acceptor"
|
||||
|
||||
|
|
@ -530,7 +530,7 @@ func wsTestCaseBiDirectionalSubscription(ht *lntemp.HarnessTest) {
|
|||
const numChannels = 3
|
||||
for i := 0; i < numChannels; i++ {
|
||||
chanPoint := ht.OpenChannel(
|
||||
bob, alice, lntemp.OpenChannelParams{Amt: 500000},
|
||||
bob, alice, lntest.OpenChannelParams{Amt: 500000},
|
||||
)
|
||||
defer ht.CloseChannel(bob, chanPoint)
|
||||
|
||||
|
|
@ -545,7 +545,7 @@ func wsTestCaseBiDirectionalSubscription(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func wsTestPingPongTimeout(ht *lntemp.HarnessTest) {
|
||||
func wsTestPingPongTimeout(ht *lntest.HarnessTest) {
|
||||
initialRequest := &lnrpc.InvoiceSubscription{
|
||||
AddIndex: 1, SettleIndex: 1,
|
||||
}
|
||||
|
|
@ -12,7 +12,6 @@ import (
|
|||
"github.com/lightningnetwork/lnd/funding"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -21,7 +20,7 @@ import (
|
|||
// testRevokedCloseRetribution tests that Carol is able carry out
|
||||
// retribution in the event that she fails immediately after detecting Bob's
|
||||
// breach txn in the mempool.
|
||||
func testRevokedCloseRetribution(ht *lntemp.HarnessTest) {
|
||||
func testRevokedCloseRetribution(ht *lntest.HarnessTest) {
|
||||
const (
|
||||
chanAmt = funding.MaxBtcFundingAmount
|
||||
paymentAmt = 10000
|
||||
|
|
@ -51,7 +50,7 @@ func testRevokedCloseRetribution(ht *lntemp.HarnessTest) {
|
|||
// closure by Bob, we'll first open up a channel between them with a
|
||||
// 0.5 BTC value.
|
||||
chanPoint := ht.OpenChannel(
|
||||
carol, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
carol, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// With the channel open, we'll create a few invoices for Bob that
|
||||
|
|
@ -158,7 +157,7 @@ func testRevokedCloseRetribution(ht *lntemp.HarnessTest) {
|
|||
// tx's confHeight+CSV-1 blocks and since we've already mined one that
|
||||
// included the justice tx we only need to mine extra DefaultCSV-2
|
||||
// blocks to unlock it.
|
||||
ht.MineBlocks(lntest.DefaultCSV - 2)
|
||||
ht.MineBlocks(defaultCSV - 2)
|
||||
|
||||
ht.AssertNumPendingForceClose(bob, 0)
|
||||
}
|
||||
|
|
@ -166,7 +165,7 @@ func testRevokedCloseRetribution(ht *lntemp.HarnessTest) {
|
|||
// testRevokedCloseRetributionZeroValueRemoteOutput tests that Dave is able
|
||||
// carry out retribution in the event that he fails in state where the remote
|
||||
// commitment output has zero-value.
|
||||
func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntemp.HarnessTest) {
|
||||
func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntest.HarnessTest) {
|
||||
const (
|
||||
chanAmt = funding.MaxBtcFundingAmount
|
||||
paymentAmt = 10000
|
||||
|
|
@ -199,7 +198,7 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntemp.HarnessTest) {
|
|||
// closure by Carol, we'll first open up a channel between them with a
|
||||
// 0.5 BTC value.
|
||||
chanPoint := ht.OpenChannel(
|
||||
dave, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
dave, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// With the channel open, we'll create a few invoices for Carol that
|
||||
|
|
@ -224,6 +223,9 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntemp.HarnessTest) {
|
|||
// backup.
|
||||
ht.EnsureConnected(dave, carol)
|
||||
|
||||
// Once connected, give Dave some time to enable the channel again.
|
||||
ht.AssertTopologyChannelOpen(dave, chanPoint)
|
||||
|
||||
// Finally, send payments from Dave to Carol, consuming Carol's
|
||||
// remaining payment hashes.
|
||||
ht.CompletePaymentRequestsNoWait(dave, carolPayReqs, chanPoint)
|
||||
|
|
@ -298,7 +300,7 @@ func testRevokedCloseRetributionZeroValueRemoteOutput(ht *lntemp.HarnessTest) {
|
|||
// testRevokedCloseRetributionRemoteHodl tests that Dave properly responds to a
|
||||
// channel breach made by the remote party, specifically in the case that the
|
||||
// remote party breaches before settling extended HTLCs.
|
||||
func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
|
||||
func testRevokedCloseRetributionRemoteHodl(ht *lntest.HarnessTest) {
|
||||
const (
|
||||
chanAmt = funding.MaxBtcFundingAmount
|
||||
pushAmt = 200000
|
||||
|
|
@ -333,7 +335,7 @@ func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
|
|||
// by Carol, we'll first open up a channel between them with a
|
||||
// funding.MaxBtcFundingAmount (2^24) satoshis value.
|
||||
chanPoint := ht.OpenChannel(
|
||||
dave, carol, lntemp.OpenChannelParams{
|
||||
dave, carol, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
},
|
||||
|
|
@ -401,6 +403,9 @@ func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
|
|||
// backup.
|
||||
ht.EnsureConnected(dave, carol)
|
||||
|
||||
// Once connected, give Dave some time to enable the channel again.
|
||||
ht.AssertTopologyChannelOpen(dave, chanPoint)
|
||||
|
||||
// Finally, send payments from Dave to Carol, consuming Carol's
|
||||
// remaining payment hashes.
|
||||
ht.CompletePaymentRequestsNoWait(
|
||||
|
|
@ -472,7 +477,14 @@ func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
|
|||
for _, txid := range mempool {
|
||||
// Check that the justice tx has the appropriate number
|
||||
// of inputs.
|
||||
tx := ht.Miner.GetRawTransaction(txid)
|
||||
//
|
||||
// NOTE: We don't use `ht.Miner.GetRawTransaction`
|
||||
// which asserts a txid must be found as the HTLC
|
||||
// spending txes might be aggregated.
|
||||
tx, err := ht.Miner.Client.GetRawTransaction(txid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
exNumInputs := 2 + numInvoices
|
||||
if len(tx.MsgTx().TxIn) == exNumInputs {
|
||||
|
|
@ -578,7 +590,7 @@ func testRevokedCloseRetributionRemoteHodl(ht *lntemp.HarnessTest) {
|
|||
// trigger a breach. Carol is kept offline throughout the process and the test
|
||||
// asserts that Willy responds by broadcasting the justice transaction on
|
||||
// Carol's behalf sweeping her funds without a reward.
|
||||
func testRevokedCloseRetributionAltruistWatchtower(ht *lntemp.HarnessTest) {
|
||||
func testRevokedCloseRetributionAltruistWatchtower(ht *lntest.HarnessTest) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
anchors bool
|
||||
|
|
@ -592,7 +604,7 @@ func testRevokedCloseRetributionAltruistWatchtower(ht *lntemp.HarnessTest) {
|
|||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
testFunc := func(ht *lntemp.HarnessTest) {
|
||||
testFunc := func(ht *lntest.HarnessTest) {
|
||||
testRevokedCloseRetributionAltruistWatchtowerCase(
|
||||
ht, tc.anchors,
|
||||
)
|
||||
|
|
@ -601,7 +613,7 @@ func testRevokedCloseRetributionAltruistWatchtower(ht *lntemp.HarnessTest) {
|
|||
success := ht.Run(tc.name, func(tt *testing.T) {
|
||||
st := ht.Subtest(tt)
|
||||
|
||||
st.RunTestCase(&lntemp.TestCase{
|
||||
st.RunTestCase(&lntest.TestCase{
|
||||
Name: tc.name,
|
||||
TestFunc: testFunc,
|
||||
})
|
||||
|
|
@ -619,7 +631,7 @@ func testRevokedCloseRetributionAltruistWatchtower(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntemp.HarnessTest,
|
||||
func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntest.HarnessTest,
|
||||
anchors bool) {
|
||||
|
||||
const (
|
||||
|
|
@ -696,7 +708,7 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntemp.HarnessTest,
|
|||
// In order to test Dave's response to an uncooperative channel
|
||||
// closure by Carol, we'll first open up a channel between them with a
|
||||
// 0.5 BTC value.
|
||||
params := lntemp.OpenChannelParams{
|
||||
params := lntest.OpenChannelParams{
|
||||
Amt: 3 * (chanAmt / 4),
|
||||
PushAmt: chanAmt / 4,
|
||||
}
|
||||
|
|
@ -727,6 +739,9 @@ func testRevokedCloseRetributionAltruistWatchtowerCase(ht *lntemp.HarnessTest,
|
|||
// backup.
|
||||
ht.EnsureConnected(dave, carol)
|
||||
|
||||
// Once connected, give Dave some time to enable the channel again.
|
||||
ht.AssertTopologyChannelOpen(dave, chanPoint)
|
||||
|
||||
// Finally, send payments from Dave to Carol, consuming Carol's
|
||||
// remaining payment hashes.
|
||||
ht.CompletePaymentRequestsNoWait(dave, carolPayReqs, chanPoint)
|
||||
|
|
@ -10,8 +10,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/chainreg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -65,7 +65,7 @@ var singleHopSendToRouteCases = []singleHopSendToRouteCase{
|
|||
// by feeding the route back into the various SendToRoute RPC methods. Here we
|
||||
// test all three SendToRoute endpoints, forcing each to perform both a regular
|
||||
// payment and an MPP payment.
|
||||
func testSingleHopSendToRoute(ht *lntemp.HarnessTest) {
|
||||
func testSingleHopSendToRoute(ht *lntest.HarnessTest) {
|
||||
for _, test := range singleHopSendToRouteCases {
|
||||
test := test
|
||||
|
||||
|
|
@ -76,7 +76,7 @@ func testSingleHopSendToRoute(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func testSingleHopSendToRouteCase(ht *lntemp.HarnessTest,
|
||||
func testSingleHopSendToRouteCase(ht *lntest.HarnessTest,
|
||||
test singleHopSendToRouteCase) {
|
||||
|
||||
const chanAmt = btcutil.Amount(100000)
|
||||
|
|
@ -97,7 +97,7 @@ func testSingleHopSendToRouteCase(ht *lntemp.HarnessTest,
|
|||
// Open a channel with 100k satoshis between Carol and Dave with Carol
|
||||
// being the sole funder of the channel.
|
||||
chanPointCarol := ht.OpenChannel(
|
||||
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
carol, dave, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
defer ht.CloseChannel(carol, chanPointCarol)
|
||||
|
||||
|
|
@ -289,7 +289,7 @@ func testSingleHopSendToRouteCase(ht *lntemp.HarnessTest,
|
|||
//
|
||||
// We'll query the daemon for routes from Alice to Carol and then
|
||||
// send payments through the routes.
|
||||
func testMultiHopSendToRoute(ht *lntemp.HarnessTest) {
|
||||
func testMultiHopSendToRoute(ht *lntest.HarnessTest) {
|
||||
ht.Run("with cache", func(tt *testing.T) {
|
||||
st := ht.Subtest(tt)
|
||||
runMultiHopSendToRoute(st, true)
|
||||
|
|
@ -309,7 +309,7 @@ func testMultiHopSendToRoute(ht *lntemp.HarnessTest) {
|
|||
//
|
||||
// We'll query the daemon for routes from Alice to Carol and then
|
||||
// send payments through the routes.
|
||||
func runMultiHopSendToRoute(ht *lntemp.HarnessTest, useGraphCache bool) {
|
||||
func runMultiHopSendToRoute(ht *lntest.HarnessTest, useGraphCache bool) {
|
||||
var opts []string
|
||||
if !useGraphCache {
|
||||
opts = append(opts, "--db.no-graph-cache")
|
||||
|
|
@ -325,7 +325,7 @@ func runMultiHopSendToRoute(ht *lntemp.HarnessTest, useGraphCache bool) {
|
|||
// Open a channel with 100k satoshis between Alice and Bob with Alice
|
||||
// being the sole funder of the channel.
|
||||
chanPointAlice := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
defer ht.CloseChannel(alice, chanPointAlice)
|
||||
|
||||
|
|
@ -337,10 +337,13 @@ func runMultiHopSendToRoute(ht *lntemp.HarnessTest, useGraphCache bool) {
|
|||
ht.ConnectNodes(carol, bob)
|
||||
|
||||
chanPointBob := ht.OpenChannel(
|
||||
bob, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
bob, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
defer ht.CloseChannel(carol, chanPointBob)
|
||||
|
||||
// Make sure Alice knows the channel between Bob and Carol.
|
||||
ht.AssertTopologyChannelOpen(alice, chanPointBob)
|
||||
|
||||
// Create 5 invoices for Carol, which expect a payment from Alice for
|
||||
// 1k satoshis with a different preimage each time.
|
||||
const (
|
||||
|
|
@ -407,14 +410,14 @@ func runMultiHopSendToRoute(ht *lntemp.HarnessTest, useGraphCache bool) {
|
|||
|
||||
// testSendToRouteErrorPropagation tests propagation of errors that occur
|
||||
// while processing a multi-hop payment through an unknown route.
|
||||
func testSendToRouteErrorPropagation(ht *lntemp.HarnessTest) {
|
||||
func testSendToRouteErrorPropagation(ht *lntest.HarnessTest) {
|
||||
const chanAmt = btcutil.Amount(100000)
|
||||
|
||||
// Open a channel with 100k satoshis between Alice and Bob with Alice
|
||||
// being the sole funder of the channel.
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
chanPointAlice := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Create a new nodes (Carol and Charlie), load her with some funds,
|
||||
|
|
@ -432,7 +435,7 @@ func testSendToRouteErrorPropagation(ht *lntemp.HarnessTest) {
|
|||
ht.FundCoins(btcutil.SatoshiPerBitcoin, charlie)
|
||||
|
||||
ht.ConnectNodes(carol, charlie)
|
||||
ht.OpenChannel(carol, charlie, lntemp.OpenChannelParams{Amt: chanAmt})
|
||||
ht.OpenChannel(carol, charlie, lntest.OpenChannelParams{Amt: chanAmt})
|
||||
|
||||
// Query routes from Carol to Charlie which will be an invalid route
|
||||
// for Alice -> Bob.
|
||||
|
|
@ -476,7 +479,9 @@ func testSendToRouteErrorPropagation(ht *lntemp.HarnessTest) {
|
|||
// testPrivateChannels tests that a private channel can be used for
|
||||
// routing by the two endpoints of the channel, but is not known by
|
||||
// the rest of the nodes in the graph.
|
||||
func testPrivateChannels(ht *lntemp.HarnessTest) {
|
||||
//
|
||||
//nolint:dupword
|
||||
func testPrivateChannels(ht *lntest.HarnessTest) {
|
||||
const chanAmt = btcutil.Amount(100000)
|
||||
|
||||
// We create the following topology:
|
||||
|
|
@ -493,7 +498,7 @@ func testPrivateChannels(ht *lntemp.HarnessTest) {
|
|||
// Open a channel with 200k satoshis between Alice and Bob.
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
chanPointAlice := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt * 2},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt * 2},
|
||||
)
|
||||
|
||||
// Create Dave, and a channel to Alice of 100k.
|
||||
|
|
@ -502,7 +507,7 @@ func testPrivateChannels(ht *lntemp.HarnessTest) {
|
|||
ht.FundCoins(btcutil.SatoshiPerBitcoin, dave)
|
||||
|
||||
chanPointDave := ht.OpenChannel(
|
||||
dave, alice, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
dave, alice, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Next, we'll create Carol and establish a channel from her to
|
||||
|
|
@ -512,14 +517,14 @@ func testPrivateChannels(ht *lntemp.HarnessTest) {
|
|||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||
|
||||
chanPointCarol := ht.OpenChannel(
|
||||
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
carol, dave, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Now create a _private_ channel directly between Carol and
|
||||
// Alice of 100k.
|
||||
ht.ConnectNodes(carol, alice)
|
||||
chanPointPrivate := ht.OpenChannel(
|
||||
carol, alice, lntemp.OpenChannelParams{
|
||||
carol, alice, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
Private: true,
|
||||
},
|
||||
|
|
@ -602,7 +607,7 @@ func testPrivateChannels(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testInvoiceRoutingHints tests that the routing hints for an invoice are
|
||||
// created properly.
|
||||
func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
||||
func testInvoiceRoutingHints(ht *lntest.HarnessTest) {
|
||||
const chanAmt = btcutil.Amount(100000)
|
||||
|
||||
// Throughout this test, we'll be opening a channel between Alice and
|
||||
|
|
@ -615,7 +620,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
|||
// invoice's payment.
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
chanPointBob := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: chanAmt / 2,
|
||||
Private: true,
|
||||
|
|
@ -629,7 +634,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
|||
|
||||
ht.ConnectNodes(alice, carol)
|
||||
chanPointCarol := ht.OpenChannel(
|
||||
alice, carol, lntemp.OpenChannelParams{
|
||||
alice, carol, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: chanAmt / 2,
|
||||
},
|
||||
|
|
@ -642,7 +647,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
|||
// that wish to stay unadvertised.
|
||||
ht.ConnectNodes(bob, carol)
|
||||
chanPointBobCarol := ht.OpenChannel(
|
||||
bob, carol, lntemp.OpenChannelParams{
|
||||
bob, carol, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: chanAmt / 2,
|
||||
},
|
||||
|
|
@ -656,7 +661,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
|||
|
||||
ht.ConnectNodes(alice, dave)
|
||||
chanPointDave := ht.OpenChannel(
|
||||
alice, dave, lntemp.OpenChannelParams{
|
||||
alice, dave, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
Private: true,
|
||||
},
|
||||
|
|
@ -669,7 +674,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
|||
eve := ht.NewNode("Eve", nil)
|
||||
ht.ConnectNodes(alice, eve)
|
||||
chanPointEve := ht.OpenChannel(
|
||||
alice, eve, lntemp.OpenChannelParams{
|
||||
alice, eve, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: chanAmt / 2,
|
||||
Private: true,
|
||||
|
|
@ -744,7 +749,7 @@ func testInvoiceRoutingHints(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testMultiHopOverPrivateChannels tests that private channels can be used as
|
||||
// intermediate hops in a route for payments.
|
||||
func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
|
||||
func testMultiHopOverPrivateChannels(ht *lntest.HarnessTest) {
|
||||
// We'll test that multi-hop payments over private channels work as
|
||||
// intended. To do so, we'll create the following topology:
|
||||
// private public private
|
||||
|
|
@ -755,7 +760,7 @@ func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
|
|||
// being the funder.
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
chanPointAlice := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
Private: true,
|
||||
},
|
||||
|
|
@ -766,7 +771,7 @@ func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
|
|||
carol := ht.NewNode("Carol", nil)
|
||||
ht.ConnectNodes(bob, carol)
|
||||
chanPointBob := ht.OpenChannel(
|
||||
bob, carol, lntemp.OpenChannelParams{
|
||||
bob, carol, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
},
|
||||
)
|
||||
|
|
@ -781,7 +786,7 @@ func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
|
|||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||
|
||||
chanPointCarol := ht.OpenChannel(
|
||||
carol, dave, lntemp.OpenChannelParams{
|
||||
carol, dave, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
Private: true,
|
||||
},
|
||||
|
|
@ -851,7 +856,7 @@ func testMultiHopOverPrivateChannels(ht *lntemp.HarnessTest) {
|
|||
// Alice --> Bob --> Carol --> Dave
|
||||
//
|
||||
// and query the daemon for routes from Alice to Dave.
|
||||
func testQueryRoutes(ht *lntemp.HarnessTest) {
|
||||
func testQueryRoutes(ht *lntest.HarnessTest) {
|
||||
const chanAmt = btcutil.Amount(100000)
|
||||
|
||||
// Grab Alice and Bob from the standby nodes.
|
||||
|
|
@ -869,8 +874,8 @@ func testQueryRoutes(ht *lntemp.HarnessTest) {
|
|||
|
||||
// We now proceed to open channels:
|
||||
// Alice=>Bob, Bob=>Carol and Carol=>Dave.
|
||||
p := lntemp.OpenChannelParams{Amt: chanAmt}
|
||||
reqs := []*lntemp.OpenChannelRequest{
|
||||
p := lntest.OpenChannelParams{Amt: chanAmt}
|
||||
reqs := []*lntest.OpenChannelRequest{
|
||||
{Local: alice, Remote: bob, Param: p},
|
||||
{Local: bob, Remote: carol, Param: p},
|
||||
{Local: carol, Remote: dave, Param: p},
|
||||
|
|
@ -1086,7 +1091,7 @@ func testMissionControlCfg(t *testing.T, hn *node.HarnessNode) {
|
|||
|
||||
// testMissionControlImport tests import of mission control results from an
|
||||
// external source.
|
||||
func testMissionControlImport(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
||||
func testMissionControlImport(ht *lntest.HarnessTest, hn *node.HarnessNode,
|
||||
fromNode, toNode []byte) {
|
||||
|
||||
// Reset mission control so that our query will return the default
|
||||
|
|
@ -1138,7 +1143,7 @@ func testMissionControlImport(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
|||
|
||||
// testRouteFeeCutoff tests that we are able to prevent querying routes and
|
||||
// sending payments that incur a fee higher than the fee limit.
|
||||
func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
|
||||
func testRouteFeeCutoff(ht *lntest.HarnessTest) {
|
||||
// For this test, we'll create the following topology:
|
||||
//
|
||||
// --- Bob ---
|
||||
|
|
@ -1155,7 +1160,7 @@ func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
|
|||
// Open a channel between Alice and Bob.
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
chanPointAliceBob := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Create Carol's node and open a channel between her and Alice with
|
||||
|
|
@ -1165,7 +1170,7 @@ func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
|
|||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||
|
||||
chanPointAliceCarol := ht.OpenChannel(
|
||||
alice, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Create Dave's node and open a channel between him and Bob with Bob
|
||||
|
|
@ -1173,13 +1178,13 @@ func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
|
|||
dave := ht.NewNode("Dave", nil)
|
||||
ht.ConnectNodes(dave, bob)
|
||||
chanPointBobDave := ht.OpenChannel(
|
||||
bob, dave, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
bob, dave, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Open a channel between Carol and Dave.
|
||||
ht.ConnectNodes(carol, dave)
|
||||
chanPointCarolDave := ht.OpenChannel(
|
||||
carol, dave, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
carol, dave, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Now that all the channels were set up, we'll wait for all the nodes
|
||||
|
|
@ -1203,7 +1208,7 @@ func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
|
|||
baseFee := int64(10000)
|
||||
feeRate := int64(5)
|
||||
timeLockDelta := uint32(chainreg.DefaultBitcoinTimeLockDelta)
|
||||
maxHtlc := calculateMaxHtlc(chanAmt)
|
||||
maxHtlc := lntest.CalculateMaxHtlc(chanAmt)
|
||||
|
||||
expectedPolicy := &lnrpc.RoutingPolicy{
|
||||
FeeBaseMsat: baseFee,
|
||||
|
|
@ -1285,7 +1290,8 @@ func testRouteFeeCutoff(ht *lntemp.HarnessTest) {
|
|||
case *lnrpc.FeeLimit_Fixed:
|
||||
sendReq.FeeLimitMsat = 1000 * limit.Fixed
|
||||
case *lnrpc.FeeLimit_Percent:
|
||||
sendReq.FeeLimitMsat = 1000 * paymentAmt * limit.Percent / 100
|
||||
sendReq.FeeLimitMsat = 1000 * paymentAmt *
|
||||
limit.Percent / 100
|
||||
}
|
||||
|
||||
result := ht.SendPaymentAssertSettled(alice, sendReq)
|
||||
|
|
@ -8,8 +8,8 @@ import (
|
|||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"github.com/lightningnetwork/lnd/zpay32"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -19,7 +19,7 @@ import (
|
|||
|
||||
// testRPCMiddlewareInterceptor tests that the RPC middleware interceptor can
|
||||
// be used correctly and in a safe way.
|
||||
func testRPCMiddlewareInterceptor(ht *lntemp.HarnessTest) {
|
||||
func testRPCMiddlewareInterceptor(ht *lntest.HarnessTest) {
|
||||
// Let's first enable the middleware interceptor.
|
||||
//
|
||||
// NOTE: we cannot use standby nodes here as the test messes with
|
||||
|
|
@ -32,7 +32,7 @@ func testRPCMiddlewareInterceptor(ht *lntemp.HarnessTest) {
|
|||
// data to inspect when doing RPC calls to Alice later.
|
||||
ht.EnsureConnected(alice, bob)
|
||||
ht.FundCoins(btcutil.SatoshiPerBitcoin, alice)
|
||||
ht.OpenChannel(alice, bob, lntemp.OpenChannelParams{Amt: 1_234_567})
|
||||
ht.OpenChannel(alice, bob, lntest.OpenChannelParams{Amt: 1_234_567})
|
||||
|
||||
// Load or bake the macaroons that the simulated users will use to
|
||||
// access the RPC.
|
||||
|
|
@ -545,7 +545,7 @@ func middlewareRequestManipulationTest(t *testing.T, node *node.HarnessNode,
|
|||
|
||||
// middlewareMandatoryTest tests that all RPC requests are blocked if there is
|
||||
// a mandatory middleware declared that's currently not registered.
|
||||
func middlewareMandatoryTest(ht *lntemp.HarnessTest, node *node.HarnessNode) {
|
||||
func middlewareMandatoryTest(ht *lntest.HarnessTest, node *node.HarnessNode) {
|
||||
// Let's declare our itest interceptor as mandatory but don't register
|
||||
// it just yet. That should cause all RPC requests to fail, except for
|
||||
// the registration itself.
|
||||
|
|
@ -6,13 +6,13 @@ import (
|
|||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// testSendMultiPathPayment tests that we are able to successfully route a
|
||||
// payment using multiple shards across different paths.
|
||||
func testSendMultiPathPayment(ht *lntemp.HarnessTest) {
|
||||
func testSendMultiPathPayment(ht *lntest.HarnessTest) {
|
||||
mts := newMppTestScenario(ht)
|
||||
|
||||
const paymentAmt = btcutil.Amount(300000)
|
||||
|
|
@ -13,8 +13,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
|
@ -22,7 +22,7 @@ import (
|
|||
// DeriveSharedKey. It creates an ephemeral private key, performing an ECDH with
|
||||
// the node's pubkey and a customized public key to check the validity of the
|
||||
// result.
|
||||
func testDeriveSharedKey(ht *lntemp.HarnessTest) {
|
||||
func testDeriveSharedKey(ht *lntest.HarnessTest) {
|
||||
runDeriveSharedKey(ht, ht.Alice)
|
||||
}
|
||||
|
||||
|
|
@ -30,7 +30,7 @@ func testDeriveSharedKey(ht *lntemp.HarnessTest) {
|
|||
// DeriveSharedKey. It creates an ephemeral private key, performing an ECDH with
|
||||
// the node's pubkey and a customized public key to check the validity of the
|
||||
// result.
|
||||
func runDeriveSharedKey(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
||||
func runDeriveSharedKey(ht *lntest.HarnessTest, alice *node.HarnessNode) {
|
||||
// Create an ephemeral key, extracts its public key, and make a
|
||||
// PrivKeyECDH using the ephemeral key.
|
||||
ephemeralPriv, err := btcec.NewPrivateKey()
|
||||
|
|
@ -194,13 +194,13 @@ func runDeriveSharedKey(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
|||
|
||||
// testSignOutputRaw makes sure that the SignOutputRaw RPC can be used with all
|
||||
// custom ways of specifying the signing key in the key descriptor/locator.
|
||||
func testSignOutputRaw(ht *lntemp.HarnessTest) {
|
||||
func testSignOutputRaw(ht *lntest.HarnessTest) {
|
||||
runSignOutputRaw(ht, ht.Alice)
|
||||
}
|
||||
|
||||
// runSignOutputRaw makes sure that the SignOutputRaw RPC can be used with all
|
||||
// custom ways of specifying the signing key in the key descriptor/locator.
|
||||
func runSignOutputRaw(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
||||
func runSignOutputRaw(ht *lntest.HarnessTest, alice *node.HarnessNode) {
|
||||
// For the next step, we need a public key. Let's use a special family
|
||||
// for this. We want this to be an index of zero.
|
||||
const testCustomKeyFamily = 44
|
||||
|
|
@ -272,7 +272,7 @@ func runSignOutputRaw(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
|||
// assertSignOutputRaw sends coins to a p2wkh address derived from the given
|
||||
// target public key and then tries to spend that output again by invoking the
|
||||
// SignOutputRaw RPC with the key descriptor provided.
|
||||
func assertSignOutputRaw(ht *lntemp.HarnessTest,
|
||||
func assertSignOutputRaw(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode, targetPubKey *btcec.PublicKey,
|
||||
keyDesc *signrpc.KeyDescriptor,
|
||||
sigHash txscript.SigHashType) {
|
||||
|
|
@ -373,14 +373,14 @@ func assertSignOutputRaw(ht *lntemp.HarnessTest,
|
|||
// testSignVerifyMessage makes sure that the SignMessage RPC can be used with
|
||||
// all custom flags by verifying with VerifyMessage. Tests both ECDSA and
|
||||
// Schnorr signatures.
|
||||
func testSignVerifyMessage(ht *lntemp.HarnessTest) {
|
||||
func testSignVerifyMessage(ht *lntest.HarnessTest) {
|
||||
runSignVerifyMessage(ht, ht.Alice)
|
||||
}
|
||||
|
||||
// runSignVerifyMessage makes sure that the SignMessage RPC can be used with
|
||||
// all custom flags by verifying with VerifyMessage. Tests both ECDSA and
|
||||
// Schnorr signatures.
|
||||
func runSignVerifyMessage(ht *lntemp.HarnessTest, alice *node.HarnessNode) {
|
||||
func runSignVerifyMessage(ht *lntest.HarnessTest, alice *node.HarnessNode) {
|
||||
aliceMsg := []byte("alice msg")
|
||||
keyLoc := &signrpc.KeyLocator{
|
||||
KeyFamily: int32(keychain.KeyFamilyNodeKey),
|
||||
|
|
@ -7,20 +7,20 @@ import (
|
|||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/record"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func testSingleHopInvoice(ht *lntemp.HarnessTest) {
|
||||
func testSingleHopInvoice(ht *lntest.HarnessTest) {
|
||||
// Open a channel with 100k satoshis between Alice and Bob with Alice
|
||||
// being the sole funder of the channel.
|
||||
chanAmt := btcutil.Amount(100000)
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
cp := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// assertAmountPaid is a helper closure that asserts the amount paid by
|
||||
|
|
@ -3,8 +3,8 @@ package itest
|
|||
import (
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
|
@ -21,11 +21,11 @@ const (
|
|||
//
|
||||
// The general flow of this test:
|
||||
// 1. Carol --> Dave --> Alice --> Bob forward payment
|
||||
// 2. -------X X X Bob restart sender and intermediaries
|
||||
// 2. X X X Bob restart sender and intermediaries
|
||||
// 3. Carol <-- Dave <-- Alice <-- Bob expect settle to propagate
|
||||
//
|
||||
//nolint:dupword
|
||||
func testSwitchCircuitPersistence(ht *lntemp.HarnessTest) {
|
||||
func testSwitchCircuitPersistence(ht *lntest.HarnessTest) {
|
||||
// Setup our test scenario. We should now have four nodes running with
|
||||
// three channels.
|
||||
s := setupScenarioFourNodes(ht)
|
||||
|
|
@ -95,7 +95,7 @@ func testSwitchCircuitPersistence(ht *lntemp.HarnessTest) {
|
|||
// 2. Carol --- Dave X Alice --- Bob disconnect intermediaries
|
||||
// 3. Carol --- Dave X Alice <-- Bob settle last hop
|
||||
// 4. Carol <-- Dave <-- Alice --- Bob reconnect, expect settle to propagate
|
||||
func testSwitchOfflineDelivery(ht *lntemp.HarnessTest) {
|
||||
func testSwitchOfflineDelivery(ht *lntest.HarnessTest) {
|
||||
// Setup our test scenario. We should now have four nodes running with
|
||||
// three channels.
|
||||
s := setupScenarioFourNodes(ht)
|
||||
|
|
@ -131,11 +131,6 @@ func testSwitchOfflineDelivery(ht *lntemp.HarnessTest) {
|
|||
// Wait until all outstanding htlcs in the network have been settled.
|
||||
s.assertHTLCs(ht, 0)
|
||||
|
||||
// When asserting the amount of satoshis moved, we'll factor in the
|
||||
// default base fee, as we didn't modify the fee structure when
|
||||
// creating the seed nodes in the network.
|
||||
const baseFee = 1
|
||||
|
||||
// At this point all the channels within our proto network should be
|
||||
// shifted by 5k satoshis in the direction of Carol, the sink within the
|
||||
// payment flow generated above. The order of asserts corresponds to
|
||||
|
|
@ -174,7 +169,9 @@ func testSwitchOfflineDelivery(ht *lntemp.HarnessTest) {
|
|||
// 3. Carol --- Dave X Alice <-- Bob settle last hop
|
||||
// 4. Carol --- Dave X X Bob restart Alice
|
||||
// 5. Carol <-- Dave <-- Alice --- Bob expect settle to propagate
|
||||
func testSwitchOfflineDeliveryPersistence(ht *lntemp.HarnessTest) {
|
||||
//
|
||||
//nolint:dupword
|
||||
func testSwitchOfflineDeliveryPersistence(ht *lntest.HarnessTest) {
|
||||
// Setup our test scenario. We should now have four nodes running with
|
||||
// three channels.
|
||||
s := setupScenarioFourNodes(ht)
|
||||
|
|
@ -260,7 +257,9 @@ func testSwitchOfflineDeliveryPersistence(ht *lntemp.HarnessTest) {
|
|||
// 3. Carol --- Dave X Alice <-- Bob settle last hop
|
||||
// 4. Carol --- Dave X X shutdown Bob, restart Alice
|
||||
// 5. Carol <-- Dave <-- Alice X expect settle to propagate
|
||||
func testSwitchOfflineDeliveryOutgoingOffline(ht *lntemp.HarnessTest) {
|
||||
//
|
||||
//nolint:dupword
|
||||
func testSwitchOfflineDeliveryOutgoingOffline(ht *lntest.HarnessTest) {
|
||||
// Setup our test scenario. We should now have four nodes running with
|
||||
// three channels. Note that we won't call the cleanUp function here as
|
||||
// we will manually stop the node Carol and her channel.
|
||||
|
|
@ -371,13 +370,13 @@ type scenarioFourNodes struct {
|
|||
//
|
||||
// NOTE: caller needs to call cleanUp to clean the nodes and channels created
|
||||
// from this setup.
|
||||
func setupScenarioFourNodes(ht *lntemp.HarnessTest) *scenarioFourNodes {
|
||||
func setupScenarioFourNodes(ht *lntest.HarnessTest) *scenarioFourNodes {
|
||||
const (
|
||||
chanAmt = btcutil.Amount(1000000)
|
||||
pushAmt = btcutil.Amount(900000)
|
||||
)
|
||||
|
||||
params := lntemp.OpenChannelParams{
|
||||
params := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
}
|
||||
|
|
@ -404,7 +403,7 @@ func setupScenarioFourNodes(ht *lntemp.HarnessTest) *scenarioFourNodes {
|
|||
ht.FundCoins(btcutil.SatoshiPerBitcoin, carol)
|
||||
|
||||
// Open channels in batch to save blocks mined.
|
||||
reqs := []*lntemp.OpenChannelRequest{
|
||||
reqs := []*lntest.OpenChannelRequest{
|
||||
{Local: alice, Remote: bob, Param: params},
|
||||
{Local: dave, Remote: alice, Param: params},
|
||||
{Local: carol, Remote: dave, Param: params},
|
||||
|
|
@ -456,7 +455,7 @@ func setupScenarioFourNodes(ht *lntemp.HarnessTest) *scenarioFourNodes {
|
|||
|
||||
// assertHTLCs is a helper function which asserts the desired num of
|
||||
// HTLCs has been seen in the nodes.
|
||||
func (s *scenarioFourNodes) assertHTLCs(ht *lntemp.HarnessTest, num int) {
|
||||
func (s *scenarioFourNodes) assertHTLCs(ht *lntest.HarnessTest, num int) {
|
||||
// Alice should have both the same number of outgoing and
|
||||
// incoming HTLCs.
|
||||
ht.AssertNumActiveHtlcs(s.alice, num*2)
|
||||
|
|
@ -472,7 +471,7 @@ func (s *scenarioFourNodes) assertHTLCs(ht *lntemp.HarnessTest, num int) {
|
|||
// assertAmoutPaid is a helper method which takes a given paid amount
|
||||
// and number of payments and asserts the desired payments are made in
|
||||
// the four nodes.
|
||||
func (s *scenarioFourNodes) assertAmoutPaid(ht *lntemp.HarnessTest,
|
||||
func (s *scenarioFourNodes) assertAmoutPaid(ht *lntest.HarnessTest,
|
||||
amt int64, num int64) {
|
||||
|
||||
ht.AssertAmountPaid(
|
||||
|
|
@ -20,8 +20,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -47,7 +47,7 @@ var (
|
|||
|
||||
// testTaproot ensures that the daemon can send to and spend from taproot (p2tr)
|
||||
// outputs.
|
||||
func testTaproot(ht *lntemp.HarnessTest) {
|
||||
func testTaproot(ht *lntest.HarnessTest) {
|
||||
testTaprootSendCoinsKeySpendBip86(ht, ht.Alice)
|
||||
testTaprootComputeInputScriptKeySpendBip86(ht, ht.Alice)
|
||||
testTaprootSignOutputRawScriptSpend(ht, ht.Alice)
|
||||
|
|
@ -81,7 +81,7 @@ func testTaproot(ht *lntemp.HarnessTest) {
|
|||
// testTaprootSendCoinsKeySpendBip86 tests sending to and spending from
|
||||
// p2tr key spend only (BIP-0086) addresses through the SendCoins RPC which
|
||||
// internally uses the ComputeInputScript method for signing.
|
||||
func testTaprootSendCoinsKeySpendBip86(ht *lntemp.HarnessTest,
|
||||
func testTaprootSendCoinsKeySpendBip86(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode) {
|
||||
|
||||
// We'll start the test by sending Alice some coins, which she'll use to
|
||||
|
|
@ -137,7 +137,7 @@ func testTaprootSendCoinsKeySpendBip86(ht *lntemp.HarnessTest,
|
|||
// testTaprootComputeInputScriptKeySpendBip86 tests sending to and spending from
|
||||
// p2tr key spend only (BIP-0086) addresses through the SendCoins RPC which
|
||||
// internally uses the ComputeInputScript method for signing.
|
||||
func testTaprootComputeInputScriptKeySpendBip86(ht *lntemp.HarnessTest,
|
||||
func testTaprootComputeInputScriptKeySpendBip86(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode) {
|
||||
|
||||
// We'll start the test by sending Alice some coins, which she'll use
|
||||
|
|
@ -234,7 +234,7 @@ func testTaprootComputeInputScriptKeySpendBip86(ht *lntemp.HarnessTest,
|
|||
|
||||
// testTaprootSignOutputRawScriptSpend tests sending to and spending from p2tr
|
||||
// script addresses using the script path with the SignOutputRaw RPC.
|
||||
func testTaprootSignOutputRawScriptSpend(ht *lntemp.HarnessTest,
|
||||
func testTaprootSignOutputRawScriptSpend(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode, sigHashType ...txscript.SigHashType) {
|
||||
|
||||
// For the next step, we need a public key. Let's use a special family
|
||||
|
|
@ -260,9 +260,7 @@ func testTaprootSignOutputRawScriptSpend(ht *lntemp.HarnessTest,
|
|||
require.NoError(ht, err)
|
||||
|
||||
// Send some coins to the generated tapscript address.
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
||||
ht, alice, taprootKey, testAmount,
|
||||
)
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||
|
||||
// Spend the output again, this time back to a p2wkh address.
|
||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||
|
|
@ -392,7 +390,7 @@ func testTaprootSignOutputRawScriptSpend(ht *lntemp.HarnessTest,
|
|||
// testTaprootSignOutputRawKeySpendBip86 tests that a tapscript address can
|
||||
// also be spent using the key spend path through the SignOutputRaw RPC using a
|
||||
// BIP0086 key spend only commitment.
|
||||
func testTaprootSignOutputRawKeySpendBip86(ht *lntemp.HarnessTest,
|
||||
func testTaprootSignOutputRawKeySpendBip86(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode, sigHashType ...txscript.SigHashType) {
|
||||
|
||||
// For the next step, we need a public key. Let's use a special family
|
||||
|
|
@ -413,9 +411,7 @@ func testTaprootSignOutputRawKeySpendBip86(ht *lntemp.HarnessTest,
|
|||
taprootKey := txscript.ComputeTaprootKeyNoScript(internalKey)
|
||||
|
||||
// Send some coins to the generated tapscript address.
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
||||
ht, alice, taprootKey, testAmount,
|
||||
)
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||
|
||||
// Spend the output again, this time back to a p2wkh address.
|
||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||
|
|
@ -490,7 +486,7 @@ func testTaprootSignOutputRawKeySpendBip86(ht *lntemp.HarnessTest,
|
|||
// testTaprootSignOutputRawKeySpendRootHash tests that a tapscript address can
|
||||
// also be spent using the key spend path through the SignOutputRaw RPC using a
|
||||
// tapscript root hash.
|
||||
func testTaprootSignOutputRawKeySpendRootHash(ht *lntemp.HarnessTest,
|
||||
func testTaprootSignOutputRawKeySpendRootHash(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode) {
|
||||
|
||||
// For the next step, we need a public key. Let's use a special family
|
||||
|
|
@ -514,9 +510,7 @@ func testTaprootSignOutputRawKeySpendRootHash(ht *lntemp.HarnessTest,
|
|||
taprootKey := txscript.ComputeTaprootOutputKey(internalKey, rootHash[:])
|
||||
|
||||
// Send some coins to the generated tapscript address.
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
||||
ht, alice, taprootKey, testAmount,
|
||||
)
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||
|
||||
// Spend the output again, this time back to a p2wkh address.
|
||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||
|
|
@ -583,7 +577,7 @@ func testTaprootSignOutputRawKeySpendRootHash(ht *lntemp.HarnessTest,
|
|||
|
||||
// testTaprootMuSig2KeySpendBip86 tests that a combined MuSig2 key can also be
|
||||
// used as a BIP-0086 key spend only key.
|
||||
func testTaprootMuSig2KeySpendBip86(ht *lntemp.HarnessTest,
|
||||
func testTaprootMuSig2KeySpendBip86(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode, version signrpc.MuSig2Version) {
|
||||
|
||||
// We're not going to commit to a script. So our taproot tweak will be
|
||||
|
|
@ -601,9 +595,7 @@ func testTaprootMuSig2KeySpendBip86(ht *lntemp.HarnessTest,
|
|||
)
|
||||
|
||||
// Send some coins to the generated tapscript address.
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
||||
ht, alice, taprootKey, testAmount,
|
||||
)
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||
|
||||
// Spend the output again, this time back to a p2wkh address.
|
||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||
|
|
@ -711,7 +703,7 @@ func testTaprootMuSig2KeySpendBip86(ht *lntemp.HarnessTest,
|
|||
|
||||
// testTaprootMuSig2KeySpendRootHash tests that a tapscript address can also be
|
||||
// spent using a MuSig2 combined key.
|
||||
func testTaprootMuSig2KeySpendRootHash(ht *lntemp.HarnessTest,
|
||||
func testTaprootMuSig2KeySpendRootHash(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode, version signrpc.MuSig2Version) {
|
||||
|
||||
// We're going to commit to a script as well. This is a hash lock with a
|
||||
|
|
@ -733,9 +725,7 @@ func testTaprootMuSig2KeySpendRootHash(ht *lntemp.HarnessTest,
|
|||
)
|
||||
|
||||
// Send some coins to the generated tapscript address.
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
||||
ht, alice, taprootKey, testAmount,
|
||||
)
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||
|
||||
// Spend the output again, this time back to a p2wkh address.
|
||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||
|
|
@ -843,7 +833,7 @@ func testTaprootMuSig2KeySpendRootHash(ht *lntemp.HarnessTest,
|
|||
|
||||
// testTaprootMuSig2ScriptSpend tests that a tapscript address with an internal
|
||||
// key that is a MuSig2 combined key can also be spent using the script path.
|
||||
func testTaprootMuSig2ScriptSpend(ht *lntemp.HarnessTest,
|
||||
func testTaprootMuSig2ScriptSpend(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode, version signrpc.MuSig2Version) {
|
||||
|
||||
// We're going to commit to a script and spend the output using the
|
||||
|
|
@ -870,9 +860,7 @@ func testTaprootMuSig2ScriptSpend(ht *lntemp.HarnessTest,
|
|||
tapscript := input.TapscriptFullTree(internalKey, leaf1)
|
||||
|
||||
// Send some coins to the generated tapscript address.
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
||||
ht, alice, taprootKey, testAmount,
|
||||
)
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||
|
||||
// Spend the output again, this time back to a p2wkh address.
|
||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||
|
|
@ -926,7 +914,7 @@ func testTaprootMuSig2ScriptSpend(ht *lntemp.HarnessTest,
|
|||
|
||||
// testTaprootMuSig2CombinedLeafKeySpend tests that a MuSig2 combined key can be
|
||||
// used for an OP_CHECKSIG inside a tap script leaf spend.
|
||||
func testTaprootMuSig2CombinedLeafKeySpend(ht *lntemp.HarnessTest,
|
||||
func testTaprootMuSig2CombinedLeafKeySpend(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode, version signrpc.MuSig2Version) {
|
||||
|
||||
// We're using the combined MuSig2 key in a script leaf. So we need to
|
||||
|
|
@ -951,9 +939,7 @@ func testTaprootMuSig2CombinedLeafKeySpend(ht *lntemp.HarnessTest,
|
|||
require.NoError(ht, err)
|
||||
|
||||
// Send some coins to the generated tapscript address.
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
||||
ht, alice, taprootKey, testAmount,
|
||||
)
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||
|
||||
// Spend the output again, this time back to a p2wkh address.
|
||||
p2wkhAddr, p2wkhPkScript := newAddrWithScript(
|
||||
|
|
@ -1102,7 +1088,7 @@ func testTaprootMuSig2CombinedLeafKeySpend(ht *lntemp.HarnessTest,
|
|||
|
||||
// testTaprootImportTapscriptScriptSpend tests importing p2tr script addresses
|
||||
// using the script path with the full tree known.
|
||||
func testTaprootImportTapscriptFullTree(ht *lntemp.HarnessTest,
|
||||
func testTaprootImportTapscriptFullTree(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode) {
|
||||
|
||||
// For the next step, we need a public key. Let's use a special family
|
||||
|
|
@ -1151,9 +1137,7 @@ func testTaprootImportTapscriptFullTree(ht *lntemp.HarnessTest,
|
|||
require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
|
||||
|
||||
// Send some coins to the generated tapscript address.
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
||||
ht, alice, taprootKey, testAmount,
|
||||
)
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||
p2trOutputRPC := &lnrpc.OutPoint{
|
||||
TxidBytes: p2trOutpoint.Hash[:],
|
||||
OutputIndex: p2trOutpoint.Index,
|
||||
|
|
@ -1176,7 +1160,7 @@ func testTaprootImportTapscriptFullTree(ht *lntemp.HarnessTest,
|
|||
|
||||
// testTaprootImportTapscriptPartialReveal tests importing p2tr script addresses
|
||||
// for which we only know part of the tree.
|
||||
func testTaprootImportTapscriptPartialReveal(ht *lntemp.HarnessTest,
|
||||
func testTaprootImportTapscriptPartialReveal(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode) {
|
||||
|
||||
// For the next step, we need a public key. Let's use a special family
|
||||
|
|
@ -1221,9 +1205,7 @@ func testTaprootImportTapscriptPartialReveal(ht *lntemp.HarnessTest,
|
|||
require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
|
||||
|
||||
// Send some coins to the generated tapscript address.
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
||||
ht, alice, taprootKey, testAmount,
|
||||
)
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||
|
||||
p2trOutputRPC := &lnrpc.OutPoint{
|
||||
TxidBytes: p2trOutpoint.Hash[:],
|
||||
|
|
@ -1247,7 +1229,7 @@ func testTaprootImportTapscriptPartialReveal(ht *lntemp.HarnessTest,
|
|||
|
||||
// testTaprootImportTapscriptRootHashOnly tests importing p2tr script addresses
|
||||
// for which we only know the root hash.
|
||||
func testTaprootImportTapscriptRootHashOnly(ht *lntemp.HarnessTest,
|
||||
func testTaprootImportTapscriptRootHashOnly(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode) {
|
||||
|
||||
// For the next step, we need a public key. Let's use a special family
|
||||
|
|
@ -1280,9 +1262,7 @@ func testTaprootImportTapscriptRootHashOnly(ht *lntemp.HarnessTest,
|
|||
require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
|
||||
|
||||
// Send some coins to the generated tapscript address.
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
||||
ht, alice, taprootKey, testAmount,
|
||||
)
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||
|
||||
p2trOutputRPC := &lnrpc.OutPoint{
|
||||
TxidBytes: p2trOutpoint.Hash[:],
|
||||
|
|
@ -1306,7 +1286,7 @@ func testTaprootImportTapscriptRootHashOnly(ht *lntemp.HarnessTest,
|
|||
|
||||
// testTaprootImportTapscriptFullKey tests importing p2tr script addresses for
|
||||
// which we only know the full Taproot key.
|
||||
func testTaprootImportTapscriptFullKey(ht *lntemp.HarnessTest,
|
||||
func testTaprootImportTapscriptFullKey(ht *lntest.HarnessTest,
|
||||
alice *node.HarnessNode) {
|
||||
|
||||
// For the next step, we need a public key. Let's use a special family
|
||||
|
|
@ -1339,9 +1319,7 @@ func testTaprootImportTapscriptFullKey(ht *lntemp.HarnessTest,
|
|||
require.Equal(ht, calculatedAddr.String(), importResp.P2TrAddress)
|
||||
|
||||
// Send some coins to the generated tapscript address.
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(
|
||||
ht, alice, taprootKey, testAmount,
|
||||
)
|
||||
p2trOutpoint, p2trPkScript := sendToTaprootOutput(ht, alice, taprootKey)
|
||||
|
||||
p2trOutputRPC := &lnrpc.OutPoint{
|
||||
TxidBytes: p2trOutpoint.Hash[:],
|
||||
|
|
@ -1365,7 +1343,7 @@ func testTaprootImportTapscriptFullKey(ht *lntemp.HarnessTest,
|
|||
|
||||
// clearWalletImportedTapscriptBalance manually assembles and then attempts to
|
||||
// sign a TX to sweep funds from an imported tapscript address.
|
||||
func clearWalletImportedTapscriptBalance(ht *lntemp.HarnessTest,
|
||||
func clearWalletImportedTapscriptBalance(ht *lntest.HarnessTest,
|
||||
hn *node.HarnessNode, utxo *wire.TxOut, outPoint wire.OutPoint,
|
||||
internalKey *btcec.PublicKey, derivationPath []uint32,
|
||||
rootHash []byte) {
|
||||
|
|
@ -1460,7 +1438,7 @@ func testScriptSchnorrSig(t *testing.T,
|
|||
}
|
||||
|
||||
// newAddrWithScript returns a new address and its pkScript.
|
||||
func newAddrWithScript(ht *lntemp.HarnessTest, node *node.HarnessNode,
|
||||
func newAddrWithScript(ht *lntest.HarnessTest, node *node.HarnessNode,
|
||||
addrType lnrpc.AddressType) (btcutil.Address, []byte) {
|
||||
|
||||
p2wkhResp := node.RPC.NewAddress(&lnrpc.NewAddressRequest{
|
||||
|
|
@ -1479,8 +1457,8 @@ func newAddrWithScript(ht *lntemp.HarnessTest, node *node.HarnessNode,
|
|||
|
||||
// sendToTaprootOutput sends coins to a p2tr output of the given taproot key and
|
||||
// mines a block to confirm the coins.
|
||||
func sendToTaprootOutput(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
||||
taprootKey *btcec.PublicKey, amt int64) (wire.OutPoint, []byte) {
|
||||
func sendToTaprootOutput(ht *lntest.HarnessTest, hn *node.HarnessNode,
|
||||
taprootKey *btcec.PublicKey) (wire.OutPoint, []byte) {
|
||||
|
||||
tapScriptAddr, err := btcutil.NewAddressTaproot(
|
||||
schnorr.SerializePubKey(taprootKey), harnessNetParams,
|
||||
|
|
@ -1492,7 +1470,7 @@ func sendToTaprootOutput(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
|||
// Send some coins to the generated tapscript address.
|
||||
req := &lnrpc.SendCoinsRequest{
|
||||
Addr: tapScriptAddr.String(),
|
||||
Amount: amt,
|
||||
Amount: testAmount,
|
||||
}
|
||||
hn.RPC.SendCoins(req)
|
||||
|
||||
|
|
@ -1542,7 +1520,7 @@ func sendToTaprootOutput(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
|||
// after checking its weight against an estimate. After asserting the given
|
||||
// spend request, the given sweep address' balance is verified to be seen as
|
||||
// funds belonging to the wallet.
|
||||
func publishTxAndConfirmSweep(ht *lntemp.HarnessTest, node *node.HarnessNode,
|
||||
func publishTxAndConfirmSweep(ht *lntest.HarnessTest, node *node.HarnessNode,
|
||||
tx *wire.MsgTx, estimatedWeight int64,
|
||||
spendRequest *chainrpc.SpendRequest, sweepAddr string) {
|
||||
|
||||
|
|
@ -1604,7 +1582,7 @@ func publishTxAndConfirmSweep(ht *lntemp.HarnessTest, node *node.HarnessNode,
|
|||
// confirmAddress makes sure that a transaction in the mempool spends funds to
|
||||
// the given address. It also checks that a confirmation notification for the
|
||||
// address is triggered when the transaction is mined.
|
||||
func confirmAddress(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
||||
func confirmAddress(ht *lntest.HarnessTest, hn *node.HarnessNode,
|
||||
addrString string) {
|
||||
|
||||
// Wait until the tx that sends to the address is found.
|
||||
|
|
@ -1654,7 +1632,7 @@ func confirmAddress(ht *lntemp.HarnessTest, hn *node.HarnessNode,
|
|||
|
||||
// deriveSigningKeys derives three signing keys and returns their descriptors,
|
||||
// as well as the public keys in the Schnorr serialized format.
|
||||
func deriveSigningKeys(ht *lntemp.HarnessTest, node *node.HarnessNode,
|
||||
func deriveSigningKeys(ht *lntest.HarnessTest, node *node.HarnessNode,
|
||||
version signrpc.MuSig2Version) (*signrpc.KeyDescriptor,
|
||||
*signrpc.KeyDescriptor, *signrpc.KeyDescriptor, [][]byte) {
|
||||
|
||||
|
|
@ -1700,7 +1678,7 @@ func deriveSigningKeys(ht *lntemp.HarnessTest, node *node.HarnessNode,
|
|||
// combined into a single key. The same node is used for the three signing
|
||||
// participants but a separate key is generated for each session. So the result
|
||||
// should be the same as if it were three different nodes.
|
||||
func createMuSigSessions(ht *lntemp.HarnessTest, node *node.HarnessNode,
|
||||
func createMuSigSessions(ht *lntest.HarnessTest, node *node.HarnessNode,
|
||||
taprootTweak *signrpc.TaprootTweakDesc,
|
||||
keyDesc1, keyDesc2, keyDesc3 *signrpc.KeyDescriptor,
|
||||
allPubKeys [][]byte, version signrpc.MuSig2Version) (*btcec.PublicKey,
|
||||
|
|
@ -1838,7 +1816,7 @@ func createMuSigSessions(ht *lntemp.HarnessTest, node *node.HarnessNode,
|
|||
// testTaprootCoopClose asserts that if both peers signal ShutdownAnySegwit,
|
||||
// then a taproot closing addr is used. Otherwise, we shouldn't expect one to
|
||||
// be used.
|
||||
func testTaprootCoopClose(ht *lntemp.HarnessTest) {
|
||||
func testTaprootCoopClose(ht *lntest.HarnessTest) {
|
||||
// We'll start by making two new nodes, and funding a channel between
|
||||
// them.
|
||||
carol := ht.NewNode("Carol", nil)
|
||||
|
|
@ -1853,7 +1831,7 @@ func testTaprootCoopClose(ht *lntemp.HarnessTest) {
|
|||
|
||||
// We'll now open a channel between Carol and Dave.
|
||||
chanPoint := ht.OpenChannel(
|
||||
carol, dave, lntemp.OpenChannelParams{
|
||||
carol, dave, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
SatPerVByte: satPerVbyte,
|
||||
|
|
@ -1888,7 +1866,7 @@ func testTaprootCoopClose(ht *lntemp.HarnessTest) {
|
|||
|
||||
// We'll now open up a chanel again between Carol and Eve.
|
||||
chanPoint = ht.OpenChannel(
|
||||
carol, eve, lntemp.OpenChannelParams{
|
||||
carol, eve, lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: pushAmt,
|
||||
SatPerVByte: satPerVbyte,
|
||||
|
|
@ -1904,7 +1882,7 @@ func testTaprootCoopClose(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testMuSig2CombineKey makes sure that combining a key with MuSig2 returns the
|
||||
// correct result according to the MuSig2 version specified.
|
||||
func testMuSig2CombineKey(ht *lntemp.HarnessTest, alice *node.HarnessNode,
|
||||
func testMuSig2CombineKey(ht *lntest.HarnessTest, alice *node.HarnessNode,
|
||||
version signrpc.MuSig2Version) {
|
||||
|
||||
testVector040Key1 := hexDecode(
|
||||
|
|
@ -4,6 +4,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
|
|
@ -11,9 +12,12 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/integration/rpctest"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/grpclog"
|
||||
)
|
||||
|
|
@ -26,9 +30,25 @@ const (
|
|||
// defaultRunTranche is the default index of the test cases tranche that
|
||||
// we run.
|
||||
defaultRunTranche uint = 0
|
||||
|
||||
defaultTimeout = wait.DefaultTimeout
|
||||
itestLndBinary = "../lnd-itest"
|
||||
|
||||
// TODO(yy): remove the following defined constants and put them in the
|
||||
// specific tests where they are used?
|
||||
testFeeBase = 1e+6
|
||||
anchorSize = 330
|
||||
defaultCSV = node.DefaultCSV
|
||||
noFeeLimitMsat = math.MaxInt64
|
||||
|
||||
AddrTypeWitnessPubkeyHash = lnrpc.AddressType_WITNESS_PUBKEY_HASH
|
||||
AddrTypeNestedPubkeyHash = lnrpc.AddressType_NESTED_PUBKEY_HASH
|
||||
AddrTypeTaprootPubkey = lnrpc.AddressType_TAPROOT_PUBKEY
|
||||
)
|
||||
|
||||
var (
|
||||
harnessNetParams = &chaincfg.RegressionNetParams
|
||||
|
||||
// testCasesSplitParts is the number of tranches the test cases should
|
||||
// be split into. By default this is set to 1, so no splitting happens.
|
||||
// If this value is increased, then the -runtranche flag must be
|
||||
|
|
@ -49,31 +69,32 @@ var (
|
|||
|
||||
// dbBackendFlag specifies the backend to use.
|
||||
dbBackendFlag = flag.String("dbbackend", "bbolt", "Database backend "+
|
||||
"(bbolt, etcd, postgres, sqlite)")
|
||||
"(bbolt, etcd, postgres)")
|
||||
|
||||
// lndExecutable is the full path to the lnd binary.
|
||||
lndExecutable = flag.String(
|
||||
"lndexec", itestLndBinary, "full path to lnd binary",
|
||||
)
|
||||
)
|
||||
|
||||
// TestLightningNetworkDaemonTemp performs a series of integration tests
|
||||
// amongst a programmatically driven network of lnd nodes.
|
||||
func TestLightningNetworkDaemonTemp(t *testing.T) {
|
||||
if !*tempTest {
|
||||
t.Skip("Running old tests, new tests are skipped")
|
||||
}
|
||||
|
||||
// TestLightningNetworkDaemon performs a series of integration tests amongst a
|
||||
// programmatically driven network of lnd nodes.
|
||||
func TestLightningNetworkDaemon(t *testing.T) {
|
||||
// If no tests are registered, then we can exit early.
|
||||
if len(allTestCasesTemp) == 0 {
|
||||
t.Skip("integration tests not selected with flag 'rpctest'")
|
||||
if len(allTestCases) == 0 {
|
||||
t.Skip("integration tests not selected with flag 'integration'")
|
||||
}
|
||||
|
||||
// Get the test cases to be run in this tranche.
|
||||
testCases, trancheIndex, trancheOffset := getTestCaseSplitTranche()
|
||||
lntest.ApplyPortOffset(uint32(trancheIndex) * 1000)
|
||||
node.ApplyPortOffset(uint32(trancheIndex) * 1000)
|
||||
|
||||
// Create a simple fee service.
|
||||
feeService := lntemp.NewFeeService(t)
|
||||
feeService := lntest.NewFeeService(t)
|
||||
|
||||
// Get the binary path and setup the harness test.
|
||||
binary := getLndBinary(t)
|
||||
harnessTest := lntemp.SetupHarness(
|
||||
harnessTest := lntest.SetupHarness(
|
||||
t, binary, *dbBackendFlag, feeService,
|
||||
)
|
||||
defer harnessTest.Stop()
|
||||
|
|
@ -126,12 +147,16 @@ func TestLightningNetworkDaemonTemp(t *testing.T) {
|
|||
break
|
||||
}
|
||||
}
|
||||
|
||||
_, height := harnessTest.Miner.GetBestBlock()
|
||||
t.Logf("=========> tests finished for tranche: %v, tested %d "+
|
||||
"cases, end height: %d\n", trancheIndex, len(testCases), height)
|
||||
}
|
||||
|
||||
// getTestCaseSplitTranche returns the sub slice of the test cases that should
|
||||
// be run as the current split tranche as well as the index and slice offset of
|
||||
// the tranche.
|
||||
func getTestCaseSplitTranche() ([]*lntemp.TestCase, uint, uint) {
|
||||
func getTestCaseSplitTranche() ([]*lntest.TestCase, uint, uint) {
|
||||
numTranches := defaultSplitTranches
|
||||
if testCasesSplitTranches != nil {
|
||||
numTranches = *testCasesSplitTranches
|
||||
|
|
@ -150,7 +175,7 @@ func getTestCaseSplitTranche() ([]*lntemp.TestCase, uint, uint) {
|
|||
runTranche = 0
|
||||
}
|
||||
|
||||
numCases := uint(len(allTestCasesTemp))
|
||||
numCases := uint(len(allTestCases))
|
||||
testsPerTranche := numCases / numTranches
|
||||
trancheOffset := runTranche * testsPerTranche
|
||||
trancheEnd := trancheOffset + testsPerTranche
|
||||
|
|
@ -158,7 +183,7 @@ func getTestCaseSplitTranche() ([]*lntemp.TestCase, uint, uint) {
|
|||
trancheEnd = numCases
|
||||
}
|
||||
|
||||
return allTestCasesTemp[trancheOffset:trancheEnd], threadID,
|
||||
return allTestCases[trancheOffset:trancheEnd], threadID,
|
||||
trancheOffset
|
||||
}
|
||||
|
||||
|
|
@ -188,7 +213,7 @@ func init() {
|
|||
// Before we start any node, we need to make sure that any btcd node
|
||||
// that is started through the RPC harness uses a unique port as well
|
||||
// to avoid any port collisions.
|
||||
rpctest.ListenAddressGenerator = lntest.GenerateBtcdListenerAddresses
|
||||
rpctest.ListenAddressGenerator = node.GenerateBtcdListenerAddresses
|
||||
|
||||
// Swap out grpc's default logger with out fake logger which drops the
|
||||
// statements on the floor.
|
||||
|
|
@ -7,17 +7,17 @@ import (
|
|||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// testTrackPayments tests whether a client that calls the TrackPayments api
|
||||
// receives payment updates.
|
||||
func testTrackPayments(ht *lntemp.HarnessTest) {
|
||||
func testTrackPayments(ht *lntest.HarnessTest) {
|
||||
// Open a channel between alice and bob.
|
||||
alice, bob := ht.Alice, ht.Bob
|
||||
channel := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{
|
||||
alice, bob, lntest.OpenChannelParams{
|
||||
Amt: btcutil.Amount(300000),
|
||||
},
|
||||
)
|
||||
|
|
@ -16,8 +16,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/funding"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
|
@ -51,7 +51,7 @@ func walletToLNAddrType(t *testing.T,
|
|||
|
||||
// newExternalAddr generates a new external address of an imported account for a
|
||||
// pair of nodes, where one acts as the funder and the other as the signer.
|
||||
func newExternalAddr(ht *lntemp.HarnessTest, funder, signer *node.HarnessNode,
|
||||
func newExternalAddr(ht *lntest.HarnessTest, funder, signer *node.HarnessNode,
|
||||
importedAccount string, addrType walletrpc.AddressType) string {
|
||||
|
||||
// We'll generate a new address for Carol from Dave's node to receive
|
||||
|
|
@ -125,7 +125,7 @@ func assertOutputScriptType(t *testing.T, expType txscript.ScriptClass,
|
|||
|
||||
// psbtSendFromImportedAccount attempts to fund a PSBT from the given imported
|
||||
// account, originating from the source node to the destination.
|
||||
func psbtSendFromImportedAccount(ht *lntemp.HarnessTest, srcNode, destNode,
|
||||
func psbtSendFromImportedAccount(ht *lntest.HarnessTest, srcNode, destNode,
|
||||
signer *node.HarnessNode, account string,
|
||||
accountAddrType walletrpc.AddressType) {
|
||||
|
||||
|
|
@ -236,7 +236,7 @@ func psbtSendFromImportedAccount(ht *lntemp.HarnessTest, srcNode, destNode,
|
|||
// node. To ensure the channel is operational before closing it, a test payment
|
||||
// is made. Several balance assertions are made along the way for the sake of
|
||||
// correctness.
|
||||
func fundChanAndCloseFromImportedAccount(ht *lntemp.HarnessTest, srcNode,
|
||||
func fundChanAndCloseFromImportedAccount(ht *lntest.HarnessTest, srcNode,
|
||||
destNode, signer *node.HarnessNode, account string,
|
||||
accountAddrType walletrpc.AddressType, utxoAmt, chanSize int64) {
|
||||
|
||||
|
|
@ -256,7 +256,7 @@ func fundChanAndCloseFromImportedAccount(ht *lntemp.HarnessTest, srcNode,
|
|||
// The source node will then fund the channel through a PSBT shim.
|
||||
pendingChanID := ht.Random32Bytes()
|
||||
chanUpdates, rawPsbt := ht.OpenChannelPsbt(
|
||||
srcNode, destNode, lntemp.OpenChannelParams{
|
||||
srcNode, destNode, lntest.OpenChannelParams{
|
||||
Amt: btcutil.Amount(chanSize),
|
||||
FundingShim: &lnrpc.FundingShim{
|
||||
Shim: &lnrpc.FundingShim_PsbtShim{
|
||||
|
|
@ -463,7 +463,7 @@ func fundChanAndCloseFromImportedAccount(ht *lntemp.HarnessTest, srcNode,
|
|||
// testWalletImportAccount tests that an imported account can fund transactions
|
||||
// and channels through PSBTs, by having one node (the one with the imported
|
||||
// account) craft the transactions and another node act as the signer.
|
||||
func testWalletImportAccount(ht *lntemp.HarnessTest) {
|
||||
func testWalletImportAccount(ht *lntest.HarnessTest) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
addrType walletrpc.AddressType
|
||||
|
|
@ -491,7 +491,7 @@ func testWalletImportAccount(ht *lntemp.HarnessTest) {
|
|||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
success := ht.Run(tc.name, func(tt *testing.T) {
|
||||
testFunc := func(ht *lntemp.HarnessTest) {
|
||||
testFunc := func(ht *lntest.HarnessTest) {
|
||||
testWalletImportAccountScenario(
|
||||
ht, tc.addrType,
|
||||
)
|
||||
|
|
@ -499,7 +499,7 @@ func testWalletImportAccount(ht *lntemp.HarnessTest) {
|
|||
|
||||
st := ht.Subtest(tt)
|
||||
|
||||
st.RunTestCase(&lntemp.TestCase{
|
||||
st.RunTestCase(&lntest.TestCase{
|
||||
Name: tc.name,
|
||||
TestFunc: testFunc,
|
||||
})
|
||||
|
|
@ -515,7 +515,7 @@ func testWalletImportAccount(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func testWalletImportAccountScenario(ht *lntemp.HarnessTest,
|
||||
func testWalletImportAccountScenario(ht *lntest.HarnessTest,
|
||||
addrType walletrpc.AddressType) {
|
||||
|
||||
// We'll start our test by having two nodes, Carol and Dave. Carol's
|
||||
|
|
@ -529,7 +529,7 @@ func testWalletImportAccountScenario(ht *lntemp.HarnessTest,
|
|||
runWalletImportAccountScenario(ht, addrType, carol, dave)
|
||||
}
|
||||
|
||||
func runWalletImportAccountScenario(ht *lntemp.HarnessTest,
|
||||
func runWalletImportAccountScenario(ht *lntest.HarnessTest,
|
||||
addrType walletrpc.AddressType, carol, dave *node.HarnessNode) {
|
||||
|
||||
const utxoAmt int64 = btcutil.SatoshiPerBitcoin
|
||||
|
|
@ -619,7 +619,7 @@ func runWalletImportAccountScenario(ht *lntemp.HarnessTest,
|
|||
// testWalletImportPubKey tests that an imported public keys can fund
|
||||
// transactions and channels through PSBTs, by having one node (the one with the
|
||||
// imported account) craft the transactions and another node act as the signer.
|
||||
func testWalletImportPubKey(ht *lntemp.HarnessTest) {
|
||||
func testWalletImportPubKey(ht *lntest.HarnessTest) {
|
||||
testCases := []struct {
|
||||
name string
|
||||
addrType walletrpc.AddressType
|
||||
|
|
@ -642,7 +642,7 @@ func testWalletImportPubKey(ht *lntemp.HarnessTest) {
|
|||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
success := ht.Run(tc.name, func(tt *testing.T) {
|
||||
testFunc := func(ht *lntemp.HarnessTest) {
|
||||
testFunc := func(ht *lntest.HarnessTest) {
|
||||
testWalletImportPubKeyScenario(
|
||||
ht, tc.addrType,
|
||||
)
|
||||
|
|
@ -650,7 +650,7 @@ func testWalletImportPubKey(ht *lntemp.HarnessTest) {
|
|||
|
||||
st := ht.Subtest(tt)
|
||||
|
||||
st.RunTestCase(&lntemp.TestCase{
|
||||
st.RunTestCase(&lntest.TestCase{
|
||||
Name: tc.name,
|
||||
TestFunc: testFunc,
|
||||
})
|
||||
|
|
@ -666,7 +666,7 @@ func testWalletImportPubKey(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func testWalletImportPubKeyScenario(ht *lntemp.HarnessTest,
|
||||
func testWalletImportPubKeyScenario(ht *lntest.HarnessTest,
|
||||
addrType walletrpc.AddressType) {
|
||||
|
||||
const utxoAmt int64 = btcutil.SatoshiPerBitcoin
|
||||
|
|
@ -5,12 +5,10 @@ import (
|
|||
|
||||
"github.com/lightningnetwork/lnd/chainreg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
type pendingChan *lnrpc.PendingChannelsResponse_PendingChannel
|
||||
|
||||
// testWipeForwardingPackagesLocal tests that when a channel is closed, either
|
||||
// through local force close, remote close, or coop close, all the forwarding
|
||||
// packages of that particular channel are deleted. The test creates a
|
||||
|
|
@ -21,7 +19,7 @@ type pendingChan *lnrpc.PendingChannelsResponse_PendingChannel
|
|||
// packages are wiped.
|
||||
// - Bob coop closes the channel Bob->Carol, and checks from both Bob PoVs
|
||||
// that the forwarding packages are wiped.
|
||||
func testWipeForwardingPackages(ht *lntemp.HarnessTest) {
|
||||
func testWipeForwardingPackages(ht *lntest.HarnessTest) {
|
||||
const (
|
||||
chanAmt = 10e6
|
||||
paymentAmt = 10e4
|
||||
|
|
@ -41,12 +39,12 @@ func testWipeForwardingPackages(ht *lntemp.HarnessTest) {
|
|||
|
||||
// Open a channel between Alice and Bob.
|
||||
chanPointAB := ht.OpenChannel(
|
||||
alice, bob, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
alice, bob, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Open a channel between Bob and Carol.
|
||||
chanPointBC := ht.OpenChannel(
|
||||
bob, carol, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
bob, carol, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
|
||||
// Before we continue, make sure Alice has seen the channel between Bob
|
||||
|
|
@ -3,7 +3,7 @@ package itest
|
|||
import (
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/lightningnetwork/lnd/funding"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
)
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ import (
|
|||
// acceptances will allow a wumbo channel to be created. Additionally, if a
|
||||
// node is running with mini channels only enabled, then they should reject any
|
||||
// inbound wumbo channel requests.
|
||||
func testWumboChannels(ht *lntemp.HarnessTest) {
|
||||
func testWumboChannels(ht *lntest.HarnessTest) {
|
||||
// With all the channel types exercised, we'll now make sure the wumbo
|
||||
// signalling support works properly.
|
||||
//
|
||||
|
|
@ -33,7 +33,7 @@ func testWumboChannels(ht *lntemp.HarnessTest) {
|
|||
// The test should indicate a failure due to the channel being too
|
||||
// large.
|
||||
ht.OpenChannelAssertErr(
|
||||
wumboNode, miniNode, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
wumboNode, miniNode, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
lnwallet.ErrChanTooLarge(chanAmt, funding.MaxBtcFundingAmount),
|
||||
)
|
||||
|
||||
|
|
@ -46,7 +46,7 @@ func testWumboChannels(ht *lntemp.HarnessTest) {
|
|||
// Creating a wumbo channel between these two nodes should succeed.
|
||||
ht.EnsureConnected(wumboNode, wumboNode2)
|
||||
chanPoint := ht.OpenChannel(
|
||||
wumboNode, wumboNode2, lntemp.OpenChannelParams{Amt: chanAmt},
|
||||
wumboNode, wumboNode2, lntest.OpenChannelParams{Amt: chanAmt},
|
||||
)
|
||||
ht.CloseChannel(wumboNode, chanPoint)
|
||||
}
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
package itest
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
|
@ -13,10 +13,9 @@ import (
|
|||
"github.com/lightningnetwork/lnd/chainreg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -24,7 +23,7 @@ import (
|
|||
|
||||
// testZeroConfChannelOpen tests that opening a zero-conf channel works and
|
||||
// sending payments also works.
|
||||
func testZeroConfChannelOpen(ht *lntemp.HarnessTest) {
|
||||
func testZeroConfChannelOpen(ht *lntest.HarnessTest) {
|
||||
// Since option-scid-alias is opt-in, the provided harness nodes will
|
||||
// not have the feature bit set. Also need to set anchors as those are
|
||||
// default-off in itests.
|
||||
|
|
@ -40,7 +39,7 @@ func testZeroConfChannelOpen(ht *lntemp.HarnessTest) {
|
|||
|
||||
// We'll open a regular public channel between Bob and Carol here.
|
||||
chanAmt := btcutil.Amount(1_000_000)
|
||||
p := lntemp.OpenChannelParams{
|
||||
p := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
}
|
||||
chanPoint := ht.OpenChannel(bob, carol, p)
|
||||
|
|
@ -59,7 +58,7 @@ func testZeroConfChannelOpen(ht *lntemp.HarnessTest) {
|
|||
go acceptChannel(ht.T, true, acceptStream)
|
||||
|
||||
// Open a private zero-conf anchors channel of 1M satoshis.
|
||||
params := lntemp.OpenChannelParams{
|
||||
params := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
Private: true,
|
||||
CommitmentType: lnrpc.CommitmentType_ANCHORS,
|
||||
|
|
@ -192,7 +191,7 @@ func testZeroConfChannelOpen(ht *lntemp.HarnessTest) {
|
|||
|
||||
// testOptionScidAlias checks that opening an option_scid_alias channel-type
|
||||
// channel or w/o the channel-type works properly.
|
||||
func testOptionScidAlias(ht *lntemp.HarnessTest) {
|
||||
func testOptionScidAlias(ht *lntest.HarnessTest) {
|
||||
type scidTestCase struct {
|
||||
name string
|
||||
|
||||
|
|
@ -235,7 +234,7 @@ func testOptionScidAlias(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func optionScidAliasScenario(ht *lntemp.HarnessTest, chantype, private bool) {
|
||||
func optionScidAliasScenario(ht *lntest.HarnessTest, chantype, private bool) {
|
||||
// Option-scid-alias is opt-in, as is anchors.
|
||||
scidAliasArgs := []string{
|
||||
"--protocol.option-scid-alias",
|
||||
|
|
@ -257,7 +256,7 @@ func optionScidAliasScenario(ht *lntemp.HarnessTest, chantype, private bool) {
|
|||
|
||||
chanAmt := btcutil.Amount(1_000_000)
|
||||
|
||||
params := lntemp.OpenChannelParams{
|
||||
params := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
Private: private,
|
||||
CommitmentType: lnrpc.CommitmentType_ANCHORS,
|
||||
|
|
@ -283,7 +282,7 @@ func optionScidAliasScenario(ht *lntemp.HarnessTest, chantype, private bool) {
|
|||
// We'll now open a regular public channel between Bob and Carol and
|
||||
// assert that Bob can pay Dave. We'll also assert that the invoice
|
||||
// Dave issues has the startingAlias as a hop hint.
|
||||
p := lntemp.OpenChannelParams{
|
||||
p := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
}
|
||||
fundingPoint2 := ht.OpenChannel(bob, carol, p)
|
||||
|
|
@ -313,6 +312,7 @@ func optionScidAliasScenario(ht *lntemp.HarnessTest, chantype, private bool) {
|
|||
require.Len(ht, decodedReq.RouteHints, 0)
|
||||
payReq := daveInvoiceResp2.PaymentRequest
|
||||
ht.CompletePaymentRequests(bob, []string{payReq})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -410,7 +410,7 @@ func waitForZeroConfGraphChange(hn *node.HarnessNode,
|
|||
// testUpdateChannelPolicyScidAlias checks that option-scid-alias, zero-conf
|
||||
// channel-types, and option-scid-alias feature-bit-only channels have the
|
||||
// expected graph and that payments work when updating the channel policy.
|
||||
func testUpdateChannelPolicyScidAlias(ht *lntemp.HarnessTest) {
|
||||
func testUpdateChannelPolicyScidAlias(ht *lntest.HarnessTest) {
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
|
|
@ -462,7 +462,7 @@ func testUpdateChannelPolicyScidAlias(ht *lntemp.HarnessTest) {
|
|||
}
|
||||
}
|
||||
|
||||
func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
||||
func testPrivateUpdateAlias(ht *lntest.HarnessTest,
|
||||
zeroConf, scidAliasType, private bool) {
|
||||
|
||||
// We'll create a new node Eve that will not have option-scid-alias
|
||||
|
|
@ -495,7 +495,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
|||
|
||||
chanAmt := btcutil.Amount(1_000_000)
|
||||
|
||||
p := lntemp.OpenChannelParams{
|
||||
p := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: chanAmt / 2,
|
||||
}
|
||||
|
|
@ -509,7 +509,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
|||
go acceptChannel(ht.T, zeroConf, acceptStream)
|
||||
|
||||
// Open a private channel, optionally specifying a channel-type.
|
||||
params := lntemp.OpenChannelParams{
|
||||
params := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
Private: private,
|
||||
CommitmentType: lnrpc.CommitmentType_ANCHORS,
|
||||
|
|
@ -542,7 +542,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
|||
FeeRateMilliMsat: testFeeBase * feeRate,
|
||||
TimeLockDelta: timeLockDelta,
|
||||
MinHtlc: 1000, // default value
|
||||
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
|
||||
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
|
||||
}
|
||||
|
||||
// Assert that Dave receives Carol's policy update.
|
||||
|
|
@ -568,7 +568,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
|||
FeeRateMilliMsat: testFeeBase * feeRate,
|
||||
TimeLockDelta: timeLockDelta,
|
||||
MinHtlc: 1000,
|
||||
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
|
||||
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
|
||||
}
|
||||
|
||||
// Assert that Carol receives Dave's policy update.
|
||||
|
|
@ -655,7 +655,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
|||
FeeRateMilliMsat: testFeeBase * feeRate,
|
||||
TimeLockDelta: timeLockDelta,
|
||||
MinHtlc: 1000,
|
||||
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
|
||||
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
|
||||
}
|
||||
|
||||
// Assert Dave receives Carol's policy update.
|
||||
|
|
@ -744,7 +744,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
|||
FeeRateMilliMsat: testFeeBase * feeRate,
|
||||
TimeLockDelta: timeLockDelta,
|
||||
MinHtlc: 1000,
|
||||
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
|
||||
MaxHtlcMsat: lntest.CalculateMaxHtlc(chanAmt),
|
||||
}
|
||||
|
||||
// Assert Dave and optionally Eve receives Carol's update.
|
||||
|
|
@ -764,7 +764,7 @@ func testPrivateUpdateAlias(ht *lntemp.HarnessTest,
|
|||
|
||||
// testOptionScidUpgrade tests that toggling the option-scid-alias feature bit
|
||||
// correctly upgrades existing channels.
|
||||
func testOptionScidUpgrade(ht *lntemp.HarnessTest) {
|
||||
func testOptionScidUpgrade(ht *lntest.HarnessTest) {
|
||||
bob := ht.Bob
|
||||
|
||||
// Start carol with anchors only.
|
||||
|
|
@ -788,7 +788,7 @@ func testOptionScidUpgrade(ht *lntemp.HarnessTest) {
|
|||
|
||||
chanAmt := btcutil.Amount(1_000_000)
|
||||
|
||||
p := lntemp.OpenChannelParams{
|
||||
p := lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
PushAmt: chanAmt / 2,
|
||||
Private: true,
|
||||
|
|
@ -798,7 +798,7 @@ func testOptionScidUpgrade(ht *lntemp.HarnessTest) {
|
|||
// Bob will open a channel to Carol now.
|
||||
ht.EnsureConnected(bob, carol)
|
||||
|
||||
p = lntemp.OpenChannelParams{
|
||||
p = lntest.OpenChannelParams{
|
||||
Amt: chanAmt,
|
||||
}
|
||||
fundingPoint2 := ht.OpenChannel(bob, carol, p)
|
||||
|
|
@ -822,25 +822,34 @@ func testOptionScidUpgrade(ht *lntemp.HarnessTest) {
|
|||
var startingAlias lnwire.ShortChannelID
|
||||
startingAlias.BlockHeight = 16_000_000
|
||||
|
||||
err := wait.Predicate(func() bool {
|
||||
// TODO(yy): Carol and Dave will attempt to connect to each other
|
||||
// during restart. However, due to the race condition in peer
|
||||
// connection, they may both fail. Thus we need to ensure the
|
||||
// connection here. Once the race is fixed, we can remove this line.
|
||||
ht.EnsureConnected(dave, carol)
|
||||
|
||||
err := wait.NoError(func() error {
|
||||
invoiceResp := dave.RPC.AddInvoice(daveParams)
|
||||
decodedReq := dave.RPC.DecodePayReq(invoiceResp.PaymentRequest)
|
||||
|
||||
if len(decodedReq.RouteHints) != 1 {
|
||||
return false
|
||||
return fmt.Errorf("expected 1 route hint, got %v",
|
||||
decodedReq.RouteHints)
|
||||
}
|
||||
|
||||
if len(decodedReq.RouteHints[0].HopHints) != 1 {
|
||||
return false
|
||||
return fmt.Errorf("expected 1 hop hint, got %v",
|
||||
len(decodedReq.RouteHints[0].HopHints))
|
||||
}
|
||||
|
||||
hopHint := decodedReq.RouteHints[0].HopHints[0].ChanId
|
||||
if startingAlias.ToUint64() == hopHint {
|
||||
daveInvoice = invoiceResp
|
||||
return true
|
||||
return nil
|
||||
}
|
||||
|
||||
return false
|
||||
return fmt.Errorf("unmatched alias, expected %v, got %v",
|
||||
startingAlias.ToUint64(), hopHint)
|
||||
}, defaultTimeout)
|
||||
require.NoError(ht, err)
|
||||
|
||||
|
|
@ -892,15 +901,12 @@ func acceptChannel(t *testing.T, zeroConf bool, stream rpc.AcceptorClient) {
|
|||
// testZeroConfReorg tests that a reorg does not cause a zero-conf channel to
|
||||
// be deleted from the channel graph. This was previously the case due to logic
|
||||
// in the function DisconnectBlockAtHeight.
|
||||
func testZeroConfReorg(ht *lntemp.HarnessTest) {
|
||||
if ht.ChainBackendName() == lntest.NeutrinoBackendName {
|
||||
func testZeroConfReorg(ht *lntest.HarnessTest) {
|
||||
if ht.IsNeutrinoBackend() {
|
||||
ht.Skipf("skipping zero-conf reorg test for neutrino backend")
|
||||
}
|
||||
|
||||
var (
|
||||
ctxb = context.Background()
|
||||
temp = "temp"
|
||||
)
|
||||
var temp = "temp"
|
||||
|
||||
// Since zero-conf is opt in, the harness nodes provided won't be able
|
||||
// to open zero-conf channels. In that case, we just spin up new nodes.
|
||||
|
|
@ -926,7 +932,7 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
|
|||
go acceptChannel(ht.T, true, acceptStream)
|
||||
|
||||
// Open a private zero-conf anchors channel of 1M satoshis.
|
||||
params := lntemp.OpenChannelParams{
|
||||
params := lntest.OpenChannelParams{
|
||||
Amt: btcutil.Amount(1_000_000),
|
||||
CommitmentType: lnrpc.CommitmentType_ANCHORS,
|
||||
ZeroConf: true,
|
||||
|
|
@ -949,10 +955,9 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
|
|||
// We will now attempt to query for the alias SCID in Carol's graph.
|
||||
// We will query for the starting alias, which is exported by the
|
||||
// aliasmgr package.
|
||||
_, err := carol.RPC.LN.GetChanInfo(ctxb, &lnrpc.ChanInfoRequest{
|
||||
carol.RPC.GetChanInfo(&lnrpc.ChanInfoRequest{
|
||||
ChanId: aliasmgr.StartingAlias.ToUint64(),
|
||||
})
|
||||
require.NoError(ht.T, err)
|
||||
|
||||
// Now we will trigger a reorg and we'll assert that the edge still
|
||||
// exists in the graph.
|
||||
|
|
@ -960,7 +965,7 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
|
|||
// First, we'll setup a new miner that we can use to cause a reorg.
|
||||
tempLogDir := ".tempminerlogs"
|
||||
logFilename := "output-open_channel_reorg-temp_miner.log"
|
||||
tempMiner := lntemp.NewTempMiner(
|
||||
tempMiner := lntest.NewTempMiner(
|
||||
ht.Context(), ht.T, tempLogDir, logFilename,
|
||||
)
|
||||
defer tempMiner.Stop()
|
||||
|
|
@ -971,7 +976,7 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
|
|||
|
||||
// We start by connecting the new miner to our original miner, such
|
||||
// that it will sync to our original chain.
|
||||
err = ht.Miner.Client.Node(
|
||||
err := ht.Miner.Client.Node(
|
||||
btcjson.NConnect, tempMiner.P2PAddress(), &temp,
|
||||
)
|
||||
require.NoError(ht.T, err, "unable to connect node")
|
||||
|
|
@ -991,18 +996,16 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
|
|||
require.NoError(ht.T, err, "unable to remove node")
|
||||
|
||||
// We now cause a fork, by letting our original miner mine 1 block and
|
||||
// our new miner will mine 2.
|
||||
ht.MineBlocks(1)
|
||||
_, err = tempMiner.Client.Generate(2)
|
||||
require.NoError(ht.T, err, "unable to generate blocks")
|
||||
// our new miner will mine 2. We also expect the funding transition to
|
||||
// be mined.
|
||||
ht.MineBlocksAndAssertNumTxes(1, 1)
|
||||
tempMiner.MineEmptyBlocks(2)
|
||||
|
||||
// Ensure the temp miner is one block ahead.
|
||||
assertMinerBlockHeightDelta(ht, ht.Miner, tempMiner, 1)
|
||||
|
||||
// Wait for Carol to sync to the original miner's chain.
|
||||
_, minerHeight, err := ht.Miner.Client.GetBestBlock()
|
||||
require.NoError(ht.T, err, "unable to get current blockheight")
|
||||
|
||||
_, minerHeight := ht.Miner.GetBestBlock()
|
||||
ht.WaitForNodeBlockHeight(carol, minerHeight)
|
||||
|
||||
// Now we'll disconnect Carol's chain backend from the original miner
|
||||
|
|
@ -1033,24 +1036,19 @@ func testZeroConfReorg(ht *lntemp.HarnessTest) {
|
|||
|
||||
ht.ConnectMiner()
|
||||
|
||||
// This should have caused a reorg and Alice should sync to the new
|
||||
// This should have caused a reorg and Carol should sync to the new
|
||||
// chain.
|
||||
_, tempMinerHeight, err := tempMiner.Client.GetBestBlock()
|
||||
require.NoError(ht.T, err, "unable to get current blockheight")
|
||||
|
||||
_, tempMinerHeight := tempMiner.GetBestBlock()
|
||||
ht.WaitForNodeBlockHeight(carol, tempMinerHeight)
|
||||
|
||||
err = wait.Predicate(func() bool {
|
||||
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
|
||||
// Make sure all active nodes are synced.
|
||||
ht.AssertActiveNodesSynced()
|
||||
|
||||
_, err = carol.RPC.LN.GetChanInfo(ctxt, &lnrpc.ChanInfoRequest{
|
||||
ChanId: aliasmgr.StartingAlias.ToUint64(),
|
||||
})
|
||||
|
||||
return err == nil
|
||||
}, defaultTimeout)
|
||||
require.NoError(ht.T, err, "carol doesn't have zero-conf edge")
|
||||
// Carol should have the channel once synced.
|
||||
carol.RPC.GetChanInfo(&lnrpc.ChanInfoRequest{
|
||||
ChanId: aliasmgr.StartingAlias.ToUint64(),
|
||||
})
|
||||
|
||||
// Mine the zero-conf funding transaction so the test doesn't fail.
|
||||
ht.MineBlocks(1)
|
||||
ht.MineBlocksAndAssertNumTxes(1, 1)
|
||||
}
|
||||
|
|
@ -1,6 +1,3 @@
|
|||
//go:build !rpctest
|
||||
// +build !rpctest
|
||||
|
||||
package lncfg
|
||||
|
||||
import (
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//go:build !rpctest
|
||||
// +build !rpctest
|
||||
//go:build !integration
|
||||
|
||||
package lncfg
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
//go:build rpctest
|
||||
// +build rpctest
|
||||
//go:build integration
|
||||
|
||||
package lncfg
|
||||
|
||||
|
|
@ -7,6 +6,8 @@ package lncfg
|
|||
// compatibility of protocol additions, while defaulting to the latest within
|
||||
// lnd, or to enable experimental protocol changes.
|
||||
//
|
||||
// TODO(yy): delete this build flag to unify with `lncfg/protocol.go`.
|
||||
//
|
||||
//nolint:lll
|
||||
type ProtocolOptions struct {
|
||||
// LegacyProtocol is a sub-config that houses all the legacy protocol
|
||||
|
|
@ -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
|
||||
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/rpcclient"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
)
|
||||
|
||||
// logDirPattern is the pattern of the name of the temporary log directory.
|
||||
|
|
@ -37,7 +38,7 @@ type BitcoindBackendConfig struct {
|
|||
|
||||
// A compile time assertion to ensure BitcoindBackendConfig meets the
|
||||
// BackendConfig interface.
|
||||
var _ BackendConfig = (*BitcoindBackendConfig)(nil)
|
||||
var _ node.BackendConfig = (*BitcoindBackendConfig)(nil)
|
||||
|
||||
// GenArgs returns the arguments needed to be passed to LND at startup for
|
||||
// using this node as a chain backend.
|
||||
|
|
@ -89,7 +90,7 @@ func (b BitcoindBackendConfig) Name() string {
|
|||
func newBackend(miner string, netParams *chaincfg.Params, extraArgs []string,
|
||||
rpcPolling bool) (*BitcoindBackendConfig, func() error, error) {
|
||||
|
||||
baseLogDir := fmt.Sprintf(logDirPattern, GetLogDir())
|
||||
baseLogDir := fmt.Sprintf(logDirPattern, node.GetLogDir())
|
||||
if netParams != &chaincfg.RegressionNetParams {
|
||||
return nil, nil, fmt.Errorf("only regtest supported")
|
||||
}
|
||||
|
|
@ -109,10 +110,12 @@ func newBackend(miner string, netParams *chaincfg.Params, extraArgs []string,
|
|||
fmt.Errorf("unable to create temp directory: %v", err)
|
||||
}
|
||||
|
||||
zmqBlockAddr := fmt.Sprintf("tcp://127.0.0.1:%d", NextAvailablePort())
|
||||
zmqTxAddr := fmt.Sprintf("tcp://127.0.0.1:%d", NextAvailablePort())
|
||||
rpcPort := NextAvailablePort()
|
||||
p2pPort := NextAvailablePort()
|
||||
zmqBlockAddr := fmt.Sprintf("tcp://127.0.0.1:%d",
|
||||
node.NextAvailablePort())
|
||||
zmqTxAddr := fmt.Sprintf("tcp://127.0.0.1:%d",
|
||||
node.NextAvailablePort())
|
||||
rpcPort := node.NextAvailablePort()
|
||||
p2pPort := node.NextAvailablePort()
|
||||
|
||||
cmdArgs := []string{
|
||||
"-datadir=" + tempBitcoindDir,
|
||||
|
|
@ -146,9 +149,9 @@ func newBackend(miner string, netParams *chaincfg.Params, extraArgs []string,
|
|||
// After shutting down the chain backend, we'll make a copy of
|
||||
// the log file before deleting the temporary log dir.
|
||||
logDestination := fmt.Sprintf(
|
||||
"%s/output_bitcoind_chainbackend.log", GetLogDir(),
|
||||
"%s/output_bitcoind_chainbackend.log", node.GetLogDir(),
|
||||
)
|
||||
err := CopyFile(logDestination, logFile)
|
||||
err := node.CopyFile(logDestination, logFile)
|
||||
if err != nil {
|
||||
errStr += fmt.Sprintf("unable to copy file: %v\n", err)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@ import (
|
|||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/integration/rpctest"
|
||||
"github.com/btcsuite/btcd/rpcclient"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
)
|
||||
|
||||
// logDirPattern is the pattern of the name of the temporary log directory.
|
||||
|
|
@ -41,7 +42,7 @@ type BtcdBackendConfig struct {
|
|||
|
||||
// A compile time assertion to ensure BtcdBackendConfig meets the BackendConfig
|
||||
// interface.
|
||||
var _ BackendConfig = (*BtcdBackendConfig)(nil)
|
||||
var _ node.BackendConfig = (*BtcdBackendConfig)(nil)
|
||||
|
||||
// GenArgs returns the arguments needed to be passed to LND at startup for
|
||||
// using this node as a chain backend.
|
||||
|
|
@ -83,7 +84,7 @@ func (b BtcdBackendConfig) Name() string {
|
|||
func NewBackend(miner string, netParams *chaincfg.Params) (
|
||||
*BtcdBackendConfig, func() error, error) {
|
||||
|
||||
baseLogDir := fmt.Sprintf(logDirPattern, GetLogDir())
|
||||
baseLogDir := fmt.Sprintf(logDirPattern, node.GetLogDir())
|
||||
args := []string{
|
||||
"--rejectnonstd",
|
||||
"--txindex",
|
||||
|
|
@ -98,9 +99,12 @@ func NewBackend(miner string, netParams *chaincfg.Params) (
|
|||
// Don't disconnect if a reply takes too long.
|
||||
"--nostalldetect",
|
||||
}
|
||||
chainBackend, err := rpctest.New(netParams, nil, args, GetBtcdBinary())
|
||||
chainBackend, err := rpctest.New(
|
||||
netParams, nil, args, node.GetBtcdBinary(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to create btcd node: %v", err)
|
||||
return nil, nil, fmt.Errorf("unable to create btcd node: %w",
|
||||
err)
|
||||
}
|
||||
|
||||
// We want to overwrite some of the connection settings to make the
|
||||
|
|
@ -108,11 +112,17 @@ func NewBackend(miner string, netParams *chaincfg.Params) (
|
|||
// are already blocks present, which will take a bit longer than the
|
||||
// 1 second the default settings amount to. Doubling both values will
|
||||
// give us retries up to 4 seconds.
|
||||
chainBackend.MaxConnRetries = rpctest.DefaultMaxConnectionRetries * 2
|
||||
chainBackend.ConnectionRetryTimeout = rpctest.DefaultConnectionRetryTimeout * 2
|
||||
const (
|
||||
maxConnRetries = rpctest.DefaultMaxConnectionRetries * 2
|
||||
connRetryTimeout = rpctest.DefaultConnectionRetryTimeout * 2
|
||||
)
|
||||
|
||||
chainBackend.MaxConnRetries = maxConnRetries
|
||||
chainBackend.ConnectionRetryTimeout = connRetryTimeout
|
||||
|
||||
if err := chainBackend.SetUp(false, 0); err != nil {
|
||||
return nil, nil, fmt.Errorf("unable to set up btcd backend: %v", err)
|
||||
return nil, nil, fmt.Errorf("unable to set up btcd backend: %w",
|
||||
err)
|
||||
}
|
||||
|
||||
bd := &BtcdBackendConfig{
|
||||
|
|
@ -141,14 +151,16 @@ func NewBackend(miner string, netParams *chaincfg.Params) (
|
|||
for _, file := range files {
|
||||
logFile := fmt.Sprintf("%s/%s", logDir, file.Name())
|
||||
newFilename := strings.Replace(
|
||||
file.Name(), "btcd.log", "output_btcd_chainbackend.log", 1,
|
||||
file.Name(), "btcd.log",
|
||||
"output_btcd_chainbackend.log", 1,
|
||||
)
|
||||
logDestination := fmt.Sprintf(
|
||||
"%s/%s", GetLogDir(), newFilename,
|
||||
"%s/%s", node.GetLogDir(), newFilename,
|
||||
)
|
||||
err := CopyFile(logDestination, logFile)
|
||||
err := node.CopyFile(logDestination, logFile)
|
||||
if err != nil {
|
||||
errStr += fmt.Sprintf("unable to copy file: %v\n", err)
|
||||
errStr += fmt.Sprintf("unable to copy file: "+
|
||||
"%v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,45 +9,72 @@ import (
|
|||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// WebFeeService defines an interface that's used to provide fee estimation
|
||||
// service used in the integration tests. It must provide an URL so that a lnd
|
||||
// node can be started with the flag `--feeurl` and uses the customized fee
|
||||
// estimator.
|
||||
type WebFeeService interface {
|
||||
// Start starts the service.
|
||||
Start() error
|
||||
|
||||
// Stop stops the service.
|
||||
Stop() error
|
||||
|
||||
// URL returns the service's endpoint.
|
||||
URL() string
|
||||
|
||||
// SetFeeRate sets the estimated fee rate for a given confirmation
|
||||
// target.
|
||||
SetFeeRate(feeRate chainfee.SatPerKWeight, conf uint32)
|
||||
}
|
||||
|
||||
const (
|
||||
// feeServiceTarget is the confirmation target for which a fee estimate
|
||||
// is returned. Requests for higher confirmation targets will fall back
|
||||
// to this.
|
||||
feeServiceTarget = 1
|
||||
|
||||
// DefaultFeeRateSatPerKw specifies the default fee rate used in the
|
||||
// tests.
|
||||
DefaultFeeRateSatPerKw = 12500
|
||||
)
|
||||
|
||||
// feeService runs a web service that provides fee estimation information.
|
||||
type feeService struct {
|
||||
feeEstimates
|
||||
// FeeService runs a web service that provides fee estimation information.
|
||||
type FeeService struct {
|
||||
*testing.T
|
||||
|
||||
t *testing.T
|
||||
|
||||
srv *http.Server
|
||||
wg sync.WaitGroup
|
||||
|
||||
url string
|
||||
feeRateMap map[uint32]uint32
|
||||
url string
|
||||
|
||||
srv *http.Server
|
||||
wg sync.WaitGroup
|
||||
lock sync.Mutex
|
||||
}
|
||||
|
||||
// feeEstimates contains the current fee estimates.
|
||||
type feeEstimates struct {
|
||||
Fees map[uint32]uint32 `json:"fee_by_block_target"`
|
||||
}
|
||||
// Compile-time check for the WebFeeService interface.
|
||||
var _ WebFeeService = (*FeeService)(nil)
|
||||
|
||||
// startFeeService spins up a go-routine to serve fee estimates.
|
||||
func startFeeService(t *testing.T) *feeService {
|
||||
port := NextAvailablePort()
|
||||
f := feeService{
|
||||
t: t,
|
||||
url: fmt.Sprintf("http://localhost:%v/fee-estimates.json", port),
|
||||
// Start spins up a go-routine to serve fee estimates.
|
||||
func NewFeeService(t *testing.T) *FeeService {
|
||||
t.Helper()
|
||||
|
||||
port := node.NextAvailablePort()
|
||||
f := FeeService{
|
||||
T: t,
|
||||
url: fmt.Sprintf(
|
||||
"http://localhost:%v/fee-estimates.json", port,
|
||||
),
|
||||
}
|
||||
|
||||
// Initialize default fee estimate.
|
||||
f.Fees = map[uint32]uint32{feeServiceTarget: 50000}
|
||||
f.feeRateMap = map[uint32]uint32{
|
||||
feeServiceTarget: DefaultFeeRateSatPerKw,
|
||||
}
|
||||
|
||||
listenAddr := fmt.Sprintf(":%v", port)
|
||||
mux := http.NewServeMux()
|
||||
|
|
@ -58,57 +85,60 @@ func startFeeService(t *testing.T) *feeService {
|
|||
Handler: mux,
|
||||
}
|
||||
|
||||
return &f
|
||||
}
|
||||
|
||||
// Start starts the web server.
|
||||
func (f *FeeService) Start() error {
|
||||
f.wg.Add(1)
|
||||
go func() {
|
||||
defer f.wg.Done()
|
||||
|
||||
if err := f.srv.ListenAndServe(); err != http.ErrServerClosed {
|
||||
f.t.Errorf("error: cannot start fee api: %v", err)
|
||||
require.NoErrorf(f, err, "cannot start fee api")
|
||||
}
|
||||
}()
|
||||
|
||||
return &f
|
||||
return nil
|
||||
}
|
||||
|
||||
// handleRequest handles a client request for fee estimates.
|
||||
func (f *feeService) handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
func (f *FeeService) handleRequest(w http.ResponseWriter, r *http.Request) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
bytes, err := json.Marshal(f.feeEstimates)
|
||||
if err != nil {
|
||||
f.t.Errorf("error: cannot serialize estimates: %v", err)
|
||||
|
||||
return
|
||||
}
|
||||
bytes, err := json.Marshal(
|
||||
struct {
|
||||
Fees map[uint32]uint32 `json:"fee_by_block_target"`
|
||||
}{
|
||||
Fees: f.feeRateMap,
|
||||
},
|
||||
)
|
||||
require.NoErrorf(f, err, "cannot serialize estimates")
|
||||
|
||||
_, err = io.WriteString(w, string(bytes))
|
||||
if err != nil {
|
||||
f.t.Errorf("error: cannot send estimates: %v", err)
|
||||
}
|
||||
require.NoError(f, err, "cannot send estimates")
|
||||
}
|
||||
|
||||
// stop stops the web server.
|
||||
func (f *feeService) stop() {
|
||||
if err := f.srv.Shutdown(context.Background()); err != nil {
|
||||
f.t.Errorf("error: cannot stop fee api: %v", err)
|
||||
}
|
||||
// Stop stops the web server.
|
||||
func (f *FeeService) Stop() error {
|
||||
err := f.srv.Shutdown(context.Background())
|
||||
require.NoError(f, err, "cannot stop fee api")
|
||||
|
||||
f.wg.Wait()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// setFee changes the current fee estimate for the fixed confirmation target.
|
||||
func (f *feeService) setFee(fee chainfee.SatPerKWeight) {
|
||||
// SetFeeRate sets a fee for the given confirmation target.
|
||||
func (f *FeeService) SetFeeRate(fee chainfee.SatPerKWeight, conf uint32) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
f.Fees[feeServiceTarget] = uint32(fee.FeePerKVByte())
|
||||
f.feeRateMap[conf] = uint32(fee.FeePerKVByte())
|
||||
}
|
||||
|
||||
// setFeeWithConf sets a fee for the given confirmation target.
|
||||
func (f *feeService) setFeeWithConf(fee chainfee.SatPerKWeight, conf uint32) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
f.Fees[conf] = uint32(fee.FeePerKVByte())
|
||||
// URL returns the service endpoint.
|
||||
func (f *FeeService) URL() string {
|
||||
return f.url
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 (
|
||||
"context"
|
||||
|
|
@ -17,9 +17,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
|
|
@ -38,6 +37,10 @@ const (
|
|||
// numBlocksOpenChannel specifies the number of blocks mined when
|
||||
// opening a channel.
|
||||
numBlocksOpenChannel = 6
|
||||
|
||||
// lndErrorChanSize specifies the buffer size used to receive errors
|
||||
// from lnd process.
|
||||
lndErrorChanSize = 10
|
||||
)
|
||||
|
||||
// TestCase defines a test case that's been used in the integration test.
|
||||
|
|
@ -85,7 +88,7 @@ type HarnessTest struct {
|
|||
// runCtx is a context with cancel method. It's used to signal when the
|
||||
// node needs to quit, and used as the parent context when spawning
|
||||
// children contexts for RPC requests.
|
||||
runCtx context.Context
|
||||
runCtx context.Context //nolint:containedctx
|
||||
cancel context.CancelFunc
|
||||
|
||||
// stopChainBackend points to the cleanup function returned by the
|
||||
|
|
@ -100,12 +103,15 @@ type HarnessTest struct {
|
|||
// NewHarnessTest creates a new instance of a harnessTest from a regular
|
||||
// testing.T instance.
|
||||
func NewHarnessTest(t *testing.T, lndBinary string, feeService WebFeeService,
|
||||
dbBackend lntest.DatabaseBackend) *HarnessTest {
|
||||
dbBackend node.DatabaseBackend) *HarnessTest {
|
||||
|
||||
t.Helper()
|
||||
|
||||
// Create the run context.
|
||||
ctxt, cancel := context.WithCancel(context.Background())
|
||||
|
||||
manager := newNodeManager(lndBinary, dbBackend)
|
||||
|
||||
return &HarnessTest{
|
||||
T: t,
|
||||
manager: manager,
|
||||
|
|
@ -114,7 +120,7 @@ func NewHarnessTest(t *testing.T, lndBinary string, feeService WebFeeService,
|
|||
cancel: cancel,
|
||||
// We need to use buffered channel here as we don't want to
|
||||
// block sending errors.
|
||||
lndErrorChan: make(chan error, 10),
|
||||
lndErrorChan: make(chan error, lndErrorChanSize),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -180,21 +186,18 @@ func (h *HarnessTest) SetupStandbyNodes() {
|
|||
h.Alice = h.NewNode("Alice", lndArgs)
|
||||
h.Bob = h.NewNode("Bob", lndArgs)
|
||||
|
||||
// First, make a connection between the two nodes. This will wait until
|
||||
// both nodes are fully started since the Connect RPC is guarded behind
|
||||
// the server.Started() flag that waits for all subsystems to be ready.
|
||||
h.ConnectNodes(h.Alice, h.Bob)
|
||||
|
||||
addrReq := &lnrpc.NewAddressRequest{
|
||||
Type: lnrpc.AddressType_WITNESS_PUBKEY_HASH,
|
||||
}
|
||||
|
||||
// Load up the wallets of the seeder nodes with 10 outputs of 10 BTC
|
||||
const initialFund = 1 * btcutil.SatoshiPerBitcoin
|
||||
|
||||
// Load up the wallets of the seeder nodes with 100 outputs of 1 BTC
|
||||
// each.
|
||||
nodes := []*node.HarnessNode{h.Alice, h.Bob}
|
||||
for _, hn := range nodes {
|
||||
h.manager.standbyNodes[hn.Cfg.NodeID] = hn
|
||||
for i := 0; i < 10; i++ {
|
||||
for i := 0; i < 100; i++ {
|
||||
resp := hn.RPC.NewAddress(addrReq)
|
||||
|
||||
addr, err := btcutil.DecodeAddress(
|
||||
|
|
@ -207,7 +210,7 @@ func (h *HarnessTest) SetupStandbyNodes() {
|
|||
|
||||
output := &wire.TxOut{
|
||||
PkScript: addrScript,
|
||||
Value: 10 * btcutil.SatoshiPerBitcoin,
|
||||
Value: initialFund,
|
||||
}
|
||||
h.Miner.SendOutput(output, defaultMinerFeeRate)
|
||||
}
|
||||
|
|
@ -215,7 +218,7 @@ func (h *HarnessTest) SetupStandbyNodes() {
|
|||
|
||||
// We generate several blocks in order to give the outputs created
|
||||
// above a good number of confirmations.
|
||||
const totalTxes = 20
|
||||
const totalTxes = 200
|
||||
h.MineBlocksAndAssertNumTxes(numBlocksSendOutput, totalTxes)
|
||||
|
||||
// Now we want to wait for the nodes to catch up.
|
||||
|
|
@ -223,7 +226,7 @@ func (h *HarnessTest) SetupStandbyNodes() {
|
|||
h.WaitForBlockchainSync(h.Bob)
|
||||
|
||||
// Now block until both wallets have fully synced up.
|
||||
expectedBalance := int64(btcutil.SatoshiPerBitcoin * 100)
|
||||
const expectedBalance = 100 * initialFund
|
||||
err := wait.NoError(func() error {
|
||||
aliceResp := h.Alice.RPC.WalletBalance()
|
||||
bobResp := h.Bob.RPC.WalletBalance()
|
||||
|
|
@ -286,6 +289,8 @@ func (h *HarnessTest) RunTestCase(testCase *TestCase) {
|
|||
// resetStandbyNodes resets all standby nodes by attaching the new testing.T
|
||||
// and restarting them with the original config.
|
||||
func (h *HarnessTest) resetStandbyNodes(t *testing.T) {
|
||||
t.Helper()
|
||||
|
||||
for _, hn := range h.manager.standbyNodes {
|
||||
// Inherit the testing.T.
|
||||
h.T = t
|
||||
|
|
@ -313,7 +318,7 @@ func (h *HarnessTest) Subtest(t *testing.T) *HarnessTest {
|
|||
Miner: h.Miner,
|
||||
standbyNodes: h.standbyNodes,
|
||||
feeService: h.feeService,
|
||||
lndErrorChan: make(chan error, 10),
|
||||
lndErrorChan: make(chan error, lndErrorChanSize),
|
||||
}
|
||||
|
||||
// Inherit context from the main test.
|
||||
|
|
@ -341,6 +346,7 @@ func (h *HarnessTest) Subtest(t *testing.T) *HarnessTest {
|
|||
// Don't bother run the cleanups if the test is failed.
|
||||
if st.Failed() {
|
||||
st.Log("test failed, skipped cleanup")
|
||||
st.shutdownAllNodes()
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -381,10 +387,21 @@ func (h *HarnessTest) Subtest(t *testing.T) *HarnessTest {
|
|||
|
||||
// shutdownNonStandbyNodes will shutdown any non-standby nodes.
|
||||
func (h *HarnessTest) shutdownNonStandbyNodes() {
|
||||
h.shutdownNodes(true)
|
||||
}
|
||||
|
||||
// shutdownAllNodes will shutdown all running nodes.
|
||||
func (h *HarnessTest) shutdownAllNodes() {
|
||||
h.shutdownNodes(false)
|
||||
}
|
||||
|
||||
// shutdownNodes will shutdown any non-standby nodes. If skipStandby is false,
|
||||
// all the standby nodes will be shutdown too.
|
||||
func (h *HarnessTest) shutdownNodes(skipStandby bool) {
|
||||
for nid, node := range h.manager.activeNodes {
|
||||
// If it's a standby node, skip.
|
||||
_, ok := h.manager.standbyNodes[nid]
|
||||
if ok {
|
||||
if ok && skipStandby {
|
||||
continue
|
||||
}
|
||||
|
||||
|
|
@ -394,7 +411,11 @@ func (h *HarnessTest) shutdownNonStandbyNodes() {
|
|||
err := wait.NoError(func() error {
|
||||
return h.manager.shutdownNode(node)
|
||||
}, DefaultTimeout)
|
||||
require.NoErrorf(h, err, "unable to shutdown %s", node.Name())
|
||||
|
||||
// Instead of returning the error, we will log it instead. This
|
||||
// is needed so other nodes can continue their shutdown
|
||||
// processes.
|
||||
h.Logf("unable to shutdown %s, got err: %v", node.Name(), err)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -636,7 +657,7 @@ func (h *HarnessTest) NewNodeEtcd(name string, etcdCfg *etcd.Config,
|
|||
leaderSessionTTL int) *node.HarnessNode {
|
||||
|
||||
// We don't want to use the embedded etcd instance.
|
||||
h.manager.dbBackend = lntest.BackendBbolt
|
||||
h.manager.dbBackend = node.BackendBbolt
|
||||
|
||||
extraArgs := node.ExtraArgsEtcd(
|
||||
etcdCfg, name, cluster, leaderSessionTTL,
|
||||
|
|
@ -659,7 +680,7 @@ func (h *HarnessTest) NewNodeWithSeedEtcd(name string, etcdCfg *etcd.Config,
|
|||
leaderSessionTTL int) (*node.HarnessNode, []string, []byte) {
|
||||
|
||||
// We don't want to use the embedded etcd instance.
|
||||
h.manager.dbBackend = lntest.BackendBbolt
|
||||
h.manager.dbBackend = node.BackendBbolt
|
||||
|
||||
// Create a request to generate a new aezeed. The new seed will have
|
||||
// the same password as the internal wallet.
|
||||
|
|
@ -1082,7 +1103,19 @@ func (h *HarnessTest) CloseChannelAssertPending(hn *node.HarnessNode,
|
|||
// transaction to be broadcast, then wait for the closing tx to be seen
|
||||
// within the network.
|
||||
event, err := h.ReceiveCloseChannelUpdate(stream)
|
||||
require.NoError(h, err)
|
||||
if err != nil {
|
||||
// TODO(yy): remove the sleep once the following bug is fixed.
|
||||
// We may receive the error `cannot co-op close channel with
|
||||
// active htlcs` or `link failed to shutdown` if we close the
|
||||
// channel. We need to investigate the order of settling the
|
||||
// payments and updating commitments to properly fix it.
|
||||
time.Sleep(2 * time.Second)
|
||||
|
||||
// Give it another chance.
|
||||
stream = hn.RPC.CloseChannel(closeReq)
|
||||
event, err = h.ReceiveCloseChannelUpdate(stream)
|
||||
require.NoError(h, err)
|
||||
}
|
||||
|
||||
pendingClose, ok := event.Update.(*lnrpc.CloseStatusUpdate_ClosePending)
|
||||
require.Truef(h, ok, "expected channel close update, instead got %v",
|
||||
|
|
@ -1277,7 +1310,7 @@ func (h *HarnessTest) completePaymentRequestsAssertStatus(hn *node.HarnessNode,
|
|||
send := func(payReq string) {
|
||||
req := &routerrpc.SendPaymentRequest{
|
||||
PaymentRequest: payReq,
|
||||
TimeoutSeconds: defaultPaymentTimeout,
|
||||
TimeoutSeconds: int32(wait.PaymentTimeout.Seconds()),
|
||||
FeeLimitMsat: noFeeLimitMsat,
|
||||
}
|
||||
stream := hn.RPC.SendPayment(req)
|
||||
|
|
@ -1293,7 +1326,7 @@ func (h *HarnessTest) completePaymentRequestsAssertStatus(hn *node.HarnessNode,
|
|||
}
|
||||
|
||||
// Wait for all payments to report the expected status.
|
||||
timer := time.After(DefaultTimeout)
|
||||
timer := time.After(wait.PaymentTimeout)
|
||||
select {
|
||||
case stream := <-results:
|
||||
h.AssertPaymentStatusFromStream(stream, status)
|
||||
|
|
@ -1402,7 +1435,7 @@ func (h *HarnessTest) CleanupForceClose(hn *node.HarnessNode,
|
|||
//
|
||||
// The commit sweep resolver is able to broadcast the sweep tx up to
|
||||
// one block before the CSV elapses, so wait until defaulCSV-1.
|
||||
h.MineBlocks(lntest.DefaultCSV - 1)
|
||||
h.MineBlocks(node.DefaultCSV - 1)
|
||||
|
||||
// The node should now sweep the funds, clean up by mining the sweeping
|
||||
// tx.
|
||||
|
|
@ -1686,7 +1719,7 @@ func (h *HarnessTest) OpenMultiChannelsAsync(
|
|||
case cp := <-r.result:
|
||||
channelPoints = append(channelPoints, cp)
|
||||
|
||||
case <-time.After(lntest.ChannelOpenTimeout):
|
||||
case <-time.After(wait.ChannelOpenTimeout):
|
||||
require.Failf(h, "timeout", "wait channel point "+
|
||||
"timeout for channel %s=>%s", r.Local.Name(),
|
||||
r.Remote.Name())
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package lntemp
|
||||
package lntest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
|
|
@ -23,8 +23,8 @@ import (
|
|||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
|
@ -38,6 +38,7 @@ func (h *HarnessTest) WaitForBlockchainSync(hn *node.HarnessNode) {
|
|||
if resp.SyncedToChain {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("%s is not synced to chain", hn.Name())
|
||||
}, DefaultTimeout)
|
||||
|
||||
|
|
@ -145,6 +146,12 @@ func (h *HarnessTest) EnsureConnected(a, b *node.HarnessNode) {
|
|||
// connected to the peer.
|
||||
errConnectionRequested := "connection request in progress"
|
||||
|
||||
// windowsErr is an error we've seen from windows build where
|
||||
// connecting to an already connected node gives such error from the
|
||||
// receiver side.
|
||||
windowsErr := "An established connection was aborted by the software " +
|
||||
"in your host machine."
|
||||
|
||||
tryConnect := func(a, b *node.HarnessNode) error {
|
||||
bInfo := b.RPC.GetInfo()
|
||||
|
||||
|
|
@ -165,17 +172,21 @@ func (h *HarnessTest) EnsureConnected(a, b *node.HarnessNode) {
|
|||
return nil
|
||||
}
|
||||
|
||||
// If the connection is in process, we return no error.
|
||||
if strings.Contains(err.Error(), errConnectionRequested) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// If the two are already connected, we return early with no
|
||||
// error.
|
||||
if strings.Contains(err.Error(), "already connected to peer") {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Otherwise we log the error to console.
|
||||
h.Logf("EnsureConnected %s=>%s got err: %v", a.Name(),
|
||||
b.Name(), err)
|
||||
|
||||
// If the connection is in process, we return no error.
|
||||
if strings.Contains(err.Error(), errConnectionRequested) {
|
||||
return nil
|
||||
}
|
||||
|
||||
// We may get connection refused error if we happens to be in
|
||||
// the middle of a previous node disconnection, e.g., a restart
|
||||
// from one of the nodes.
|
||||
|
|
@ -183,6 +194,16 @@ func (h *HarnessTest) EnsureConnected(a, b *node.HarnessNode) {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Check for windows error. If Alice connects to Bob, Alice
|
||||
// will throw "i/o timeout" and Bob will give windowsErr.
|
||||
if strings.Contains(err.Error(), windowsErr) {
|
||||
return nil
|
||||
}
|
||||
|
||||
if strings.Contains(err.Error(), "i/o timeout") {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -231,8 +252,10 @@ func (h *HarnessTest) AssertNumEdges(hn *node.HarnessNode,
|
|||
// slice.
|
||||
edges = chanGraph.Edges[old:]
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
return errNumNotMatched(hn.Name(), "num of channel edges",
|
||||
expected, total-old, total, old)
|
||||
}, DefaultTimeout)
|
||||
|
|
@ -925,7 +948,9 @@ func (h *HarnessTest) AssertNodesNumPendingOpenChannels(a, b *node.HarnessNode,
|
|||
func (h *HarnessTest) AssertPaymentStatusFromStream(stream rpc.PaymentClient,
|
||||
status lnrpc.Payment_PaymentStatus) *lnrpc.Payment {
|
||||
|
||||
return h.assertPaymentStatusWithTimeout(stream, status, DefaultTimeout)
|
||||
return h.assertPaymentStatusWithTimeout(
|
||||
stream, status, wait.PaymentTimeout,
|
||||
)
|
||||
}
|
||||
|
||||
// AssertPaymentSucceedWithTimeout asserts that a payment is succeeded within
|
||||
|
|
@ -1166,7 +1191,9 @@ func (h *HarnessTest) AssertActiveHtlcs(hn *node.HarnessNode,
|
|||
h := hex.EncodeToString(htlc.HashLock)
|
||||
_, ok := htlcHashes[h]
|
||||
if ok {
|
||||
return fmt.Errorf("duplicate HashLock")
|
||||
return fmt.Errorf("duplicate HashLock "+
|
||||
"in PendingHtlcs: %v",
|
||||
ch.PendingHtlcs)
|
||||
}
|
||||
htlcHashes[h] = struct{}{}
|
||||
}
|
||||
|
|
@ -1732,7 +1759,8 @@ func (h *HarnessTest) AssertNumPayments(hn *node.HarnessNode,
|
|||
return errNumNotMatched(hn.Name(), "num of payments",
|
||||
num, len(payments), have+len(payments), have)
|
||||
}, DefaultTimeout)
|
||||
require.NoError(h, err, "timeout checking num of payments")
|
||||
require.NoError(h, err, "%s: timeout checking num of payments",
|
||||
hn.Name())
|
||||
|
||||
return payments
|
||||
}
|
||||
|
|
@ -1745,7 +1773,8 @@ func (h *HarnessTest) AssertNumNodeAnns(hn *node.HarnessNode,
|
|||
// We will get the current number of channel updates first and add it
|
||||
// to our expected number of newly created channel updates.
|
||||
anns, err := hn.Watcher.WaitForNumNodeUpdates(pubkey, num)
|
||||
require.NoError(h, err, "failed to assert num of channel updates")
|
||||
require.NoError(h, err, "%s: failed to assert num of node anns",
|
||||
hn.Name())
|
||||
|
||||
return anns
|
||||
}
|
||||
|
|
@ -1757,7 +1786,8 @@ func (h *HarnessTest) AssertNumChannelUpdates(hn *node.HarnessNode,
|
|||
|
||||
op := h.OutPointFromChannelPoint(chanPoint)
|
||||
err := hn.Watcher.WaitForNumChannelUpdates(op, num)
|
||||
require.NoError(h, err, "failed to assert num of channel updates")
|
||||
require.NoError(h, err, "%s: failed to assert num of channel updates",
|
||||
hn.Name())
|
||||
}
|
||||
|
||||
// CreateBurnAddr creates a random burn address of the given type.
|
||||
|
|
@ -1,18 +1,26 @@
|
|||
package lntest
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/btcsuite/btcd/btcjson"
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/integration/rpctest"
|
||||
"github.com/btcsuite/btcd/rpcclient"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -21,16 +29,21 @@ const (
|
|||
|
||||
// minerLogDir is the default log dir for the miner node.
|
||||
minerLogDir = ".minerlogs"
|
||||
|
||||
// slowMineDelay defines a wait period between mining new blocks.
|
||||
slowMineDelay = 100 * time.Millisecond
|
||||
)
|
||||
|
||||
var harnessNetParams = &chaincfg.RegressionNetParams
|
||||
|
||||
type HarnessMiner struct {
|
||||
*testing.T
|
||||
*rpctest.Harness
|
||||
|
||||
// runCtx is a context with cancel method. It's used to signal when the
|
||||
// node needs to quit, and used as the parent context when spawning
|
||||
runCtx context.Context
|
||||
// children contexts for RPC requests.
|
||||
runCtx context.Context //nolint:containedctx
|
||||
cancel context.CancelFunc
|
||||
|
||||
// logPath is the directory path of the miner's logs.
|
||||
|
|
@ -42,21 +55,30 @@ type HarnessMiner struct {
|
|||
|
||||
// NewMiner creates a new miner using btcd backend with the default log file
|
||||
// dir and name.
|
||||
func NewMiner() (*HarnessMiner, error) {
|
||||
return newMiner(minerLogDir, minerLogFilename)
|
||||
func NewMiner(ctxt context.Context, t *testing.T) *HarnessMiner {
|
||||
t.Helper()
|
||||
return newMiner(ctxt, t, minerLogDir, minerLogFilename)
|
||||
}
|
||||
|
||||
// NewTempMiner creates a new miner using btcd backend with the specified log
|
||||
// file dir and name.
|
||||
func NewTempMiner(tempDir, tempLogFilename string) (*HarnessMiner, error) {
|
||||
return newMiner(tempDir, tempLogFilename)
|
||||
func NewTempMiner(ctxt context.Context, t *testing.T,
|
||||
tempDir, tempLogFilename string) *HarnessMiner {
|
||||
|
||||
t.Helper()
|
||||
|
||||
return newMiner(ctxt, t, tempDir, tempLogFilename)
|
||||
}
|
||||
|
||||
// newMiner creates a new miner using btcd's rpctest.
|
||||
func newMiner(minerDirName, logFilename string) (*HarnessMiner, error) {
|
||||
func newMiner(ctxb context.Context, t *testing.T, minerDirName,
|
||||
logFilename string) *HarnessMiner {
|
||||
|
||||
t.Helper()
|
||||
|
||||
handler := &rpcclient.NotificationHandlers{}
|
||||
btcdBinary := GetBtcdBinary()
|
||||
baseLogPath := fmt.Sprintf("%s/%s", GetLogDir(), minerDirName)
|
||||
btcdBinary := node.GetBtcdBinary()
|
||||
baseLogPath := fmt.Sprintf("%s/%s", node.GetLogDir(), minerDirName)
|
||||
|
||||
args := []string{
|
||||
"--rejectnonstd",
|
||||
|
|
@ -71,42 +93,28 @@ func newMiner(minerDirName, logFilename string) (*HarnessMiner, error) {
|
|||
}
|
||||
|
||||
miner, err := rpctest.New(harnessNetParams, handler, args, btcdBinary)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to create mining node: %v", err)
|
||||
}
|
||||
require.NoError(t, err, "unable to create mining node")
|
||||
|
||||
ctxt, cancel := context.WithCancel(context.Background())
|
||||
m := &HarnessMiner{
|
||||
ctxt, cancel := context.WithCancel(ctxb)
|
||||
|
||||
return &HarnessMiner{
|
||||
T: t,
|
||||
Harness: miner,
|
||||
runCtx: ctxt,
|
||||
cancel: cancel,
|
||||
logPath: baseLogPath,
|
||||
logFilename: logFilename,
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// Stop shuts down the miner and saves its logs.
|
||||
func (h *HarnessMiner) Stop() error {
|
||||
h.cancel()
|
||||
|
||||
if err := h.TearDown(); err != nil {
|
||||
return fmt.Errorf("tear down miner got error: %s", err)
|
||||
}
|
||||
|
||||
return h.saveLogs()
|
||||
}
|
||||
|
||||
// saveLogs copies the node logs and save it to the file specified by
|
||||
// h.logFilename.
|
||||
func (h *HarnessMiner) saveLogs() error {
|
||||
func (h *HarnessMiner) saveLogs() {
|
||||
// After shutting down the miner, we'll make a copy of the log files
|
||||
// before deleting the temporary log dir.
|
||||
path := fmt.Sprintf("%s/%s", h.logPath, harnessNetParams.Name)
|
||||
files, err := ioutil.ReadDir(path)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to read log directory: %v", err)
|
||||
}
|
||||
require.NoError(h, err, "unable to read log directory")
|
||||
|
||||
for _, file := range files {
|
||||
newFilename := strings.Replace(
|
||||
|
|
@ -116,46 +124,332 @@ func (h *HarnessMiner) saveLogs() error {
|
|||
|
||||
logFile := fmt.Sprintf("%s/%s", path, file.Name())
|
||||
err := CopyFile(filepath.Clean(copyPath), logFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to copy file: %v", err)
|
||||
require.NoError(h, err, "unable to copy file")
|
||||
}
|
||||
|
||||
err = os.RemoveAll(h.logPath)
|
||||
require.NoErrorf(h, err, "cannot remove dir %s", h.logPath)
|
||||
}
|
||||
|
||||
// Stop shuts down the miner and saves its logs.
|
||||
func (h *HarnessMiner) Stop() {
|
||||
h.cancel()
|
||||
require.NoError(h, h.TearDown(), "tear down miner got error")
|
||||
h.saveLogs()
|
||||
}
|
||||
|
||||
// GetBestBlock makes a RPC request to miner and asserts.
|
||||
func (h *HarnessMiner) GetBestBlock() (*chainhash.Hash, int32) {
|
||||
blockHash, height, err := h.Client.GetBestBlock()
|
||||
require.NoError(h, err, "failed to GetBestBlock")
|
||||
|
||||
return blockHash, height
|
||||
}
|
||||
|
||||
// GetRawMempool makes a RPC call to the miner's GetRawMempool and
|
||||
// asserts.
|
||||
func (h *HarnessMiner) GetRawMempool() []*chainhash.Hash {
|
||||
mempool, err := h.Client.GetRawMempool()
|
||||
require.NoError(h, err, "unable to get mempool")
|
||||
|
||||
return mempool
|
||||
}
|
||||
|
||||
// GenerateBlocks mine 'num' of blocks and returns them.
|
||||
func (h *HarnessMiner) GenerateBlocks(num uint32) []*chainhash.Hash {
|
||||
blockHashes, err := h.Client.Generate(num)
|
||||
require.NoError(h, err, "unable to generate blocks")
|
||||
require.Len(h, blockHashes, int(num), "wrong num of blocks generated")
|
||||
|
||||
return blockHashes
|
||||
}
|
||||
|
||||
// GetBlock gets a block using its block hash.
|
||||
func (h *HarnessMiner) GetBlock(blockHash *chainhash.Hash) *wire.MsgBlock {
|
||||
block, err := h.Client.GetBlock(blockHash)
|
||||
require.NoError(h, err, "unable to get block")
|
||||
|
||||
return block
|
||||
}
|
||||
|
||||
// MineBlocks mine 'num' of blocks and check that blocks are present in
|
||||
// node blockchain.
|
||||
func (h *HarnessMiner) MineBlocks(num uint32) []*wire.MsgBlock {
|
||||
blocks := make([]*wire.MsgBlock, num)
|
||||
|
||||
blockHashes := h.GenerateBlocks(num)
|
||||
|
||||
for i, blockHash := range blockHashes {
|
||||
block := h.GetBlock(blockHash)
|
||||
blocks[i] = block
|
||||
}
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
// AssertNumTxsInMempool polls until finding the desired number of transactions
|
||||
// in the provided miner's mempool. It will asserrt if this number is not met
|
||||
// after the given timeout.
|
||||
func (h *HarnessMiner) AssertNumTxsInMempool(n int) []*chainhash.Hash {
|
||||
var (
|
||||
mem []*chainhash.Hash
|
||||
err error
|
||||
)
|
||||
|
||||
err = wait.NoError(func() error {
|
||||
// We require the RPC call to be succeeded and won't wait for
|
||||
// it as it's an unexpected behavior.
|
||||
mem = h.GetRawMempool()
|
||||
if len(mem) == n {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("want %v, got %v in mempool: %v",
|
||||
n, len(mem), mem)
|
||||
}, wait.MinerMempoolTimeout)
|
||||
require.NoError(h, err, "assert tx in mempool timeout")
|
||||
|
||||
return mem
|
||||
}
|
||||
|
||||
// AssertTxInBlock asserts that a given txid can be found in the passed block.
|
||||
func (h *HarnessMiner) AssertTxInBlock(block *wire.MsgBlock,
|
||||
txid *chainhash.Hash) {
|
||||
|
||||
blockTxes := make([]chainhash.Hash, 0)
|
||||
|
||||
for _, tx := range block.Transactions {
|
||||
sha := tx.TxHash()
|
||||
blockTxes = append(blockTxes, sha)
|
||||
|
||||
if bytes.Equal(txid[:], sha[:]) {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if err = os.RemoveAll(h.logPath); err != nil {
|
||||
return fmt.Errorf("cannot remove dir %s: %v", h.logPath, err)
|
||||
}
|
||||
|
||||
return nil
|
||||
require.Failf(h, "tx was not included in block", "tx:%v, block has:%v",
|
||||
txid, blockTxes)
|
||||
}
|
||||
|
||||
// waitForTxInMempool blocks until the target txid is seen in the mempool. If
|
||||
// the transaction isn't seen within the network before the passed timeout,
|
||||
// then an error is returned.
|
||||
func (h *HarnessMiner) waitForTxInMempool(txid chainhash.Hash) error {
|
||||
ticker := time.NewTicker(50 * time.Millisecond)
|
||||
defer ticker.Stop()
|
||||
// MineBlocksAndAssertNumTxes mine 'num' of blocks and check that blocks are
|
||||
// present in node blockchain. numTxs should be set to the number of
|
||||
// transactions (excluding the coinbase) we expect to be included in the first
|
||||
// mined block.
|
||||
func (h *HarnessMiner) MineBlocksAndAssertNumTxes(num uint32,
|
||||
numTxs int) []*wire.MsgBlock {
|
||||
|
||||
var mempool []*chainhash.Hash
|
||||
for {
|
||||
select {
|
||||
case <-h.runCtx.Done():
|
||||
return fmt.Errorf("NetworkHarness has been torn down")
|
||||
case <-time.After(DefaultTimeout):
|
||||
return fmt.Errorf("wanted %v, found %v txs "+
|
||||
"in mempool: %v", txid, len(mempool), mempool)
|
||||
// If we expect transactions to be included in the blocks we'll mine,
|
||||
// we wait here until they are seen in the miner's mempool.
|
||||
txids := h.AssertNumTxsInMempool(numTxs)
|
||||
|
||||
case <-ticker.C:
|
||||
var err error
|
||||
mempool, err = h.Client.GetRawMempool()
|
||||
// Mine blocks.
|
||||
blocks := h.MineBlocks(num)
|
||||
|
||||
// Finally, assert that all the transactions were included in the first
|
||||
// block.
|
||||
for _, txid := range txids {
|
||||
h.AssertTxInBlock(blocks[0], txid)
|
||||
}
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
// GetRawTransaction makes a RPC call to the miner's GetRawTransaction and
|
||||
// asserts.
|
||||
func (h *HarnessMiner) GetRawTransaction(txid *chainhash.Hash) *btcutil.Tx {
|
||||
tx, err := h.Client.GetRawTransaction(txid)
|
||||
require.NoErrorf(h, err, "failed to get raw tx: %v", txid)
|
||||
return tx
|
||||
}
|
||||
|
||||
// GetRawTransactionVerbose makes a RPC call to the miner's
|
||||
// GetRawTransactionVerbose and asserts.
|
||||
func (h *HarnessMiner) GetRawTransactionVerbose(
|
||||
txid *chainhash.Hash) *btcjson.TxRawResult {
|
||||
|
||||
tx, err := h.Client.GetRawTransactionVerbose(txid)
|
||||
require.NoErrorf(h, err, "failed to get raw tx verbose: %v", txid)
|
||||
return tx
|
||||
}
|
||||
|
||||
// AssertTxInMempool asserts a given transaction can be found in the mempool.
|
||||
func (h *HarnessMiner) AssertTxInMempool(txid *chainhash.Hash) *wire.MsgTx {
|
||||
var msgTx *wire.MsgTx
|
||||
|
||||
err := wait.NoError(func() error {
|
||||
// We require the RPC call to be succeeded and won't wait for
|
||||
// it as it's an unexpected behavior.
|
||||
mempool := h.GetRawMempool()
|
||||
|
||||
if len(mempool) == 0 {
|
||||
return fmt.Errorf("empty mempool")
|
||||
}
|
||||
|
||||
for _, memTx := range mempool {
|
||||
// Check the values are equal.
|
||||
if *memTx == *txid {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("txid %v not found in mempool: %v", txid,
|
||||
mempool)
|
||||
}, wait.MinerMempoolTimeout)
|
||||
|
||||
require.NoError(h, err, "timeout checking mempool")
|
||||
|
||||
return msgTx
|
||||
}
|
||||
|
||||
// SendOutputsWithoutChange uses the miner to send the given outputs using the
|
||||
// specified fee rate and returns the txid.
|
||||
func (h *HarnessMiner) SendOutputsWithoutChange(outputs []*wire.TxOut,
|
||||
feeRate btcutil.Amount) *chainhash.Hash {
|
||||
|
||||
txid, err := h.Harness.SendOutputsWithoutChange(
|
||||
outputs, feeRate,
|
||||
)
|
||||
require.NoErrorf(h, err, "failed to send output")
|
||||
|
||||
return txid
|
||||
}
|
||||
|
||||
// CreateTransaction uses the miner to create a transaction using the given
|
||||
// outputs using the specified fee rate and returns the transaction.
|
||||
func (h *HarnessMiner) CreateTransaction(outputs []*wire.TxOut,
|
||||
feeRate btcutil.Amount) *wire.MsgTx {
|
||||
|
||||
tx, err := h.Harness.CreateTransaction(outputs, feeRate, false)
|
||||
require.NoErrorf(h, err, "failed to create transaction")
|
||||
|
||||
return tx
|
||||
}
|
||||
|
||||
// SendOutput creates, signs, and finally broadcasts a transaction spending
|
||||
// the harness' available mature coinbase outputs to create the new output.
|
||||
func (h *HarnessMiner) SendOutput(newOutput *wire.TxOut,
|
||||
feeRate btcutil.Amount) *chainhash.Hash {
|
||||
|
||||
hash, err := h.Harness.SendOutputs([]*wire.TxOut{newOutput}, feeRate)
|
||||
require.NoErrorf(h, err, "failed to send outputs")
|
||||
|
||||
return hash
|
||||
}
|
||||
|
||||
// MineBlocksSlow mines 'num' of blocks. Between each mined block an artificial
|
||||
// delay is introduced to give all network participants time to catch up.
|
||||
func (h *HarnessMiner) MineBlocksSlow(num uint32) []*wire.MsgBlock {
|
||||
blocks := make([]*wire.MsgBlock, num)
|
||||
blockHashes := make([]*chainhash.Hash, 0, num)
|
||||
|
||||
for i := uint32(0); i < num; i++ {
|
||||
generatedHashes := h.GenerateBlocks(1)
|
||||
blockHashes = append(blockHashes, generatedHashes...)
|
||||
|
||||
time.Sleep(slowMineDelay)
|
||||
}
|
||||
|
||||
for i, blockHash := range blockHashes {
|
||||
block, err := h.Client.GetBlock(blockHash)
|
||||
require.NoError(h, err, "get blocks")
|
||||
|
||||
blocks[i] = block
|
||||
}
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
||||
// AssertOutpointInMempool asserts a given outpoint can be found in the mempool.
|
||||
func (h *HarnessMiner) AssertOutpointInMempool(op wire.OutPoint) *wire.MsgTx {
|
||||
var msgTx *wire.MsgTx
|
||||
|
||||
err := wait.NoError(func() error {
|
||||
// We require the RPC call to be succeeded and won't wait for
|
||||
// it as it's an unexpected behavior.
|
||||
mempool := h.GetRawMempool()
|
||||
|
||||
if len(mempool) == 0 {
|
||||
return fmt.Errorf("empty mempool")
|
||||
}
|
||||
|
||||
for _, txid := range mempool {
|
||||
// We don't use `ht.Miner.GetRawTransaction` which
|
||||
// asserts a txid must be found. While iterating here,
|
||||
// the actual mempool state might have been changed,
|
||||
// causing a given txid being removed and cannot be
|
||||
// found. For instance, the aggregation logic used in
|
||||
// sweeping HTLC outputs will update the mempool by
|
||||
// replacing the HTLC spending txes with a single one.
|
||||
tx, err := h.Client.GetRawTransaction(txid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, mempoolTx := range mempool {
|
||||
if *mempoolTx == txid {
|
||||
msgTx = tx.MsgTx()
|
||||
for _, txIn := range msgTx.TxIn {
|
||||
if txIn.PreviousOutPoint == op {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Errorf("outpoint %v not found in mempool", op)
|
||||
}, wait.MinerMempoolTimeout)
|
||||
|
||||
require.NoError(h, err, "timeout checking mempool")
|
||||
|
||||
return msgTx
|
||||
}
|
||||
|
||||
// GetNumTxsFromMempool polls until finding the desired number of transactions
|
||||
// in the miner's mempool and returns the full transactions to the caller.
|
||||
func (h *HarnessMiner) GetNumTxsFromMempool(n int) []*wire.MsgTx {
|
||||
txids := h.AssertNumTxsInMempool(n)
|
||||
|
||||
var txes []*wire.MsgTx
|
||||
for _, txid := range txids {
|
||||
tx := h.GetRawTransaction(txid)
|
||||
txes = append(txes, tx.MsgTx())
|
||||
}
|
||||
|
||||
return txes
|
||||
}
|
||||
|
||||
// NewMinerAddress creates a new address for the miner and asserts.
|
||||
func (h *HarnessMiner) NewMinerAddress() btcutil.Address {
|
||||
addr, err := h.NewAddress()
|
||||
require.NoError(h, err, "failed to create new miner address")
|
||||
return addr
|
||||
}
|
||||
|
||||
// MineBlocksWithTxes mines a single block to include the specifies
|
||||
// transactions only.
|
||||
func (h *HarnessMiner) MineBlockWithTxes(txes []*btcutil.Tx) *wire.MsgBlock {
|
||||
var emptyTime time.Time
|
||||
|
||||
// Generate a block.
|
||||
b, err := h.GenerateAndSubmitBlock(txes, -1, emptyTime)
|
||||
require.NoError(h, err, "unable to mine block")
|
||||
|
||||
block, err := h.Client.GetBlock(b.Hash())
|
||||
require.NoError(h, err, "unable to get block")
|
||||
|
||||
return block
|
||||
}
|
||||
|
||||
// MineEmptyBlocks mines a given number of empty blocks.
|
||||
func (h *HarnessMiner) MineEmptyBlocks(num int) []*wire.MsgBlock {
|
||||
var emptyTime time.Time
|
||||
|
||||
blocks := make([]*wire.MsgBlock, num)
|
||||
for i := 0; i < num; i++ {
|
||||
// Generate an empty block.
|
||||
b, err := h.GenerateAndSubmitBlock(nil, -1, emptyTime)
|
||||
require.NoError(h, err, "unable to mine empty block")
|
||||
|
||||
block := h.GetBlock(b.Hash())
|
||||
blocks[i] = block
|
||||
}
|
||||
|
||||
return blocks
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
|||
package lntemp
|
||||
package lntest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
|
@ -8,8 +8,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
)
|
||||
|
||||
|
|
@ -30,7 +29,7 @@ type nodeManager struct {
|
|||
lndBinary string
|
||||
|
||||
// dbBackend sets the database backend to use.
|
||||
dbBackend lntest.DatabaseBackend
|
||||
dbBackend node.DatabaseBackend
|
||||
|
||||
// activeNodes is a map of all running nodes, format:
|
||||
// {pubkey: *HarnessNode}.
|
||||
|
|
@ -50,7 +49,7 @@ type nodeManager struct {
|
|||
|
||||
// newNodeManager creates a new node manager instance.
|
||||
func newNodeManager(lndBinary string,
|
||||
dbBackend lntest.DatabaseBackend) *nodeManager {
|
||||
dbBackend node.DatabaseBackend) *nodeManager {
|
||||
|
||||
return &nodeManager{
|
||||
lndBinary: lndBinary,
|
||||
|
|
@ -80,7 +79,7 @@ func (nm *nodeManager) newNode(t *testing.T, name string, extraArgs []string,
|
|||
BackendCfg: nm.chainBackend,
|
||||
ExtraArgs: extraArgs,
|
||||
FeeURL: nm.feeServiceURL,
|
||||
DbBackend: nm.dbBackend,
|
||||
DBBackend: nm.dbBackend,
|
||||
NodeID: nm.nextNodeID(),
|
||||
LndBinary: nm.lndBinary,
|
||||
NetParams: harnessNetParams,
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package lntemp
|
||||
package lntest
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
|
@ -6,7 +6,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/integration/rpctest"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
|
|
@ -23,11 +23,11 @@ func SetupHarness(t *testing.T, binaryPath, dbBackendName string,
|
|||
t.Log("Setting up HarnessTest...")
|
||||
|
||||
// Parse testing flags that influence our test execution.
|
||||
logDir := lntest.GetLogDir()
|
||||
logDir := node.GetLogDir()
|
||||
require.NoError(t, os.MkdirAll(logDir, 0700), "create log dir failed")
|
||||
|
||||
// Parse database backend
|
||||
dbBackend := prepareDbBackend(t, dbBackendName)
|
||||
dbBackend := prepareDBBackend(t, dbBackendName)
|
||||
|
||||
// Create a new HarnessTest.
|
||||
ht := NewHarnessTest(t, binaryPath, feeService, dbBackend)
|
||||
|
|
@ -82,9 +82,9 @@ func prepareMiner(ctxt context.Context, t *testing.T) *HarnessMiner {
|
|||
|
||||
// prepareChainBackend creates a new chain backend.
|
||||
func prepareChainBackend(t *testing.T,
|
||||
minerAddr string) (lntest.BackendConfig, func()) {
|
||||
minerAddr string) (node.BackendConfig, func()) {
|
||||
|
||||
chainBackend, cleanUp, err := lntest.NewBackend(
|
||||
chainBackend, cleanUp, err := NewBackend(
|
||||
minerAddr, harnessNetParams,
|
||||
)
|
||||
require.NoError(t, err, "new backend")
|
||||
|
|
@ -94,23 +94,23 @@ func prepareChainBackend(t *testing.T,
|
|||
}
|
||||
}
|
||||
|
||||
// prepareDbBackend parses a DatabaseBackend based on the name given.
|
||||
func prepareDbBackend(t *testing.T,
|
||||
dbBackendName string) lntest.DatabaseBackend {
|
||||
// prepareDBBackend parses a DatabaseBackend based on the name given.
|
||||
func prepareDBBackend(t *testing.T,
|
||||
dbBackendName string) node.DatabaseBackend {
|
||||
|
||||
var dbBackend lntest.DatabaseBackend
|
||||
var dbBackend node.DatabaseBackend
|
||||
switch dbBackendName {
|
||||
case "bbolt":
|
||||
dbBackend = lntest.BackendBbolt
|
||||
dbBackend = node.BackendBbolt
|
||||
|
||||
case "etcd":
|
||||
dbBackend = lntest.BackendEtcd
|
||||
dbBackend = node.BackendEtcd
|
||||
|
||||
case "postgres":
|
||||
dbBackend = lntest.BackendPostgres
|
||||
dbBackend = node.BackendPostgres
|
||||
|
||||
case "sqlite":
|
||||
dbBackend = lntest.BackendSqlite
|
||||
dbBackend = node.BackendSqlite
|
||||
|
||||
default:
|
||||
require.Fail(t, "unknown db backend")
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -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
|
||||
}
|
||||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"fmt"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/lightningnetwork/lnd/lntest/node"
|
||||
)
|
||||
|
||||
// NeutrinoBackendConfig is an implementation of the BackendConfig interface
|
||||
|
|
@ -17,7 +18,7 @@ type NeutrinoBackendConfig struct {
|
|||
|
||||
// A compile time assertion to ensure NeutrinoBackendConfig meets the
|
||||
// BackendConfig interface.
|
||||
var _ BackendConfig = (*NeutrinoBackendConfig)(nil)
|
||||
var _ node.BackendConfig = (*NeutrinoBackendConfig)(nil)
|
||||
|
||||
// GenArgs returns the arguments needed to be passed to LND at startup for
|
||||
// using this node as a chain backend.
|
||||
|
|
|
|||
|
|
@ -1,20 +1,63 @@
|
|||
package node
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/lightningnetwork/lnd/chanbackup"
|
||||
"github.com/lightningnetwork/lnd/kvdb/etcd"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
)
|
||||
|
||||
const (
|
||||
// ListenerFormat is the format string that is used to generate local
|
||||
// listener addresses.
|
||||
ListenerFormat = "127.0.0.1:%d"
|
||||
|
||||
// DefaultCSV is the CSV delay (remotedelay) we will start our test
|
||||
// nodes with.
|
||||
DefaultCSV = 4
|
||||
|
||||
// defaultNodePort is the start of the range for listening ports of
|
||||
// harness nodes. Ports are monotonically increasing starting from this
|
||||
// number and are determined by the results of NextAvailablePort().
|
||||
defaultNodePort = 5555
|
||||
)
|
||||
|
||||
var (
|
||||
// lastPort is the last port determined to be free for use by a new
|
||||
// node. It should be used atomically.
|
||||
lastPort uint32 = defaultNodePort
|
||||
|
||||
// logOutput is a flag that can be set to append the output from the
|
||||
// seed nodes to log files.
|
||||
logOutput = flag.Bool("logoutput", false,
|
||||
"log output from node n to file output-n.log")
|
||||
|
||||
// logSubDir is the default directory where the logs are written to if
|
||||
// logOutput is true.
|
||||
logSubDir = flag.String("logdir", ".", "default dir to write logs to")
|
||||
|
||||
// btcdExecutable is the full path to the btcd binary.
|
||||
btcdExecutable = flag.String(
|
||||
"btcdexec", "", "full path to btcd binary",
|
||||
)
|
||||
)
|
||||
|
||||
type DatabaseBackend int
|
||||
|
||||
const (
|
||||
BackendBbolt DatabaseBackend = iota
|
||||
BackendEtcd
|
||||
BackendPostgres
|
||||
BackendSqlite
|
||||
)
|
||||
|
||||
// Option is a function for updating a node's configuration.
|
||||
|
|
@ -73,7 +116,7 @@ type BaseNodeConfig struct {
|
|||
|
||||
FeeURL string
|
||||
|
||||
DbBackend lntest.DatabaseBackend
|
||||
DBBackend DatabaseBackend
|
||||
PostgresDsn string
|
||||
|
||||
// NodeID is a unique ID used to identify the node.
|
||||
|
|
@ -83,12 +126,12 @@ type BaseNodeConfig struct {
|
|||
// compiled with all required itest flags.
|
||||
LndBinary string
|
||||
|
||||
// backupDbDir is the path where a database backup is stored, if any.
|
||||
backupDbDir string
|
||||
// backupDBDir is the path where a database backup is stored, if any.
|
||||
backupDBDir string
|
||||
|
||||
// postgresDbName is the name of the postgres database where lnd data
|
||||
// postgresDBName is the name of the postgres database where lnd data
|
||||
// is stored in.
|
||||
postgresDbName string
|
||||
postgresDBName string
|
||||
}
|
||||
|
||||
func (cfg BaseNodeConfig) P2PAddr() string {
|
||||
|
|
@ -126,16 +169,16 @@ func (cfg BaseNodeConfig) ChanBackupPath() string {
|
|||
// current lightning network test.
|
||||
func (cfg *BaseNodeConfig) GenerateListeningPorts() {
|
||||
if cfg.P2PPort == 0 {
|
||||
cfg.P2PPort = lntest.NextAvailablePort()
|
||||
cfg.P2PPort = NextAvailablePort()
|
||||
}
|
||||
if cfg.RPCPort == 0 {
|
||||
cfg.RPCPort = lntest.NextAvailablePort()
|
||||
cfg.RPCPort = NextAvailablePort()
|
||||
}
|
||||
if cfg.RESTPort == 0 {
|
||||
cfg.RESTPort = lntest.NextAvailablePort()
|
||||
cfg.RESTPort = NextAvailablePort()
|
||||
}
|
||||
if cfg.ProfilePort == 0 {
|
||||
cfg.ProfilePort = lntest.NextAvailablePort()
|
||||
cfg.ProfilePort = NextAvailablePort()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -169,8 +212,7 @@ func (cfg *BaseNodeConfig) GenArgs() []string {
|
|||
"--accept-keysend",
|
||||
"--keep-failed-payment-attempts",
|
||||
fmt.Sprintf("--db.batch-commit-interval=%v", commitInterval),
|
||||
fmt.Sprintf("--bitcoin.defaultremotedelay=%v",
|
||||
lntest.DefaultCSV),
|
||||
fmt.Sprintf("--bitcoin.defaultremotedelay=%v", DefaultCSV),
|
||||
fmt.Sprintf("--rpclisten=%v", cfg.RPCAddr()),
|
||||
fmt.Sprintf("--restlisten=%v", cfg.RESTAddr()),
|
||||
fmt.Sprintf("--restcors=https://%v", cfg.RESTAddr()),
|
||||
|
|
@ -182,7 +224,6 @@ func (cfg *BaseNodeConfig) GenArgs() []string {
|
|||
fmt.Sprintf("--invoicemacaroonpath=%v", cfg.InvoiceMacPath),
|
||||
fmt.Sprintf("--trickledelay=%v", trickleDelay),
|
||||
fmt.Sprintf("--profile=%d", cfg.ProfilePort),
|
||||
fmt.Sprintf("--caches.rpc-graph-cache-duration=%d", 0),
|
||||
|
||||
// Use a small batch window so we can broadcast our sweep
|
||||
// transactions faster.
|
||||
|
|
@ -191,27 +232,32 @@ func (cfg *BaseNodeConfig) GenArgs() []string {
|
|||
// Use a small batch delay so we can broadcast the
|
||||
// announcements quickly in the tests.
|
||||
"--gossip.sub-batch-delay=5ms",
|
||||
|
||||
// Use a small cache duration so the `DescribeGraph` can be
|
||||
// updated quicker.
|
||||
"--caches.rpc-graph-cache-duration=100ms",
|
||||
}
|
||||
|
||||
args = append(args, nodeArgs...)
|
||||
|
||||
if cfg.Password == nil {
|
||||
args = append(args, "--noseedbackup")
|
||||
}
|
||||
|
||||
switch cfg.DbBackend {
|
||||
case lntest.BackendEtcd:
|
||||
switch cfg.DBBackend {
|
||||
case BackendEtcd:
|
||||
args = append(args, "--db.backend=etcd")
|
||||
args = append(args, "--db.etcd.embedded")
|
||||
args = append(
|
||||
args, fmt.Sprintf(
|
||||
"--db.etcd.embedded_client_port=%v",
|
||||
lntest.NextAvailablePort(),
|
||||
NextAvailablePort(),
|
||||
),
|
||||
)
|
||||
args = append(
|
||||
args, fmt.Sprintf(
|
||||
"--db.etcd.embedded_peer_port=%v",
|
||||
lntest.NextAvailablePort(),
|
||||
NextAvailablePort(),
|
||||
),
|
||||
)
|
||||
args = append(
|
||||
|
|
@ -221,14 +267,14 @@ func (cfg *BaseNodeConfig) GenArgs() []string {
|
|||
),
|
||||
)
|
||||
|
||||
case lntest.BackendPostgres:
|
||||
case BackendPostgres:
|
||||
args = append(args, "--db.backend=postgres")
|
||||
args = append(args, "--db.postgres.dsn="+cfg.PostgresDsn)
|
||||
|
||||
case lntest.BackendSqlite:
|
||||
case BackendSqlite:
|
||||
args = append(args, "--db.backend=sqlite")
|
||||
args = append(args, fmt.Sprintf("--db.sqlite.busytimeout=%v",
|
||||
lntest.SqliteBusyTimeout))
|
||||
wait.SqliteBusyTimeout))
|
||||
}
|
||||
|
||||
if cfg.FeeURL != "" {
|
||||
|
|
@ -272,3 +318,86 @@ func ExtraArgsEtcd(etcdCfg *etcd.Config, name string, cluster bool,
|
|||
|
||||
return extraArgs
|
||||
}
|
||||
|
||||
// NextAvailablePort returns the first port that is available for listening by
|
||||
// a new node. It panics if no port is found and the maximum available TCP port
|
||||
// is reached.
|
||||
func NextAvailablePort() int {
|
||||
port := atomic.AddUint32(&lastPort, 1)
|
||||
for port < 65535 {
|
||||
// If there are no errors while attempting to listen on this
|
||||
// port, close the socket and return it as available. While it
|
||||
// could be the case that some other process picks up this port
|
||||
// between the time the socket is closed and it's reopened in
|
||||
// the harness node, in practice in CI servers this seems much
|
||||
// less likely than simply some other process already being
|
||||
// bound at the start of the tests.
|
||||
addr := fmt.Sprintf(ListenerFormat, port)
|
||||
l, err := net.Listen("tcp4", addr)
|
||||
if err == nil {
|
||||
err := l.Close()
|
||||
if err == nil {
|
||||
return int(port)
|
||||
}
|
||||
}
|
||||
port = atomic.AddUint32(&lastPort, 1)
|
||||
}
|
||||
|
||||
// No ports available? Must be a mistake.
|
||||
panic("no ports available for listening")
|
||||
}
|
||||
|
||||
// GetLogDir returns the passed --logdir flag or the default value if it wasn't
|
||||
// set.
|
||||
func GetLogDir() string {
|
||||
if logSubDir != nil && *logSubDir != "" {
|
||||
return *logSubDir
|
||||
}
|
||||
|
||||
return "."
|
||||
}
|
||||
|
||||
// CopyFile copies the file src to dest.
|
||||
func CopyFile(dest, src string) error {
|
||||
s, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer s.Close()
|
||||
|
||||
d, err := os.Create(dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if _, err := io.Copy(d, s); err != nil {
|
||||
d.Close()
|
||||
return err
|
||||
}
|
||||
|
||||
return d.Close()
|
||||
}
|
||||
|
||||
// GetBtcdBinary returns the full path to the binary of the custom built btcd
|
||||
// executable or an empty string if none is set.
|
||||
func GetBtcdBinary() string {
|
||||
if btcdExecutable != nil {
|
||||
return *btcdExecutable
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
|
||||
// GenerateBtcdListenerAddresses is a function that returns two listener
|
||||
// addresses with unique ports and should be used to overwrite rpctest's
|
||||
// default generator which is prone to use colliding ports.
|
||||
func GenerateBtcdListenerAddresses() (string, string) {
|
||||
return fmt.Sprintf(ListenerFormat, NextAvailablePort()),
|
||||
fmt.Sprintf(ListenerFormat, NextAvailablePort())
|
||||
}
|
||||
|
||||
// ApplyPortOffset adds the given offset to the lastPort variable, making it
|
||||
// possible to run the tests in parallel without colliding on the same ports.
|
||||
func ApplyPortOffset(offset uint32) {
|
||||
_ = atomic.AddUint32(&lastPort, offset)
|
||||
}
|
||||
|
|
@ -18,8 +18,7 @@ import (
|
|||
|
||||
"github.com/jackc/pgx/v4/pgxpool"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"google.golang.org/grpc"
|
||||
|
|
@ -81,7 +80,7 @@ type HarnessNode struct {
|
|||
// runCtx is a context with cancel method. It's used to signal when the
|
||||
// node needs to quit, and used as the parent context when spawning
|
||||
// children contexts for RPC requests.
|
||||
runCtx context.Context
|
||||
runCtx context.Context //nolint:containedctx
|
||||
cancel context.CancelFunc
|
||||
|
||||
// filename is the log file's name.
|
||||
|
|
@ -117,9 +116,9 @@ func NewHarnessNode(t *testing.T, cfg *BaseNodeConfig) (*HarnessNode, error) {
|
|||
|
||||
// Create temporary database.
|
||||
var dbName string
|
||||
if cfg.DbBackend == lntest.BackendPostgres {
|
||||
if cfg.DBBackend == BackendPostgres {
|
||||
var err error
|
||||
dbName, err = createTempPgDb()
|
||||
dbName, err = createTempPgDB()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -127,7 +126,7 @@ func NewHarnessNode(t *testing.T, cfg *BaseNodeConfig) (*HarnessNode, error) {
|
|||
}
|
||||
|
||||
cfg.OriginalExtraArgs = cfg.ExtraArgs
|
||||
cfg.postgresDbName = dbName
|
||||
cfg.postgresDBName = dbName
|
||||
|
||||
return &HarnessNode{
|
||||
T: t,
|
||||
|
|
@ -324,7 +323,7 @@ func (hn *HarnessNode) ConnectRPCWithMacaroon(mac *macaroon.Macaroon) (
|
|||
hn.Cfg.TLSCertPath, "",
|
||||
)
|
||||
return err
|
||||
}, DefaultTimeout)
|
||||
}, wait.DefaultTimeout)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error reading TLS cert: %v", err)
|
||||
}
|
||||
|
|
@ -334,7 +333,7 @@ func (hn *HarnessNode) ConnectRPCWithMacaroon(mac *macaroon.Macaroon) (
|
|||
grpc.WithTransportCredentials(tlsCreds),
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(hn.runCtx, DefaultTimeout)
|
||||
ctx, cancel := context.WithTimeout(hn.runCtx, wait.DefaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
if mac == nil {
|
||||
|
|
@ -354,7 +353,7 @@ func (hn *HarnessNode) ConnectRPCWithMacaroon(mac *macaroon.Macaroon) (
|
|||
func (hn *HarnessNode) ConnectRPC() (*grpc.ClientConn, error) {
|
||||
// If we should use a macaroon, always take the admin macaroon as a
|
||||
// default.
|
||||
mac, err := hn.ReadMacaroon(hn.Cfg.AdminMacPath, DefaultTimeout)
|
||||
mac, err := hn.ReadMacaroon(hn.Cfg.AdminMacPath, wait.DefaultTimeout)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -375,7 +374,7 @@ func (hn *HarnessNode) StartLndCmd(ctxb context.Context) error {
|
|||
hn.runCtx, hn.cancel = context.WithCancel(ctxb)
|
||||
|
||||
args := hn.Cfg.GenArgs()
|
||||
hn.cmd = exec.Command(hn.Cfg.LndBinary, args...) //nolint:gosec
|
||||
hn.cmd = exec.Command(hn.Cfg.LndBinary, args...)
|
||||
|
||||
// Redirect stderr output to buffer
|
||||
var errb bytes.Buffer
|
||||
|
|
@ -383,7 +382,7 @@ func (hn *HarnessNode) StartLndCmd(ctxb context.Context) error {
|
|||
|
||||
// If the logoutput flag is passed, redirect output from the nodes to
|
||||
// log files.
|
||||
if *lntest.LogOutput {
|
||||
if *logOutput {
|
||||
err := addLogFile(hn)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -540,7 +539,7 @@ func (hn *HarnessNode) waitTillServerState(
|
|||
|
||||
for {
|
||||
select {
|
||||
case <-time.After(lntest.NodeStartTimeout):
|
||||
case <-time.After(wait.NodeStartTimeout):
|
||||
return fmt.Errorf("timeout waiting for server state")
|
||||
case err := <-errChan:
|
||||
return fmt.Errorf("receive server state err: %v", err)
|
||||
|
|
@ -581,7 +580,7 @@ func (hn *HarnessNode) initLightningClient() error {
|
|||
"got err: %v", err)
|
||||
}
|
||||
|
||||
case <-time.After(DefaultTimeout):
|
||||
case <-time.After(wait.DefaultTimeout):
|
||||
return fmt.Errorf("timeout creating topology client stream")
|
||||
}
|
||||
|
||||
|
|
@ -615,8 +614,8 @@ func (hn *HarnessNode) attachPubKey() error {
|
|||
|
||||
// cleanup cleans up all the temporary files created by the node's process.
|
||||
func (hn *HarnessNode) cleanup() error {
|
||||
if hn.Cfg.backupDbDir != "" {
|
||||
err := os.RemoveAll(hn.Cfg.backupDbDir)
|
||||
if hn.Cfg.backupDBDir != "" {
|
||||
err := os.RemoveAll(hn.Cfg.backupDBDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to remove backup dir: %v",
|
||||
err)
|
||||
|
|
@ -650,9 +649,10 @@ func (hn *HarnessNode) waitForProcessExit() {
|
|||
// Otherwise, we print the error, break the select and save
|
||||
// logs.
|
||||
hn.printErrf("wait process exit got err: %v", err)
|
||||
|
||||
break
|
||||
|
||||
case <-time.After(DefaultTimeout * 2):
|
||||
case <-time.After(wait.DefaultTimeout):
|
||||
hn.printErrf("timeout waiting for process to exit")
|
||||
}
|
||||
|
||||
|
|
@ -705,7 +705,7 @@ func (hn *HarnessNode) Stop() error {
|
|||
default:
|
||||
return nil
|
||||
}
|
||||
}, DefaultTimeout)
|
||||
}, wait.DefaultTimeout)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -720,7 +720,7 @@ func (hn *HarnessNode) Stop() error {
|
|||
// If the goroutines fail to finish before timeout, we'll print
|
||||
// the error to console and continue.
|
||||
select {
|
||||
case <-time.After(DefaultTimeout):
|
||||
case <-time.After(wait.DefaultTimeout):
|
||||
hn.printErrf("timeout on wait group")
|
||||
case <-done:
|
||||
}
|
||||
|
|
@ -784,23 +784,23 @@ func (hn *HarnessNode) Kill() error {
|
|||
|
||||
// printErrf prints an error to the console.
|
||||
func (hn *HarnessNode) printErrf(format string, a ...interface{}) {
|
||||
fmt.Printf("itest error from [%s:%s]: %s\n", // nolint:forbidigo
|
||||
fmt.Printf("itest error from [%s:%s]: %s\n", //nolint:forbidigo
|
||||
hn.Cfg.LogFilenamePrefix, hn.Cfg.Name,
|
||||
fmt.Sprintf(format, a...))
|
||||
}
|
||||
|
||||
// BackupDB creates a backup of the current database.
|
||||
func (hn *HarnessNode) BackupDB() error {
|
||||
if hn.Cfg.backupDbDir != "" {
|
||||
if hn.Cfg.backupDBDir != "" {
|
||||
return fmt.Errorf("backup already created")
|
||||
}
|
||||
|
||||
if hn.Cfg.postgresDbName != "" {
|
||||
if hn.Cfg.postgresDBName != "" {
|
||||
// Backup database.
|
||||
backupDBName := hn.Cfg.postgresDbName + "_backup"
|
||||
backupDBName := hn.Cfg.postgresDBName + "_backup"
|
||||
err := executePgQuery(
|
||||
"CREATE DATABASE " + backupDBName + " WITH TEMPLATE " +
|
||||
hn.Cfg.postgresDbName,
|
||||
hn.Cfg.postgresDBName,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -818,7 +818,7 @@ func (hn *HarnessNode) BackupDB() error {
|
|||
err)
|
||||
}
|
||||
|
||||
hn.Cfg.backupDbDir = tempDir
|
||||
hn.Cfg.backupDBDir = tempDir
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -826,39 +826,39 @@ func (hn *HarnessNode) BackupDB() error {
|
|||
|
||||
// RestoreDB restores a database backup.
|
||||
func (hn *HarnessNode) RestoreDB() error {
|
||||
if hn.Cfg.postgresDbName != "" {
|
||||
if hn.Cfg.postgresDBName != "" {
|
||||
// Restore database.
|
||||
backupDBName := hn.Cfg.postgresDbName + "_backup"
|
||||
backupDBName := hn.Cfg.postgresDBName + "_backup"
|
||||
err := executePgQuery(
|
||||
"DROP DATABASE " + hn.Cfg.postgresDbName,
|
||||
"DROP DATABASE " + hn.Cfg.postgresDBName,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = executePgQuery(
|
||||
"ALTER DATABASE " + backupDBName + " RENAME TO " +
|
||||
hn.Cfg.postgresDbName,
|
||||
hn.Cfg.postgresDBName,
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
// Restore files.
|
||||
if hn.Cfg.backupDbDir == "" {
|
||||
if hn.Cfg.backupDBDir == "" {
|
||||
return fmt.Errorf("no database backup created")
|
||||
}
|
||||
|
||||
err := copyAll(hn.Cfg.DBDir(), hn.Cfg.backupDbDir)
|
||||
err := copyAll(hn.Cfg.DBDir(), hn.Cfg.backupDBDir)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to copy database files: %w",
|
||||
err)
|
||||
}
|
||||
|
||||
if err := os.RemoveAll(hn.Cfg.backupDbDir); err != nil {
|
||||
if err := os.RemoveAll(hn.Cfg.backupDBDir); err != nil {
|
||||
return fmt.Errorf("unable to remove backup dir: %w",
|
||||
err)
|
||||
}
|
||||
hn.Cfg.backupDbDir = ""
|
||||
hn.Cfg.backupDBDir = ""
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
@ -868,8 +868,8 @@ func postgresDatabaseDsn(dbName string) string {
|
|||
return fmt.Sprintf(postgresDsn, dbName)
|
||||
}
|
||||
|
||||
// createTempPgDb creates a temp postgres database.
|
||||
func createTempPgDb() (string, error) {
|
||||
// createTempPgDB creates a temp postgres database.
|
||||
func createTempPgDB() (string, error) {
|
||||
// Create random database name.
|
||||
randBytes := make([]byte, 8)
|
||||
_, err := rand.Read(randBytes)
|
||||
|
|
@ -918,10 +918,8 @@ func getFinalizedLogFilePrefix(hn *HarnessNode) string {
|
|||
hn.PubKey[:logPubKeyBytes],
|
||||
)
|
||||
|
||||
return fmt.Sprintf("%s/%d-%s-%s-%s",
|
||||
lntest.GetLogDir(), hn.Cfg.NodeID,
|
||||
hn.Cfg.LogFilenamePrefix,
|
||||
hn.Cfg.Name, pubKeyHex)
|
||||
return fmt.Sprintf("%s/%d-%s-%s-%s", GetLogDir(), hn.Cfg.NodeID,
|
||||
hn.Cfg.LogFilenamePrefix, hn.Cfg.Name, pubKeyHex)
|
||||
}
|
||||
|
||||
// finalizeLogfile makes sure the log file cleanup function is initialized,
|
||||
|
|
@ -935,7 +933,7 @@ func finalizeLogfile(hn *HarnessNode) {
|
|||
hn.logFile.Close()
|
||||
|
||||
// If logoutput flag is not set, return early.
|
||||
if !*lntest.LogOutput {
|
||||
if !*logOutput {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -948,7 +946,7 @@ func finalizeLogfile(hn *HarnessNode) {
|
|||
// finalizeEtcdLog saves the etcd log files when test ends.
|
||||
func finalizeEtcdLog(hn *HarnessNode) {
|
||||
// Exit early if this is not etcd backend.
|
||||
if hn.Cfg.DbBackend != lntest.BackendEtcd {
|
||||
if hn.Cfg.DBBackend != BackendEtcd {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -964,7 +962,7 @@ func finalizeEtcdLog(hn *HarnessNode) {
|
|||
func addLogFile(hn *HarnessNode) error {
|
||||
var fileName string
|
||||
|
||||
dir := lntest.GetLogDir()
|
||||
dir := GetLogDir()
|
||||
fileName = fmt.Sprintf("%s/%d-%s-%s-%s.log", dir, hn.Cfg.NodeID,
|
||||
hn.Cfg.LogFilenamePrefix, hn.Cfg.Name,
|
||||
hex.EncodeToString(hn.PubKey[:logPubKeyBytes]))
|
||||
|
|
@ -1028,7 +1026,7 @@ func copyAll(dstDir, srcDir string) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err := lntest.CopyFile(dstPath, srcPath); err != nil {
|
||||
} else if err := CopyFile(dstPath, srcPath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||
"github.com/lightningnetwork/lnd/lnutils"
|
||||
)
|
||||
|
||||
|
|
@ -11,8 +11,7 @@ import (
|
|||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
"github.com/lightningnetwork/lnd/lntest/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||
"github.com/lightningnetwork/lnd/lnutils"
|
||||
)
|
||||
|
|
@ -31,9 +30,6 @@ const (
|
|||
// watchPolicyUpdate specifies that this is a request to watch a policy
|
||||
// update event.
|
||||
watchPolicyUpdate
|
||||
|
||||
// TODO(yy): remove once temp tests is finished.
|
||||
DefaultTimeout = lntest.DefaultTimeout
|
||||
)
|
||||
|
||||
// chanWatchRequest is a request to the lightningNetworkWatcher to be notified
|
||||
|
|
@ -123,7 +119,7 @@ func (nw *nodeWatcher) WaitForNumChannelUpdates(op wire.OutPoint,
|
|||
"want %d, got %d", expected, num)
|
||||
}
|
||||
|
||||
return wait.NoError(checkNumUpdates, DefaultTimeout)
|
||||
return wait.NoError(checkNumUpdates, wait.DefaultTimeout)
|
||||
}
|
||||
|
||||
// WaitForNumNodeUpdates will block until a given number of node updates has
|
||||
|
|
@ -142,8 +138,7 @@ func (nw *nodeWatcher) WaitForNumNodeUpdates(pubkey string,
|
|||
return fmt.Errorf("timeout waiting for num node updates, "+
|
||||
"want %d, got %d", expected, num)
|
||||
}
|
||||
|
||||
err := wait.NoError(checkNumUpdates, DefaultTimeout)
|
||||
err := wait.NoError(checkNumUpdates, wait.DefaultTimeout)
|
||||
|
||||
return updates, err
|
||||
}
|
||||
|
|
@ -161,7 +156,7 @@ func (nw *nodeWatcher) WaitForChannelOpen(chanPoint *lnrpc.ChannelPoint) error {
|
|||
chanWatchType: watchOpenChannel,
|
||||
}
|
||||
|
||||
timer := time.After(DefaultTimeout)
|
||||
timer := time.After(wait.DefaultTimeout)
|
||||
select {
|
||||
case <-eventChan:
|
||||
return nil
|
||||
|
|
@ -192,7 +187,7 @@ func (nw *nodeWatcher) WaitForChannelClose(
|
|||
chanWatchType: watchCloseChannel,
|
||||
}
|
||||
|
||||
timer := time.After(DefaultTimeout)
|
||||
timer := time.After(wait.DefaultTimeout)
|
||||
select {
|
||||
case <-eventChan:
|
||||
closedChan, ok := nw.state.closedChans.Load(op)
|
||||
|
|
@ -218,7 +213,7 @@ func (nw *nodeWatcher) WaitForChannelPolicyUpdate(
|
|||
op := nw.rpc.MakeOutpoint(chanPoint)
|
||||
|
||||
ticker := time.NewTicker(wait.PollInterval)
|
||||
timer := time.After(DefaultTimeout)
|
||||
timer := time.After(wait.DefaultTimeout)
|
||||
defer ticker.Stop()
|
||||
|
||||
eventChan := make(chan struct{})
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue