Skip to content

Commit d5cb601

Browse files
authored
Merge pull request #642 from hieblmi/static-addr-1
[1/?] Static Loop-In Address - Create
2 parents a66210b + 11d058d commit d5cb601

28 files changed

+1834
-433
lines changed

client.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -151,8 +151,8 @@ func NewClient(dbDir string, loopDB loopdb.SwapStore,
151151
config := &clientConfig{
152152
LndServices: cfg.Lnd,
153153
Server: swapServerClient,
154-
Store: loopDB,
155154
Conn: swapServerClient.conn,
155+
Store: loopDB,
156156
LsatStore: lsatStore,
157157
CreateExpiryTimer: func(d time.Duration) <-chan time.Time {
158158
return time.NewTimer(d).C

cmd/loop/loopin.go

+3
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,9 @@ var (
5252
Name: "in",
5353
Usage: "perform an on-chain to off-chain swap (loop in)",
5454
ArgsUsage: "amt",
55+
Subcommands: []cli.Command{
56+
staticAddressCommands,
57+
},
5558
Description: `
5659
Send the amount in satoshis specified by the amt argument
5760
off-chain.

cmd/loop/main.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ func main() {
148148
listSwapsCommand, swapInfoCommand, getLiquidityParamsCommand,
149149
setLiquidityRuleCommand, suggestSwapCommand, setParamsCommand,
150150
getInfoCommand, abandonSwapCommand, reservationsCommands,
151-
instantOutCommand,
151+
instantOutCommand, staticAddressCommands,
152152
}
153153

154154
err := app.Run(os.Args)

cmd/loop/staticaddr.go

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
package main
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/lightninglabs/loop/looprpc"
8+
"github.com/urfave/cli"
9+
)
10+
11+
var staticAddressCommands = cli.Command{
12+
Name: "static",
13+
ShortName: "s",
14+
Usage: "manage static loop-in addresses",
15+
Category: "StaticAddress",
16+
Subcommands: []cli.Command{
17+
newStaticAddressCommand,
18+
},
19+
}
20+
21+
var newStaticAddressCommand = cli.Command{
22+
Name: "new",
23+
ShortName: "n",
24+
Usage: "Create a new static loop in address.",
25+
Description: `
26+
Requests a new static loop in address from the server. Funds that are
27+
sent to this address will be locked by a 2:2 multisig between us and the
28+
loop server, or a timeout path that we can sweep once it opens up. The
29+
funds can either be cooperatively spent with a signature from the server
30+
or looped in.
31+
`,
32+
Action: newStaticAddress,
33+
}
34+
35+
func newStaticAddress(ctx *cli.Context) error {
36+
ctxb := context.Background()
37+
if ctx.NArg() > 0 {
38+
return cli.ShowCommandHelp(ctx, "new")
39+
}
40+
41+
client, cleanup, err := getAddressClient(ctx)
42+
if err != nil {
43+
return err
44+
}
45+
defer cleanup()
46+
47+
resp, err := client.NewAddress(
48+
ctxb, &looprpc.NewAddressRequest{},
49+
)
50+
if err != nil {
51+
return err
52+
}
53+
54+
fmt.Printf("Received a new static loop-in address from the server: "+
55+
"%s\n", resp.Address)
56+
57+
return nil
58+
}
59+
60+
func getAddressClient(ctx *cli.Context) (looprpc.StaticAddressClientClient,
61+
func(), error) {
62+
63+
rpcServer := ctx.GlobalString("rpcserver")
64+
tlsCertPath, macaroonPath, err := extractPathArgs(ctx)
65+
if err != nil {
66+
return nil, nil, err
67+
}
68+
conn, err := getClientConn(rpcServer, tlsCertPath, macaroonPath)
69+
if err != nil {
70+
return nil, nil, err
71+
}
72+
cleanup := func() { conn.Close() }
73+
74+
addressClient := looprpc.NewStaticAddressClientClient(conn)
75+
return addressClient, cleanup, nil
76+
}

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ require (
1717
github.com/grpc-ecosystem/grpc-gateway/v2 v2.11.3
1818
github.com/jackc/pgconn v1.14.0
1919
github.com/jackc/pgerrcode v0.0.0-20220416144525-469b46aa5efa
20+
github.com/jackc/pgx/v4 v4.18.1
2021
github.com/jessevdk/go-flags v1.4.0
2122
github.com/lib/pq v1.10.7
2223
github.com/lightninglabs/aperture v0.1.21-beta.0.20230705004936-87bb996a4030
@@ -96,7 +97,6 @@ require (
9697
github.com/jackc/pgproto3/v2 v2.3.2 // indirect
9798
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
9899
github.com/jackc/pgtype v1.14.0 // indirect
99-
github.com/jackc/pgx/v4 v4.18.1 // indirect
100100
github.com/jackpal/gateway v1.0.5 // indirect
101101
github.com/jackpal/go-nat-pmp v0.0.0-20170405195558-28a68d0c24ad // indirect
102102
github.com/jonboulle/clockwork v0.2.2 // indirect

loopd/daemon.go

+42-37
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,13 @@ import (
1717
"github.com/lightninglabs/lndclient"
1818
"github.com/lightninglabs/loop"
1919
"github.com/lightninglabs/loop/instantout"
20+
"github.com/lightninglabs/loop/instantout/reservation"
2021
"github.com/lightninglabs/loop/loopd/perms"
2122
"github.com/lightninglabs/loop/loopdb"
22-
"github.com/lightninglabs/loop/sweepbatcher"
23-
24-
"github.com/lightninglabs/loop/instantout/reservation"
2523
loop_looprpc "github.com/lightninglabs/loop/looprpc"
26-
24+
"github.com/lightninglabs/loop/staticaddr"
2725
loop_swaprpc "github.com/lightninglabs/loop/swapserverrpc"
26+
"github.com/lightninglabs/loop/sweepbatcher"
2827
"github.com/lightningnetwork/lnd/clock"
2928
"github.com/lightningnetwork/lnd/lntypes"
3029
"github.com/lightningnetwork/lnd/macaroons"
@@ -69,6 +68,12 @@ type Daemon struct {
6968
// same process.
7069
swapClientServer
7170

71+
// AddressServer is the embedded RPC server that satisfies the
72+
// static address client RPC interface. We embed this struct so the
73+
// Daemon itself can be registered to an existing grpc.Server to run as
74+
// a subserver in the same process.
75+
*staticaddr.AddressServer
76+
7277
// ErrChan is an error channel that users of the Daemon struct must use
7378
// to detect runtime errors and also whether a shutdown is fully
7479
// completed.
@@ -234,6 +239,7 @@ func (d *Daemon) startWebServers() error {
234239
grpc.StreamInterceptor(streamInterceptor),
235240
)
236241
loop_looprpc.RegisterSwapClientServer(d.grpcServer, d)
242+
loop_looprpc.RegisterStaticAddressClientServer(d.grpcServer, d)
237243

238244
// Register our debug server if it is compiled in.
239245
d.registerDebugServer()
@@ -545,6 +551,26 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
545551
instantOutManager: instantOutManager,
546552
}
547553

554+
// Create a static address server client.
555+
staticAddressClient := loop_swaprpc.NewStaticAddressServerClient(
556+
swapClient.Conn,
557+
)
558+
559+
store := staticaddr.NewSqlStore(baseDb)
560+
561+
cfg := &staticaddr.ManagerConfig{
562+
AddressClient: staticAddressClient,
563+
SwapClient: swapClient,
564+
Store: store,
565+
WalletKit: d.lnd.WalletKit,
566+
ChainParams: d.lnd.ChainParams,
567+
}
568+
staticAddressManager := staticaddr.NewAddressManager(cfg)
569+
570+
d.AddressServer = staticaddr.NewAddressServer(
571+
staticAddressClient, staticAddressManager,
572+
)
573+
548574
// Retrieve all currently existing swaps from the database.
549575
swapsList, err := d.impl.FetchSwaps(d.mainCtx)
550576
if err != nil {
@@ -635,42 +661,21 @@ func (d *Daemon) initialize(withMacaroonService bool) error {
635661
}()
636662
}
637663

638-
// Start the instant out manager.
639-
if d.instantOutManager != nil {
640-
d.wg.Add(1)
641-
initChan := make(chan struct{})
642-
go func() {
643-
defer d.wg.Done()
644-
645-
getInfo, err := d.lnd.Client.GetInfo(d.mainCtx)
646-
if err != nil {
647-
d.internalErrChan <- err
648-
return
649-
}
664+
// Start the static address manager.
665+
d.wg.Add(1)
666+
go func() {
667+
defer d.wg.Done()
650668

651-
log.Info("Starting instantout manager")
652-
defer log.Info("Instantout manager stopped")
669+
log.Info("Starting static address manager...")
670+
err = staticAddressManager.Run(d.mainCtx)
671+
if err != nil && !errors.Is(context.Canceled, err) {
672+
d.internalErrChan <- err
673+
}
653674

654-
err = d.instantOutManager.Run(
655-
d.mainCtx, initChan, int32(getInfo.BlockHeight),
656-
)
657-
if err != nil && !errors.Is(err, context.Canceled) {
658-
d.internalErrChan <- err
659-
}
660-
}()
675+
log.Info("Static address manager stopped")
676+
}()
661677

662-
// Wait for the instantout server to be ready before starting the
663-
// grpc server.
664-
timeOutCtx, cancel := context.WithTimeout(d.mainCtx, 10*time.Second)
665-
select {
666-
case <-timeOutCtx.Done():
667-
cancel()
668-
return fmt.Errorf("reservation server not ready: %v",
669-
timeOutCtx.Err())
670-
case <-initChan:
671-
cancel()
672-
}
673-
}
678+
staticAddressManager.WaitInitComplete()
674679

675680
// Last, start our internal error handler. This will return exactly one
676681
// error or nil on the main error channel to inform the caller that

loopd/log.go

+2
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/lightninglabs/loop/instantout/reservation"
1111
"github.com/lightninglabs/loop/liquidity"
1212
"github.com/lightninglabs/loop/loopdb"
13+
"github.com/lightninglabs/loop/staticaddr"
1314
"github.com/lightninglabs/loop/sweepbatcher"
1415
"github.com/lightningnetwork/lnd"
1516
"github.com/lightningnetwork/lnd/build"
@@ -37,6 +38,7 @@ func SetupLoggers(root *build.RotatingLogWriter, intercept signal.Interceptor) {
3738
lnd.AddSubLogger(root, "SWEEP", intercept, sweepbatcher.UseLogger)
3839
lnd.AddSubLogger(root, "LNDC", intercept, lndclient.UseLogger)
3940
lnd.AddSubLogger(root, "STORE", intercept, loopdb.UseLogger)
41+
lnd.AddSubLogger(root, "SADDR", intercept, staticaddr.UseLogger)
4042
lnd.AddSubLogger(root, lsat.Subsystem, intercept, lsat.UseLogger)
4143
lnd.AddSubLogger(
4244
root, liquidity.Subsystem, intercept, liquidity.UseLogger,

loopd/perms/perms.go

+7
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ var RequiredPermissions = map[string][]bakery.Op{
6969
Entity: "loop",
7070
Action: "in",
7171
}},
72+
"/looprpc.StaticAddressClient/NewAddress": {{
73+
Entity: "swap",
74+
Action: "read",
75+
}, {
76+
Entity: "loop",
77+
Action: "in",
78+
}},
7279
"/looprpc.SwapClient/GetLsatTokens": {{
7380
Entity: "auth",
7481
Action: "read",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
DROP TABLE IF EXISTS static_addresses;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
-- static_address stores the static loop-in addresses that clients
2+
-- cooperatively created with the server.
3+
CREATE TABLE IF NOT EXISTS static_addresses (
4+
-- id is the auto-incrementing primary key for a static address.
5+
id INTEGER PRIMARY KEY,
6+
7+
-- client_pubkey is the client side public taproot key that is used to
8+
-- construct the 2-of-2 MuSig2 taproot output that represents the static
9+
-- address.
10+
client_pubkey BYTEA NOT NULL,
11+
12+
-- server_pubkey is the server side public taproot key that is used to
13+
-- construct the 2-of-2 MuSig2 taproot output that represents the static
14+
-- address.
15+
server_pubkey BYTEA NOT NULL,
16+
17+
-- expiry denotes the CSV delay at which funds at a specific static address
18+
-- can be swept back to the client.
19+
expiry INT NOT NULL,
20+
21+
-- client_key_family is the key family of the client public key from the
22+
-- client's lnd wallet.
23+
client_key_family INT NOT NULL,
24+
25+
-- client_key_index is the key index of the client public key from the
26+
-- client's lnd wallet.
27+
client_key_index INT NOT NULL,
28+
29+
-- pkscript is the witness program that represents the static address. It is
30+
-- unique amongst all static addresses.
31+
pkscript BYTEA NOT NULL UNIQUE,
32+
33+
-- protocol_version is the protocol version that the swap was created with.
34+
-- Note that this version is not upgraded if the client upgrades or
35+
-- downgrades their protocol version for static address outputs already in
36+
-- use.
37+
protocol_version INTEGER NOT NULL
38+
);

loopdb/sqlc/models.go

+11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

loopdb/sqlc/querier.go

+3
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
-- name: AllStaticAddresses :many
2+
SELECT * FROM static_addresses;
3+
4+
-- name: GetStaticAddress :one
5+
SELECT * FROM static_addresses
6+
WHERE pkscript=$1;
7+
8+
-- name: CreateStaticAddress :exec
9+
INSERT INTO static_addresses (
10+
client_pubkey,
11+
server_pubkey,
12+
expiry,
13+
client_key_family,
14+
client_key_index,
15+
pkscript,
16+
protocol_version
17+
) VALUES (
18+
$1,
19+
$2,
20+
$3,
21+
$4,
22+
$5,
23+
$6,
24+
$7
25+
);

0 commit comments

Comments
 (0)