2019-03-06 21:13:50 +01:00
|
|
|
package test
|
|
|
|
|
|
|
|
|
|
import (
|
2020-04-06 10:58:50 +02:00
|
|
|
"bytes"
|
2025-07-08 00:14:02 -03:00
|
|
|
"context"
|
2019-03-06 21:13:50 +01:00
|
|
|
"sync"
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
|
|
|
|
"github.com/btcsuite/btcd/wire"
|
2023-01-09 16:36:52 +01:00
|
|
|
"github.com/lightninglabs/lndclient"
|
2019-03-06 21:13:50 +01:00
|
|
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
2024-04-03 13:01:12 +02:00
|
|
|
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
|
2019-03-06 21:13:50 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
type mockChainNotifier struct {
|
2024-09-02 18:49:22 +02:00
|
|
|
lndclient.ChainNotifierClient
|
2020-04-07 10:57:21 +02:00
|
|
|
sync.Mutex
|
2025-08-19 17:06:42 +02:00
|
|
|
|
2020-04-07 10:57:21 +02:00
|
|
|
lnd *LndMockServices
|
|
|
|
|
confRegistrations []*ConfRegistration
|
|
|
|
|
wg sync.WaitGroup
|
2019-03-06 21:13:50 +01:00
|
|
|
}
|
|
|
|
|
|
2024-04-03 13:01:12 +02:00
|
|
|
var _ lndclient.ChainNotifierClient = (*mockChainNotifier)(nil)
|
|
|
|
|
|
|
|
|
|
func (c *mockChainNotifier) RawClientWithMacAuth(
|
|
|
|
|
ctx context.Context) (context.Context, time.Duration,
|
|
|
|
|
chainrpc.ChainNotifierClient) {
|
|
|
|
|
|
|
|
|
|
return ctx, 0, nil
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-06 21:13:50 +01:00
|
|
|
// SpendRegistration contains registration details.
|
|
|
|
|
type SpendRegistration struct {
|
2025-04-28 02:07:40 -03:00
|
|
|
Outpoint *wire.OutPoint
|
|
|
|
|
PkScript []byte
|
|
|
|
|
HeightHint int32
|
|
|
|
|
SpendChannel chan<- *chainntnfs.SpendDetail
|
|
|
|
|
ErrChan chan<- error
|
2019-03-06 21:13:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// ConfRegistration contains registration details.
|
|
|
|
|
type ConfRegistration struct {
|
|
|
|
|
TxID *chainhash.Hash
|
|
|
|
|
PkScript []byte
|
|
|
|
|
HeightHint int32
|
|
|
|
|
NumConfs int32
|
2020-04-07 10:57:21 +02:00
|
|
|
ConfChan chan *chainntnfs.TxConfirmation
|
2025-04-08 18:40:36 -03:00
|
|
|
ErrChan chan<- error
|
2019-03-06 21:13:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *mockChainNotifier) RegisterSpendNtfn(ctx context.Context,
|
2025-07-16 18:53:57 +02:00
|
|
|
outpoint *wire.OutPoint, pkScript []byte, heightHint int32,
|
|
|
|
|
_ ...lndclient.NotifierOption) (chan *chainntnfs.SpendDetail,
|
|
|
|
|
chan error, error) {
|
2019-03-06 21:13:50 +01:00
|
|
|
|
2025-04-28 02:07:40 -03:00
|
|
|
spendChan0 := make(chan *chainntnfs.SpendDetail)
|
2025-04-08 18:40:36 -03:00
|
|
|
spendErrChan := make(chan error, 1)
|
|
|
|
|
|
|
|
|
|
reg := &SpendRegistration{
|
2025-04-28 02:07:40 -03:00
|
|
|
HeightHint: heightHint,
|
|
|
|
|
Outpoint: outpoint,
|
|
|
|
|
PkScript: pkScript,
|
|
|
|
|
SpendChannel: spendChan0,
|
|
|
|
|
ErrChan: spendErrChan,
|
2019-03-06 21:13:50 +01:00
|
|
|
}
|
|
|
|
|
|
2025-04-08 18:40:36 -03:00
|
|
|
c.lnd.RegisterSpendChannel <- reg
|
|
|
|
|
|
2019-03-06 21:13:50 +01:00
|
|
|
spendChan := make(chan *chainntnfs.SpendDetail, 1)
|
|
|
|
|
errChan := make(chan error, 1)
|
|
|
|
|
|
2026-03-05 12:18:05 +01:00
|
|
|
c.wg.Go(func() {
|
2019-03-06 21:13:50 +01:00
|
|
|
select {
|
|
|
|
|
case m := <-c.lnd.SpendChannel:
|
|
|
|
|
select {
|
|
|
|
|
case spendChan <- m:
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
}
|
2025-04-08 18:40:36 -03:00
|
|
|
|
2025-04-28 02:07:40 -03:00
|
|
|
case m := <-spendChan0:
|
|
|
|
|
select {
|
|
|
|
|
case spendChan <- m:
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
}
|
|
|
|
|
|
2025-04-08 18:40:36 -03:00
|
|
|
case err := <-spendErrChan:
|
|
|
|
|
select {
|
|
|
|
|
case errChan <- err:
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-06 21:13:50 +01:00
|
|
|
case <-ctx.Done():
|
|
|
|
|
}
|
2026-03-05 12:18:05 +01:00
|
|
|
})
|
2019-03-06 21:13:50 +01:00
|
|
|
|
|
|
|
|
return spendChan, errChan, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *mockChainNotifier) WaitForFinished() {
|
|
|
|
|
c.wg.Wait()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *mockChainNotifier) RegisterBlockEpochNtfn(ctx context.Context) (
|
|
|
|
|
chan int32, chan error, error) {
|
|
|
|
|
|
|
|
|
|
blockErrorChan := make(chan error, 1)
|
2024-01-15 17:07:25 +01:00
|
|
|
blockEpochChan := make(chan int32, 1)
|
|
|
|
|
|
|
|
|
|
c.lnd.lock.Lock()
|
|
|
|
|
c.lnd.blockHeightListeners = append(
|
|
|
|
|
c.lnd.blockHeightListeners, blockEpochChan,
|
|
|
|
|
)
|
|
|
|
|
c.lnd.lock.Unlock()
|
2019-03-06 21:13:50 +01:00
|
|
|
|
2026-03-05 12:18:05 +01:00
|
|
|
c.wg.Go(func() {
|
2024-01-15 17:07:25 +01:00
|
|
|
defer func() {
|
|
|
|
|
c.lnd.lock.Lock()
|
|
|
|
|
defer c.lnd.lock.Unlock()
|
2026-03-05 12:18:05 +01:00
|
|
|
for i := range len(c.lnd.blockHeightListeners) {
|
2024-01-15 17:07:25 +01:00
|
|
|
if c.lnd.blockHeightListeners[i] == blockEpochChan {
|
|
|
|
|
c.lnd.blockHeightListeners = append(
|
|
|
|
|
c.lnd.blockHeightListeners[:i],
|
|
|
|
|
c.lnd.blockHeightListeners[i+1:]...,
|
|
|
|
|
)
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}()
|
2019-03-06 21:13:50 +01:00
|
|
|
|
|
|
|
|
// Send initial block height
|
2024-01-15 17:07:25 +01:00
|
|
|
c.lnd.lock.Lock()
|
2019-03-06 21:13:50 +01:00
|
|
|
select {
|
|
|
|
|
case blockEpochChan <- c.lnd.Height:
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
}
|
2024-01-15 17:07:25 +01:00
|
|
|
c.lnd.lock.Unlock()
|
2019-03-06 21:13:50 +01:00
|
|
|
|
2024-01-15 17:07:25 +01:00
|
|
|
<-ctx.Done()
|
2026-03-05 12:18:05 +01:00
|
|
|
})
|
2019-03-06 21:13:50 +01:00
|
|
|
|
|
|
|
|
return blockEpochChan, blockErrorChan, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func (c *mockChainNotifier) RegisterConfirmationsNtfn(ctx context.Context,
|
2023-01-09 16:36:52 +01:00
|
|
|
txid *chainhash.Hash, pkScript []byte, numConfs, heightHint int32,
|
|
|
|
|
opts ...lndclient.NotifierOption) (chan *chainntnfs.TxConfirmation,
|
|
|
|
|
chan error, error) {
|
2019-03-06 21:13:50 +01:00
|
|
|
|
2025-04-08 18:40:36 -03:00
|
|
|
confErrChan := make(chan error, 1)
|
|
|
|
|
|
2020-04-07 10:57:21 +02:00
|
|
|
reg := &ConfRegistration{
|
|
|
|
|
PkScript: pkScript,
|
|
|
|
|
TxID: txid,
|
|
|
|
|
HeightHint: heightHint,
|
|
|
|
|
NumConfs: numConfs,
|
|
|
|
|
ConfChan: make(chan *chainntnfs.TxConfirmation, 1),
|
2025-04-08 18:40:36 -03:00
|
|
|
ErrChan: confErrChan,
|
2020-04-07 10:57:21 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c.Lock()
|
|
|
|
|
c.confRegistrations = append(c.confRegistrations, reg)
|
|
|
|
|
c.Unlock()
|
|
|
|
|
|
2019-03-06 21:13:50 +01:00
|
|
|
errChan := make(chan error, 1)
|
|
|
|
|
|
2026-03-05 12:18:05 +01:00
|
|
|
c.wg.Go(func() {
|
2019-03-06 21:13:50 +01:00
|
|
|
select {
|
|
|
|
|
case m := <-c.lnd.ConfChannel:
|
2020-04-07 10:57:21 +02:00
|
|
|
c.Lock()
|
|
|
|
|
for i := 0; i < len(c.confRegistrations); i++ {
|
|
|
|
|
r := c.confRegistrations[i]
|
|
|
|
|
|
|
|
|
|
// Whichever conf notifier catches the confirmation
|
2024-01-12 20:56:44 +08:00
|
|
|
// will forward it to all matching subscribers.
|
2020-04-07 10:57:21 +02:00
|
|
|
if bytes.Equal(m.Tx.TxOut[0].PkScript, r.PkScript) {
|
|
|
|
|
// Unregister the "notifier".
|
|
|
|
|
c.confRegistrations = append(
|
|
|
|
|
c.confRegistrations[:i], c.confRegistrations[i+1:]...,
|
|
|
|
|
)
|
|
|
|
|
i--
|
|
|
|
|
|
|
|
|
|
select {
|
|
|
|
|
case r.ConfChan <- m:
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
}
|
2020-04-06 10:58:50 +02:00
|
|
|
}
|
2019-03-06 21:13:50 +01:00
|
|
|
}
|
2020-04-07 10:57:21 +02:00
|
|
|
c.Unlock()
|
2025-04-08 18:40:36 -03:00
|
|
|
|
|
|
|
|
case err := <-confErrChan:
|
|
|
|
|
select {
|
|
|
|
|
case errChan <- err:
|
|
|
|
|
case <-ctx.Done():
|
|
|
|
|
}
|
|
|
|
|
|
2019-03-06 21:13:50 +01:00
|
|
|
case <-ctx.Done():
|
|
|
|
|
}
|
2026-03-05 12:18:05 +01:00
|
|
|
})
|
2019-03-06 21:13:50 +01:00
|
|
|
|
|
|
|
|
select {
|
2020-04-07 10:57:21 +02:00
|
|
|
case c.lnd.RegisterConfChannel <- reg:
|
2019-03-06 21:13:50 +01:00
|
|
|
case <-time.After(Timeout):
|
|
|
|
|
return nil, nil, ErrTimeout
|
|
|
|
|
}
|
|
|
|
|
|
2020-04-07 10:57:21 +02:00
|
|
|
return reg.ConfChan, errChan, nil
|
2019-03-06 21:13:50 +01:00
|
|
|
}
|