Skip to content

Commit 4876037

Browse files
committed
lndclient: Add watchtower client interface
Add the wtclient_client.go file which contains the lnd watchtower client interface. Signed-off-by: Jonathan <[email protected]>
1 parent e896a14 commit 4876037

File tree

1 file changed

+254
-0
lines changed

1 file changed

+254
-0
lines changed

wtclient_client.go

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
package lndclient
2+
3+
import (
4+
"context"
5+
"time"
6+
7+
"github.com/lightningnetwork/lnd/lnrpc/wtclientrpc"
8+
"google.golang.org/grpc"
9+
)
10+
11+
// WatchtowerClientClient implements the watchtower client interface
12+
// https://lightning.engineering/api-docs/category/watchtowerclient-service/
13+
type WatchtowerClientClient interface {
14+
ServiceClient[wtclientrpc.WatchtowerClientClient]
15+
16+
// AddTower adds a new watchtower reachable at the given address and
17+
// considers it for new sessions. If the watchtower already exists, then
18+
// any new addresses included will be considered when dialing it for
19+
// session negotiations and backups.
20+
AddTower(ctx context.Context, pubkey []byte, address string) error
21+
22+
// DeactivateTower sets the given tower's status to inactive so that it
23+
// is not considered for session negotiation. Its sessions will also not
24+
// be used while the tower is inactive.
25+
DeactivateTower(ctx context.Context, pubkey []byte) (string, error)
26+
27+
// GetTowerInfo gets information about a watchtower that corresponds to
28+
// the given pubkey. The `includeSessions` flag controls whether session
29+
// information is included. The `excludeExhaustedSessions` controls
30+
// whether exhausted sessions are included in the response.
31+
GetTowerInfo(ctx context.Context, pubkey []byte, includeSessions,
32+
excludeExhaustedSessions bool) (*wtclientrpc.Tower, error)
33+
34+
// ListTowers gets information about all registered watchtowers. The
35+
// `includeSessions` and `excludeExhaustedSessions` flags serve the same
36+
// function as in the `GetTowerInfo` method.
37+
ListTowers(ctx context.Context, includeSessions,
38+
excludeExhaustedSessions bool) ([]*wtclientrpc.Tower, error)
39+
40+
// Policy returns the active watchtower client policy configuration.
41+
Policy(ctx context.Context, policyType wtclientrpc.PolicyType) (
42+
*wtclientrpc.PolicyResponse, error)
43+
44+
// RemoveTower removes a watchtower from being considered for future
45+
// session negotiations and from being used for any subsequent backups
46+
// until it's added again. If an address is provided, then this RPC only
47+
// serves as a way of removing the address from the watchtower instead.
48+
RemoveTower(ctx context.Context, pubkey []byte, address string) error
49+
50+
// Stats returns the in-memory statistics of the client since startup.
51+
Stats(ctx context.Context) (*wtclientrpc.StatsResponse, error)
52+
53+
// TerminateSession terminates the given session and marks it to not be
54+
// used for backups anymore. Returns a human readable status string.
55+
TerminateSession(ctx context.Context, sessionId []byte) (string, error)
56+
}
57+
58+
type wtClientClient struct {
59+
client wtclientrpc.WatchtowerClientClient
60+
wtClientMac serializedMacaroon
61+
timeout time.Duration
62+
}
63+
64+
// A compile time check to ensure that wtClientClient implements the
65+
// WtclientClient interface.
66+
var _ WatchtowerClientClient = (*wtClientClient)(nil)
67+
68+
// newClientClient creates a new watchtower client interface.
69+
func newWtClientClient(conn grpc.ClientConnInterface,
70+
wtClientMac serializedMacaroon, timeout time.Duration) *wtClientClient {
71+
72+
return &wtClientClient{
73+
client: wtclientrpc.NewWatchtowerClientClient(conn),
74+
wtClientMac: wtClientMac,
75+
timeout: timeout,
76+
}
77+
}
78+
79+
// RawClientWithMacAuth returns a context with the proper macaroon
80+
// authentication, the default RPC timeout, and the raw client.
81+
func (m *wtClientClient) RawClientWithMacAuth(
82+
parentCtx context.Context) (context.Context, time.Duration,
83+
wtclientrpc.WatchtowerClientClient) {
84+
85+
return m.wtClientMac.WithMacaroonAuth(parentCtx), m.timeout, m.client
86+
}
87+
88+
// AddTower adds a new watchtower reachable at the given address and
89+
// considers it for new sessions. If the watchtower already exists, then
90+
// any new addresses included will be considered when dialing it for
91+
// session negotiations and backups.
92+
func (m *wtClientClient) AddTower(ctx context.Context, pubkey []byte,
93+
address string) error {
94+
95+
rpcCtx, cancel := context.WithTimeout(ctx, m.timeout)
96+
defer cancel()
97+
98+
rpcReq := &wtclientrpc.AddTowerRequest{
99+
Pubkey: pubkey,
100+
Address: address,
101+
}
102+
103+
rpcCtx = m.wtClientMac.WithMacaroonAuth(rpcCtx)
104+
_, err := m.client.AddTower(rpcCtx, rpcReq)
105+
if err != nil {
106+
return err
107+
}
108+
109+
return nil
110+
}
111+
112+
// DeactivateTower sets the given tower's status to inactive so that it
113+
// is not considered for session negotiation. Its sessions will also not
114+
// be used while the tower is inactive.
115+
func (m *wtClientClient) DeactivateTower(ctx context.Context, pubkey []byte) (
116+
string, error) {
117+
118+
rpcCtx, cancel := context.WithTimeout(ctx, m.timeout)
119+
defer cancel()
120+
121+
rpcCtx = m.wtClientMac.WithMacaroonAuth(rpcCtx)
122+
resp, err := m.client.DeactivateTower(rpcCtx,
123+
&wtclientrpc.DeactivateTowerRequest{
124+
Pubkey: pubkey,
125+
},
126+
)
127+
if err != nil {
128+
return "", err
129+
}
130+
131+
return resp.Status, nil
132+
}
133+
134+
// GetTowerInfo gets information about a watchtower that corresponds to
135+
// the given pubkey. The `includeSessions` flag controls whether session
136+
// information is included. The `excludeExhaustedSessions` controls
137+
// whether exhausted sessions are included in the response.
138+
func (m *wtClientClient) GetTowerInfo(ctx context.Context, pubkey []byte,
139+
includeSessions, excludeExhaustedSessions bool) (*wtclientrpc.Tower,
140+
error) {
141+
142+
rpcCtx, cancel := context.WithTimeout(ctx, m.timeout)
143+
defer cancel()
144+
145+
rpcCtx = m.wtClientMac.WithMacaroonAuth(rpcCtx)
146+
resp, err := m.client.GetTowerInfo(rpcCtx,
147+
&wtclientrpc.GetTowerInfoRequest{
148+
Pubkey: pubkey,
149+
IncludeSessions: includeSessions,
150+
ExcludeExhaustedSessions: excludeExhaustedSessions,
151+
},
152+
)
153+
if err != nil {
154+
return nil, err
155+
}
156+
157+
return resp, nil
158+
}
159+
160+
// ListTowers gets information about all registered watchtowers. The
161+
// `includeSessions` and `excludeExhaustedSessions` flags serve the same
162+
// function as in the `GetTowerInfo` method.
163+
func (m *wtClientClient) ListTowers(ctx context.Context, includeSessions,
164+
excludeExhaustedSessions bool) ([]*wtclientrpc.Tower, error) {
165+
166+
rpcCtx, cancel := context.WithTimeout(ctx, m.timeout)
167+
defer cancel()
168+
169+
rpcCtx = m.wtClientMac.WithMacaroonAuth(rpcCtx)
170+
resp, err := m.client.ListTowers(rpcCtx, &wtclientrpc.ListTowersRequest{
171+
IncludeSessions: includeSessions,
172+
ExcludeExhaustedSessions: excludeExhaustedSessions,
173+
})
174+
if err != nil {
175+
return nil, err
176+
}
177+
178+
return resp.Towers, nil
179+
}
180+
181+
// Policy returns the active watchtower client policy configuration.
182+
func (m *wtClientClient) Policy(ctx context.Context,
183+
policyType wtclientrpc.PolicyType) (*wtclientrpc.PolicyResponse, error) {
184+
185+
rpcCtx, cancel := context.WithTimeout(ctx, m.timeout)
186+
defer cancel()
187+
188+
rpcCtx = m.wtClientMac.WithMacaroonAuth(rpcCtx)
189+
resp, err := m.client.Policy(rpcCtx, &wtclientrpc.PolicyRequest{
190+
PolicyType: policyType,
191+
})
192+
if err != nil {
193+
return nil, err
194+
}
195+
196+
return resp, nil
197+
}
198+
199+
// RemoveTower removes a watchtower from being considered for future
200+
// session negotiations and from being used for any subsequent backups
201+
// until it's added again. If an address is provided, then this RPC only
202+
// serves as a way of removing the address from the watchtower instead.
203+
func (m *wtClientClient) RemoveTower(ctx context.Context, pubkey []byte,
204+
address string) error {
205+
206+
rpcCtx, cancel := context.WithTimeout(ctx, m.timeout)
207+
defer cancel()
208+
209+
rpcCtx = m.wtClientMac.WithMacaroonAuth(rpcCtx)
210+
_, err := m.client.RemoveTower(rpcCtx, &wtclientrpc.RemoveTowerRequest{
211+
Pubkey: pubkey,
212+
Address: address,
213+
})
214+
if err != nil {
215+
return err
216+
}
217+
218+
return nil
219+
}
220+
221+
// Stats returns the in-memory statistics of the client since startup.
222+
func (m *wtClientClient) Stats(ctx context.Context) (*wtclientrpc.StatsResponse, error) {
223+
rpcCtx, cancel := context.WithTimeout(ctx, m.timeout)
224+
defer cancel()
225+
226+
rpcCtx = m.wtClientMac.WithMacaroonAuth(rpcCtx)
227+
resp, err := m.client.Stats(rpcCtx, &wtclientrpc.StatsRequest{})
228+
if err != nil {
229+
return nil, err
230+
}
231+
232+
return resp, nil
233+
}
234+
235+
// TerminateSession terminates the given session and marks it to not be used
236+
// for backups anymore. Returns a human readable status string.
237+
func (m *wtClientClient) TerminateSession(ctx context.Context,
238+
sessionId []byte) (string, error) {
239+
240+
rpcCtx, cancel := context.WithTimeout(ctx, m.timeout)
241+
defer cancel()
242+
243+
rpcCtx = m.wtClientMac.WithMacaroonAuth(rpcCtx)
244+
resp, err := m.client.TerminateSession(rpcCtx,
245+
&wtclientrpc.TerminateSessionRequest{
246+
SessionId: sessionId,
247+
},
248+
)
249+
if err != nil {
250+
return "", err
251+
}
252+
253+
return resp.Status, nil
254+
}

0 commit comments

Comments
 (0)