2
0
mirror of https://github.com/lightninglabs/loop synced 2024-11-13 13:10:30 +00:00
loop/test/chainnotifier_mock.go

163 lines
3.3 KiB
Go
Raw Normal View History

2019-03-06 20:13:50 +00:00
package test
import (
"bytes"
2019-03-06 20:13:50 +00:00
"sync"
"time"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
"github.com/lightninglabs/lndclient"
2019-03-06 20:13:50 +00:00
"github.com/lightningnetwork/lnd/chainntnfs"
"golang.org/x/net/context"
)
type mockChainNotifier struct {
sync.Mutex
lnd *LndMockServices
confRegistrations []*ConfRegistration
wg sync.WaitGroup
2019-03-06 20:13:50 +00:00
}
// SpendRegistration contains registration details.
type SpendRegistration struct {
Outpoint *wire.OutPoint
PkScript []byte
HeightHint int32
}
// ConfRegistration contains registration details.
type ConfRegistration struct {
TxID *chainhash.Hash
PkScript []byte
HeightHint int32
NumConfs int32
ConfChan chan *chainntnfs.TxConfirmation
2019-03-06 20:13:50 +00:00
}
func (c *mockChainNotifier) RegisterSpendNtfn(ctx context.Context,
outpoint *wire.OutPoint, pkScript []byte, heightHint int32) (
chan *chainntnfs.SpendDetail, chan error, error) {
c.lnd.RegisterSpendChannel <- &SpendRegistration{
HeightHint: heightHint,
Outpoint: outpoint,
PkScript: pkScript,
}
spendChan := make(chan *chainntnfs.SpendDetail, 1)
errChan := make(chan error, 1)
c.wg.Add(1)
go func() {
defer c.wg.Done()
select {
case m := <-c.lnd.SpendChannel:
select {
case spendChan <- m:
case <-ctx.Done():
}
case <-ctx.Done():
}
}()
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)
blockEpochChan := make(chan int32)
c.wg.Add(1)
go func() {
defer c.wg.Done()
// Send initial block height
select {
case blockEpochChan <- c.lnd.Height:
case <-ctx.Done():
return
}
for {
select {
case m := <-c.lnd.epochChannel:
select {
case blockEpochChan <- m:
case <-ctx.Done():
return
}
case <-ctx.Done():
return
}
}
}()
return blockEpochChan, blockErrorChan, nil
}
func (c *mockChainNotifier) RegisterConfirmationsNtfn(ctx context.Context,
txid *chainhash.Hash, pkScript []byte, numConfs, heightHint int32,
opts ...lndclient.NotifierOption) (chan *chainntnfs.TxConfirmation,
chan error, error) {
2019-03-06 20:13:50 +00:00
reg := &ConfRegistration{
PkScript: pkScript,
TxID: txid,
HeightHint: heightHint,
NumConfs: numConfs,
ConfChan: make(chan *chainntnfs.TxConfirmation, 1),
}
c.Lock()
c.confRegistrations = append(c.confRegistrations, reg)
c.Unlock()
2019-03-06 20:13:50 +00:00
errChan := make(chan error, 1)
c.wg.Add(1)
go func() {
defer c.wg.Done()
select {
case m := <-c.lnd.ConfChannel:
c.Lock()
for i := 0; i < len(c.confRegistrations); i++ {
r := c.confRegistrations[i]
// Whichever conf notifier catches the confirmation
// will forward it to all matching subscibers.
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():
}
}
2019-03-06 20:13:50 +00:00
}
c.Unlock()
2019-03-06 20:13:50 +00:00
case <-ctx.Done():
}
}()
select {
case c.lnd.RegisterConfChannel <- reg:
2019-03-06 20:13:50 +00:00
case <-time.After(Timeout):
return nil, nil, ErrTimeout
}
return reg.ConfChan, errChan, nil
2019-03-06 20:13:50 +00:00
}