Browse Source

multi: finalize rename from uncharge to loop out

pull/9/head
Olaoluwa Osuntokun 2 years ago
parent
commit
94f347e673
No known key found for this signature in database GPG Key ID: CE58F7F8E20FD9A2
26 changed files with 656 additions and 572 deletions
  1. +29
    -28
      client.go
  2. +23
    -22
      client_test.go
  3. +177
    -0
      cmd/loop/commands.go
  4. +25
    -171
      cmd/loop/main.go
  5. +5
    -5
      cmd/loopd/daemon.go
  6. +3
    -3
      cmd/loopd/log.go
  7. +7
    -4
      cmd/loopd/main.go
  8. +37
    -35
      cmd/loopd/swapclient_server.go
  9. +5
    -3
      cmd/loopd/utils.go
  10. +4
    -4
      cmd/loopd/view.go
  11. +2
    -1
      config.go
  12. +7
    -3
      executor.go
  13. +41
    -31
      interface.go
  14. +10
    -10
      loopdb/interface.go
  15. +68
    -18
      loopdb/loopout.go
  16. +17
    -18
      loopdb/store.go
  17. +9
    -9
      loopdb/store_test.go
  18. +0
    -41
      loopdb/swapcontract.go
  19. +69
    -66
      loopout.go
  20. +6
    -5
      loopout_test.go
  21. +18
    -18
      server_mock_test.go
  22. +51
    -38
      store_mock_test.go
  23. +13
    -12
      swap.go
  24. +19
    -17
      swap_server_client.go
  25. +2
    -2
      sweep/sweeper.go
  26. +9
    -8
      testcontext_test.go

+ 29
- 28
client.go View File

@ -11,8 +11,9 @@ import (
"github.com/btcsuite/btcutil"
"github.com/lightninglabs/loop/lndclient"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/swap"
"github.com/lightninglabs/loop/sweep"
"github.com/lightninglabs/loop/utils"
"github.com/lightningnetwork/lnd/lntypes"
)
@ -66,7 +67,7 @@ type Client struct {
func NewClient(dbDir string, serverAddress string, insecure bool,
lnd *lndclient.LndServices) (*Client, func(), error) {
store, err := newBoltSwapClientStore(dbDir)
store, err := loopdb.NewBoltSwapStore(dbDir)
if err != nil {
return nil, nil, err
}
@ -112,9 +113,9 @@ func NewClient(dbDir string, serverAddress string, insecure bool,
return client, cleanup, nil
}
// GetUnchargeSwaps returns a list of all swaps currently in the database.
func (s *Client) GetUnchargeSwaps() ([]*PersistentUncharge, error) {
return s.Store.getUnchargeSwaps()
// FetchLoopOutSwaps returns a list of all swaps currently in the database.
func (s *Client) FetchLoopOutSwaps() ([]*loopdb.LoopOut, error) {
return s.Store.FetchLoopOutSwaps()
}
// Run is a blocking call that executes all swaps. Any pending swaps are
@ -143,7 +144,7 @@ func (s *Client) Run(ctx context.Context,
// Query store before starting event loop to prevent new swaps from
// being treated as swaps that need to be resumed.
pendingSwaps, err := s.Store.getUnchargeSwaps()
pendingSwaps, err := s.Store.FetchLoopOutSwaps()
if err != nil {
return err
}
@ -193,17 +194,17 @@ func (s *Client) Run(ctx context.Context,
// resumeSwaps restarts all pending swaps from the provided list.
func (s *Client) resumeSwaps(ctx context.Context,
swaps []*PersistentUncharge) {
swaps []*loopdb.LoopOut) {
for _, pend := range swaps {
if pend.State().Type() != StateTypePending {
if pend.State().Type() != loopdb.StateTypePending {
continue
}
swapCfg := &swapConfig{
lnd: s.lndServices,
store: s.Store,
}
swap, err := resumeUnchargeSwap(ctx, swapCfg, pend)
swap, err := resumeLoopOutSwap(ctx, swapCfg, pend)
if err != nil {
logger.Errorf("resuming swap: %v", err)
continue
@ -213,21 +214,21 @@ func (s *Client) resumeSwaps(ctx context.Context,
}
}
// Uncharge initiates a uncharge swap. It blocks until the swap is initiation
// LoopOut initiates a loop out swap. It blocks until the swap is initiation
// with the swap server is completed (typically this takes only a short amount
// of time). From there on further status information can be acquired through
// the status channel returned from the Run call.
//
// When the call returns, the swap has been persisted and will be
// resumed automatically after restarts.
// When the call returns, the swap has been persisted and will be resumed
// automatically after restarts.
//
// The return value is a hash that uniquely identifies the new swap.
func (s *Client) Uncharge(globalCtx context.Context,
request *UnchargeRequest) (*lntypes.Hash, error) {
func (s *Client) LoopOut(globalCtx context.Context,
request *OutRequest) (*lntypes.Hash, error) {
logger.Infof("Uncharge %v to %v (channel: %v)",
logger.Infof("LoopOut %v to %v (channel: %v)",
request.Amount, request.DestAddr,
request.UnchargeChannel,
request.LoopOutChannel,
)
if err := s.waitForInitialized(globalCtx); err != nil {
@ -241,7 +242,7 @@ func (s *Client) Uncharge(globalCtx context.Context,
store: s.Store,
server: s.Server,
}
swap, err := newUnchargeSwap(
swap, err := newLoopOutSwap(
globalCtx, swapCfg, initiationHeight, request,
)
if err != nil {
@ -256,13 +257,13 @@ func (s *Client) Uncharge(globalCtx context.Context,
return &swap.hash, nil
}
// UnchargeQuote takes a Uncharge amount and returns a break down of estimated
// LoopOutQuote takes a LoopOut amount and returns a break down of estimated
// costs for the client. Both the swap server and the on-chain fee estimator
// are queried to get to build the quote response.
func (s *Client) UnchargeQuote(ctx context.Context,
request *UnchargeQuoteRequest) (*UnchargeQuote, error) {
func (s *Client) LoopOutQuote(ctx context.Context,
request *LoopOutQuoteRequest) (*LoopOutQuote, error) {
terms, err := s.Server.GetUnchargeTerms(ctx)
terms, err := s.Server.GetLoopOutTerms(ctx)
if err != nil {
return nil, err
}
@ -277,30 +278,30 @@ func (s *Client) UnchargeQuote(ctx context.Context,
logger.Infof("Offchain swap destination: %x", terms.SwapPaymentDest)
swapFee := utils.CalcFee(
swapFee := swap.CalcFee(
request.Amount, terms.SwapFeeBase, terms.SwapFeeRate,
)
minerFee, err := s.sweeper.GetSweepFee(
ctx, utils.QuoteHtlc.MaxSuccessWitnessSize,
ctx, swap.QuoteHtlc.MaxSuccessWitnessSize,
request.SweepConfTarget,
)
if err != nil {
return nil, err
}
return &UnchargeQuote{
return &LoopOutQuote{
SwapFee: swapFee,
MinerFee: minerFee,
PrepayAmount: btcutil.Amount(terms.PrepayAmt),
}, nil
}
// UnchargeTerms returns the terms on which the server executes swaps.
func (s *Client) UnchargeTerms(ctx context.Context) (
*UnchargeTerms, error) {
// LoopOutTerms returns the terms on which the server executes swaps.
func (s *Client) LoopOutTerms(ctx context.Context) (
*LoopOutTerms, error) {
return s.Server.GetUnchargeTerms(ctx)
return s.Server.GetLoopOutTerms(ctx)
}
// waitForInitialized for swaps to be resumed and executor ready.

+ 23
- 22
client_test.go View File

@ -9,6 +9,7 @@ import (
"github.com/btcsuite/btcutil"
"github.com/lightninglabs/loop/lndclient"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/test"
"github.com/lightningnetwork/lnd/lntypes"
)
@ -17,7 +18,7 @@ var (
testAddr, _ = btcutil.DecodeAddress(
"rbsHiPKwAgxeo1EQYiyzJTkA8XEmWSVAKx", nil)
testRequest = &UnchargeRequest{
testRequest = &OutRequest{
Amount: btcutil.Amount(50000),
DestAddr: testAddr,
MaxMinerFee: 50000,
@ -40,13 +41,13 @@ func TestSuccess(t *testing.T) {
// Initiate uncharge.
hash, err := ctx.swapClient.Uncharge(context.Background(), testRequest)
hash, err := ctx.swapClient.LoopOut(context.Background(), testRequest)
if err != nil {
t.Fatal(err)
}
ctx.assertStored()
ctx.assertStatus(StateInitiated)
ctx.assertStatus(loopdb.StateInitiated)
signalSwapPaymentResult := ctx.AssertPaid(swapInvoiceDesc)
signalPrepaymentResult := ctx.AssertPaid(prepayInvoiceDesc)
@ -67,13 +68,13 @@ func TestFailOffchain(t *testing.T) {
ctx := createClientTestContext(t, nil)
_, err := ctx.swapClient.Uncharge(context.Background(), testRequest)
_, err := ctx.swapClient.LoopOut(context.Background(), testRequest)
if err != nil {
t.Fatal(err)
}
ctx.assertStored()
ctx.assertStatus(StateInitiated)
ctx.assertStatus(loopdb.StateInitiated)
signalSwapPaymentResult := ctx.AssertPaid(swapInvoiceDesc)
signalPrepaymentResult := ctx.AssertPaid(prepayInvoiceDesc)
@ -86,9 +87,9 @@ func TestFailOffchain(t *testing.T) {
signalPrepaymentResult(
errors.New(lndclient.PaymentResultUnknownPaymentHash),
)
ctx.assertStatus(StateFailOffchainPayments)
ctx.assertStatus(loopdb.StateFailOffchainPayments)
ctx.assertStoreFinished(StateFailOffchainPayments)
ctx.assertStoreFinished(loopdb.StateFailOffchainPayments)
ctx.finish()
}
@ -105,7 +106,7 @@ func TestFailWrongAmount(t *testing.T) {
// Modify mock for this subtest.
modifier(ctx.serverMock)
_, err := ctx.swapClient.Uncharge(
_, err := ctx.swapClient.LoopOut(
context.Background(), testRequest,
)
if err != expectedErr {
@ -175,17 +176,17 @@ func testResume(t *testing.T, expired, preimageRevealed, expectSuccess bool) {
var receiverKey [33]byte
copy(receiverKey[:], receiverPubKey.SerializeCompressed())
state := StateInitiated
state := loopdb.StateInitiated
if preimageRevealed {
state = StatePreimageRevealed
state = loopdb.StatePreimageRevealed
}
pendingSwap := &PersistentUncharge{
Contract: &UnchargeContract{
pendingSwap := &loopdb.LoopOut{
Contract: &loopdb.LoopOutContract{
DestAddr: dest,
SwapInvoice: swapPayReq,
SweepConfTarget: 2,
MaxSwapRoutingFee: 70000,
SwapContract: SwapContract{
SwapContract: loopdb.SwapContract{
Preimage: preimage,
AmountRequested: amt,
CltvExpiry: 744,
@ -196,7 +197,7 @@ func testResume(t *testing.T, expired, preimageRevealed, expectSuccess bool) {
MaxMinerFee: 50000,
},
},
Events: []*PersistentUnchargeEvent{
Events: []*loopdb.LoopOutEvent{
{
State: state,
},
@ -210,12 +211,12 @@ func testResume(t *testing.T, expired, preimageRevealed, expectSuccess bool) {
pendingSwap.Contract.CltvExpiry = 610
}
ctx := createClientTestContext(t, []*PersistentUncharge{pendingSwap})
ctx := createClientTestContext(t, []*loopdb.LoopOut{pendingSwap})
if preimageRevealed {
ctx.assertStatus(StatePreimageRevealed)
ctx.assertStatus(loopdb.StatePreimageRevealed)
} else {
ctx.assertStatus(StateInitiated)
ctx.assertStatus(loopdb.StateInitiated)
}
signalSwapPaymentResult := ctx.AssertPaid(swapInvoiceDesc)
@ -228,8 +229,8 @@ func testResume(t *testing.T, expired, preimageRevealed, expectSuccess bool) {
signalPrepaymentResult(nil)
if !expectSuccess {
ctx.assertStatus(StateFailTimeout)
ctx.assertStoreFinished(StateFailTimeout)
ctx.assertStatus(loopdb.StateFailTimeout)
ctx.assertStoreFinished(loopdb.StateFailTimeout)
ctx.finish()
return
}
@ -259,7 +260,7 @@ func testSuccess(ctx *testContext, amt btcutil.Amount, hash lntypes.Hash,
ctx.expiryChan <- testTime
if !preimageRevealed {
ctx.assertStatus(StatePreimageRevealed)
ctx.assertStatus(loopdb.StatePreimageRevealed)
ctx.assertStorePreimageReveal()
}
@ -283,9 +284,9 @@ func testSuccess(ctx *testContext, amt btcutil.Amount, hash lntypes.Hash,
ctx.NotifySpend(sweepTx, 0)
ctx.assertStatus(StateSuccess)
ctx.assertStatus(loopdb.StateSuccess)
ctx.assertStoreFinished(StateSuccess)
ctx.assertStoreFinished(loopdb.StateSuccess)
ctx.finish()
}

+ 177
- 0
cmd/loop/commands.go View File

@ -0,0 +1,177 @@
package main
import (
"context"
"fmt"
"github.com/btcsuite/btcutil"
"github.com/lightninglabs/loop/looprpc"
"github.com/lightninglabs/loop/swap"
"github.com/urfave/cli"
)
var loopOutCommand = cli.Command{
Name: "out",
Usage: "perform an off-chain to on-chain swap (looping out)",
ArgsUsage: "amt [addr]",
Description: `
Attempts loop out the target amount into either the backing lnd's
wallet, or a targeted address.
The amount is to be specified in satoshis.
Optionally a BASE58/bech32 encoded bitcoin destination address may be
specified. If not specified, a new wallet address will be generated.`,
Flags: []cli.Flag{
cli.Uint64Flag{
Name: "channel",
Usage: "the 8-byte compact channel ID of the channel to loop out",
},
},
Action: loopOut,
}
func loopOut(ctx *cli.Context) error {
// Show command help if no arguments and flags were provided.
if ctx.NArg() < 1 {
cli.ShowCommandHelp(ctx, "out")
return nil
}
args := ctx.Args()
amt, err := parseAmt(args[0])
if err != nil {
return err
}
var destAddr string
args = args.Tail()
if args.Present() {
destAddr = args.First()
}
client, cleanup, err := getClient(ctx)
if err != nil {
return err
}
defer cleanup()
quote, err := client.GetLoopOutQuote(
context.Background(),
&looprpc.QuoteRequest{
Amt: int64(amt),
},
)
if err != nil {
return err
}
limits := getLimits(amt, quote)
if err := displayLimits(amt, limits); err != nil {
return err
}
var unchargeChannel uint64
if ctx.IsSet("channel") {
unchargeChannel = ctx.Uint64("channel")
}
resp, err := client.LoopOut(context.Background(), &looprpc.LoopOutRequest{
Amt: int64(amt),
Dest: destAddr,
MaxMinerFee: int64(limits.maxMinerFee),
MaxPrepayAmt: int64(limits.maxPrepayAmt),
MaxSwapFee: int64(limits.maxSwapFee),
MaxPrepayRoutingFee: int64(limits.maxPrepayRoutingFee),
MaxSwapRoutingFee: int64(limits.maxSwapRoutingFee),
LoopOutChannel: unchargeChannel,
})
if err != nil {
return err
}
fmt.Printf("Swap initiated with id: %v\n", resp.Id[:8])
fmt.Printf("Run `loop monitor` to monitor progress.\n")
return nil
}
var termsCommand = cli.Command{
Name: "terms",
Usage: "show current server swap terms",
Action: terms,
}
func terms(ctx *cli.Context) error {
client, cleanup, err := getClient(ctx)
if err != nil {
return err
}
defer cleanup()
terms, err := client.GetLoopOutTerms(
context.Background(), &looprpc.TermsRequest{},
)
if err != nil {
return err
}
fmt.Printf("Amount: %d - %d\n",
btcutil.Amount(terms.MinSwapAmount),
btcutil.Amount(terms.MaxSwapAmount),
)
if err != nil {
return err
}
printTerms := func(terms *looprpc.TermsResponse) {
fmt.Printf("Amount: %d - %d\n",
btcutil.Amount(terms.MinSwapAmount),
btcutil.Amount(terms.MaxSwapAmount),
)
fmt.Printf("Fee: %d + %.4f %% (%d prepaid)\n",
btcutil.Amount(terms.SwapFeeBase),
swap.FeeRateAsPercentage(terms.SwapFeeRate),
btcutil.Amount(terms.PrepayAmt),
)
fmt.Printf("Cltv delta: %v blocks\n", terms.CltvDelta)
}
fmt.Println("Loop Out")
fmt.Println("--------")
printTerms(terms)
return nil
}
var monitorCommand = cli.Command{
Name: "monitor",
Usage: "monitor progress of any active swaps",
Description: "Allows the user to monitor progress of any active swaps",
Action: monitor,
}
func monitor(ctx *cli.Context) error {
client, cleanup, err := getClient(ctx)
if err != nil {
return err
}
defer cleanup()
stream, err := client.Monitor(
context.Background(), &looprpc.MonitorRequest{})
if err != nil {
return err
}
for {
swap, err := stream.Recv()
if err != nil {
return fmt.Errorf("recv: %v", err)
}
logSwap(swap)
}
}

+ 25
- 171
cmd/loop/main.go View File

@ -1,7 +1,6 @@
package main
import (
"context"
"errors"
"fmt"
"os"
@ -9,7 +8,7 @@ import (
"time"
"github.com/lightninglabs/loop/looprpc"
"github.com/lightninglabs/loop/utils"
"github.com/lightninglabs/loop/swap"
"github.com/btcsuite/btcutil"
@ -18,131 +17,50 @@ import (
)
var (
swapdAddress = "localhost:11010"
loopdAddress = "localhost:11010"
// Define route independent max routing fees. We have currently no way
// to get a reliable estimate of the routing fees. Best we can do is the
// minimum routing fees, which is not very indicative.
// to get a reliable estimate of the routing fees. Best we can do is
// the minimum routing fees, which is not very indicative.
maxRoutingFeeBase = btcutil.Amount(10)
maxRoutingFeeRate = int64(50000)
)
var unchargeCommand = cli.Command{
Name: "uncharge",
Usage: "perform an off-chain to on-chain swap",
ArgsUsage: "amt [addr]",
Description: `
Send the amount in satoshis specified by the amt argument on-chain.
Optionally a BASE58 encoded bitcoin destination address may be
specified. If not specified, a new wallet address will be generated.`,
Flags: []cli.Flag{
cli.Uint64Flag{
Name: "channel",
Usage: "the 8-byte compact channel ID of the channel to uncharge",
},
},
Action: uncharge,
}
var termsCommand = cli.Command{
Name: "terms",
Usage: "show current server swap terms",
Action: terms,
func fatal(err error) {
fmt.Fprintf(os.Stderr, "[loop] %v\n", err)
os.Exit(1)
}
func main() {
app := cli.NewApp()
app.Version = "0.0.1"
app.Usage = "command line interface to swapd"
app.Commands = []cli.Command{unchargeCommand, termsCommand}
app.Action = monitor
err := app.Run(os.Args)
if err != nil {
fmt.Println(err)
}
}
func terms(ctx *cli.Context) error {
client, cleanup, err := getClient(ctx)
if err != nil {
return err
}
defer cleanup()
terms, err := client.GetUnchargeTerms(
context.Background(), &looprpc.TermsRequest{},
)
if err != nil {
return err
app.Name = "loop"
app.Usage = "control plane for your loopd"
app.Commands = []cli.Command{
loopOutCommand, termsCommand, monitorCommand,
}
fmt.Printf("Amount: %d - %d\n",
btcutil.Amount(terms.MinSwapAmount),
btcutil.Amount(terms.MaxSwapAmount),
)
if err != nil {
return err
}
printTerms := func(terms *looprpc.TermsResponse) {
fmt.Printf("Amount: %d - %d\n",
btcutil.Amount(terms.MinSwapAmount),
btcutil.Amount(terms.MaxSwapAmount),
)
fmt.Printf("Fee: %d + %.4f %% (%d prepaid)\n",
btcutil.Amount(terms.SwapFeeBase),
utils.FeeRateAsPercentage(terms.SwapFeeRate),
btcutil.Amount(terms.PrepayAmt),
)
fmt.Printf("Cltv delta: %v blocks\n", terms.CltvDelta)
}
fmt.Println("Uncharge")
fmt.Println("--------")
printTerms(terms)
return nil
}
func monitor(ctx *cli.Context) error {
client, cleanup, err := getClient(ctx)
if err != nil {
return err
}
defer cleanup()
stream, err := client.Monitor(
context.Background(), &looprpc.MonitorRequest{})
err := app.Run(os.Args)
if err != nil {
return err
}
for {
swap, err := stream.Recv()
if err != nil {
return fmt.Errorf("recv: %v", err)
}
logSwap(swap)
fatal(err)
}
}
func getClient(ctx *cli.Context) (looprpc.SwapClientClient, func(), error) {
conn, err := getSwapCliConn(swapdAddress)
conn, err := getClientConn(loopdAddress)
if err != nil {
return nil, nil, err
}
cleanup := func() { conn.Close() }
swapCliClient := looprpc.NewSwapClientClient(conn)
return swapCliClient, cleanup, nil
loopClient := looprpc.NewSwapClientClient(conn)
return loopClient, cleanup, nil
}
func getMaxRoutingFee(amt btcutil.Amount) btcutil.Amount {
return utils.CalcFee(amt, maxRoutingFeeBase, maxRoutingFeeRate)
return swap.CalcFee(amt, maxRoutingFeeBase, maxRoutingFeeRate)
}
type limits struct {
@ -160,8 +78,8 @@ func getLimits(amt btcutil.Amount, quote *looprpc.QuoteResponse) *limits {
quote.PrepayAmt,
)),
// Apply a multiplier to the estimated miner fee, to not get the swap
// canceled because fees increased in the mean time.
// Apply a multiplier to the estimated miner fee, to not get
// the swap canceled because fees increased in the mean time.
maxMinerFee: btcutil.Amount(quote.MinerFee) * 3,
maxSwapFee: btcutil.Amount(quote.SwapFee),
@ -173,12 +91,15 @@ func displayLimits(amt btcutil.Amount, l *limits) error {
totalSuccessMax := l.maxSwapRoutingFee + l.maxPrepayRoutingFee +
l.maxMinerFee + l.maxSwapFee
fmt.Printf("Max swap fees for %d uncharge: %d\n",
fmt.Printf("Max swap fees for %d loop out: %d\n",
btcutil.Amount(amt), totalSuccessMax,
)
fmt.Printf("CONTINUE SWAP? (y/n), expand fee detail (x): ")
var answer string
fmt.Scanln(&answer)
switch answer {
case "y":
return nil
@ -211,73 +132,6 @@ func parseAmt(text string) (btcutil.Amount, error) {
return btcutil.Amount(amtInt64), nil
}
func uncharge(ctx *cli.Context) error {
// Show command help if no arguments and flags were provided.
if ctx.NArg() < 1 {
cli.ShowCommandHelp(ctx, "uncharge")
return nil
}
args := ctx.Args()
amt, err := parseAmt(args[0])
if err != nil {
return err
}
var destAddr string
args = args.Tail()
if args.Present() {
destAddr = args.First()
}
client, cleanup, err := getClient(ctx)
if err != nil {
return err
}
defer cleanup()
quote, err := client.GetUnchargeQuote(
context.Background(),
&looprpc.QuoteRequest{
Amt: int64(amt),
},
)
if err != nil {
return err
}
limits := getLimits(amt, quote)
if err := displayLimits(amt, limits); err != nil {
return err
}
var unchargeChannel uint64
if ctx.IsSet("channel") {
unchargeChannel = ctx.Uint64("channel")
}
resp, err := client.Uncharge(context.Background(), &looprpc.UnchargeRequest{
Amt: int64(amt),
Dest: destAddr,
MaxMinerFee: int64(limits.maxMinerFee),
MaxPrepayAmt: int64(limits.maxPrepayAmt),
MaxSwapFee: int64(limits.maxSwapFee),
MaxPrepayRoutingFee: int64(limits.maxPrepayRoutingFee),
MaxSwapRoutingFee: int64(limits.maxSwapRoutingFee),
UnchargeChannel: unchargeChannel,
})
if err != nil {
return err
}
fmt.Printf("Swap initiated with id: %v\n", resp.Id[:8])
fmt.Printf("Run swapcli without a command to monitor progress.\n")
return nil
}
func logSwap(swap *looprpc.SwapStatus) {
fmt.Printf("%v %v %v %v - %v\n",
time.Unix(0, swap.LastUpdateTime).Format(time.RFC3339),
@ -286,7 +140,7 @@ func logSwap(swap *looprpc.SwapStatus) {
)
}
func getSwapCliConn(address string) (*grpc.ClientConn, error) {
func getClientConn(address string) (*grpc.ClientConn, error) {
opts := []grpc.DialOption{
grpc.WithInsecure(),
}

+ 5
- 5
cmd/loopd/daemon.go View File

@ -10,7 +10,7 @@ import (
"sync"
"time"
"github.com/lightninglabs/loop/client"
"github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/looprpc"
"github.com/urfave/cli"
"google.golang.org/grpc"
@ -34,13 +34,13 @@ func daemon(ctx *cli.Context) error {
// Before starting the client, build an in-memory view of all swaps.
// This view is used to update newly connected clients with the most
// recent swaps.
storedSwaps, err := swapClient.GetUnchargeSwaps()
storedSwaps, err := swapClient.FetchLoopOutSwaps()
if err != nil {
return err
}
for _, swap := range storedSwaps {
swaps[swap.Hash] = client.SwapInfo{
SwapType: client.SwapTypeUncharge,
swaps[swap.Hash] = loop.SwapInfo{
SwapType: loop.TypeOut,
SwapContract: swap.Contract.SwapContract,
State: swap.State(),
SwapHash: swap.Hash,
@ -68,7 +68,7 @@ func daemon(ctx *cli.Context) error {
}
defer lis.Close()
statusChan := make(chan client.SwapInfo)
statusChan := make(chan loop.SwapInfo)
mainCtx, cancel := context.WithCancel(context.Background())
var wg sync.WaitGroup

+ 3
- 3
cmd/loopd/log.go View File

@ -6,9 +6,9 @@ import (
"github.com/btcsuite/btclog"
)
// log is a logger that is initialized with no output filters. This
// means the package will not perform any logging by default until the caller
// requests it.
// log is a logger that is initialized with no output filters. This means the
// package will not perform any logging by default until the caller requests
// it.
var (
backendLog = btclog.NewBackend(logWriter{})
logger = backendLog.Logger("SWAPD")

+ 7
- 4
cmd/loopd/main.go View File

@ -6,7 +6,7 @@ import (
"sync"
"github.com/btcsuite/btcutil"
"github.com/lightninglabs/loop/client"
"github.com/lightninglabs/loop"
"github.com/lightningnetwork/lnd/lntypes"
"github.com/urfave/cli"
)
@ -20,7 +20,7 @@ var (
defaultListenAddr = fmt.Sprintf("localhost:%d", defaultListenPort)
defaultSwapletDir = btcutil.AppDataDir("swaplet", false)
swaps = make(map[lntypes.Hash]client.SwapInfo)
swaps = make(map[lntypes.Hash]loop.SwapInfo)
subscribers = make(map[int]chan<- interface{})
nextSubscriberID int
swapsLock sync.Mutex
@ -58,9 +58,12 @@ func main() {
Usage: "disable tls",
},
}
app.Name = "loopd"
app.Version = "0.0.1"
app.Usage = "swaps execution daemon"
app.Commands = []cli.Command{viewCommand}
app.Usage = "Lightning Loop Client Daemon"
app.Commands = []cli.Command{
viewCommand,
}
app.Action = daemon
err := app.Run(os.Args)

+ 37
- 35
cmd/loopd/swapclient_server.go View File

@ -7,31 +7,32 @@ import (
"github.com/lightningnetwork/lnd/queue"
"github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/lndclient"
"github.com/lightninglabs/loop/utils"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/swap"
"github.com/btcsuite/btcutil"
"github.com/lightninglabs/loop/client"
"github.com/lightninglabs/loop/looprpc"
)
const completedSwapsCount = 5
// swapClientServer implements the grpc service exposed by swapd.
// swapClientServer implements the grpc service exposed by loopd.
type swapClientServer struct {
impl *client.Client
impl *loop.Client
lnd *lndclient.LndServices
}
// Uncharge initiates an uncharge swap with the given parameters. The call
// LoopOut initiates an loop out swap with the given parameters. The call
// returns after the swap has been set up with the swap server. From that point
// onwards, progress can be tracked via the UnchargeStatus stream that is
// onwards, progress can be tracked via the LoopOutStatus stream that is
// returned from Monitor().
func (s *swapClientServer) Uncharge(ctx context.Context,
in *looprpc.UnchargeRequest) (
func (s *swapClientServer) LoopOut(ctx context.Context,
in *looprpc.LoopOutRequest) (
*looprpc.SwapResponse, error) {
logger.Infof("Uncharge request received")
logger.Infof("LoopOut request received")
var sweepAddr btcutil.Address
if in.Dest == "" {
@ -49,7 +50,7 @@ func (s *swapClientServer) Uncharge(ctx context.Context,
}
}
req := &client.UnchargeRequest{
req := &loop.OutRequest{
Amount: btcutil.Amount(in.Amt),
DestAddr: sweepAddr,
MaxMinerFee: btcutil.Amount(in.MaxMinerFee),
@ -59,12 +60,12 @@ func (s *swapClientServer) Uncharge(ctx context.Context,
MaxSwapFee: btcutil.Amount(in.MaxSwapFee),
SweepConfTarget: defaultConfTarget,
}
if in.UnchargeChannel != 0 {
req.UnchargeChannel = &in.UnchargeChannel
if in.LoopOutChannel != 0 {
req.LoopOutChannel = &in.LoopOutChannel
}
hash, err := s.impl.Uncharge(ctx, req)
hash, err := s.impl.LoopOut(ctx, req)
if err != nil {
logger.Errorf("Uncharge: %v", err)
logger.Errorf("LoopOut: %v", err)
return nil, err
}
@ -73,24 +74,25 @@ func (s *swapClientServer) Uncharge(ctx context.Context,
}, nil
}
func (s *swapClientServer) marshallSwap(swap *client.SwapInfo) (
func (s *swapClientServer) marshallSwap(loopSwap *loop.SwapInfo) (
*looprpc.SwapStatus, error) {
var state looprpc.SwapState
switch swap.State {
case client.StateInitiated:
switch loopSwap.State {
case loopdb.StateInitiated:
state = looprpc.SwapState_INITIATED
case client.StatePreimageRevealed:
case loopdb.StatePreimageRevealed:
state = looprpc.SwapState_PREIMAGE_REVEALED
case client.StateSuccess:
case loopdb.StateSuccess:
state = looprpc.SwapState_SUCCESS
default:
// Return less granular status over rpc.
state = looprpc.SwapState_FAILED
}
htlc, err := utils.NewHtlc(swap.CltvExpiry, swap.SenderKey,
swap.ReceiverKey, swap.SwapHash,
htlc, err := swap.NewHtlc(
loopSwap.CltvExpiry, loopSwap.SenderKey, loopSwap.ReceiverKey,
loopSwap.SwapHash,
)
if err != nil {
return nil, err
@ -102,13 +104,13 @@ func (s *swapClientServer) marshallSwap(swap *client.SwapInfo) (
}
return &looprpc.SwapStatus{
Amt: int64(swap.AmountRequested),
Id: swap.SwapHash.String(),
Amt: int64(loopSwap.AmountRequested),
Id: loopSwap.SwapHash.String(),
State: state,
InitiationTime: swap.InitiationTime.UnixNano(),
LastUpdateTime: swap.LastUpdate.UnixNano(),
InitiationTime: loopSwap.InitiationTime.UnixNano(),
LastUpdateTime: loopSwap.LastUpdate.UnixNano(),
HtlcAddress: address.EncodeAddress(),
Type: looprpc.SwapType_UNCHARGE,
Type: looprpc.SwapType_LOOP_OUT,
}, nil
}
@ -118,7 +120,7 @@ func (s *swapClientServer) Monitor(in *looprpc.MonitorRequest,
logger.Infof("Monitor request received")
send := func(info client.SwapInfo) error {
send := func(info loop.SwapInfo) error {
rpcSwap, err := s.marshallSwap(&info)
if err != nil {
return err
@ -140,9 +142,9 @@ func (s *swapClientServer) Monitor(in *looprpc.MonitorRequest,
nextSubscriberID++
subscribers[id] = queue.ChanIn()
var pendingSwaps, completedSwaps []client.SwapInfo
var pendingSwaps, completedSwaps []loop.SwapInfo
for _, swap := range swaps {
if swap.State.Type() == client.StateTypePending {
if swap.State.Type() == loopdb.StateTypePending {
pendingSwaps = append(pendingSwaps, swap)
} else {
completedSwaps = append(completedSwaps, swap)
@ -196,7 +198,7 @@ func (s *swapClientServer) Monitor(in *looprpc.MonitorRequest,
return nil
}
swap := queueItem.(client.SwapInfo)
swap := queueItem.(loop.SwapInfo)
if err := send(swap); err != nil {
return err
}
@ -207,12 +209,12 @@ func (s *swapClientServer) Monitor(in *looprpc.MonitorRequest,
}
// GetTerms returns the terms that the server enforces for swaps.
func (s *swapClientServer) GetUnchargeTerms(ctx context.Context, req *looprpc.TermsRequest) (
*looprpc.TermsResponse, error) {
func (s *swapClientServer) GetLoopOutTerms(ctx context.Context,
req *looprpc.TermsRequest) (*looprpc.TermsResponse, error) {
logger.Infof("Terms request received")
terms, err := s.impl.UnchargeTerms(ctx)
terms, err := s.impl.LoopOutTerms(ctx)
if err != nil {
logger.Errorf("Terms request: %v", err)
return nil, err
@ -229,10 +231,10 @@ func (s *swapClientServer) GetUnchargeTerms(ctx context.Context, req *looprpc.Te
}
// GetQuote returns a quote for a swap with the provided parameters.
func (s *swapClientServer) GetUnchargeQuote(ctx context.Context,
func (s *swapClientServer) GetLoopOutQuote(ctx context.Context,
req *looprpc.QuoteRequest) (*looprpc.QuoteResponse, error) {
quote, err := s.impl.UnchargeQuote(ctx, &client.UnchargeQuoteRequest{
quote, err := s.impl.LoopOutQuote(ctx, &loop.LoopOutQuoteRequest{
Amount: btcutil.Amount(req.Amt),
SweepConfTarget: defaultConfTarget,
})

+ 5
- 3
cmd/loopd/utils.go View File

@ -4,7 +4,7 @@ import (
"os"
"path/filepath"
"github.com/lightninglabs/loop/client"
"github.com/lightninglabs/loop"
"github.com/lightninglabs/loop/lndclient"
"github.com/urfave/cli"
)
@ -20,7 +20,9 @@ func getLnd(ctx *cli.Context) (*lndclient.GrpcLndServices, error) {
}
// getClient returns an instance of the swap client.
func getClient(ctx *cli.Context, lnd *lndclient.LndServices) (*client.Client, func(), error) {
func getClient(ctx *cli.Context,
lnd *lndclient.LndServices) (*loop.Client, func(), error) {
network := ctx.GlobalString("network")
storeDir, err := getStoreDir(network)
@ -28,7 +30,7 @@ func getClient(ctx *cli.Context, lnd *lndclient.LndServices) (*client.Client, fu
return nil, nil, err
}
swapClient, cleanUp, err := client.NewClient(
swapClient, cleanUp, err := loop.NewClient(
storeDir, ctx.GlobalString("swapserver"),
ctx.GlobalBool("insecure"), lnd,
)

+ 4
- 4
cmd/loopd/view.go View File

@ -4,7 +4,7 @@ import (
"fmt"
"strconv"
"github.com/lightninglabs/loop/utils"
"github.com/lightninglabs/loop/swap"
"github.com/urfave/cli"
)
@ -21,7 +21,7 @@ var viewCommand = cli.Command{
func view(ctx *cli.Context) error {
network := ctx.GlobalString("network")
chainParams, err := utils.ChainParamsFromNetwork(network)
chainParams, err := swap.ChainParamsFromNetwork(network)
if err != nil {
return err
}
@ -38,13 +38,13 @@ func view(ctx *cli.Context) error {
}
defer cleanup()
swaps, err := swapClient.GetUnchargeSwaps()
swaps, err := swapClient.FetchLoopOutSwaps()
if err != nil {
return err
}
for _, s := range swaps {
htlc, err := utils.NewHtlc(
htlc, err := swap.NewHtlc(
s.Contract.CltvExpiry,
s.Contract.SenderKey,
s.Contract.ReceiverKey,

+ 2
- 1
config.go View File

@ -4,12 +4,13 @@ import (
"time"
"github.com/lightninglabs/loop/lndclient"
"github.com/lightninglabs/loop/loopdb"
)
// clientConfig contains config items for the swap client.
type clientConfig struct {
LndServices *lndclient.LndServices
Server swapServerClient
Store swapClientStore
Store loopdb.SwapStore
CreateExpiryTimer func(expiry time.Duration) <-chan time.Time
}

+ 7
- 3
executor.go View File

@ -8,15 +8,19 @@ import (
"time"
"github.com/lightninglabs/loop/lndclient"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightninglabs/loop/sweep"
"github.com/lightningnetwork/lnd/queue"
)
// executorConfig contains executor configuration data.
type executorConfig struct {
lnd *lndclient.LndServices
sweeper *sweep.Sweeper
store swapClientStore
lnd *lndclient.LndServices
sweeper *sweep.Sweeper
store loopdb.SwapStore
createExpiryTimer func(expiry time.Duration) <-chan time.Time
}

+ 41
- 31
interface.go View File

@ -4,11 +4,12 @@ import (
"time"
"github.com/btcsuite/btcutil"
"github.com/lightninglabs/loop/loopdb"
"github.com/lightningnetwork/lnd/lntypes"
)
// UnchargeRequest contains the required parameters for the swap.
type UnchargeRequest struct {
// OutRequest contains the required parameters for a loop out swap.
type OutRequest struct {
// Amount specifies the requested swap amount in sat. This does not
// include the swap and miner fee.
Amount btcutil.Amount
@ -19,19 +20,19 @@ type UnchargeRequest struct {
// MaxSwapRoutingFee is the maximum off-chain fee in msat that may be
// paid for payment to the server. This limit is applied during path
// finding. Typically this value is taken from the response of the
// UnchargeQuote call.
// LoopOutQuote call.
MaxSwapRoutingFee btcutil.Amount
// MaxPrepayRoutingFee is the maximum off-chain fee in msat that may be
// paid for payment to the server. This limit is applied during path
// finding. Typically this value is taken from the response of the
// UnchargeQuote call.
// LoopOutQuote call.
MaxPrepayRoutingFee btcutil.Amount
// MaxSwapFee is the maximum we are willing to pay the server for the
// swap. This value is not disclosed in the swap initiation call, but
// if the server asks for a higher fee, we abort the swap. Typically
// this value is taken from the response of the UnchargeQuote call. It
// this value is taken from the response of the LoopOutQuote call. It
// includes the prepay amount.
MaxSwapFee btcutil.Amount
@ -54,26 +55,32 @@ type UnchargeRequest struct {
// revocation.
//
// MaxMinerFee is typically taken from the response of the
// UnchargeQuote call.
// LoopOutQuote call.
MaxMinerFee btcutil.Amount
// SweepConfTarget specifies the targeted confirmation target for the
// client sweep tx.
SweepConfTarget int32
// UnchargeChannel optionally specifies the short channel id of the
// LoopOutChannel optionally specifies the short channel id of the
// channel to uncharge.
UnchargeChannel *uint64
LoopOutChannel *uint64
}
// UnchargeSwapInfo contains status information for a uncharge swap.
type UnchargeSwapInfo struct {
UnchargeContract
// Out contains the full details of a loop out request. This includes things
// like the payment hash, the total value, and the final CTLV delay of the
// swap. We'll use this to track an active swap throughout that various swap
// stages.
type Out struct {
// LoopOutContract describes the details of this loop.Out. Using these
// details,the full swap can be executed.
loopdb.LoopOutContract
SwapInfoKit
// State is the current state of the target swap.
State loopdb.SwapState
// State where the swap is in.
State SwapState
// SwapInfoKit contains shared data amongst all swap types.
SwapInfoKit
}
// SwapCost is a breakdown of the final swap costs.
@ -85,9 +92,9 @@ type SwapCost struct {
Onchain btcutil.Amount
}
// UnchargeQuoteRequest specifies the swap parameters for which a quote is
// LoopOutQuoteRequest specifies the swap parameters for which a quote is
// requested.
type UnchargeQuoteRequest struct {
type LoopOutQuoteRequest struct {
// Amount specifies the requested swap amount in sat. This does not
// include the swap and miner fee.
Amount btcutil.Amount
@ -107,9 +114,9 @@ type UnchargeQuoteRequest struct {
// final cltv delta values for the off-chain payments.
}
// UnchargeQuote contains estimates for the fees making up the total swap cost
// LoopOutQuote contains estimates for the fees making up the total swap cost
// for the client.
type UnchargeQuote struct {
type LoopOutQuote struct {
// SwapFee is the fee that the swap server is charging for the swap.
SwapFee btcutil.Amount
@ -122,8 +129,8 @@ type UnchargeQuote struct {
MinerFee btcutil.Amount
}
// UnchargeTerms are the server terms on which it executes swaps.
type UnchargeTerms struct {
// LoopOutTerms are the server terms on which it executes swaps.
type LoopOutTerms struct {
// SwapFeeBase is the fixed per-swap base fee.
SwapFeeBase btcutil.Amount
@ -161,23 +168,26 @@ type SwapInfoKit struct {
LastUpdateTime time.Time
}
// SwapType indicates the type of swap.
type SwapType uint8
// Type indicates the type of swap.
type Type uint8
const (
// SwapTypeCharge is a charge swap.
SwapTypeCharge SwapType = iota
// TypeIn is a loop in swap.
TypeIn Type = iota
// SwapTypeUncharge is an uncharge swap.
SwapTypeUncharge
// TypeOut is a loop out swap.
TypeOut
)
// SwapInfo exposes common info fields for charge and uncharge swaps.
// SwapInfo exposes common info fields for loop in and loop out swaps.
type SwapInfo struct {
LastUpdate time.Time
SwapHash lntypes.Hash
State SwapState
SwapType SwapType
SwapContract
SwapHash lntypes.Hash
State loopdb.SwapState
SwapType Type
loopdb.SwapContract
}

+ 10
- 10
loopdb/interface.go View File

@ -6,19 +6,19 @@ import (
"github.com/lightningnetwork/lnd/lntypes"
)
// SwapStore is the priamry database interface used by the loopd system. It
// houses informatino for all pending completed/failed swaps.
// SwapStore is the primary database interface used by the loopd system. It
// houses information for all pending completed/failed swaps.
type SwapStore interface {
// FetchUnchargeSwaps returns all swaps currently in the store.
FetchUnchargeSwaps() ([]*PersistentUncharge, error)
// FetchLoopOutSwaps returns all swaps currently in the store.
FetchLoopOutSwaps() ([]*LoopOut, error)
// CreateUncharge adds an initiated swap to the store.
CreateUncharge(hash lntypes.Hash, swap *UnchargeContract) error
// CreateLoopOut adds an initiated swap to the store.
CreateLoopOut(hash lntypes.Hash, swap *LoopOutContract) error
// UpdateUncharge stores a swap updateUncharge. This appends to the
// event log for a particular swap as it goes through the various
// stages in its lifetime.
UpdateUncharge(hash lntypes.Hash, time time.Time, state SwapState) error
// UpdateLoopOut stores a new event for a target loop out swap. This
// appends to the event log for a particular swap as it goes through
// the various stages in its lifetime.
UpdateLoopOut(hash lntypes.Hash, time time.Time, state SwapState) error
// Close closes the underlying database.
Close() error

loopdb/uncharge.go → loopdb/loopout.go View File

@ -12,13 +12,63 @@ import (
"github.com/lightningnetwork/lnd/lntypes"
)
// UnchargeContract contains the data that is serialized to persistent storage
// SwapContract contains the base data that is serialized to persistent storage
// for pending swaps.
type UnchargeContract struct {
type SwapContract struct {
// Preimage is the preimage for the swap.
Preimage lntypes.Preimage
// AmountRequested is the total amount of the swap.
AmountRequested btcutil.Amount
// PrepayInvoice is the invoice that the client should pay to the
// server that will be returned if the swap is complete.
PrepayInvoice string
// SenderKey is the key of the sender that will be used in the on-chain
// HTLC.
SenderKey [33]byte
// ReceiverKey is the of the receiver that will be used in the on-chain
// HTLC.
ReceiverKey [33]byte
// CltvExpiry is the total absolute CLTV expiry of the swap.
CltvExpiry int32
// MaxPrepayRoutingFee is the maximum off-chain fee in msat that may be
// paid for the prepayment to the server.
MaxPrepayRoutingFee btcutil.Amount
// MaxSwapFee is the maximum we are willing to pay the server for the
// swap.
MaxSwapFee btcutil.Amount
// MaxMinerFee is the maximum in on-chain fees that we are willing to
// spend.
MaxMinerFee btcutil.Amount
// InitiationHeight is the block height at which the swap was
// initiated.
InitiationHeight int32
// InitiationTime is the time at which the swap was initiated.
InitiationTime time.Time
}
// LoopOutContract contains the data that is serialized to persistent storage
// for pending swaps.
type LoopOutContract struct {
// SwapContract contains basic information pertaining to this swap.
// Each swap type has a base contract, then swap specific information
// on top of it.
SwapContract
// DestAddr is the destination address of the loop out swap.
DestAddr btcutil.Address
// SwapInvoice is the invoice that is to be paid by the client to
// initiate the loop out swap.
SwapInvoice string
// MaxSwapRoutingFee is the maximum off-chain fee in msat that may be
@ -29,13 +79,13 @@ type UnchargeContract struct {
// client sweep tx.
SweepConfTarget int32
// UnchargeChannel is the channel to uncharge. If zero, any channel may
// TargetChannel is the channel to loop out. If zero, any channel may
// be used.
UnchargeChannel *uint64
}
// PersistentUnchargeEvent contains the dynamic data of a swap.
type PersistentUnchargeEvent struct {
// LoopOutEvent contains the dynamic data of a swap.
type LoopOutEvent struct {
// State is the new state for this swap as a result of this event.
State SwapState
@ -43,22 +93,22 @@ type PersistentUnchargeEvent struct {
Time time.Time
}
// PersistentUncharge is a combination of the contract and the updates.
type PersistentUncharge struct {
// LoopOut is a combination of the contract and the updates.
type LoopOut struct {
// Hash is the hash that uniquely identifies this swap.
Hash lntypes.Hash
// Contract is the active contract for this swap. It describes the
// precise details of the swap including the final fee, CLTV value,
// etc.
Contract *UnchargeContract
Contract *LoopOutContract
// Events are each of the state transitions that this swap underwent.
Events []*PersistentUnchargeEvent
Events []*LoopOutEvent
}
// State returns the most recent state of this swap.
func (s *PersistentUncharge) State() SwapState {
func (s *LoopOut) State() SwapState {
lastUpdate := s.LastUpdate()
if lastUpdate == nil {
return StateInitiated
@ -68,7 +118,7 @@ func (s *PersistentUncharge) State() SwapState {
}
// LastUpdate returns the most recent update of this swap.
func (s *PersistentUncharge) LastUpdate() *PersistentUnchargeEvent {
func (s *LoopOut) LastUpdate() *LoopOutEvent {
eventCount := len(s.Events)
if eventCount == 0 {
@ -80,7 +130,7 @@ func (s *PersistentUncharge) LastUpdate() *PersistentUnchargeEvent {
}
// LastUpdateTime returns the last update time of this swap.
func (s *PersistentUncharge) LastUpdateTime() time.Time {
func (s *LoopOut) LastUpdateTime() time.Time {
lastUpdate := s.LastUpdate()
if lastUpdate == nil {
return s.Contract.InitiationTime
@ -89,7 +139,7 @@ func (s *PersistentUncharge) LastUpdateTime() time.Time {
return lastUpdate.Time
}
func deserializeUnchargeContract(value []byte) (*UnchargeContract, error) {
func deserializeLoopOutContract(value []byte) (*LoopOutContract, error) {
r := bytes.NewReader(value)
contract, err := deserializeContract(r)
@ -97,7 +147,7 @@ func deserializeUnchargeContract(value []byte) (*UnchargeContract, error) {
return nil, err
}
swap := UnchargeContract{
swap := LoopOutContract{
SwapContract: *contract,
}
@ -134,7 +184,7 @@ func deserializeUnchargeContract(value []byte) (*UnchargeContract, error) {
return &swap, nil
}
func serializeUnchargeContract(swap *UnchargeContract) (
func serializeLoopOutContract(swap *LoopOutContract) (
[]byte, error) {
var b bytes.Buffer
@ -282,7 +332,7 @@ func serializeContract(swap *SwapContract, b *bytes.Buffer) error {
return nil
}
func serializeUnchargeUpdate(time time.Time, state SwapState) (
func serializeLoopOutEvent(time time.Time, state SwapState) (
[]byte, error) {
var b bytes.Buffer
@ -298,8 +348,8 @@ func serializeUnchargeUpdate(time time.Time, state SwapState) (
return b.Bytes(), nil
}
func deserializeUnchargeUpdate(value []byte) (*PersistentUnchargeEvent, error) {
update := &PersistentUnchargeEvent{}
func deserializeLoopOutEvent(value []byte) (*LoopOutEvent, error) {
update := &LoopOutEvent{}
r := bytes.NewReader(value)

+ 17
- 18
loopdb/store.go View File

@ -67,9 +67,8 @@ type boltSwapStore struct {
// interface.
var _ = (*boltSwapStore)(nil)
// newBoltSwapStore creates a new client swap store.
func newBoltSwapStore(dbPath string) (*boltSwapStore, error) {
// NewBoltSwapStore creates a new client swap store.
func NewBoltSwapStore(dbPath string) (*boltSwapStore, error) {
// If the target path for the swap store doesn't exist, then we'll
// create it now before we proceed.
if !fileExists(dbPath) {
@ -119,11 +118,11 @@ func newBoltSwapStore(dbPath string) (*boltSwapStore, error) {
</