Merge pull request #1583 from halseth/multibackend-integration-test
[itests] Bitcoind integration test
This commit is contained in:
commit
b43a9f2e20
@ -18,6 +18,7 @@ env:
|
|||||||
- RACE=true
|
- RACE=true
|
||||||
- ITEST=true
|
- ITEST=true
|
||||||
- NEUTRINO_ITEST=true
|
- NEUTRINO_ITEST=true
|
||||||
|
- BITCOIND_ITEST=true
|
||||||
- COVER=true
|
- COVER=true
|
||||||
|
|
||||||
sudo: required
|
sudo: required
|
||||||
@ -35,6 +36,9 @@ script:
|
|||||||
# Run neutrino integration tests.
|
# Run neutrino integration tests.
|
||||||
- 'if [ "$NEUTRINO_ITEST" = true ]; then make travis-itest backend=neutrino; fi'
|
- 'if [ "$NEUTRINO_ITEST" = true ]; then make travis-itest backend=neutrino; fi'
|
||||||
|
|
||||||
|
# Run bitcoind integration tests.
|
||||||
|
- 'if [ "$BITCOIND_ITEST" = true ]; then make travis-itest backend=bitcoind; fi'
|
||||||
|
|
||||||
# Run unit tests and generate coverage report.
|
# Run unit tests and generate coverage report.
|
||||||
- 'if [ "$COVER" = true ]; then make travis-cover; fi'
|
- 'if [ "$COVER" = true ]; then make travis-cover; fi'
|
||||||
|
|
||||||
|
185
lntest/bitcoind.go
Normal file
185
lntest/bitcoind.go
Normal file
@ -0,0 +1,185 @@
|
|||||||
|
// +build bitcoind
|
||||||
|
|
||||||
|
package lntest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"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) {
|
||||||
|
|
||||||
|
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() {
|
||||||
|
bitcoind.Process.Kill()
|
||||||
|
bitcoind.Wait()
|
||||||
|
|
||||||
|
// 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 {
|
||||||
|
fmt.Printf("unable to copy file: %v\n", err)
|
||||||
|
}
|
||||||
|
if err = os.RemoveAll(logDir); err != nil {
|
||||||
|
fmt.Printf("Cannot remove dir %s: %v\n", logDir, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
os.RemoveAll(tempBitcoindDir)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
// We start by adding the miner to the bitcoind addnode list. We do
|
||||||
|
// this instead of connecting using command line flags, because it will
|
||||||
|
// allow us to disconnect the miner using the AddNode command later.
|
||||||
|
if err := client.AddNode(miner, rpcclient.ANAdd); err != nil {
|
||||||
|
cleanUp()
|
||||||
|
return nil, nil, fmt.Errorf("unable to add node: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
bd := BitcoindBackendConfig{
|
||||||
|
rpcHost: rpcHost,
|
||||||
|
rpcUser: rpcUser,
|
||||||
|
rpcPass: rpcPass,
|
||||||
|
zmqBlockPath: zmqBlockPath,
|
||||||
|
zmqTxPath: zmqTxPath,
|
||||||
|
p2pPort: p2pPort,
|
||||||
|
rpcClient: client,
|
||||||
|
minerAddr: miner,
|
||||||
|
}
|
||||||
|
|
||||||
|
return &bd, cleanUp, nil
|
||||||
|
}
|
@ -35,6 +35,10 @@ type BtcdBackendConfig struct {
|
|||||||
minerAddr string
|
minerAddr string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A compile time assertion to ensure BtcdBackendConfig meets the BackendConfig
|
||||||
|
// interface.
|
||||||
|
var _ BackendConfig = (*BtcdBackendConfig)(nil)
|
||||||
|
|
||||||
// GenArgs returns the arguments needed to be passed to LND at startup for
|
// GenArgs returns the arguments needed to be passed to LND at startup for
|
||||||
// using this node as a chain backend.
|
// using this node as a chain backend.
|
||||||
func (b BtcdBackendConfig) GenArgs() []string {
|
func (b BtcdBackendConfig) GenArgs() []string {
|
||||||
@ -67,7 +71,9 @@ func (b BtcdBackendConfig) Name() string {
|
|||||||
// NewBackend starts a new rpctest.Harness and returns a BtcdBackendConfig for
|
// NewBackend starts a new rpctest.Harness and returns a BtcdBackendConfig for
|
||||||
// that node. miner should be set to the P2P address of the miner to connect
|
// that node. miner should be set to the P2P address of the miner to connect
|
||||||
// to.
|
// to.
|
||||||
func NewBackend(miner string) (*BtcdBackendConfig, func(), error) {
|
func NewBackend(miner string, netParams *chaincfg.Params) (
|
||||||
|
*BtcdBackendConfig, func(), error) {
|
||||||
|
|
||||||
args := []string{
|
args := []string{
|
||||||
"--rejectnonstd",
|
"--rejectnonstd",
|
||||||
"--txindex",
|
"--txindex",
|
||||||
@ -76,7 +82,6 @@ func NewBackend(miner string) (*BtcdBackendConfig, func(), error) {
|
|||||||
"--logdir=" + logDir,
|
"--logdir=" + logDir,
|
||||||
"--connect=" + miner,
|
"--connect=" + miner,
|
||||||
}
|
}
|
||||||
netParams := &chaincfg.SimNetParams
|
|
||||||
chainBackend, err := rpctest.New(netParams, nil, args)
|
chainBackend, err := rpctest.New(netParams, nil, args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, fmt.Errorf("unable to create btcd node: %v", err)
|
return nil, nil, fmt.Errorf("unable to create btcd node: %v", err)
|
||||||
|
@ -45,7 +45,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
harnessNetParams = &chaincfg.SimNetParams
|
harnessNetParams = &chaincfg.RegressionNetParams
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -8853,7 +8853,6 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
//
|
//
|
||||||
const chanAmt = btcutil.Amount(1000000)
|
const chanAmt = btcutil.Amount(1000000)
|
||||||
ctxb := context.Background()
|
ctxb := context.Background()
|
||||||
timeout := time.Duration(time.Second * 5)
|
|
||||||
|
|
||||||
// Create Carol with reject htlc flag.
|
// Create Carol with reject htlc flag.
|
||||||
carol, err := net.NewNode("Carol", []string{"--rejecthtlc"})
|
carol, err := net.NewNode("Carol", []string{"--rejecthtlc"})
|
||||||
@ -8885,7 +8884,7 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Open a channel between Alice and Carol.
|
// Open a channel between Alice and Carol.
|
||||||
ctxt, _ := context.WithTimeout(ctxb, timeout)
|
ctxt, _ := context.WithTimeout(ctxb, channelOpenTimeout)
|
||||||
chanPointAlice := openChannelAndAssert(
|
chanPointAlice := openChannelAndAssert(
|
||||||
ctxt, t, net, net.Alice, carol,
|
ctxt, t, net, net.Alice, carol,
|
||||||
lntest.OpenChannelParams{
|
lntest.OpenChannelParams{
|
||||||
@ -8894,7 +8893,7 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
// Open a channel between Carol and Bob.
|
// Open a channel between Carol and Bob.
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, channelOpenTimeout)
|
||||||
chanPointCarol := openChannelAndAssert(
|
chanPointCarol := openChannelAndAssert(
|
||||||
ctxt, t, net, carol, net.Bob,
|
ctxt, t, net, carol, net.Bob,
|
||||||
lntest.OpenChannelParams{
|
lntest.OpenChannelParams{
|
||||||
@ -8934,7 +8933,7 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Alice pays Carols invoice.
|
// Alice pays Carols invoice.
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
||||||
err = completePaymentRequests(
|
err = completePaymentRequests(
|
||||||
ctxt, net.Alice, []string{resp.PaymentRequest}, true,
|
ctxt, net.Alice, []string{resp.PaymentRequest}, true,
|
||||||
)
|
)
|
||||||
@ -8959,7 +8958,7 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Carol pays Bobs invoice.
|
// Carol pays Bobs invoice.
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
||||||
err = completePaymentRequests(
|
err = completePaymentRequests(
|
||||||
ctxt, carol, []string{resp.PaymentRequest}, true,
|
ctxt, carol, []string{resp.PaymentRequest}, true,
|
||||||
)
|
)
|
||||||
@ -8987,7 +8986,7 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
// Alice attempts to pay Bobs invoice. This payment should be rejected since
|
// Alice attempts to pay Bobs invoice. This payment should be rejected since
|
||||||
// we are using Carol as an intermediary hop, Carol is running lnd with
|
// we are using Carol as an intermediary hop, Carol is running lnd with
|
||||||
// --rejecthtlc.
|
// --rejecthtlc.
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
|
||||||
err = completePaymentRequests(
|
err = completePaymentRequests(
|
||||||
ctxt, net.Alice, []string{resp.PaymentRequest}, true,
|
ctxt, net.Alice, []string{resp.PaymentRequest}, true,
|
||||||
)
|
)
|
||||||
@ -9001,9 +9000,9 @@ func testRejectHTLC(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Close all channels.
|
// Close all channels.
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout)
|
||||||
closeChannelAndAssert(ctxt, t, net, net.Alice, chanPointAlice, false)
|
closeChannelAndAssert(ctxt, t, net, net.Alice, chanPointAlice, false)
|
||||||
ctxt, _ = context.WithTimeout(ctxb, timeout)
|
ctxt, _ = context.WithTimeout(ctxb, channelCloseTimeout)
|
||||||
closeChannelAndAssert(ctxt, t, net, carol, chanPointCarol, false)
|
closeChannelAndAssert(ctxt, t, net, carol, chanPointCarol, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12760,6 +12759,10 @@ func testSendUpdateDisableChannel(net *lntest.NetworkHarness, t *harnessTest) {
|
|||||||
},
|
},
|
||||||
)
|
)
|
||||||
mineBlocks(t, net, 1, 1)
|
mineBlocks(t, net, 1, 1)
|
||||||
|
|
||||||
|
// And finally, clean up the force closed channel by mining the
|
||||||
|
// sweeping transaction.
|
||||||
|
cleanupForceClose(t, net, net.Alice, chanPointAliceCarol)
|
||||||
}
|
}
|
||||||
|
|
||||||
// testAbandonChannel abandones a channel and asserts that it is no
|
// testAbandonChannel abandones a channel and asserts that it is no
|
||||||
@ -14415,7 +14418,9 @@ func TestLightningNetworkDaemon(t *testing.T) {
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
// Start a chain backend.
|
// Start a chain backend.
|
||||||
chainBackend, cleanUp, err := lntest.NewBackend(miner.P2PAddress())
|
chainBackend, cleanUp, err := lntest.NewBackend(
|
||||||
|
miner.P2PAddress(), harnessNetParams,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ht.Fatalf("unable to start backend: %v", err)
|
ht.Fatalf("unable to start backend: %v", err)
|
||||||
}
|
}
|
||||||
@ -14454,7 +14459,7 @@ func TestLightningNetworkDaemon(t *testing.T) {
|
|||||||
|
|
||||||
// Next mine enough blocks in order for segwit and the CSV package
|
// Next mine enough blocks in order for segwit and the CSV package
|
||||||
// soft-fork to activate on SimNet.
|
// soft-fork to activate on SimNet.
|
||||||
numBlocks := chaincfg.SimNetParams.MinerConfirmationWindow * 2
|
numBlocks := harnessNetParams.MinerConfirmationWindow * 2
|
||||||
if _, err := miner.Node.Generate(numBlocks); err != nil {
|
if _, err := miner.Node.Generate(numBlocks); err != nil {
|
||||||
ht.Fatalf("unable to generate blocks: %v", err)
|
ht.Fatalf("unable to generate blocks: %v", err)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
package lntest
|
package lntest
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/btcsuite/btcd/chaincfg"
|
||||||
|
)
|
||||||
|
|
||||||
// NeutrinoBackendConfig is an implementation of the BackendConfig interface
|
// NeutrinoBackendConfig is an implementation of the BackendConfig interface
|
||||||
// backed by a neutrino node.
|
// backed by a neutrino node.
|
||||||
@ -10,6 +14,10 @@ type NeutrinoBackendConfig struct {
|
|||||||
minerAddr string
|
minerAddr string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A compile time assertion to ensure NeutrinoBackendConfig meets the
|
||||||
|
// BackendConfig interface.
|
||||||
|
var _ BackendConfig = (*NeutrinoBackendConfig)(nil)
|
||||||
|
|
||||||
// GenArgs returns the arguments needed to be passed to LND at startup for
|
// GenArgs returns the arguments needed to be passed to LND at startup for
|
||||||
// using this node as a chain backend.
|
// using this node as a chain backend.
|
||||||
func (b NeutrinoBackendConfig) GenArgs() []string {
|
func (b NeutrinoBackendConfig) GenArgs() []string {
|
||||||
@ -35,7 +43,9 @@ func (b NeutrinoBackendConfig) Name() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewBackend starts and returns a NeutrinoBackendConfig for the node.
|
// NewBackend starts and returns a NeutrinoBackendConfig for the node.
|
||||||
func NewBackend(miner string) (*NeutrinoBackendConfig, func(), error) {
|
func NewBackend(miner string, _ *chaincfg.Params) (
|
||||||
|
*NeutrinoBackendConfig, func(), error) {
|
||||||
|
|
||||||
bd := &NeutrinoBackendConfig{
|
bd := &NeutrinoBackendConfig{
|
||||||
minerAddr: miner,
|
minerAddr: miner,
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user