567fa9ed10
Previously the chainbackend connected to the miner using a permanent connection, which would retry the connection when it’s disconnected. It would leave multiple connections between the chainbackend and the miner, causing difficulties in debugging. Currently, there are two occasions when disconnection happens. One happens when running the open channel reorg test, the miner is connected/disconnected multiple times on purpose. The other happens when the chainbackend receives a MSG_WITNESS_TX type from the miner, which would be considered as an invalid type and disconnects the miner. With the latter one being fixed in btcd, the chainbackend will still be disconnected from the miner if it reaches the ban score by requesting too many notfound messages in a short time which is why the `--nobanning` flag is added.
190 lines
4.8 KiB
Go
190 lines
4.8 KiB
Go
// +build bitcoind
|
|
|
|
package lntest
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"math/rand"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"time"
|
|
|
|
"github.com/btcsuite/btcd/chaincfg"
|
|
"github.com/btcsuite/btcd/rpcclient"
|
|
)
|
|
|
|
// logDir is the name of the temporary log directory.
|
|
const logDir = "./.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
|
|
|
|
// 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 _ 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))
|
|
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)
|
|
}
|
|
|
|
// Name returns the name of the backend type.
|
|
func (b BitcoindBackendConfig) Name() string {
|
|
return "bitcoind"
|
|
}
|
|
|
|
// NewBackend starts a bitcoind node and returns a BitoindBackendConfig for
|
|
// that node.
|
|
func NewBackend(miner string, netParams *chaincfg.Params) (
|
|
*BitcoindBackendConfig, func() error, error) {
|
|
|
|
if netParams != &chaincfg.RegressionNetParams {
|
|
return nil, nil, fmt.Errorf("only regtest supported")
|
|
}
|
|
|
|
if err := os.MkdirAll(logDir, 0700); err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
logFile, err := filepath.Abs(logDir + "/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: %v", err)
|
|
}
|
|
|
|
zmqBlockPath := "ipc:///" + tempBitcoindDir + "/blocks.socket"
|
|
zmqTxPath := "ipc:///" + tempBitcoindDir + "/txs.socket"
|
|
rpcPort := rand.Int()%(65536-1024) + 1024
|
|
p2pPort := rand.Int()%(65536-1024) + 1024
|
|
|
|
bitcoind := exec.Command(
|
|
"bitcoind",
|
|
"-datadir="+tempBitcoindDir,
|
|
"-debug",
|
|
"-regtest",
|
|
"-txindex",
|
|
"-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),
|
|
"-disablewallet",
|
|
"-zmqpubrawblock="+zmqBlockPath,
|
|
"-zmqpubrawtx="+zmqTxPath,
|
|
"-debuglogfile="+logFile,
|
|
)
|
|
|
|
err = bitcoind.Start()
|
|
if err != nil {
|
|
os.RemoveAll(tempBitcoindDir)
|
|
return nil, nil, fmt.Errorf("couldn't start bitcoind: %v", 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.
|
|
err := CopyFile("./output_bitcoind_chainbackend.log", logFile)
|
|
if err != nil {
|
|
errStr += fmt.Sprintf("unable to copy file: %v\n", err)
|
|
}
|
|
if err = os.RemoveAll(logDir); err != nil {
|
|
errStr += fmt.Sprintf(
|
|
"cannot remove dir %s: %v\n", logDir, 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: zmqBlockPath,
|
|
zmqTxPath: zmqTxPath,
|
|
p2pPort: p2pPort,
|
|
rpcClient: client,
|
|
minerAddr: miner,
|
|
}
|
|
|
|
return &bd, cleanUp, nil
|
|
}
|