mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-06-29 10:09:08 +02:00
This commit adds a new RPC command: `channelbalance` which returns the sum of all available channel capacity across all open channels. The total balance is currently returned in units of `satoshis`. Additionally the `networkHarness` has been modified slightly to allow specifying the additional "extra" command line parameters when creating the initial seed nodes. Minor refactoring within the integration tests has been undertaken in order to increase code re-use across tests. Closes #29.
This commit is contained in:
committed by
Olaoluwa Osuntokun
parent
4c01e42670
commit
2788dbeaa8
194
lnd_test.go
194
lnd_test.go
@ -13,6 +13,7 @@ import (
|
||||
"github.com/roasbeef/btcd/wire"
|
||||
"github.com/roasbeef/btcrpcclient"
|
||||
"github.com/roasbeef/btcutil"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
)
|
||||
|
||||
type lndTestCase func(net *networkHarness, t *testing.T)
|
||||
@ -27,81 +28,134 @@ func assertTxInBlock(block *btcutil.Block, txid *wire.ShaHash, t *testing.T) {
|
||||
t.Fatalf("funding tx was not included in block")
|
||||
}
|
||||
|
||||
// testBasicChannelFunding performs a test excercising expected behavior from a
|
||||
func getChannelHelpers(ctxb context.Context, net *networkHarness, t *testing.T) (func(*lightningNode,
|
||||
*lightningNode, btcutil.Amount) *lnrpc.ChannelPoint, func(*lightningNode, *lnrpc.ChannelPoint)) {
|
||||
|
||||
openChannel := func(alice *lightningNode, bob *lightningNode, amount btcutil.Amount) *lnrpc.ChannelPoint {
|
||||
chanOpenUpdate, err := net.OpenChannel(ctxb, alice, bob, amount, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to open channel: %v", err)
|
||||
}
|
||||
|
||||
// Mine a block, then wait for Alice's node to notify us that the
|
||||
// channel has been opened. The funding transaction should be found
|
||||
// within the newly mined block.
|
||||
blockHash, err := net.Miner.Node.Generate(1)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to generate block: %v", err)
|
||||
}
|
||||
block, err := net.Miner.Node.GetBlock(blockHash[0])
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get block: %v", err)
|
||||
}
|
||||
fundingChanPoint, err := net.WaitForChannelOpen(chanOpenUpdate)
|
||||
if err != nil {
|
||||
t.Fatalf("error while waiting for channeel open: %v", err)
|
||||
}
|
||||
fundingTxID, err := wire.NewShaHash(fundingChanPoint.FundingTxid)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create sha hash: %v", err)
|
||||
}
|
||||
assertTxInBlock(block, fundingTxID, t)
|
||||
|
||||
// The channel should be listed in the peer information returned by
|
||||
// both peers.
|
||||
chanPoint := wire.OutPoint{
|
||||
Hash: *fundingTxID,
|
||||
Index: fundingChanPoint.OutputIndex,
|
||||
}
|
||||
err = net.AssertChannelExists(ctxb, alice, &chanPoint)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to assert channel existence: %v", err)
|
||||
}
|
||||
|
||||
return fundingChanPoint
|
||||
}
|
||||
|
||||
closeChannel := func(node *lightningNode, fundingChanPoint *lnrpc.ChannelPoint) {
|
||||
closeUpdates, err := net.CloseChannel(ctxb, node, fundingChanPoint, false)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to clsoe channel: %v", err)
|
||||
}
|
||||
|
||||
// Finally, generate a single block, wait for the final close status
|
||||
// update, then ensure that the closing transaction was included in the
|
||||
// block.
|
||||
blockHash, err := net.Miner.Node.Generate(1)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to generate block: %v", err)
|
||||
}
|
||||
block, err := net.Miner.Node.GetBlock(blockHash[0])
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get block: %v", err)
|
||||
}
|
||||
|
||||
closingTxid, err := net.WaitForChannelClose(closeUpdates)
|
||||
if err != nil {
|
||||
t.Fatalf("error while waiting for channel close: %v", err)
|
||||
}
|
||||
assertTxInBlock(block, closingTxid, t)
|
||||
|
||||
}
|
||||
|
||||
return openChannel, closeChannel
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
// testBasicChannelFunding performs a test exercising expected behavior from a
|
||||
// basic funding workflow. The test creates a new channel between Alice and
|
||||
// Bob, then immediately closes the channel after asserting some expected post
|
||||
// conditions. Finally, the chain itelf is checked to ensure the closing
|
||||
// conditions. Finally, the chain itself is checked to ensure the closing
|
||||
// transaction was mined.
|
||||
func testBasicChannelFunding(net *networkHarness, t *testing.T) {
|
||||
ctxb := context.Background()
|
||||
|
||||
// First establish a channel with a capacity of 0.5 BTC between Alice
|
||||
// and Bob.
|
||||
openChannel, closeChannel := getChannelHelpers(ctxb, net, t)
|
||||
chanAmt := btcutil.Amount(btcutil.SatoshiPerBitcoin / 2)
|
||||
chanOpenUpdate, err := net.OpenChannel(ctxb, net.Alice, net.Bob, chanAmt, 1)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to open channel: %v", err)
|
||||
}
|
||||
|
||||
// Mine a block, then wait for Alice's node to notify us that the
|
||||
// channel has been opened. The funding transaction should be found
|
||||
// within the newly mined block.
|
||||
blockHash, err := net.Miner.Node.Generate(1)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to generate block: %v", err)
|
||||
}
|
||||
block, err := net.Miner.Node.GetBlock(blockHash[0])
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get block: %v", err)
|
||||
}
|
||||
fundingChanPoint, err := net.WaitForChannelOpen(chanOpenUpdate)
|
||||
if err != nil {
|
||||
t.Fatalf("error while waiting for channeel open: %v", err)
|
||||
}
|
||||
fundingTxID, err := wire.NewShaHash(fundingChanPoint.FundingTxid)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create sha hash: %v", err)
|
||||
}
|
||||
assertTxInBlock(block, fundingTxID, t)
|
||||
|
||||
// The channel should be listed in the peer information returned by
|
||||
// both peers.
|
||||
chanPoint := wire.OutPoint{
|
||||
Hash: *fundingTxID,
|
||||
Index: fundingChanPoint.OutputIndex,
|
||||
}
|
||||
err = net.AssertChannelExists(ctxb, net.Alice, &chanPoint)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to assert channel existence: %v", err)
|
||||
}
|
||||
|
||||
// Initiate a close from Alice's side.
|
||||
closeUpdates, err := net.CloseChannel(ctxb, net.Alice, fundingChanPoint, false)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to clsoe channel: %v", err)
|
||||
}
|
||||
|
||||
// Finally, generate a single block, wait for the final close status
|
||||
// update, then ensure that the closing transaction was included in the
|
||||
// block.
|
||||
blockHash, err = net.Miner.Node.Generate(1)
|
||||
if err != nil {
|
||||
t.Fatalf("unable to generate block: %v", err)
|
||||
}
|
||||
block, err = net.Miner.Node.GetBlock(blockHash[0])
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get block: %v", err)
|
||||
}
|
||||
|
||||
closingTxid, err := net.WaitForChannelClose(closeUpdates)
|
||||
if err != nil {
|
||||
t.Fatalf("error while waiting for channel close: %v", err)
|
||||
}
|
||||
assertTxInBlock(block, closingTxid, t)
|
||||
chanPoint := openChannel(net.Alice, net.Bob, chanAmt)
|
||||
closeChannel(net.Alice, chanPoint)
|
||||
}
|
||||
|
||||
// testChannelForceClosure performs a test to excerise the behavior of "force"
|
||||
// closing a channel or unilterally broadcating the latest local commitment
|
||||
// testChannelBalance creates a new channel between Alice and Bob, then
|
||||
// checks channel balance to be equal amount specified while creation of channel.
|
||||
func testChannelBalance(net *networkHarness, t *testing.T) {
|
||||
ctxb := context.Background()
|
||||
|
||||
checkChannelBalance := func (node lnrpc.LightningClient, amount btcutil.Amount) {
|
||||
response, err := node.ChannelBalance(ctxb, &lnrpc.ChannelBalanceRequest{})
|
||||
if err != nil {
|
||||
t.Fatalf("unable to get channel balance: %v", err)
|
||||
}
|
||||
|
||||
balance := btcutil.Amount(response.Balance)
|
||||
if balance != amount {
|
||||
t.Fatalf("channel balance wrong: %v != %v", balance, amount)
|
||||
}
|
||||
}
|
||||
|
||||
openChannel, closeChannel := getChannelHelpers(ctxb, net, t)
|
||||
amount := btcutil.Amount(btcutil.SatoshiPerBitcoin / 2)
|
||||
|
||||
chanPoint := openChannel(net.Alice, net.Bob, amount)
|
||||
|
||||
checkChannelBalance(net.Alice, amount)
|
||||
|
||||
// Because we wait for Alice channel open notification it might happen
|
||||
// that Bob haven't added newly created channel in the list of active
|
||||
// channels, so lets wait for a second.
|
||||
time.Sleep(time.Second)
|
||||
checkChannelBalance(net.Bob, 0)
|
||||
|
||||
closeChannel(net.Alice, chanPoint)
|
||||
}
|
||||
|
||||
// testChannelForceClosure performs a test to exercise the behavior of "force"
|
||||
// closing a channel or unilaterally broadcasting the latest local commitment
|
||||
// state on-chain. The test creates a new channel between Alice and Bob, then
|
||||
// force closes the channel after some cursory assertions. Within the test, two
|
||||
// transactions should be broadcast on-chain, the commitment transaction itself
|
||||
@ -220,10 +274,12 @@ mempoolPoll:
|
||||
var lndTestCases = map[string]lndTestCase{
|
||||
"basic funding flow": testBasicChannelFunding,
|
||||
"channel force closure": testChannelForceClosure,
|
||||
"channel balance": testChannelBalance,
|
||||
}
|
||||
|
||||
|
||||
// TestLightningNetworkDaemon performs a series of integration tests amongst a
|
||||
// programatically driven network of lnd nodes.
|
||||
// programmatically driven network of lnd nodes.
|
||||
func TestLightningNetworkDaemon(t *testing.T) {
|
||||
var (
|
||||
btcdHarness *rpctest.Harness
|
||||
@ -250,7 +306,7 @@ func TestLightningNetworkDaemon(t *testing.T) {
|
||||
|
||||
// First create the network harness to gain access to its
|
||||
// 'OnTxAccepted' call back.
|
||||
lightningNetwork, err = newNetworkHarness(nil)
|
||||
lightningNetwork, err = newNetworkHarness()
|
||||
if err != nil {
|
||||
t.Fatalf("unable to create lightning network harness: %v", err)
|
||||
}
|
||||
@ -260,7 +316,7 @@ func TestLightningNetworkDaemon(t *testing.T) {
|
||||
OnTxAccepted: lightningNetwork.OnTxAccepted,
|
||||
}
|
||||
|
||||
// First create an intance of the btcd's rpctest.Harness. This will be
|
||||
// First create an instance of the btcd's rpctest.Harness. This will be
|
||||
// used to fund the wallets of the nodes within the test network and to
|
||||
// drive blockchain related events within the network.
|
||||
btcdHarness, err = rpctest.New(harnessNetParams, handlers, nil)
|
||||
@ -276,8 +332,10 @@ func TestLightningNetworkDaemon(t *testing.T) {
|
||||
}
|
||||
|
||||
// With the btcd harness created, we can now complete the
|
||||
// initialization of the network.
|
||||
if err := lightningNetwork.InitializeSeedNodes(btcdHarness); err != nil {
|
||||
// initialization of the network. args - list of lnd arguments, example: "--debuglevel=debug"
|
||||
args := []string{}
|
||||
|
||||
if err := lightningNetwork.InitializeSeedNodes(btcdHarness, args); err != nil {
|
||||
t.Fatalf("unable to initialize seed nodes: %v", err)
|
||||
}
|
||||
if err = lightningNetwork.SetUp(); err != nil {
|
||||
|
Reference in New Issue
Block a user