mirror of
https://github.com/lightningnetwork/lnd.git
synced 2024-11-19 18:10:34 +01:00
9cd7285439
With this commit we create a new function that returns system wide unique ports by using a single file to keep track of previously used ports. We'll want to use this everywhere whenever we need to listen on a new, random port during unit or integration tests. Because we now have a unique source, we don't need to apply the port offset that was used for the different tranches of parallel running integration tests before.
213 lines
5.8 KiB
Go
213 lines
5.8 KiB
Go
//go:build bitcoind
|
|
// +build bitcoind
|
|
|
|
package lntest
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/chaincfg"
|
|
"github.com/btcsuite/btcd/rpcclient"
|
|
"github.com/lightningnetwork/lnd/lntest/node"
|
|
"github.com/lightningnetwork/lnd/lntest/port"
|
|
)
|
|
|
|
// logDirPattern is the pattern of the name of the temporary log directory.
|
|
const logDirPattern = "%s/.backendlogs"
|
|
|
|
// BitcoindBackendConfig is an implementation of the BackendConfig interface
|
|
// backed by a Bitcoind node.
|
|
type BitcoindBackendConfig struct {
|
|
rpcHost string
|
|
rpcUser string
|
|
rpcPass string
|
|
zmqBlockPath string
|
|
zmqTxPath string
|
|
p2pPort int
|
|
rpcClient *rpcclient.Client
|
|
rpcPolling bool
|
|
|
|
// minerAddr is the p2p address of the miner to connect to.
|
|
minerAddr string
|
|
}
|
|
|
|
// A compile time assertion to ensure BitcoindBackendConfig meets the
|
|
// BackendConfig interface.
|
|
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.
|
|
func (b BitcoindBackendConfig) GenArgs() []string {
|
|
var args []string
|
|
args = append(args, "--bitcoin.node=bitcoind")
|
|
args = append(args, fmt.Sprintf("--bitcoind.rpchost=%v", b.rpcHost))
|
|
args = append(args, fmt.Sprintf("--bitcoind.rpcuser=%v", b.rpcUser))
|
|
args = append(args, fmt.Sprintf("--bitcoind.rpcpass=%v", b.rpcPass))
|
|
|
|
if b.rpcPolling {
|
|
args = append(args, fmt.Sprintf("--bitcoind.rpcpolling"))
|
|
args = append(args,
|
|
fmt.Sprintf("--bitcoind.blockpollinginterval=10ms"))
|
|
args = append(args,
|
|
fmt.Sprintf("--bitcoind.txpollinginterval=10ms"))
|
|
} else {
|
|
args = append(args, fmt.Sprintf("--bitcoind.zmqpubrawblock=%v",
|
|
b.zmqBlockPath))
|
|
args = append(args, fmt.Sprintf("--bitcoind.zmqpubrawtx=%v",
|
|
b.zmqTxPath))
|
|
}
|
|
|
|
return args
|
|
}
|
|
|
|
// ConnectMiner is called to establish a connection to the test miner.
|
|
func (b BitcoindBackendConfig) ConnectMiner() error {
|
|
return b.rpcClient.AddNode(b.minerAddr, rpcclient.ANAdd)
|
|
}
|
|
|
|
// DisconnectMiner is called to disconnect the miner.
|
|
func (b BitcoindBackendConfig) DisconnectMiner() error {
|
|
return b.rpcClient.AddNode(b.minerAddr, rpcclient.ANRemove)
|
|
}
|
|
|
|
// Credentials returns the rpc username, password and host for the backend.
|
|
func (b BitcoindBackendConfig) Credentials() (string, string, string, error) {
|
|
return b.rpcUser, b.rpcPass, b.rpcHost, nil
|
|
}
|
|
|
|
// Name returns the name of the backend type.
|
|
func (b BitcoindBackendConfig) Name() string {
|
|
return "bitcoind"
|
|
}
|
|
|
|
// newBackend starts a bitcoind node with the given extra parameters and returns
|
|
// a BitcoindBackendConfig for that node.
|
|
func newBackend(miner string, netParams *chaincfg.Params, extraArgs []string,
|
|
rpcPolling bool) (*BitcoindBackendConfig, func() error, error) {
|
|
|
|
baseLogDir := fmt.Sprintf(logDirPattern, node.GetLogDir())
|
|
if netParams != &chaincfg.RegressionNetParams {
|
|
return nil, nil, fmt.Errorf("only regtest supported")
|
|
}
|
|
|
|
if err := os.MkdirAll(baseLogDir, 0700); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
logFile, err := filepath.Abs(baseLogDir + "/bitcoind.log")
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
tempBitcoindDir, err := ioutil.TempDir("", "bitcoind")
|
|
if err != nil {
|
|
return nil, nil,
|
|
fmt.Errorf("unable to create temp directory: %w", err)
|
|
}
|
|
|
|
zmqBlockAddr := fmt.Sprintf("tcp://127.0.0.1:%d",
|
|
port.NextAvailablePort())
|
|
zmqTxAddr := fmt.Sprintf("tcp://127.0.0.1:%d", port.NextAvailablePort())
|
|
rpcPort := port.NextAvailablePort()
|
|
p2pPort := port.NextAvailablePort()
|
|
|
|
cmdArgs := []string{
|
|
"-datadir=" + tempBitcoindDir,
|
|
"-whitelist=127.0.0.1", // whitelist localhost to speed up relay
|
|
"-rpcauth=weks:469e9bb14ab2360f8e226efed5ca6f" +
|
|
"d$507c670e800a95284294edb5773b05544b" +
|
|
"220110063096c221be9933c82d38e1",
|
|
fmt.Sprintf("-rpcport=%d", rpcPort),
|
|
fmt.Sprintf("-port=%d", p2pPort),
|
|
"-zmqpubrawblock=" + zmqBlockAddr,
|
|
"-zmqpubrawtx=" + zmqTxAddr,
|
|
"-debuglogfile=" + logFile,
|
|
}
|
|
cmdArgs = append(cmdArgs, extraArgs...)
|
|
bitcoind := exec.Command("bitcoind", cmdArgs...)
|
|
|
|
err = bitcoind.Start()
|
|
if err != nil {
|
|
if err := os.RemoveAll(tempBitcoindDir); err != nil {
|
|
fmt.Printf("unable to remote temp dir %v: %v",
|
|
tempBitcoindDir, err)
|
|
}
|
|
return nil, nil, fmt.Errorf("couldn't start bitcoind: %w", err)
|
|
}
|
|
|
|
cleanUp := func() error {
|
|
_ = bitcoind.Process.Kill()
|
|
_ = bitcoind.Wait()
|
|
|
|
var errStr 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", node.GetLogDir(),
|
|
)
|
|
err := node.CopyFile(logDestination, logFile)
|
|
if err != nil {
|
|
errStr += fmt.Sprintf("unable to copy file: %v\n", err)
|
|
}
|
|
if err = os.RemoveAll(baseLogDir); err != nil {
|
|
errStr += fmt.Sprintf(
|
|
"cannot remove dir %s: %v\n", baseLogDir, err,
|
|
)
|
|
}
|
|
if err := os.RemoveAll(tempBitcoindDir); err != nil {
|
|
errStr += fmt.Sprintf(
|
|
"cannot remove dir %s: %v\n",
|
|
tempBitcoindDir, err,
|
|
)
|
|
}
|
|
if errStr != "" {
|
|
return errors.New(errStr)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Allow process to start.
|
|
time.Sleep(1 * time.Second)
|
|
|
|
rpcHost := fmt.Sprintf("127.0.0.1:%d", rpcPort)
|
|
rpcUser := "weks"
|
|
rpcPass := "weks"
|
|
|
|
rpcCfg := rpcclient.ConnConfig{
|
|
Host: rpcHost,
|
|
User: rpcUser,
|
|
Pass: rpcPass,
|
|
DisableConnectOnNew: true,
|
|
DisableAutoReconnect: false,
|
|
DisableTLS: true,
|
|
HTTPPostMode: true,
|
|
}
|
|
|
|
client, err := rpcclient.New(&rpcCfg, nil)
|
|
if err != nil {
|
|
_ = cleanUp()
|
|
return nil, nil, fmt.Errorf("unable to create rpc client: %v",
|
|
err)
|
|
}
|
|
|
|
bd := BitcoindBackendConfig{
|
|
rpcHost: rpcHost,
|
|
rpcUser: rpcUser,
|
|
rpcPass: rpcPass,
|
|
zmqBlockPath: zmqBlockAddr,
|
|
zmqTxPath: zmqTxAddr,
|
|
p2pPort: p2pPort,
|
|
rpcClient: client,
|
|
minerAddr: miner,
|
|
rpcPolling: rpcPolling,
|
|
}
|
|
|
|
return &bd, cleanUp, nil
|
|
}
|