|
|
@ -5,8 +5,10 @@ import (
|
|
|
|
"errors"
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"fmt"
|
|
|
|
"sort"
|
|
|
|
"sort"
|
|
|
|
|
|
|
|
"sync"
|
|
|
|
"time"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/lightningnetwork/lnd/lntypes"
|
|
|
|
"github.com/lightningnetwork/lnd/queue"
|
|
|
|
"github.com/lightningnetwork/lnd/queue"
|
|
|
|
|
|
|
|
|
|
|
|
"github.com/lightninglabs/loop"
|
|
|
|
"github.com/lightninglabs/loop"
|
|
|
@ -29,8 +31,13 @@ const (
|
|
|
|
|
|
|
|
|
|
|
|
// swapClientServer implements the grpc service exposed by loopd.
|
|
|
|
// swapClientServer implements the grpc service exposed by loopd.
|
|
|
|
type swapClientServer struct {
|
|
|
|
type swapClientServer struct {
|
|
|
|
impl *loop.Client
|
|
|
|
impl *loop.Client
|
|
|
|
lnd *lndclient.LndServices
|
|
|
|
lnd *lndclient.LndServices
|
|
|
|
|
|
|
|
swaps map[lntypes.Hash]loop.SwapInfo
|
|
|
|
|
|
|
|
subscribers map[int]chan<- interface{}
|
|
|
|
|
|
|
|
statusChan chan loop.SwapInfo
|
|
|
|
|
|
|
|
nextSubscriberID int
|
|
|
|
|
|
|
|
swapsLock sync.Mutex
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// LoopOut initiates an loop out swap with the given parameters. The call
|
|
|
|
// LoopOut initiates an loop out swap with the given parameters. The call
|
|
|
@ -162,14 +169,14 @@ func (s *swapClientServer) Monitor(in *looprpc.MonitorRequest,
|
|
|
|
// Add this subscriber to the global subscriber list. Also create a
|
|
|
|
// Add this subscriber to the global subscriber list. Also create a
|
|
|
|
// snapshot of all pending and completed swaps within the lock, to
|
|
|
|
// snapshot of all pending and completed swaps within the lock, to
|
|
|
|
// prevent subscribers from receiving duplicate updates.
|
|
|
|
// prevent subscribers from receiving duplicate updates.
|
|
|
|
swapsLock.Lock()
|
|
|
|
s.swapsLock.Lock()
|
|
|
|
|
|
|
|
|
|
|
|
id := nextSubscriberID
|
|
|
|
id := s.nextSubscriberID
|
|
|
|
nextSubscriberID++
|
|
|
|
s.nextSubscriberID++
|
|
|
|
subscribers[id] = queue.ChanIn()
|
|
|
|
s.subscribers[id] = queue.ChanIn()
|
|
|
|
|
|
|
|
|
|
|
|
var pendingSwaps, completedSwaps []loop.SwapInfo
|
|
|
|
var pendingSwaps, completedSwaps []loop.SwapInfo
|
|
|
|
for _, swap := range swaps {
|
|
|
|
for _, swap := range s.swaps {
|
|
|
|
if swap.State.Type() == loopdb.StateTypePending {
|
|
|
|
if swap.State.Type() == loopdb.StateTypePending {
|
|
|
|
pendingSwaps = append(pendingSwaps, swap)
|
|
|
|
pendingSwaps = append(pendingSwaps, swap)
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
@ -177,13 +184,13 @@ func (s *swapClientServer) Monitor(in *looprpc.MonitorRequest,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
swapsLock.Unlock()
|
|
|
|
s.swapsLock.Unlock()
|
|
|
|
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
defer func() {
|
|
|
|
queue.Stop()
|
|
|
|
queue.Stop()
|
|
|
|
swapsLock.Lock()
|
|
|
|
s.swapsLock.Lock()
|
|
|
|
delete(subscribers, id)
|
|
|
|
delete(s.subscribers, id)
|
|
|
|
swapsLock.Unlock()
|
|
|
|
s.swapsLock.Unlock()
|
|
|
|
}()
|
|
|
|
}()
|
|
|
|
|
|
|
|
|
|
|
|
// Sort completed swaps new to old.
|
|
|
|
// Sort completed swaps new to old.
|
|
|
@ -383,6 +390,36 @@ func (s *swapClientServer) GetLsatTokens(ctx context.Context,
|
|
|
|
return &looprpc.TokensResponse{Tokens: rpcTokens}, nil
|
|
|
|
return &looprpc.TokensResponse{Tokens: rpcTokens}, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// processStatusUpdates reads updates on the status channel and processes them.
|
|
|
|
|
|
|
|
//
|
|
|
|
|
|
|
|
// NOTE: This must run inside a goroutine as it blocks until the main context
|
|
|
|
|
|
|
|
// shuts down.
|
|
|
|
|
|
|
|
func (s *swapClientServer) processStatusUpdates(mainCtx context.Context) {
|
|
|
|
|
|
|
|
for {
|
|
|
|
|
|
|
|
select {
|
|
|
|
|
|
|
|
// On updates, refresh the server's in-memory state and inform
|
|
|
|
|
|
|
|
// subscribers about the changes.
|
|
|
|
|
|
|
|
case swp := <-s.statusChan:
|
|
|
|
|
|
|
|
s.swapsLock.Lock()
|
|
|
|
|
|
|
|
s.swaps[swp.SwapHash] = swp
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for _, subscriber := range s.subscribers {
|
|
|
|
|
|
|
|
select {
|
|
|
|
|
|
|
|
case subscriber <- swp:
|
|
|
|
|
|
|
|
case <-mainCtx.Done():
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
s.swapsLock.Unlock()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Server is shutting down.
|
|
|
|
|
|
|
|
case <-mainCtx.Done():
|
|
|
|
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// validateConfTarget ensures the given confirmation target is valid. If one
|
|
|
|
// validateConfTarget ensures the given confirmation target is valid. If one
|
|
|
|
// isn't specified (0 value), then the default target is used.
|
|
|
|
// isn't specified (0 value), then the default target is used.
|
|
|
|
func validateConfTarget(target, defaultTarget int32) (int32, error) {
|
|
|
|
func validateConfTarget(target, defaultTarget int32) (int32, error) {
|
|
|
|