lntemp+itest: refactor testBasicChannelCreationAndUpdates
We also temporarily comment out the `testRemoteSigner` test and will bring it back when its sub tests are refacted.
This commit is contained in:
7 files changed
+346
-329
No files matched your search
@@ -1911,3 +1911,36 @@ func (h *HarnessTest) ReceiveHtlcInterceptor(
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReceiveChannelEvent waits until a message is received from the
|
||||||
|
// ChannelEventsClient stream or the timeout is reached.
|
||||||
|
func (h *HarnessTest) ReceiveChannelEvent(
|
||||||
|
stream rpc.ChannelEventsClient) *lnrpc.ChannelEventUpdate {
|
||||||
|
|
||||||
|
chanMsg := make(chan *lnrpc.ChannelEventUpdate)
|
||||||
|
errChan := make(chan error)
|
||||||
|
go func() {
|
||||||
|
// Consume one message. This will block until the message is
|
||||||
|
// received.
|
||||||
|
resp, err := stream.Recv()
|
||||||
|
if err != nil {
|
||||||
|
errChan <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
chanMsg <- resp
|
||||||
|
}()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-time.After(DefaultTimeout):
|
||||||
|
require.Fail(h, "timeout", "timeout intercepting htlc")
|
||||||
|
|
||||||
|
case err := <-errChan:
|
||||||
|
require.Failf(h, "err from stream",
|
||||||
|
"received err from stream: %v", err)
|
||||||
|
|
||||||
|
case updateMsg := <-chanMsg:
|
||||||
|
return updateMsg
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -631,3 +631,20 @@ func (h *HarnessRPC) RegisterRPCMiddleware() (MiddlewareClient,
|
|||||||
|
|
||||||
return stream, cancel
|
return stream, cancel
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ChannelEventsClient lnrpc.Lightning_SubscribeChannelEventsClient
|
||||||
|
|
||||||
|
// SubscribeChannelEvents creates a subscription client for channel events and
|
||||||
|
// asserts its creation.
|
||||||
|
func (h *HarnessRPC) SubscribeChannelEvents() ChannelEventsClient {
|
||||||
|
req := &lnrpc.ChannelEventSubscription{}
|
||||||
|
|
||||||
|
// SubscribeChannelEvents needs to have the context alive for the
|
||||||
|
// entire test case as the returned client will be used for send and
|
||||||
|
// receive events stream. Thus we use runCtx here instead of a timeout
|
||||||
|
// context.
|
||||||
|
client, err := h.LN.SubscribeChannelEvents(h.runCtx, req)
|
||||||
|
h.NoError(err, "SubscribeChannelEvents")
|
||||||
|
|
||||||
|
return client
|
||||||
|
}
|
||||||
@@ -949,60 +949,6 @@ func assertNumPendingChannels(t *harnessTest, node *lntest.HarnessNode,
|
|||||||
require.NoErrorf(t.t, err, "got err: %v", predErr)
|
require.NoErrorf(t.t, err, "got err: %v", predErr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// verifyCloseUpdate is used to verify that a closed channel update is of the
|
|
||||||
// expected type.
|
|
||||||
func verifyCloseUpdate(chanUpdate *lnrpc.ChannelEventUpdate,
|
|
||||||
closeType lnrpc.ChannelCloseSummary_ClosureType,
|
|
||||||
closeInitiator lnrpc.Initiator) error {
|
|
||||||
|
|
||||||
// We should receive one inactive and one closed notification
|
|
||||||
// for each channel.
|
|
||||||
switch update := chanUpdate.Channel.(type) {
|
|
||||||
case *lnrpc.ChannelEventUpdate_InactiveChannel:
|
|
||||||
if chanUpdate.Type != lnrpc.ChannelEventUpdate_INACTIVE_CHANNEL {
|
|
||||||
return fmt.Errorf("update type mismatch: expected %v, got %v",
|
|
||||||
lnrpc.ChannelEventUpdate_INACTIVE_CHANNEL,
|
|
||||||
chanUpdate.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
case *lnrpc.ChannelEventUpdate_ClosedChannel:
|
|
||||||
if chanUpdate.Type !=
|
|
||||||
lnrpc.ChannelEventUpdate_CLOSED_CHANNEL {
|
|
||||||
|
|
||||||
return fmt.Errorf("update type mismatch: expected %v, got %v",
|
|
||||||
lnrpc.ChannelEventUpdate_CLOSED_CHANNEL,
|
|
||||||
chanUpdate.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
if update.ClosedChannel.CloseType != closeType {
|
|
||||||
return fmt.Errorf("channel closure type "+
|
|
||||||
"mismatch: expected %v, got %v",
|
|
||||||
closeType,
|
|
||||||
update.ClosedChannel.CloseType)
|
|
||||||
}
|
|
||||||
|
|
||||||
if update.ClosedChannel.CloseInitiator != closeInitiator {
|
|
||||||
return fmt.Errorf("expected close intiator: %v, got: %v",
|
|
||||||
closeInitiator,
|
|
||||||
update.ClosedChannel.CloseInitiator)
|
|
||||||
}
|
|
||||||
|
|
||||||
case *lnrpc.ChannelEventUpdate_FullyResolvedChannel:
|
|
||||||
if chanUpdate.Type != lnrpc.ChannelEventUpdate_FULLY_RESOLVED_CHANNEL {
|
|
||||||
return fmt.Errorf("update type mismatch: expected %v, got %v",
|
|
||||||
lnrpc.ChannelEventUpdate_FULLY_RESOLVED_CHANNEL,
|
|
||||||
chanUpdate.Type)
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("channel update channel of wrong type, "+
|
|
||||||
"expected closed channel, got %T",
|
|
||||||
update)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// assertNodeNumChannels polls the provided node's list channels rpc until it
|
// assertNodeNumChannels polls the provided node's list channels rpc until it
|
||||||
// reaches the desired number of total channels.
|
// reaches the desired number of total channels.
|
||||||
func assertNodeNumChannels(t *harnessTest, node *lntest.HarnessNode,
|
func assertNodeNumChannels(t *harnessTest, node *lntest.HarnessNode,
|
||||||
|
|||||||
@@ -437,4 +437,8 @@ var allTestCasesTemp = []*lntemp.TestCase{
|
|||||||
Name: "nonstd sweep",
|
Name: "nonstd sweep",
|
||||||
TestFunc: testNonstdSweep,
|
TestFunc: testNonstdSweep,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Name: "multiple channel creation and update subscription",
|
||||||
|
TestFunc: testBasicChannelCreationAndUpdates,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,7 @@
|
|||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcjson"
|
"github.com/btcsuite/btcd/btcjson"
|
||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
@@ -12,6 +10,8 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/funding"
|
"github.com/lightningnetwork/lnd/funding"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntemp"
|
"github.com/lightningnetwork/lnd/lntemp"
|
||||||
|
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||||
|
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
@@ -308,40 +308,33 @@ func testOpenChannelUpdateFeePolicy(net *lntest.NetworkHarness,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// testBasicChannelCreationAndUpdates tests multiple channel opening and
|
// testBasicChannelCreationAndUpdates tests multiple channel opening and
|
||||||
// closing, and ensures that if a node is subscribed to channel updates
|
// closing, and ensures that if a node is subscribed to channel updates they
|
||||||
// they will be received correctly for both cooperative and force closed
|
// will be received correctly for both cooperative and force closed channels.
|
||||||
// channels.
|
func testBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest) {
|
||||||
func testBasicChannelCreationAndUpdates(net *lntest.NetworkHarness,
|
runBasicChannelCreationAndUpdates(ht, ht.Alice, ht.Bob)
|
||||||
t *harnessTest) {
|
|
||||||
|
|
||||||
runBasicChannelCreationAndUpdates(net, t, net.Alice, net.Bob)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// runBasicChannelCreationAndUpdates tests multiple channel opening and closing,
|
// runBasicChannelCreationAndUpdates tests multiple channel opening and closing,
|
||||||
// and ensures that if a node is subscribed to channel updates they will be
|
// and ensures that if a node is subscribed to channel updates they will be
|
||||||
// received correctly for both cooperative and force closed channels.
|
// received correctly for both cooperative and force closed channels.
|
||||||
func runBasicChannelCreationAndUpdates(net *lntest.NetworkHarness,
|
func runBasicChannelCreationAndUpdates(ht *lntemp.HarnessTest,
|
||||||
t *harnessTest, alice, bob *lntest.HarnessNode) {
|
alice, bob *node.HarnessNode) {
|
||||||
|
|
||||||
ctxb := context.Background()
|
|
||||||
const (
|
const (
|
||||||
numChannels = 2
|
numChannels = 2
|
||||||
amount = funding.MaxBtcFundingAmount
|
amount = funding.MaxBtcFundingAmount
|
||||||
)
|
)
|
||||||
|
|
||||||
// Subscribe Bob and Alice to channel event notifications.
|
// Subscribe Bob and Alice to channel event notifications.
|
||||||
bobChanSub := subscribeChannelNotifications(ctxb, t, bob)
|
bobChanSub := bob.RPC.SubscribeChannelEvents()
|
||||||
defer close(bobChanSub.quit)
|
aliceChanSub := alice.RPC.SubscribeChannelEvents()
|
||||||
|
|
||||||
aliceChanSub := subscribeChannelNotifications(ctxb, t, alice)
|
|
||||||
defer close(aliceChanSub.quit)
|
|
||||||
|
|
||||||
// Open the channels between Alice and Bob, asserting that the channels
|
// Open the channels between Alice and Bob, asserting that the channels
|
||||||
// have been properly opened on-chain.
|
// have been properly opened on-chain.
|
||||||
chanPoints := make([]*lnrpc.ChannelPoint, numChannels)
|
chanPoints := make([]*lnrpc.ChannelPoint, numChannels)
|
||||||
for i := 0; i < numChannels; i++ {
|
for i := 0; i < numChannels; i++ {
|
||||||
chanPoints[i] = openChannelAndAssert(
|
chanPoints[i] = ht.OpenChannel(
|
||||||
t, net, alice, bob, lntest.OpenChannelParams{
|
alice, bob, lntemp.OpenChannelParams{
|
||||||
Amt: amount,
|
Amt: amount,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@@ -350,112 +343,91 @@ func runBasicChannelCreationAndUpdates(net *lntest.NetworkHarness,
|
|||||||
// Since each of the channels just became open, Bob and Alice should
|
// Since each of the channels just became open, Bob and Alice should
|
||||||
// each receive an open and an active notification for each channel.
|
// each receive an open and an active notification for each channel.
|
||||||
const numExpectedOpenUpdates = 3 * numChannels
|
const numExpectedOpenUpdates = 3 * numChannels
|
||||||
verifyOpenUpdatesReceived := func(sub channelSubscription) error {
|
verifyOpenUpdatesReceived := func(sub rpc.ChannelEventsClient) error {
|
||||||
numChannelUpds := 0
|
for i := 0; i < numExpectedOpenUpdates; i++ {
|
||||||
for numChannelUpds < numExpectedOpenUpdates {
|
update := ht.ReceiveChannelEvent(sub)
|
||||||
select {
|
|
||||||
case update := <-sub.updateChan:
|
|
||||||
switch update.Type {
|
|
||||||
case lnrpc.ChannelEventUpdate_PENDING_OPEN_CHANNEL:
|
|
||||||
if numChannelUpds%3 != 0 {
|
|
||||||
return fmt.Errorf("expected " +
|
|
||||||
"open or active" +
|
|
||||||
"channel ntfn, got pending open " +
|
|
||||||
"channel ntfn instead")
|
|
||||||
}
|
|
||||||
case lnrpc.ChannelEventUpdate_OPEN_CHANNEL:
|
|
||||||
if numChannelUpds%3 != 1 {
|
|
||||||
return fmt.Errorf("expected " +
|
|
||||||
"pending open or active" +
|
|
||||||
"channel ntfn, got open" +
|
|
||||||
"channel ntfn instead")
|
|
||||||
}
|
|
||||||
case lnrpc.ChannelEventUpdate_ACTIVE_CHANNEL:
|
|
||||||
if numChannelUpds%3 != 2 {
|
|
||||||
return fmt.Errorf("expected " +
|
|
||||||
"pending open or open" +
|
|
||||||
"channel ntfn, got active " +
|
|
||||||
"channel ntfn instead")
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("update type mismatch: "+
|
|
||||||
"expected open or active channel "+
|
|
||||||
"notification, got: %v",
|
|
||||||
update.Type)
|
|
||||||
}
|
|
||||||
numChannelUpds++
|
|
||||||
|
|
||||||
case <-time.After(time.Second * 10):
|
switch update.Type {
|
||||||
return fmt.Errorf("timeout waiting for channel "+
|
case lnrpc.ChannelEventUpdate_PENDING_OPEN_CHANNEL:
|
||||||
"notifications, only received %d/%d "+
|
if i%3 == 0 {
|
||||||
"chanupds", numChannelUpds,
|
continue
|
||||||
numExpectedOpenUpdates)
|
}
|
||||||
|
return fmt.Errorf("expected open or active" +
|
||||||
|
"channel ntfn, got pending open " +
|
||||||
|
"channel ntfn instead")
|
||||||
|
|
||||||
|
case lnrpc.ChannelEventUpdate_OPEN_CHANNEL:
|
||||||
|
if i%3 == 1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
return fmt.Errorf("expected pending open or " +
|
||||||
|
"active channel ntfn, got open" +
|
||||||
|
"channel ntfn instead")
|
||||||
|
|
||||||
|
case lnrpc.ChannelEventUpdate_ACTIVE_CHANNEL:
|
||||||
|
if i%3 == 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Errorf("expected pending open or " +
|
||||||
|
"open channel ntfn, got active " +
|
||||||
|
"channel ntfn instead")
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("update type mismatch: "+
|
||||||
|
"expected open or active channel "+
|
||||||
|
"notification, got: %v", update.Type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
require.NoError(
|
require.NoError(ht, verifyOpenUpdatesReceived(bobChanSub),
|
||||||
t.t, verifyOpenUpdatesReceived(bobChanSub), "bob open channels",
|
"bob open channels")
|
||||||
)
|
require.NoError(ht, verifyOpenUpdatesReceived(aliceChanSub),
|
||||||
require.NoError(
|
"alice open channels")
|
||||||
t.t, verifyOpenUpdatesReceived(aliceChanSub), "alice open "+
|
|
||||||
"channels",
|
|
||||||
)
|
|
||||||
|
|
||||||
// Close the channels between Alice and Bob, asserting that the channels
|
// Close the channels between Alice and Bob, asserting that the
|
||||||
// have been properly closed on-chain.
|
// channels have been properly closed on-chain.
|
||||||
for i, chanPoint := range chanPoints {
|
for i, chanPoint := range chanPoints {
|
||||||
// Force close the first of the two channels.
|
// Force close the first of the two channels.
|
||||||
force := i%2 == 0
|
force := i%2 == 0
|
||||||
closeChannelAndAssert(t, net, alice, chanPoint, force)
|
|
||||||
if force {
|
if force {
|
||||||
cleanupForceClose(t, net, alice, chanPoint)
|
ht.ForceCloseChannel(alice, chanPoint)
|
||||||
|
} else {
|
||||||
|
ht.CloseChannel(alice, chanPoint)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// verifyCloseUpdatesReceived is used to verify that Alice and Bob
|
// verifyCloseUpdatesReceived is used to verify that Alice and Bob
|
||||||
// receive the correct channel updates in order.
|
// receive the correct channel updates in order.
|
||||||
const numExpectedCloseUpdates = 3 * numChannels
|
const numExpectedCloseUpdates = 3 * numChannels
|
||||||
verifyCloseUpdatesReceived := func(sub channelSubscription,
|
verifyCloseUpdatesReceived := func(sub rpc.ChannelEventsClient,
|
||||||
forceType lnrpc.ChannelCloseSummary_ClosureType,
|
forceType lnrpc.ChannelCloseSummary_ClosureType,
|
||||||
closeInitiator lnrpc.Initiator) error {
|
closeInitiator lnrpc.Initiator) error {
|
||||||
|
|
||||||
// Ensure one inactive and one closed notification is received
|
// Ensure one inactive and one closed notification is received
|
||||||
// for each closed channel.
|
// for each closed channel.
|
||||||
numChannelUpds := 0
|
for i := 0; i < numExpectedCloseUpdates; i++ {
|
||||||
for numChannelUpds < numExpectedCloseUpdates {
|
expectedCloseType := lnrpc.
|
||||||
expectedCloseType := lnrpc.ChannelCloseSummary_COOPERATIVE_CLOSE
|
ChannelCloseSummary_COOPERATIVE_CLOSE
|
||||||
|
|
||||||
// Every other channel should be force closed. If this
|
// Every other channel should be force closed. If this
|
||||||
// channel was force closed, set the expected close type
|
// channel was force closed, set the expected close type
|
||||||
// to the type passed in.
|
// to the type passed in.
|
||||||
force := (numChannelUpds/3)%2 == 0
|
force := (i/3)%2 == 0
|
||||||
if force {
|
if force {
|
||||||
expectedCloseType = forceType
|
expectedCloseType = forceType
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
chanUpdate := ht.ReceiveChannelEvent(sub)
|
||||||
case chanUpdate := <-sub.updateChan:
|
err := verifyCloseUpdate(
|
||||||
err := verifyCloseUpdate(
|
chanUpdate, expectedCloseType,
|
||||||
chanUpdate, expectedCloseType,
|
closeInitiator,
|
||||||
closeInitiator,
|
)
|
||||||
)
|
if err != nil {
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
numChannelUpds++
|
|
||||||
|
|
||||||
case err := <-sub.errChan:
|
|
||||||
return err
|
return err
|
||||||
|
|
||||||
case <-time.After(time.Second * 10):
|
|
||||||
return fmt.Errorf("timeout waiting "+
|
|
||||||
"for channel notifications, only "+
|
|
||||||
"received %d/%d chanupds",
|
|
||||||
numChannelUpds, numChannelUpds)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -467,7 +439,7 @@ func runBasicChannelCreationAndUpdates(net *lntest.NetworkHarness,
|
|||||||
// All channels (cooperatively and force closed) should have a remote
|
// All channels (cooperatively and force closed) should have a remote
|
||||||
// close initiator because Alice closed the channels.
|
// close initiator because Alice closed the channels.
|
||||||
require.NoError(
|
require.NoError(
|
||||||
t.t, verifyCloseUpdatesReceived(
|
ht, verifyCloseUpdatesReceived(
|
||||||
bobChanSub,
|
bobChanSub,
|
||||||
lnrpc.ChannelCloseSummary_REMOTE_FORCE_CLOSE,
|
lnrpc.ChannelCloseSummary_REMOTE_FORCE_CLOSE,
|
||||||
lnrpc.Initiator_INITIATOR_REMOTE,
|
lnrpc.Initiator_INITIATOR_REMOTE,
|
||||||
@@ -479,7 +451,7 @@ func runBasicChannelCreationAndUpdates(net *lntest.NetworkHarness,
|
|||||||
// All channels (cooperatively and force closed) should have a local
|
// All channels (cooperatively and force closed) should have a local
|
||||||
// close initiator because Alice closed the channels.
|
// close initiator because Alice closed the channels.
|
||||||
require.NoError(
|
require.NoError(
|
||||||
t.t, verifyCloseUpdatesReceived(
|
ht, verifyCloseUpdatesReceived(
|
||||||
aliceChanSub,
|
aliceChanSub,
|
||||||
lnrpc.ChannelCloseSummary_LOCAL_FORCE_CLOSE,
|
lnrpc.ChannelCloseSummary_LOCAL_FORCE_CLOSE,
|
||||||
lnrpc.Initiator_INITIATOR_LOCAL,
|
lnrpc.Initiator_INITIATOR_LOCAL,
|
||||||
@@ -516,3 +488,57 @@ func assertMinerBlockHeightDelta(ht *lntemp.HarnessTest,
|
|||||||
}, defaultTimeout)
|
}, defaultTimeout)
|
||||||
require.NoError(ht, err, "failed to assert block height delta")
|
require.NoError(ht, err, "failed to assert block height delta")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// verifyCloseUpdate is used to verify that a closed channel update is of the
|
||||||
|
// expected type.
|
||||||
|
func verifyCloseUpdate(chanUpdate *lnrpc.ChannelEventUpdate,
|
||||||
|
closeType lnrpc.ChannelCloseSummary_ClosureType,
|
||||||
|
closeInitiator lnrpc.Initiator) error {
|
||||||
|
|
||||||
|
// We should receive one inactive and one closed notification
|
||||||
|
// for each channel.
|
||||||
|
switch update := chanUpdate.Channel.(type) {
|
||||||
|
case *lnrpc.ChannelEventUpdate_InactiveChannel:
|
||||||
|
if chanUpdate.Type != lnrpc.ChannelEventUpdate_INACTIVE_CHANNEL {
|
||||||
|
return fmt.Errorf("update type mismatch: expected %v, got %v",
|
||||||
|
lnrpc.ChannelEventUpdate_INACTIVE_CHANNEL,
|
||||||
|
chanUpdate.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *lnrpc.ChannelEventUpdate_ClosedChannel:
|
||||||
|
if chanUpdate.Type !=
|
||||||
|
lnrpc.ChannelEventUpdate_CLOSED_CHANNEL {
|
||||||
|
|
||||||
|
return fmt.Errorf("update type mismatch: expected %v, got %v",
|
||||||
|
lnrpc.ChannelEventUpdate_CLOSED_CHANNEL,
|
||||||
|
chanUpdate.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
if update.ClosedChannel.CloseType != closeType {
|
||||||
|
return fmt.Errorf("channel closure type "+
|
||||||
|
"mismatch: expected %v, got %v",
|
||||||
|
closeType,
|
||||||
|
update.ClosedChannel.CloseType)
|
||||||
|
}
|
||||||
|
|
||||||
|
if update.ClosedChannel.CloseInitiator != closeInitiator {
|
||||||
|
return fmt.Errorf("expected close intiator: %v, got: %v",
|
||||||
|
closeInitiator,
|
||||||
|
update.ClosedChannel.CloseInitiator)
|
||||||
|
}
|
||||||
|
|
||||||
|
case *lnrpc.ChannelEventUpdate_FullyResolvedChannel:
|
||||||
|
if chanUpdate.Type != lnrpc.ChannelEventUpdate_FULLY_RESOLVED_CHANNEL {
|
||||||
|
return fmt.Errorf("update type mismatch: expected %v, got %v",
|
||||||
|
lnrpc.ChannelEventUpdate_FULLY_RESOLVED_CHANNEL,
|
||||||
|
chanUpdate.Type)
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("channel update channel of wrong type, "+
|
||||||
|
"expected closed channel, got %T",
|
||||||
|
update)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
@@ -1,16 +1,12 @@
|
|||||||
package itest
|
package itest
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/btcutil"
|
|
||||||
"github.com/btcsuite/btcd/btcutil/hdkeychain"
|
"github.com/btcsuite/btcd/btcutil/hdkeychain"
|
||||||
"github.com/btcsuite/btcwallet/waddrmgr"
|
"github.com/btcsuite/btcwallet/waddrmgr"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
@@ -55,192 +51,191 @@ var (
|
|||||||
// testRemoteSigner tests that a watch-only wallet can use a remote signing
|
// testRemoteSigner tests that a watch-only wallet can use a remote signing
|
||||||
// wallet to perform any signing or ECDH operations.
|
// wallet to perform any signing or ECDH operations.
|
||||||
func testRemoteSigner(net *lntest.NetworkHarness, t *harnessTest) {
|
func testRemoteSigner(net *lntest.NetworkHarness, t *harnessTest) {
|
||||||
ctxb := context.Background()
|
// ctxb := context.Background()
|
||||||
|
|
||||||
subTests := []struct {
|
// subTests := []struct {
|
||||||
name string
|
// name string
|
||||||
randomSeed bool
|
// randomSeed bool
|
||||||
sendCoins bool
|
// sendCoins bool
|
||||||
fn func(tt *harnessTest, wo, carol *lntest.HarnessNode)
|
// fn func(tt *harnessTest, wo, carol *lntest.HarnessNode)
|
||||||
}{{
|
// }{{
|
||||||
name: "random seed",
|
// name: "random seed",
|
||||||
randomSeed: true,
|
// randomSeed: true,
|
||||||
fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
// fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
||||||
// Nothing more to test here.
|
// // Nothing more to test here.
|
||||||
},
|
// },
|
||||||
}, {
|
// }, {
|
||||||
name: "account import",
|
// name: "account import",
|
||||||
fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
// fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
||||||
runWalletImportAccountScenario(
|
// runWalletImportAccountScenario(
|
||||||
net, tt,
|
// net, tt,
|
||||||
walletrpc.AddressType_WITNESS_PUBKEY_HASH,
|
// walletrpc.AddressType_WITNESS_PUBKEY_HASH,
|
||||||
carol, wo,
|
// carol, wo,
|
||||||
)
|
// )
|
||||||
},
|
// },
|
||||||
}, {
|
// }, {
|
||||||
name: "basic channel open close",
|
// name: "basic channel open close",
|
||||||
sendCoins: true,
|
// sendCoins: true,
|
||||||
fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
// fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
||||||
runBasicChannelCreationAndUpdates(
|
// runBasicChannelCreationAndUpdates(
|
||||||
net, tt, wo, carol,
|
// net, tt, wo, carol,
|
||||||
)
|
// )
|
||||||
},
|
// },
|
||||||
}, {
|
// }, {
|
||||||
name: "async payments",
|
// name: "async payments",
|
||||||
sendCoins: true,
|
// sendCoins: true,
|
||||||
fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
// fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
||||||
runAsyncPayments(net, tt, wo, carol)
|
// runAsyncPayments(net, tt, wo, carol)
|
||||||
},
|
// },
|
||||||
}, {
|
// }, {
|
||||||
name: "shared key",
|
// name: "shared key",
|
||||||
fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
// fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
||||||
runDeriveSharedKey(tt, wo)
|
// runDeriveSharedKey(tt, wo)
|
||||||
},
|
// },
|
||||||
}, {
|
// }, {
|
||||||
name: "cpfp",
|
// name: "cpfp",
|
||||||
sendCoins: true,
|
// sendCoins: true,
|
||||||
fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
// fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
||||||
runCPFP(net, tt, wo, carol)
|
// runCPFP(net, tt, wo, carol)
|
||||||
},
|
// },
|
||||||
}, {
|
// }, {
|
||||||
name: "psbt",
|
// name: "psbt",
|
||||||
randomSeed: true,
|
// randomSeed: true,
|
||||||
fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
// fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
||||||
runPsbtChanFunding(net, tt, carol, wo)
|
// runPsbtChanFunding(net, tt, carol, wo)
|
||||||
runSignPsbtSegWitV0P2WKH(tt, net, wo)
|
// runSignPsbtSegWitV0P2WKH(tt, net, wo)
|
||||||
runSignPsbtSegWitV1KeySpendBip86(tt, net, wo)
|
// runSignPsbtSegWitV1KeySpendBip86(tt, net, wo)
|
||||||
runSignPsbtSegWitV1KeySpendRootHash(tt, net, wo)
|
// runSignPsbtSegWitV1KeySpendRootHash(tt, net, wo)
|
||||||
runSignPsbtSegWitV1ScriptSpend(tt, net, wo)
|
// runSignPsbtSegWitV1ScriptSpend(tt, net, wo)
|
||||||
},
|
// },
|
||||||
}, {
|
// }, {
|
||||||
name: "sign output raw",
|
// name: "sign output raw",
|
||||||
sendCoins: true,
|
// sendCoins: true,
|
||||||
fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
// fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
||||||
runSignOutputRaw(tt, net, wo)
|
// runSignOutputRaw(tt, net, wo)
|
||||||
},
|
// },
|
||||||
}, {
|
// }, {
|
||||||
name: "sign verify msg",
|
// name: "sign verify msg",
|
||||||
sendCoins: true,
|
// sendCoins: true,
|
||||||
fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
// fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
||||||
runSignVerifyMessage(tt, net, wo)
|
// runSignVerifyMessage(tt, net, wo)
|
||||||
},
|
// },
|
||||||
}, {
|
// }, {
|
||||||
name: "taproot",
|
// name: "taproot",
|
||||||
sendCoins: true,
|
// sendCoins: true,
|
||||||
randomSeed: true,
|
// randomSeed: true,
|
||||||
fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
// fn: func(tt *harnessTest, wo, carol *lntest.HarnessNode) {
|
||||||
longTimeout := 3 * defaultTimeout
|
// ctxt, cancel := context.WithTimeout(
|
||||||
ctxt, cancel := context.WithTimeout(ctxb, longTimeout)
|
// ctxb, 3*defaultTimeout,
|
||||||
testTaprootSendCoinsKeySpendBip86(ctxt, tt, wo, net)
|
// )
|
||||||
testTaprootComputeInputScriptKeySpendBip86(
|
// defer cancel()
|
||||||
ctxt, tt, wo, net,
|
|
||||||
)
|
|
||||||
testTaprootSignOutputRawScriptSpend(ctxt, tt, wo, net)
|
|
||||||
testTaprootSignOutputRawKeySpendBip86(ctxt, tt, wo, net)
|
|
||||||
testTaprootSignOutputRawKeySpendRootHash(
|
|
||||||
ctxt, tt, wo, net,
|
|
||||||
)
|
|
||||||
cancel()
|
|
||||||
|
|
||||||
ctxt, cancel = context.WithTimeout(ctxb, longTimeout)
|
// testTaprootSendCoinsKeySpendBip86(ctxt, tt, wo, net)
|
||||||
testTaprootMuSig2KeySpendRootHash(ctxt, tt, wo, net)
|
// testTaprootComputeInputScriptKeySpendBip86(
|
||||||
testTaprootMuSig2ScriptSpend(ctxt, tt, wo, net)
|
// ctxt, tt, wo, net,
|
||||||
testTaprootMuSig2KeySpendBip86(ctxt, tt, wo, net)
|
// )
|
||||||
testTaprootMuSig2CombinedLeafKeySpend(ctxt, tt, wo, net)
|
// testTaprootSignOutputRawScriptSpend(ctxt, tt, wo, net)
|
||||||
cancel()
|
// testTaprootSignOutputRawKeySpendBip86(ctxt, tt, wo, net)
|
||||||
},
|
// testTaprootSignOutputRawKeySpendRootHash(
|
||||||
}}
|
// ctxt, tt, wo, net,
|
||||||
|
// )
|
||||||
|
// testTaprootMuSig2KeySpendRootHash(ctxt, tt, wo, net)
|
||||||
|
// testTaprootMuSig2ScriptSpend(ctxt, tt, wo, net)
|
||||||
|
// testTaprootMuSig2KeySpendBip86(ctxt, tt, wo, net)
|
||||||
|
// testTaprootMuSig2CombinedLeafKeySpend(ctxt, tt, wo, net)
|
||||||
|
// },
|
||||||
|
// }}
|
||||||
|
|
||||||
for _, st := range subTests {
|
// for _, st := range subTests {
|
||||||
subTest := st
|
// subTest := st
|
||||||
|
|
||||||
// Signer is our signing node and has the wallet with the full
|
// // Signer is our signing node and has the wallet with the full
|
||||||
// master private key. We test that we can create the watch-only
|
// // master private key. We test that we can create the watch-only
|
||||||
// wallet from the exported accounts but also from a static key
|
// // wallet from the exported accounts but also from a static key
|
||||||
// to make sure the derivation of the account public keys is
|
// // to make sure the derivation of the account public keys is
|
||||||
// correct in both cases.
|
// // correct in both cases.
|
||||||
password := []byte("itestpassword")
|
// password := []byte("itestpassword")
|
||||||
var (
|
// var (
|
||||||
signerNodePubKey = nodePubKey
|
// signerNodePubKey = nodePubKey
|
||||||
watchOnlyAccounts = deriveCustomScopeAccounts(t.t)
|
// watchOnlyAccounts = deriveCustomScopeAccounts(t.t)
|
||||||
signer *lntest.HarnessNode
|
// signer *lntest.HarnessNode
|
||||||
err error
|
// err error
|
||||||
)
|
// )
|
||||||
if !subTest.randomSeed {
|
// if !subTest.randomSeed {
|
||||||
signer, err = net.RestoreNodeWithSeed(
|
// signer, err = net.RestoreNodeWithSeed(
|
||||||
"Signer", nil, password, nil, rootKey, 0, nil,
|
// "Signer", nil, password, nil, rootKey, 0, nil,
|
||||||
)
|
// )
|
||||||
require.NoError(t.t, err)
|
// require.NoError(t.t, err)
|
||||||
} else {
|
// } else {
|
||||||
signer = net.NewNode(t.t, "Signer", nil)
|
// signer = net.NewNode(t.t, "Signer", nil)
|
||||||
signerNodePubKey = signer.PubKeyStr
|
// signerNodePubKey = signer.PubKeyStr
|
||||||
|
|
||||||
rpcAccts, err := signer.WalletKitClient.ListAccounts(
|
// rpcAccts, err := signer.WalletKitClient.ListAccounts(
|
||||||
ctxb, &walletrpc.ListAccountsRequest{},
|
// ctxb, &walletrpc.ListAccountsRequest{},
|
||||||
)
|
// )
|
||||||
require.NoError(t.t, err)
|
// require.NoError(t.t, err)
|
||||||
|
|
||||||
watchOnlyAccounts, err = walletrpc.AccountsToWatchOnly(
|
// watchOnlyAccounts, err = walletrpc.AccountsToWatchOnly(
|
||||||
rpcAccts.Accounts,
|
// rpcAccts.Accounts,
|
||||||
)
|
// )
|
||||||
require.NoError(t.t, err)
|
// require.NoError(t.t, err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
// WatchOnly is the node that has a watch-only wallet and uses
|
// // WatchOnly is the node that has a watch-only wallet and uses
|
||||||
// the Signer node for any operation that requires access to
|
// // the Signer node for any operation that requires access to
|
||||||
// private keys.
|
// // private keys.
|
||||||
watchOnly, err := net.NewNodeRemoteSigner(
|
// watchOnly, err := net.NewNodeRemoteSigner(
|
||||||
"WatchOnly", []string{
|
// "WatchOnly", []string{
|
||||||
"--remotesigner.enable",
|
// "--remotesigner.enable",
|
||||||
fmt.Sprintf(
|
// fmt.Sprintf(
|
||||||
"--remotesigner.rpchost=localhost:%d",
|
// "--remotesigner.rpchost=localhost:%d",
|
||||||
signer.Cfg.RPCPort,
|
// signer.Cfg.RPCPort,
|
||||||
),
|
// ),
|
||||||
fmt.Sprintf(
|
// fmt.Sprintf(
|
||||||
"--remotesigner.tlscertpath=%s",
|
// "--remotesigner.tlscertpath=%s",
|
||||||
signer.Cfg.TLSCertPath,
|
// signer.Cfg.TLSCertPath,
|
||||||
),
|
// ),
|
||||||
fmt.Sprintf(
|
// fmt.Sprintf(
|
||||||
"--remotesigner.macaroonpath=%s",
|
// "--remotesigner.macaroonpath=%s",
|
||||||
signer.Cfg.AdminMacPath,
|
// signer.Cfg.AdminMacPath,
|
||||||
),
|
// ),
|
||||||
}, password, &lnrpc.WatchOnly{
|
// }, password, &lnrpc.WatchOnly{
|
||||||
MasterKeyBirthdayTimestamp: 0,
|
// MasterKeyBirthdayTimestamp: 0,
|
||||||
MasterKeyFingerprint: nil,
|
// MasterKeyFingerprint: nil,
|
||||||
Accounts: watchOnlyAccounts,
|
// Accounts: watchOnlyAccounts,
|
||||||
},
|
// },
|
||||||
)
|
// )
|
||||||
require.NoError(t.t, err)
|
// require.NoError(t.t, err)
|
||||||
|
|
||||||
resp, err := watchOnly.GetInfo(ctxb, &lnrpc.GetInfoRequest{})
|
// resp, err := watchOnly.GetInfo(ctxb, &lnrpc.GetInfoRequest{})
|
||||||
require.NoError(t.t, err)
|
// require.NoError(t.t, err)
|
||||||
|
|
||||||
require.Equal(t.t, signerNodePubKey, resp.IdentityPubkey)
|
// require.Equal(t.t, signerNodePubKey, resp.IdentityPubkey)
|
||||||
|
|
||||||
if subTest.sendCoins {
|
// if subTest.sendCoins {
|
||||||
net.SendCoins(t.t, btcutil.SatoshiPerBitcoin, watchOnly)
|
// net.SendCoins(t.t, btcutil.SatoshiPerBitcoin, watchOnly)
|
||||||
assertAccountBalance(
|
// assertAccountBalance(
|
||||||
t.t, watchOnly, "default",
|
// t.t, watchOnly, "default",
|
||||||
btcutil.SatoshiPerBitcoin, 0,
|
// btcutil.SatoshiPerBitcoin, 0,
|
||||||
)
|
// )
|
||||||
}
|
// }
|
||||||
|
|
||||||
carol := net.NewNode(t.t, "carol", nil)
|
// carol := net.NewNode(t.t, "carol", nil)
|
||||||
net.EnsureConnected(t.t, watchOnly, carol)
|
// net.EnsureConnected(t.t, watchOnly, carol)
|
||||||
|
|
||||||
success := t.t.Run(subTest.name, func(tt *testing.T) {
|
// success := t.t.Run(subTest.name, func(tt *testing.T) {
|
||||||
ht := newHarnessTest(tt, net)
|
// ht := newHarnessTest(tt, net)
|
||||||
subTest.fn(ht, watchOnly, carol)
|
// subTest.fn(ht, watchOnly, carol)
|
||||||
})
|
// })
|
||||||
|
|
||||||
shutdownAndAssert(net, t, carol)
|
// shutdownAndAssert(net, t, carol)
|
||||||
shutdownAndAssert(net, t, watchOnly)
|
// shutdownAndAssert(net, t, watchOnly)
|
||||||
shutdownAndAssert(net, t, signer)
|
// shutdownAndAssert(net, t, signer)
|
||||||
|
|
||||||
if !success {
|
// if !success {
|
||||||
return
|
// return
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
// deriveCustomScopeAccounts derives the first 255 default accounts of the custom lnd
|
// deriveCustomScopeAccounts derives the first 255 default accounts of the custom lnd
|
||||||
|
|||||||
@@ -4,10 +4,6 @@
|
|||||||
package itest
|
package itest
|
||||||
|
|
||||||
var allTestCases = []*testCase{
|
var allTestCases = []*testCase{
|
||||||
{
|
|
||||||
name: "multiple channel creation and update subscription",
|
|
||||||
test: testBasicChannelCreationAndUpdates,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "derive shared key",
|
name: "derive shared key",
|
||||||
test: testDeriveSharedKey,
|
test: testDeriveSharedKey,
|
||||||
|
|||||||
Reference in new issue
Block a user