mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-03-04 09:48:19 +01:00
lntemp: expand package to support testExternalFundingChanPoint
This commit is contained in:
parent
773cc8e295
commit
1d135c1409
6 changed files with 327 additions and 16 deletions
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/btcutil"
|
||||
|
@ -12,6 +13,7 @@ import (
|
|||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/go-errors/errors"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
|
@ -542,11 +544,12 @@ type OpenChannelParams struct {
|
|||
CommitmentType lnrpc.CommitmentType
|
||||
}
|
||||
|
||||
// openChannel attempts to open a channel between srcNode and destNode with the
|
||||
// passed channel funding parameters. Once the `OpenChannel` is called, it will
|
||||
// consume the first event it receives from the open channel client and asserts
|
||||
// it's a channel pending event.
|
||||
func (h *HarnessTest) openChannel(srcNode, destNode *node.HarnessNode,
|
||||
// OpenChannelAssertPending attempts to open a channel between srcNode and
|
||||
// destNode with the passed channel funding parameters. Once the `OpenChannel`
|
||||
// is called, it will consume the first event it receives from the open channel
|
||||
// client and asserts it's a channel pending event.
|
||||
func (h *HarnessTest) OpenChannelAssertPending(
|
||||
srcNode, destNode *node.HarnessNode,
|
||||
p OpenChannelParams) rpc.OpenChanClient {
|
||||
|
||||
// Specify the minimal confirmations of the UTXOs used for channel
|
||||
|
@ -601,7 +604,7 @@ func (h *HarnessTest) OpenChannel(alice, bob *node.HarnessNode,
|
|||
h.WaitForBlockchainSync(alice)
|
||||
h.WaitForBlockchainSync(bob)
|
||||
|
||||
chanOpenUpdate := h.openChannel(alice, bob, p)
|
||||
chanOpenUpdate := h.OpenChannelAssertPending(alice, bob, p)
|
||||
|
||||
// Mine 6 blocks, then wait for Alice's node to notify us that the
|
||||
// channel has been opened. The funding transaction should be found
|
||||
|
@ -649,7 +652,9 @@ func (h *HarnessTest) closeChannel(hn *node.HarnessNode, cp *lnrpc.ChannelPoint,
|
|||
// Consume the "channel close" update in order to wait for the closing
|
||||
// transaction to be broadcast, then wait for the closing tx to be seen
|
||||
// within the network.
|
||||
event := h.ReceiveCloseChannelUpdate(stream)
|
||||
event, err := h.ReceiveCloseChannelUpdate(stream)
|
||||
require.NoError(h, err)
|
||||
|
||||
pendingClose, ok := event.Update.(*lnrpc.CloseStatusUpdate_ClosePending)
|
||||
require.Truef(h, ok, "expected channel close update, instead got %v",
|
||||
pendingClose)
|
||||
|
@ -681,6 +686,26 @@ func (h *HarnessTest) CloseChannel(hn *node.HarnessNode,
|
|||
return h.assertChannelClosed(hn, cp, false, stream)
|
||||
}
|
||||
|
||||
// CloseChannelAssertErr closes the given channel and asserts an error
|
||||
// returned.
|
||||
func (h *HarnessTest) CloseChannelAssertErr(hn *node.HarnessNode,
|
||||
cp *lnrpc.ChannelPoint, force bool) {
|
||||
|
||||
// Calls the rpc to close the channel.
|
||||
closeReq := &lnrpc.CloseChannelRequest{
|
||||
ChannelPoint: cp,
|
||||
Force: force,
|
||||
}
|
||||
stream := hn.RPC.CloseChannel(closeReq)
|
||||
|
||||
// Consume the "channel close" update in order to wait for the closing
|
||||
// transaction to be broadcast, then wait for the closing tx to be seen
|
||||
// within the network.
|
||||
_, err := h.ReceiveCloseChannelUpdate(stream)
|
||||
require.Errorf(h, err, "%s: expect close channel to return an error",
|
||||
hn.Name())
|
||||
}
|
||||
|
||||
// IsNeutrinoBackend returns a bool indicating whether the node is using a
|
||||
// neutrino as its backend. This is useful when we want to skip certain tests
|
||||
// which cannot be done with a neutrino backend.
|
||||
|
@ -758,3 +783,84 @@ func (h *HarnessTest) fundCoins(amt btcutil.Amount, target *node.HarnessNode,
|
|||
func (h *HarnessTest) FundCoins(amt btcutil.Amount, hn *node.HarnessNode) {
|
||||
h.fundCoins(amt, hn, lnrpc.AddressType_WITNESS_PUBKEY_HASH, true)
|
||||
}
|
||||
|
||||
// CompletePaymentRequests sends payments from a node to complete all payment
|
||||
// requests. This function does not return until all payments successfully
|
||||
// complete without errors.
|
||||
func (h *HarnessTest) CompletePaymentRequests(hn *node.HarnessNode,
|
||||
paymentRequests []string) {
|
||||
|
||||
var wg sync.WaitGroup
|
||||
|
||||
// send sends a payment and asserts if it doesn't succeeded.
|
||||
send := func(payReq string) {
|
||||
defer wg.Done()
|
||||
|
||||
req := &routerrpc.SendPaymentRequest{
|
||||
PaymentRequest: payReq,
|
||||
TimeoutSeconds: defaultPaymentTimeout,
|
||||
FeeLimitMsat: noFeeLimitMsat,
|
||||
}
|
||||
stream := hn.RPC.SendPayment(req)
|
||||
h.AssertPaymentStatusFromStream(stream, lnrpc.Payment_SUCCEEDED)
|
||||
}
|
||||
|
||||
// Launch all payments simultaneously.
|
||||
for _, payReq := range paymentRequests {
|
||||
payReqCopy := payReq
|
||||
wg.Add(1)
|
||||
go send(payReqCopy)
|
||||
}
|
||||
|
||||
// Wait for all payments to report success.
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
// CompletePaymentRequestsNoWait sends payments from a node to complete all
|
||||
// payment requests without waiting for the results. Instead, it checks the
|
||||
// number of updates in the specified channel has increased.
|
||||
func (h *HarnessTest) CompletePaymentRequestsNoWait(hn *node.HarnessNode,
|
||||
paymentRequests []string, chanPoint *lnrpc.ChannelPoint) {
|
||||
|
||||
// We start by getting the current state of the client's channels. This
|
||||
// is needed to ensure the payments actually have been committed before
|
||||
// we return.
|
||||
oldResp := h.GetChannelByChanPoint(hn, chanPoint)
|
||||
|
||||
// send sends a payment and asserts if it doesn't succeeded.
|
||||
send := func(payReq string) {
|
||||
req := &routerrpc.SendPaymentRequest{
|
||||
PaymentRequest: payReq,
|
||||
TimeoutSeconds: defaultPaymentTimeout,
|
||||
FeeLimitMsat: noFeeLimitMsat,
|
||||
}
|
||||
hn.RPC.SendPayment(req)
|
||||
}
|
||||
|
||||
// Launch all payments simultaneously.
|
||||
for _, payReq := range paymentRequests {
|
||||
payReqCopy := payReq
|
||||
go send(payReqCopy)
|
||||
}
|
||||
|
||||
// We are not waiting for feedback in the form of a response, but we
|
||||
// should still wait long enough for the server to receive and handle
|
||||
// the send before cancelling the request. We wait for the number of
|
||||
// updates to one of our channels has increased before we return.
|
||||
err := wait.NoError(func() error {
|
||||
newResp := h.GetChannelByChanPoint(hn, chanPoint)
|
||||
|
||||
// If this channel has an increased number of updates, we
|
||||
// assume the payments are committed, and we can return.
|
||||
if newResp.NumUpdates > oldResp.NumUpdates {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Otherwise return an error as the NumUpdates are not
|
||||
// increased.
|
||||
return fmt.Errorf("%s: channel:%v not updated after sending "+
|
||||
"payments, old updates: %v, new updates: %v", hn.Name(),
|
||||
chanPoint, oldResp.NumUpdates, newResp.NumUpdates)
|
||||
}, DefaultTimeout)
|
||||
require.NoError(h, err, "timeout while checking for channel updates")
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/btcsuite/btcd/txscript"
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/walletrpc"
|
||||
"github.com/lightningnetwork/lnd/lntemp/node"
|
||||
"github.com/lightningnetwork/lnd/lntemp/rpc"
|
||||
|
@ -300,10 +301,10 @@ func (h *HarnessTest) findChannel(hn *node.HarnessNode,
|
|||
return nil, fmt.Errorf("channel not found using %s", chanPoint)
|
||||
}
|
||||
|
||||
// ReceiveCloseChannelUpdate waits until a message is received on the subscribe
|
||||
// channel close stream or the timeout is reached.
|
||||
// ReceiveCloseChannelUpdate waits until a message or an error is received on
|
||||
// the subscribe channel close stream or the timeout is reached.
|
||||
func (h *HarnessTest) ReceiveCloseChannelUpdate(
|
||||
stream rpc.CloseChanClient) *lnrpc.CloseStatusUpdate {
|
||||
stream rpc.CloseChanClient) (*lnrpc.CloseStatusUpdate, error) {
|
||||
|
||||
chanMsg := make(chan *lnrpc.CloseStatusUpdate)
|
||||
errChan := make(chan error)
|
||||
|
@ -322,16 +323,15 @@ func (h *HarnessTest) ReceiveCloseChannelUpdate(
|
|||
case <-time.After(DefaultTimeout):
|
||||
require.Fail(h, "timeout", "timeout waiting for close channel "+
|
||||
"update sent")
|
||||
return nil, nil
|
||||
|
||||
case err := <-errChan:
|
||||
require.Failf(h, "close channel stream",
|
||||
"received err from close channel stream: %v", err)
|
||||
return nil, fmt.Errorf("received err from close channel "+
|
||||
"stream: %v", err)
|
||||
|
||||
case updateMsg := <-chanMsg:
|
||||
return updateMsg
|
||||
return updateMsg, nil
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type WaitingCloseChannel *lnrpc.PendingChannelsResponse_WaitingCloseChannel
|
||||
|
@ -382,7 +382,8 @@ func (h HarnessTest) WaitForChannelCloseEvent(
|
|||
stream rpc.CloseChanClient) *chainhash.Hash {
|
||||
|
||||
// Consume one event.
|
||||
event := h.ReceiveCloseChannelUpdate(stream)
|
||||
event, err := h.ReceiveCloseChannelUpdate(stream)
|
||||
require.NoError(h, err)
|
||||
|
||||
resp, ok := event.Update.(*lnrpc.CloseStatusUpdate_ChanClose)
|
||||
require.Truef(h, ok, "expected channel open update, instead got %v",
|
||||
|
@ -687,3 +688,137 @@ func (h *HarnessTest) GetChannelCommitType(hn *node.HarnessNode,
|
|||
|
||||
return c.CommitmentType
|
||||
}
|
||||
|
||||
// AssertNumPendingOpenChannels asserts that a given node have the expected
|
||||
// number of pending open channels.
|
||||
func (h *HarnessTest) AssertNumPendingOpenChannels(hn *node.HarnessNode,
|
||||
expected int) []*lnrpc.PendingChannelsResponse_PendingOpenChannel {
|
||||
|
||||
var channels []*lnrpc.PendingChannelsResponse_PendingOpenChannel
|
||||
|
||||
oldNum := hn.State.OpenChannel.Pending
|
||||
|
||||
err := wait.NoError(func() error {
|
||||
resp := hn.RPC.PendingChannels()
|
||||
channels = resp.PendingOpenChannels
|
||||
total := len(channels)
|
||||
|
||||
numChans := total - oldNum
|
||||
|
||||
if numChans != expected {
|
||||
return errNumNotMatched(hn.Name(),
|
||||
"pending open channels", expected,
|
||||
numChans, total, oldNum)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, DefaultTimeout)
|
||||
|
||||
require.NoError(h, err, "num of pending open channels not match")
|
||||
|
||||
return channels
|
||||
}
|
||||
|
||||
// AssertNodesNumPendingOpenChannels asserts that both of the nodes have the
|
||||
// expected number of pending open channels.
|
||||
func (h *HarnessTest) AssertNodesNumPendingOpenChannels(a, b *node.HarnessNode,
|
||||
expected int) {
|
||||
|
||||
h.AssertNumPendingOpenChannels(a, expected)
|
||||
h.AssertNumPendingOpenChannels(b, expected)
|
||||
}
|
||||
|
||||
// AssertPaymentStatusFromStream takes a client stream and asserts the payment
|
||||
// is in desired status before default timeout. The payment found is returned
|
||||
// once succeeded.
|
||||
func (h *HarnessTest) AssertPaymentStatusFromStream(stream rpc.PaymentClient,
|
||||
status lnrpc.Payment_PaymentStatus) *lnrpc.Payment {
|
||||
|
||||
return h.assertPaymentStatusWithTimeout(stream, status, DefaultTimeout)
|
||||
}
|
||||
|
||||
// assertPaymentStatusWithTimeout takes a client stream and asserts the payment
|
||||
// is in desired status before the specified timeout. The payment found is
|
||||
// returned once succeeded.
|
||||
func (h *HarnessTest) assertPaymentStatusWithTimeout(stream rpc.PaymentClient,
|
||||
status lnrpc.Payment_PaymentStatus,
|
||||
timeout time.Duration) *lnrpc.Payment {
|
||||
|
||||
var target *lnrpc.Payment
|
||||
err := wait.NoError(func() error {
|
||||
// Consume one message. This will raise an error if the message
|
||||
// is not received within DefaultTimeout.
|
||||
payment := h.ReceivePaymentUpdate(stream)
|
||||
|
||||
// Return if the desired payment state is reached.
|
||||
if payment.Status == status {
|
||||
target = payment
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Return the err so that it can be used for debugging when
|
||||
// timeout is reached.
|
||||
return fmt.Errorf("payment status, got %v, want %v",
|
||||
payment.Status, status)
|
||||
}, timeout)
|
||||
|
||||
require.NoError(h, err, "timeout while waiting payment")
|
||||
|
||||
return target
|
||||
}
|
||||
|
||||
// ReceivePaymentUpdate waits until a message is received on the payment client
|
||||
// stream or the timeout is reached.
|
||||
func (h *HarnessTest) ReceivePaymentUpdate(
|
||||
stream rpc.PaymentClient) *lnrpc.Payment {
|
||||
|
||||
chanMsg := make(chan *lnrpc.Payment, 1)
|
||||
errChan := make(chan error, 1)
|
||||
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 waiting for payment update")
|
||||
|
||||
case err := <-errChan:
|
||||
require.Failf(h, "payment stream",
|
||||
"received err from payment stream: %v", err)
|
||||
|
||||
case updateMsg := <-chanMsg:
|
||||
return updateMsg
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// AssertInvoiceSettled asserts a given invoice specified by its payment
|
||||
// address is settled.
|
||||
func (h *HarnessTest) AssertInvoiceSettled(hn *node.HarnessNode, addr []byte) {
|
||||
msg := &invoicesrpc.LookupInvoiceMsg{
|
||||
InvoiceRef: &invoicesrpc.LookupInvoiceMsg_PaymentAddr{
|
||||
PaymentAddr: addr,
|
||||
},
|
||||
}
|
||||
|
||||
err := wait.NoError(func() error {
|
||||
invoice := hn.RPC.LookupInvoiceV2(msg)
|
||||
if invoice.State == lnrpc.Invoice_SETTLED {
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("%s: invoice with payment address %x not "+
|
||||
"settled", hn.Name(), addr)
|
||||
}, DefaultTimeout)
|
||||
require.NoError(h, err, "timeout waiting for invoice settled state")
|
||||
}
|
||||
|
|
|
@ -1,5 +1,26 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||
)
|
||||
|
||||
// =====================
|
||||
// InvoiceClient related RPCs.
|
||||
// =====================
|
||||
|
||||
// LookupInvoiceV2 queries the node's invoices using the invoice client's
|
||||
// LookupInvoiceV2.
|
||||
func (h *HarnessRPC) LookupInvoiceV2(
|
||||
req *invoicesrpc.LookupInvoiceMsg) *lnrpc.Invoice {
|
||||
|
||||
ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
resp, err := h.Invoice.LookupInvoiceV2(ctxt, req)
|
||||
h.NoError(err, "LookupInvoiceV2")
|
||||
|
||||
return resp
|
||||
}
|
||||
|
|
|
@ -238,3 +238,27 @@ func (h *HarnessRPC) FundingStateStepAssertErr(m *lnrpc.FundingTransitionMsg) {
|
|||
_, err := h.LN.FundingStateStep(ctxt, m)
|
||||
require.Error(h, err, "expected an error from FundingStateStep")
|
||||
}
|
||||
|
||||
// AddInvoice adds a invoice for the given node and asserts.
|
||||
func (h *HarnessRPC) AddInvoice(req *lnrpc.Invoice) *lnrpc.AddInvoiceResponse {
|
||||
ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
invoice, err := h.LN.AddInvoice(ctxt, req)
|
||||
h.NoError(err, "AddInvoice")
|
||||
|
||||
return invoice
|
||||
}
|
||||
|
||||
// AbandonChannel makes a RPC call to AbandonChannel and asserts.
|
||||
func (h *HarnessRPC) AbandonChannel(
|
||||
req *lnrpc.AbandonChannelRequest) *lnrpc.AbandonChannelResponse {
|
||||
|
||||
ctxt, cancel := context.WithTimeout(h.runCtx, DefaultTimeout)
|
||||
defer cancel()
|
||||
|
||||
resp, err := h.LN.AbandonChannel(ctxt, req)
|
||||
h.NoError(err, "AbandonChannel")
|
||||
|
||||
return resp
|
||||
}
|
||||
|
|
|
@ -23,3 +23,19 @@ func (h *HarnessRPC) UpdateChanStatus(
|
|||
|
||||
return resp
|
||||
}
|
||||
|
||||
type PaymentClient routerrpc.Router_SendPaymentV2Client
|
||||
|
||||
// SendPayment sends a payment using the given node and payment request. It
|
||||
// also asserts the payment being sent successfully.
|
||||
func (h *HarnessRPC) SendPayment(
|
||||
req *routerrpc.SendPaymentRequest) PaymentClient {
|
||||
|
||||
// SendPayment needs to have the context alive for the entire test case
|
||||
// as the router relies on the context to propagate HTLCs. Thus we use
|
||||
// runCtx here instead of a timeout context.
|
||||
stream, err := h.Router.SendPaymentV2(h.runCtx, req)
|
||||
h.NoError(err, "SendPaymentV2")
|
||||
|
||||
return stream
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package lntemp
|
|||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"os"
|
||||
|
||||
"github.com/lightningnetwork/lnd/lntest"
|
||||
|
@ -14,6 +15,14 @@ const (
|
|||
|
||||
// TODO(yy): delete.
|
||||
DefaultTimeout = lntest.DefaultTimeout
|
||||
|
||||
// noFeeLimitMsat is used to specify we will put no requirements on fee
|
||||
// charged when choosing a route path.
|
||||
noFeeLimitMsat = math.MaxInt64
|
||||
|
||||
// defaultPaymentTimeout specifies the default timeout in seconds when
|
||||
// sending a payment.
|
||||
defaultPaymentTimeout = 60
|
||||
)
|
||||
|
||||
// CopyFile copies the file src to dest.
|
||||
|
|
Loading…
Add table
Reference in a new issue