loop/test/lnd_services_mock.go

309 lines
8.3 KiB
Go
Raw Permalink Normal View History

2019-03-06 21:13:50 +01:00
package test
import (
2020-04-24 09:27:25 +02:00
"context"
2019-03-06 21:13:50 +01:00
"errors"
"sync"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/wire"
"github.com/lightninglabs/lndclient"
2019-03-06 21:13:50 +01:00
"github.com/lightningnetwork/lnd/chainntnfs"
2019-10-01 11:21:17 -04:00
"github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
2019-10-01 11:21:17 -04:00
"github.com/lightningnetwork/lnd/zpay32"
2019-03-06 21:13:50 +01:00
)
var (
testStartingHeight = int32(600)
testNodePubkey = "03f5374b16f0b1f1b49101de1b9d89e0b460bc57ce9c2f9" +
"132b73dfc76d3704daa"
2019-12-09 16:47:23 +01:00
testSignature = []byte{55, 66, 77, 88, 99}
testSignatureMsg = "test"
)
2019-03-06 21:13:50 +01:00
// NewMockLnd returns a new instance of LndMockServices that can be used in unit
// tests.
func NewMockLnd() *LndMockServices {
lightningClient := &mockLightningClient{}
2019-10-01 11:21:17 -04:00
walletKit := &mockWalletKit{
feeEstimates: make(map[int32]chainfee.SatPerKWeight),
2025-02-20 01:51:07 -03:00
minRelayFee: chainfee.FeePerKwFloor,
2019-10-01 11:21:17 -04:00
}
2019-03-06 21:13:50 +01:00
chainNotifier := &mockChainNotifier{}
signer := &mockSigner{}
invoices := &mockInvoices{}
router := &mockRouter{}
versioner := newMockVersioner()
2019-03-06 21:13:50 +01:00
lnd := LndMockServices{
LndServices: lndclient.LndServices{
WalletKit: walletKit,
Client: lightningClient,
ChainNotifier: chainNotifier,
Signer: signer,
Invoices: invoices,
Router: router,
2019-03-06 21:13:50 +01:00
ChainParams: &chaincfg.TestNet3Params,
Versioner: versioner,
2019-03-06 21:13:50 +01:00
},
ConfChannel: make(chan *chainntnfs.TxConfirmation),
RegisterConfChannel: make(chan *ConfRegistration),
RegisterSpendChannel: make(chan *SpendRegistration),
SpendChannel: make(chan *chainntnfs.SpendDetail),
TxPublishChannel: make(chan *wire.MsgTx),
SendOutputsChannel: make(chan wire.MsgTx),
SettleInvoiceChannel: make(chan lntypes.Preimage),
2020-05-29 11:27:47 +02:00
SingleInvoiceSubcribeChannel: make(chan *SingleInvoiceSubscription, 1),
2019-03-06 21:13:50 +01:00
RouterSendPaymentChannel: make(chan RouterPaymentChannelMessage),
TrackPaymentChannel: make(chan TrackPaymentMessage),
SignOutputRawChannel: make(chan SignOutputRawRequest),
FailInvoiceChannel: make(chan lntypes.Hash, 2),
blockHeightListeners: make([]chan int32, 0),
Height: testStartingHeight,
NodePubkey: testNodePubkey,
Signature: testSignature,
SignatureMsg: testSignatureMsg,
Invoices: make(map[lntypes.Hash]*lndclient.Invoice),
2019-03-06 21:13:50 +01:00
}
lightningClient.lnd = &lnd
chainNotifier.lnd = &lnd
walletKit.lnd = &lnd
invoices.lnd = &lnd
router.lnd = &lnd
2019-12-09 16:34:02 +01:00
signer.lnd = &lnd
2019-03-06 21:13:50 +01:00
2020-04-24 09:27:25 +02:00
// Also simulate the cached info that is loaded on startup.
info, _ := lightningClient.GetInfo(context.Background())
version, _ := versioner.GetVersion(context.Background())
2020-04-24 09:27:25 +02:00
lnd.LndServices.NodeAlias = info.Alias
lnd.LndServices.NodePubkey = info.IdentityPubkey
lnd.LndServices.Version = version
2020-04-24 09:27:25 +02:00
2019-03-06 21:13:50 +01:00
lnd.WaitForFinished = func() {
chainNotifier.WaitForFinished()
lightningClient.WaitForFinished()
invoices.WaitForFinished()
}
return &lnd
}
// TrackPaymentMessage is the data that passed through TrackPaymentChannel.
type TrackPaymentMessage struct {
Hash lntypes.Hash
Updates chan lndclient.PaymentStatus
Errors chan error
}
// RouterPaymentChannelMessage is the data that passed through RouterSendPaymentChannel.
type RouterPaymentChannelMessage struct {
lndclient.SendPaymentRequest
TrackPaymentMessage
}
// SingleInvoiceSubscription contains the single invoice subscribers.
2019-03-06 21:13:50 +01:00
type SingleInvoiceSubscription struct {
Hash lntypes.Hash
2019-03-12 16:10:37 +01:00
Update chan lndclient.InvoiceUpdate
2019-03-06 21:13:50 +01:00
Err chan error
}
// SignOutputRawRequest contains input data for a tx signing request.
type SignOutputRawRequest struct {
Tx *wire.MsgTx
SignDescriptors []*lndclient.SignDescriptor
}
// PublishHandler is optional transaction handler function called upon calling
// the method PublishTransaction.
type PublishHandler func(ctx context.Context, tx *wire.MsgTx,
label string) error
2019-03-06 21:13:50 +01:00
// LndMockServices provides a full set of mocked lnd services.
type LndMockServices struct {
lndclient.LndServices
SpendChannel chan *chainntnfs.SpendDetail
TxPublishChannel chan *wire.MsgTx
SendOutputsChannel chan wire.MsgTx
SettleInvoiceChannel chan lntypes.Preimage
FailInvoiceChannel chan lntypes.Hash
blockHeightListeners []chan int32
2019-03-06 21:13:50 +01:00
ConfChannel chan *chainntnfs.TxConfirmation
RegisterConfChannel chan *ConfRegistration
RegisterSpendChannel chan *SpendRegistration
SingleInvoiceSubcribeChannel chan *SingleInvoiceSubscription
RouterSendPaymentChannel chan RouterPaymentChannelMessage
TrackPaymentChannel chan TrackPaymentMessage
SignOutputRawChannel chan SignOutputRawRequest
2019-12-09 16:47:23 +01:00
Height int32
NodePubkey string
Signature []byte
SignatureMsg string
2019-03-06 21:13:50 +01:00
Transactions []lndclient.Transaction
Sweeps []string
SweepsVerbose []lnwallet.TransactionDetail
// Invoices is a set of invoices that have been created by the mock,
// keyed by hash string.
Invoices map[lntypes.Hash]*lndclient.Invoice
Channels []lndclient.ChannelInfo
ChannelEdges map[uint64]*lndclient.ChannelEdge
ClosedChannels []lndclient.ClosedChannel
ForwardingEvents []lndclient.ForwardingEvent
Payments []lndclient.Payment
ListPaymentsRequests []lndclient.ListPaymentsRequest
MissionControlState []lndclient.MissionControlEntry
2019-03-06 21:13:50 +01:00
WaitForFinished func()
PublishHandler PublishHandler
2019-03-06 21:13:50 +01:00
lock sync.Mutex
}
// EpochSubscribers returns the number of subscribers to block epoch
// notifications.
func (s *LndMockServices) EpochSubscribers() int32 {
s.lock.Lock()
defer s.lock.Unlock()
return int32(len(s.blockHeightListeners))
}
// ListPaymentsRequestsSnapshot returns a copy of all ListPayments requests
// recorded by the mock.
func (s *LndMockServices) ListPaymentsRequestsSnapshot() []lndclient.ListPaymentsRequest {
s.lock.Lock()
defer s.lock.Unlock()
requests := make(
[]lndclient.ListPaymentsRequest, len(s.ListPaymentsRequests),
)
copy(requests, s.ListPaymentsRequests)
return requests
}
2019-03-06 21:13:50 +01:00
// NotifyHeight notifies a new block height.
func (s *LndMockServices) NotifyHeight(height int32) error {
s.lock.Lock()
defer s.lock.Unlock()
2019-03-06 21:13:50 +01:00
s.Height = height
for _, listener := range s.blockHeightListeners {
lis := listener
go func() {
lis <- height
}()
2019-03-06 21:13:50 +01:00
}
2019-03-06 21:13:50 +01:00
return nil
}
// AddTx marks the given transaction as relevant.
func (s *LndMockServices) AddTx(tx *wire.MsgTx) {
s.lock.Lock()
s.Transactions = append(s.Transactions, lndclient.Transaction{
Tx: tx.Copy(),
})
s.lock.Unlock()
}
// SetInvoice stores a copy of the given invoice in the mock invoice store.
func (s *LndMockServices) SetInvoice(invoice *lndclient.Invoice) {
s.lock.Lock()
defer s.lock.Unlock()
invoiceCopy := *invoice
s.Invoices[invoice.Hash] = &invoiceCopy
}
2019-03-06 21:13:50 +01:00
// IsDone checks whether all channels have been fully emptied. If not this may
// indicate unexpected behaviour of the code under test.
func (s *LndMockServices) IsDone() error {
select {
case <-s.SpendChannel:
return errors.New("SpendChannel not empty")
default:
}
select {
case <-s.TxPublishChannel:
return errors.New("TxPublishChannel not empty")
default:
}
select {
case <-s.SendOutputsChannel:
return errors.New("SendOutputsChannel not empty")
default:
}
select {
case <-s.SettleInvoiceChannel:
return errors.New("SettleInvoiceChannel not empty")
default:
}
select {
case <-s.ConfChannel:
return errors.New("ConfChannel not empty")
default:
}
select {
case <-s.RegisterConfChannel:
return errors.New("RegisterConfChannel not empty")
default:
}
select {
case <-s.RegisterSpendChannel:
return errors.New("RegisterSpendChannel not empty")
default:
}
return nil
}
// DecodeInvoice decodes a payment request string.
func (s *LndMockServices) DecodeInvoice(request string) (*zpay32.Invoice,
error) {
return zpay32.Decode(request, s.ChainParams)
}
2019-10-01 11:21:17 -04:00
func (s *LndMockServices) SetFeeEstimate(confTarget int32,
feeEstimate chainfee.SatPerKWeight) {
2019-10-01 11:21:17 -04:00
2023-03-29 15:56:40 +02:00
s.LndServices.WalletKit.(*mockWalletKit).setFeeEstimate(
confTarget, feeEstimate,
)
2019-10-01 11:21:17 -04:00
}
2025-02-20 01:51:07 -03:00
func (s *LndMockServices) SetMinRelayFee(feeEstimate chainfee.SatPerKWeight) {
s.LndServices.WalletKit.(*mockWalletKit).setMinRelayFee(feeEstimate)
}
2025-08-22 14:44:04 +02:00
// SetListUnspent sets the list of UTXOs returned by the mock's WalletKit
// ListUnspent call.
func (s *LndMockServices) SetListUnspent(utxos []*lnwallet.Utxo) {
s.LndServices.WalletKit.(*mockWalletKit).setListUnspent(utxos)
}