From 8451f29f8f1455c6ce84fdff1495434001dd1d9f Mon Sep 17 00:00:00 2001 From: sputn1ck Date: Thu, 9 Jan 2025 17:08:33 +0100 Subject: [PATCH] loopd: add asset client to swap config --- client.go | 12 +++++++++--- loopd/config.go | 4 ++++ loopd/daemon.go | 31 ++++++++++++++++++++++++++++++- loopd/swapclient_server.go | 2 ++ loopd/utils.go | 6 ++++-- loopd/view.go | 11 ++++++++++- loopin_test.go | 8 ++++---- loopout_test.go | 10 +++++----- swap.go | 5 ++++- 9 files changed, 72 insertions(+), 17 deletions(-) diff --git a/client.go b/client.go index 47a875ea..a1d19cfd 100644 --- a/client.go +++ b/client.go @@ -14,6 +14,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/lightninglabs/aperture/l402" "github.com/lightninglabs/lndclient" + "github.com/lightninglabs/loop/assets" "github.com/lightninglabs/loop/loopdb" "github.com/lightninglabs/loop/swap" "github.com/lightninglabs/loop/sweep" @@ -94,6 +95,7 @@ type Client struct { lndServices *lndclient.LndServices sweeper *sweep.Sweeper executor *executor + assetClient *assets.TapdClient resumeReady chan struct{} wg sync.WaitGroup @@ -121,6 +123,9 @@ type ClientConfig struct { // Lnd is an instance of the lnd proxy. Lnd *lndclient.LndServices + // AssetClient is an instance of the assets client. + AssetClient *assets.TapdClient + // MaxL402Cost is the maximum price we are willing to pay to the server // for the token. MaxL402Cost btcutil.Amount @@ -273,6 +278,7 @@ func NewClient(dbDir string, loopDB loopdb.SwapStore, errChan: make(chan error), clientConfig: *config, lndServices: cfg.Lnd, + assetClient: cfg.AssetClient, sweeper: sweeper, executor: executor, resumeReady: make(chan struct{}), @@ -453,7 +459,7 @@ func (s *Client) Run(ctx context.Context, statusChan chan<- SwapInfo) error { func (s *Client) resumeSwaps(ctx context.Context, loopOutSwaps []*loopdb.LoopOut, loopInSwaps []*loopdb.LoopIn) { - swapCfg := newSwapConfig(s.lndServices, s.Store, s.Server) + swapCfg := newSwapConfig(s.lndServices, s.Store, s.Server, s.assetClient) for _, pend := range loopOutSwaps { if pend.State().State.Type() != loopdb.StateTypePending { @@ -523,7 +529,7 @@ func (s *Client) LoopOut(globalCtx context.Context, } // Create a new swap object for this swap. - swapCfg := newSwapConfig(s.lndServices, s.Store, s.Server) + swapCfg := newSwapConfig(s.lndServices, s.Store, s.Server, s.assetClient) initResult, err := newLoopOutSwap( globalCtx, swapCfg, initiationHeight, request, ) @@ -682,7 +688,7 @@ func (s *Client) LoopIn(globalCtx context.Context, // Create a new swap object for this swap. initiationHeight := s.executor.height() - swapCfg := newSwapConfig(s.lndServices, s.Store, s.Server) + swapCfg := newSwapConfig(s.lndServices, s.Store, s.Server, s.assetClient) initResult, err := newLoopInSwap( globalCtx, swapCfg, initiationHeight, request, ) diff --git a/loopd/config.go b/loopd/config.go index df77bf54..b4f3395b 100644 --- a/loopd/config.go +++ b/loopd/config.go @@ -11,6 +11,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/lightninglabs/aperture/l402" + "github.com/lightninglabs/loop/assets" "github.com/lightninglabs/loop/loopdb" "github.com/lightningnetwork/lnd/cert" "github.com/lightningnetwork/lnd/lncfg" @@ -196,6 +197,8 @@ type Config struct { Server *loopServerConfig `group:"server" namespace:"server"` + Tapd *assets.TapdConfig `group:"tapd" namespace:"tapd"` + View viewParameters `command:"view" alias:"v" description:"View all swaps in the database. This command can only be executed when loopd is not running."` } @@ -214,6 +217,7 @@ func DefaultConfig() Config { Server: &loopServerConfig{ NoTLS: false, }, + Tapd: assets.DefaultTapdConfig(), LoopDir: LoopDirBase, ConfigFile: defaultConfigFile, DataDir: LoopDirBase, diff --git a/loopd/daemon.go b/loopd/daemon.go index 006c195d..bdd2c951 100644 --- a/loopd/daemon.go +++ b/loopd/daemon.go @@ -16,6 +16,7 @@ import ( proxy "github.com/grpc-ecosystem/grpc-gateway/v2/runtime" "github.com/lightninglabs/lndclient" "github.com/lightninglabs/loop" + "github.com/lightninglabs/loop/assets" "github.com/lightninglabs/loop/instantout" "github.com/lightninglabs/loop/instantout/reservation" "github.com/lightninglabs/loop/loopd/perms" @@ -28,6 +29,7 @@ import ( "github.com/lightninglabs/loop/staticaddr/withdraw" loop_swaprpc "github.com/lightninglabs/loop/swapserverrpc" "github.com/lightninglabs/loop/sweepbatcher" + "github.com/lightninglabs/taproot-assets/taprpc" "github.com/lightningnetwork/lnd/clock" "github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/macaroons" @@ -82,6 +84,7 @@ type Daemon struct { internalErrChan chan error lnd *lndclient.GrpcLndServices + assetClient *assets.TapdClient clientCleanup func() wg sync.WaitGroup @@ -138,6 +141,14 @@ func (d *Daemon) Start() error { return err } + // Initialize the assets client. + if d.cfg.Tapd.Activate { + d.assetClient, err = assets.NewTapdClient(d.cfg.Tapd) + if err != nil { + return err + } + } + // With lnd connected, initialize everything else, such as the swap // server client, the swap client RPC server instance and our main swap // and error handlers. If this fails, then nothing has been started yet, @@ -435,9 +446,26 @@ func (d *Daemon) initialize(withMacaroonService bool) error { chainParams, ) + // If we're running an asset client, we'll log something here. + if d.assetClient != nil { + getInfo, err := d.assetClient.GetInfo( + d.mainCtx, &taprpc.GetInfoRequest{}, + ) + if err != nil { + return fmt.Errorf("unable to get asset client info: %v", err) + } + if getInfo.LndIdentityPubkey != d.lnd.NodePubkey.String() { + return fmt.Errorf("asset client pubkey %v does not match "+ + "lnd pubkey %v", getInfo.LndIdentityPubkey, + d.lnd.NodePubkey) + } + + log.Infof("Using asset client with version %v", getInfo.Version) + } + // Create an instance of the loop client library. swapClient, clientCleanup, err := getClient( - d.cfg, swapDb, sweeperDb, &d.lnd.LndServices, + d.cfg, swapDb, sweeperDb, &d.lnd.LndServices, d.assetClient, ) if err != nil { return err @@ -667,6 +695,7 @@ func (d *Daemon) initialize(withMacaroonService bool) error { depositManager: depositManager, withdrawalManager: withdrawalManager, staticLoopInManager: staticLoopInManager, + assetClient: d.assetClient, } // Retrieve all currently existing swaps from the database. diff --git a/loopd/swapclient_server.go b/loopd/swapclient_server.go index 3ea03715..3ed0d1fc 100644 --- a/loopd/swapclient_server.go +++ b/loopd/swapclient_server.go @@ -19,6 +19,7 @@ import ( "github.com/lightninglabs/aperture/l402" "github.com/lightninglabs/lndclient" "github.com/lightninglabs/loop" + "github.com/lightninglabs/loop/assets" "github.com/lightninglabs/loop/fsm" "github.com/lightninglabs/loop/instantout" "github.com/lightninglabs/loop/instantout/reservation" @@ -93,6 +94,7 @@ type swapClientServer struct { depositManager *deposit.Manager withdrawalManager *withdraw.Manager staticLoopInManager *loopin.Manager + assetClient *assets.TapdClient swaps map[lntypes.Hash]loop.SwapInfo subscribers map[int]chan<- interface{} statusChan chan loop.SwapInfo diff --git a/loopd/utils.go b/loopd/utils.go index 2aa4083a..6be649db 100644 --- a/loopd/utils.go +++ b/loopd/utils.go @@ -9,6 +9,7 @@ import ( "github.com/lightninglabs/aperture/l402" "github.com/lightninglabs/lndclient" "github.com/lightninglabs/loop" + "github.com/lightninglabs/loop/assets" "github.com/lightninglabs/loop/liquidity" "github.com/lightninglabs/loop/loopdb" "github.com/lightninglabs/loop/swap" @@ -19,8 +20,8 @@ import ( // getClient returns an instance of the swap client. func getClient(cfg *Config, swapDb loopdb.SwapStore, - sweeperDb sweepbatcher.BatcherStore, lnd *lndclient.LndServices) ( - *loop.Client, func(), error) { + sweeperDb sweepbatcher.BatcherStore, lnd *lndclient.LndServices, + assets *assets.TapdClient) (*loop.Client, func(), error) { // Default is not set for MaxLSATCost and MaxLSATFee to distinguish // it from user explicitly setting the option to default value. @@ -45,6 +46,7 @@ func getClient(cfg *Config, swapDb loopdb.SwapStore, SwapServerNoTLS: cfg.Server.NoTLS, TLSPathServer: cfg.Server.TLSPath, Lnd: lnd, + AssetClient: assets, MaxL402Cost: btcutil.Amount(cfg.MaxL402Cost), MaxL402Fee: btcutil.Amount(cfg.MaxL402Fee), LoopOutMaxParts: cfg.LoopOutMaxParts, diff --git a/loopd/view.go b/loopd/view.go index ce765217..2fe17acb 100644 --- a/loopd/view.go +++ b/loopd/view.go @@ -7,6 +7,7 @@ import ( "github.com/btcsuite/btcd/chaincfg" "github.com/lightninglabs/lndclient" "github.com/lightninglabs/loop" + "github.com/lightninglabs/loop/assets" "github.com/lightninglabs/loop/loopdb" "github.com/lightninglabs/loop/sweepbatcher" "github.com/lightninglabs/loop/utils" @@ -37,8 +38,16 @@ func view(config *Config, lisCfg *ListenerCfg) error { chainParams, ) + var assetClient *assets.TapdClient + if config.Tapd.Host != "" { + assetClient, err = assets.NewTapdClient(config.Tapd) + if err != nil { + return err + } + } + swapClient, cleanup, err := getClient( - config, swapDb, sweeperDb, &lnd.LndServices, + config, swapDb, sweeperDb, &lnd.LndServices, assetClient, ) if err != nil { return err diff --git a/loopin_test.go b/loopin_test.go index 5f403ba8..4c86283a 100644 --- a/loopin_test.go +++ b/loopin_test.go @@ -47,7 +47,7 @@ func testLoopInSuccess(t *testing.T) { height := int32(600) - cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server) + cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server, nil) expectedLastHop := &route.Vertex{0x02} @@ -200,7 +200,7 @@ func testLoopInTimeout(t *testing.T, externalValue int64) { height := int32(600) - cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server) + cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server, nil) req := testLoopInRequest if externalValue != 0 { @@ -414,7 +414,7 @@ func testLoopInResume(t *testing.T, state loopdb.SwapState, expired bool, ctxb := context.Background() ctx := newLoopInTestContext(t) - cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server) + cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server, nil) // Create sender and receiver keys. _, senderPubKey := test.CreateKey(1) @@ -769,7 +769,7 @@ func advanceToPublishedHtlc(t *testing.T, ctx *loopInTestContext) SwapInfo { func startNewLoopIn(t *testing.T, ctx *loopInTestContext, height int32) ( *swapConfig, error, *loopInSwap) { - cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server) + cfg := newSwapConfig(&ctx.lnd.LndServices, ctx.store, ctx.server, nil) req := &testLoopInRequest diff --git a/loopout_test.go b/loopout_test.go index f28b3b02..64a2a4ef 100644 --- a/loopout_test.go +++ b/loopout_test.go @@ -181,7 +181,7 @@ func testLateHtlcPublish(t *testing.T) { height := int32(600) - cfg := newSwapConfig(&lnd.LndServices, store, server) + cfg := newSwapConfig(&lnd.LndServices, store, server, nil) testRequest.Expiry = height + testLoopOutMinOnChainCltvDelta @@ -282,7 +282,7 @@ func testCustomSweepConfTarget(t *testing.T) { ctx.Lnd.SetFeeEstimate(DefaultSweepConfTarget, 10000) cfg := newSwapConfig( - &lnd.LndServices, loopdb.NewStoreMock(t), server, + &lnd.LndServices, loopdb.NewStoreMock(t), server, nil, ) initResult, err := newLoopOutSwap( @@ -522,7 +522,7 @@ func testPreimagePush(t *testing.T) { ) cfg := newSwapConfig( - &lnd.LndServices, loopdb.NewStoreMock(t), server, + &lnd.LndServices, loopdb.NewStoreMock(t), server, nil, ) initResult, err := newLoopOutSwap( @@ -786,7 +786,7 @@ func testFailedOffChainCancelation(t *testing.T) { testReq.Expiry = lnd.Height + 20 cfg := newSwapConfig( - &lnd.LndServices, loopdb.NewStoreMock(t), server, + &lnd.LndServices, loopdb.NewStoreMock(t), server, nil, ) initResult, err := newLoopOutSwap( @@ -940,7 +940,7 @@ func TestLoopOutMuSig2Sweep(t *testing.T) { ) cfg := newSwapConfig( - &lnd.LndServices, loopdb.NewStoreMock(t), server, + &lnd.LndServices, loopdb.NewStoreMock(t), server, nil, ) initResult, err := newLoopOutSwap( diff --git a/swap.go b/swap.go index bd5bea97..2267daed 100644 --- a/swap.go +++ b/swap.go @@ -5,6 +5,7 @@ import ( "time" "github.com/lightninglabs/lndclient" + "github.com/lightninglabs/loop/assets" "github.com/lightninglabs/loop/loopdb" "github.com/lightninglabs/loop/swap" "github.com/lightninglabs/loop/utils" @@ -79,14 +80,16 @@ type swapConfig struct { lnd *lndclient.LndServices store loopdb.SwapStore server swapServerClient + assets *assets.TapdClient } func newSwapConfig(lnd *lndclient.LndServices, store loopdb.SwapStore, - server swapServerClient) *swapConfig { + server swapServerClient, assets *assets.TapdClient) *swapConfig { return &swapConfig{ lnd: lnd, store: store, server: server, + assets: assets, } }