mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-07-01 11:00:51 +02:00
multi: add bitcoind drivers and tests
This commit is contained in:
@ -5,7 +5,9 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"testing"
|
||||
@ -13,6 +15,7 @@ import (
|
||||
|
||||
"github.com/lightninglabs/neutrino"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/ltcsuite/ltcd/btcjson"
|
||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||
"github.com/roasbeef/btcwallet/walletdb"
|
||||
|
||||
@ -24,6 +27,10 @@ import (
|
||||
"github.com/roasbeef/btcd/wire"
|
||||
"github.com/roasbeef/btcutil"
|
||||
|
||||
// Required to auto-register the bitcoind backed ChainNotifier
|
||||
// implementation.
|
||||
_ "github.com/lightningnetwork/lnd/chainntnfs/bitcoindnotify"
|
||||
|
||||
// Required to auto-register the btcd backed ChainNotifier
|
||||
// implementation.
|
||||
_ "github.com/lightningnetwork/lnd/chainntnfs/btcdnotify"
|
||||
@ -32,7 +39,8 @@ import (
|
||||
// implementation.
|
||||
_ "github.com/lightningnetwork/lnd/chainntnfs/neutrinonotify"
|
||||
|
||||
_ "github.com/roasbeef/btcwallet/walletdb/bdb" // Required to register the boltdb walletdb implementation.
|
||||
// Required to register the boltdb walletdb implementation.
|
||||
_ "github.com/roasbeef/btcwallet/walletdb/bdb"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -43,7 +51,7 @@ var (
|
||||
0x1e, 0xb, 0x4c, 0xfd, 0x9e, 0xc5, 0x8c, 0xe9,
|
||||
}
|
||||
|
||||
netParams = &chaincfg.SimNetParams
|
||||
netParams = &chaincfg.RegressionNetParams
|
||||
privKey, pubKey = btcec.PrivKeyFromBytes(btcec.S256(), testPrivKey)
|
||||
addrPk, _ = btcutil.NewAddressPubKey(pubKey.SerializeCompressed(),
|
||||
netParams)
|
||||
@ -65,6 +73,39 @@ func getTestTxId(miner *rpctest.Harness) (*chainhash.Hash, error) {
|
||||
return miner.SendOutputs(outputs, 10)
|
||||
}
|
||||
|
||||
func waitForMempoolTx(r *rpctest.Harness, txid *chainhash.Hash) error {
|
||||
var found bool
|
||||
var tx *btcutil.Tx
|
||||
var err error
|
||||
timeout := time.After(10 * time.Second)
|
||||
for !found {
|
||||
// Do a short wait
|
||||
select {
|
||||
case <-timeout:
|
||||
return fmt.Errorf("timeout after 10s")
|
||||
default:
|
||||
}
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
// Check for the harness' knowledge of the txid
|
||||
tx, err = r.Node.GetRawTransaction(txid)
|
||||
if err != nil {
|
||||
switch e := err.(type) {
|
||||
case *btcjson.RPCError:
|
||||
if e.Code == btcjson.ErrRPCNoTxInfo {
|
||||
continue
|
||||
}
|
||||
default:
|
||||
}
|
||||
return err
|
||||
}
|
||||
if tx != nil && tx.MsgTx().TxHash() == *txid {
|
||||
found = true
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func testSingleConfirmationNotification(miner *rpctest.Harness,
|
||||
notifier chainntnfs.ChainNotifier, t *testing.T) {
|
||||
|
||||
@ -80,6 +121,11 @@ func testSingleConfirmationNotification(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to create test tx: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, txid)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
_, currentHeight, err := miner.Node.GetBestBlock()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get current height: %v", err)
|
||||
@ -143,6 +189,11 @@ func testMultiConfirmationNotification(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to create test addr: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, txid)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
_, currentHeight, err := miner.Node.GetBestBlock()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get current height: %v", err)
|
||||
@ -201,6 +252,11 @@ func testBatchConfirmationNotification(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to register ntfn: %v", err)
|
||||
}
|
||||
confIntents[i] = confIntent
|
||||
err = waitForMempoolTx(miner, txid)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
initialConfHeight := uint32(currentHeight + 1)
|
||||
@ -252,6 +308,11 @@ func createSpendableOutput(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to create test addr: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, txid)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
// Mine a single block which should include that txid above.
|
||||
if _, err := miner.Node.Generate(1); err != nil {
|
||||
t.Fatalf("unable to generate single block: %v", err)
|
||||
@ -342,6 +403,11 @@ func testSpendNotification(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to broadcast tx: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, spenderSha)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
// Now we mine a single block, which should include our spend. The
|
||||
// notification should also be sent off.
|
||||
if _, err := miner.Node.Generate(1); err != nil {
|
||||
@ -453,6 +519,11 @@ func testMultiClientConfirmationNotification(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to create test tx: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, txid)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
var wg sync.WaitGroup
|
||||
const (
|
||||
numConfsClients = 5
|
||||
@ -514,6 +585,11 @@ func testTxConfirmedBeforeNtfnRegistration(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to create test tx: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, txid3)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
// Generate another block containing tx 3, but we won't register conf
|
||||
// notifications for this tx until much later. The notifier must check
|
||||
// older blocks when the confirmation event is registered below to ensure
|
||||
@ -529,11 +605,21 @@ func testTxConfirmedBeforeNtfnRegistration(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to create test tx: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, txid1)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
txid2, err := getTestTxId(miner)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create test tx: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, txid2)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
_, currentHeight, err := miner.Node.GetBestBlock()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get current height: %v", err)
|
||||
@ -654,6 +740,11 @@ func testLazyNtfnConsumer(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to create test tx: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, txid)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
_, currentHeight, err := miner.Node.GetBestBlock()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get current height: %v", err)
|
||||
@ -686,6 +777,11 @@ func testLazyNtfnConsumer(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to create test tx: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, txid)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
_, currentHeight, err = miner.Node.GetBestBlock()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get current height: %v", err)
|
||||
@ -736,6 +832,11 @@ func testSpendBeforeNtfnRegistration(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to create test addr: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, txid)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
// Mine a single block which should include that txid above.
|
||||
if _, err := miner.Node.Generate(1); err != nil {
|
||||
t.Fatalf("unable to generate single block: %v", err)
|
||||
@ -789,6 +890,11 @@ func testSpendBeforeNtfnRegistration(miner *rpctest.Harness,
|
||||
t.Fatalf("unable to brodacst tx: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, spenderSha)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
// Now we mine an additional block, which should include our spend.
|
||||
if _, err := miner.Node.Generate(1); err != nil {
|
||||
t.Fatalf("unable to generate single block: %v", err)
|
||||
@ -877,6 +983,11 @@ func testCancelSpendNtfn(node *rpctest.Harness,
|
||||
t.Fatalf("unable to brodacst tx: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(node, spenderSha)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
// Now we mine a single block, which should include our spend. The
|
||||
// notification should also be sent off.
|
||||
if _, err := node.Node.Generate(1); err != nil {
|
||||
@ -1021,6 +1132,11 @@ func testReorgConf(miner *rpctest.Harness, notifier chainntnfs.ChainNotifier,
|
||||
t.Fatalf("unable to create test tx: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, txid)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
_, currentHeight, err := miner.Node.GetBestBlock()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get current height: %v", err)
|
||||
@ -1094,11 +1210,16 @@ func testReorgConf(miner *rpctest.Harness, notifier chainntnfs.ChainNotifier,
|
||||
t.Fatalf("unable to get raw tx: %v", err)
|
||||
}
|
||||
|
||||
_, err = miner2.Node.SendRawTransaction(tx.MsgTx(), false)
|
||||
txid, err = miner2.Node.SendRawTransaction(tx.MsgTx(), false)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get send tx: %v", err)
|
||||
}
|
||||
|
||||
err = waitForMempoolTx(miner, txid)
|
||||
if err != nil {
|
||||
t.Fatalf("tx not relayed to miner: %v", err)
|
||||
}
|
||||
|
||||
_, err = miner.Node.Generate(3)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to generate single block: %v", err)
|
||||
@ -1206,12 +1327,73 @@ func TestInterfaces(t *testing.T) {
|
||||
|
||||
switch notifierType {
|
||||
|
||||
case "bitcoind":
|
||||
// Start a bitcoind instance.
|
||||
tempBitcoindDir, err := ioutil.TempDir("", "bitcoind")
|
||||
if err != nil {
|
||||
t.Fatalf("Unable to create temp dir: %v", err)
|
||||
}
|
||||
zmqPath := "ipc:///" + tempBitcoindDir + "/weks.socket"
|
||||
cleanUp1 := func() {
|
||||
os.RemoveAll(tempBitcoindDir)
|
||||
}
|
||||
cleanUp = cleanUp1
|
||||
rpcPort := rand.Int()%(65536-1024) + 1024
|
||||
bitcoind := exec.Command(
|
||||
"bitcoind",
|
||||
"-datadir="+tempBitcoindDir,
|
||||
"-regtest",
|
||||
"-connect="+p2pAddr,
|
||||
"-txindex",
|
||||
"-rpcauth=weks:469e9bb14ab2360f8e226efed5ca6f"+
|
||||
"d$507c670e800a95284294edb5773b05544b"+
|
||||
"220110063096c221be9933c82d38e1",
|
||||
fmt.Sprintf("-rpcport=%d", rpcPort),
|
||||
"-disablewallet",
|
||||
"-zmqpubrawblock="+zmqPath,
|
||||
"-zmqpubrawtx="+zmqPath,
|
||||
)
|
||||
err = bitcoind.Start()
|
||||
if err != nil {
|
||||
cleanUp1()
|
||||
t.Fatalf("Couldn't start bitcoind: %v", err)
|
||||
}
|
||||
cleanUp2 := func() {
|
||||
bitcoind.Process.Kill()
|
||||
bitcoind.Wait()
|
||||
cleanUp1()
|
||||
}
|
||||
cleanUp = cleanUp2
|
||||
|
||||
// Wait for the bitcoind instance to start up.
|
||||
time.Sleep(time.Second)
|
||||
|
||||
// Start the FilteredChainView implementation instance.
|
||||
config := rpcclient.ConnConfig{
|
||||
Host: fmt.Sprintf(
|
||||
"127.0.0.1:%d", rpcPort),
|
||||
User: "weks",
|
||||
Pass: "weks",
|
||||
DisableAutoReconnect: false,
|
||||
DisableConnectOnNew: true,
|
||||
DisableTLS: true,
|
||||
HTTPPostMode: true,
|
||||
}
|
||||
|
||||
notifier, err = notifierDriver.New(&config, zmqPath,
|
||||
*netParams)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create %v notifier: %v",
|
||||
notifierType, err)
|
||||
}
|
||||
|
||||
case "btcd":
|
||||
notifier, err = notifierDriver.New(&rpcConfig)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create %v notifier: %v",
|
||||
notifierType, err)
|
||||
}
|
||||
cleanUp = func() {}
|
||||
|
||||
case "neutrino":
|
||||
spvDir, err := ioutil.TempDir("", "neutrino")
|
||||
|
Reference in New Issue
Block a user