-
Notifications
You must be signed in to change notification settings - Fork 64
/
Copy pathREADME.md
300 lines (216 loc) · 14.3 KB
/
README.md
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# Watchtower client
This is a watchtower client plugin to interact with an [Eye of Satoshi tower](https://github.com/talaia-labs/rust-teos),
and eventually with any [BOLT13](https://github.com/sr-gi/bolt13/blob/master/13-watchtowers.md) compliant watchtower.
The plugin manages all the client-side logic to send appointment to a number of registered towers every time a new
commitment transaction is generated. It also keeps a summary of the messages sent to the towers and their responses.
The plugin has the following methods:
- `registertower <tower_id>`: registers the user id (compressed public key) with a given tower.
- `gettowerinfo <tower_id>`: gets all the locally stored data about a given tower.
- `retrytower <tower_id>`: tries to send pending appointment to a (previously) unreachable tower.
- `abandontower <tower_id>`: deletes all data associated with a given tower.
- `pingtower <tower_id>`: Polls the tower to check if it is online.
- `listtowers`: lists all registered towers.
- `getappointment <tower_id> <locator>`: queries a given tower about an appointment.
- `getsubscriptioninfo <tower_id>`: gets the subscription information by querying the tower.
- `getappointmentreceipt <tower_id> <locator>`: pulls a given appointment receipt from the local database.
- `getregistrationreceipt <tower_id>`: pulls the latest registration receipt from the local database.
The plugin also has an implicit method to send appointments to the registered towers for every new commitment transaction.
# Installing the plugin and linking it to CLN
The first step to add the plugin to CLN is installing it. To do so you need to run (from the `rust-teos` folder):
```
cargo install --locked --path watchtower-plugin
```
That will generate a binary called `watchtower-client`. That's the binary we need to link to CLN.
You can link the plugin either via cmd or by placing it in the plugins folder.
### Linking the plugin via cmd
To link the plugin via cmd simply run `lightningd` specifying the plugin to link, that is:
```
lightningd --plugin=watchtower-client
```
Notice that you'll need to do this every time you restart your node.
### Linking the plugin via the plugins folder
You can also add a plugin by adding it to the plugins folder so you don't have to link it every single time. In order to do so you need to go to the CLN user directory in your machine (that's usually `~/.lightning`). Once there, you need to create a folder called `plugins` if it does not exist:
```
cd ~/.lightning
mkdir plugins && cd plugins
```
Now you need to place the watchtower-client into this folder. To do so we will create a symbolic link to it. First, check where the binary is placed (this is usually placed in your user's home).
```
whereis watchtower-client
> watchtower-client: <your_user_home>/.cargo/bin/watchtower-client
```
Notice that here `<your_user_home>` will be the path to your user's home directory, for instance `/home/sergi/`.
Now create a symbolic link to it (make sure to replace the path for your's!):
```
ln -s <your_user_home>/.cargo/bin/watchtower-client .
```
If you check the folder you'll see that now there's a link called `watchtower-client`:
```
ls
> watchtower-client
```
You can now turn on your lightning node and the plugin will be automatically linked.
### Check that the client is properly linked
We can check the plugin was properly linked by running:
```
lightning-cli plugin list
```
That will return a list of all linked plugins, which should include the `watchtower-client`:
```
[
...
{
"name": "~/.lightning/plugins/watchtower-client",
"active": true
}
]
```
# Config file, data folder and first bootstrap
The plugin, by default, creates a data folder under the user's home folder (`~/.watchtower`), where all the plugin's data is stored. The data folder can be modified by setting the ENV variable `TOWERS_DATA_DIR`.
On first bootstrap, the plugin generates a key pair that is used as the user identifier. All requests from the user are signed using the secret key, so the tower can authenticate the user after the registration process (`registertower`).
All the appointments generated by the tower, as well as all the registered towers' data, are stored on a `SQLite3` database under the data dir (that's `~/.watchtower/watchtowers_db.sql3` for the default data dir).
# Core Lightning (CLN) config
Config options can be setup directly in the [CLN config file](https://github.com/ElementsProject/lightning#configuration-file). The currently available options are:
- `watchtower-port`: default tower API port.
- `watchtower-max-retry-time`: for how long (in seconds) a retry strategy will try to reach a temporary unreachable tower before giving up (default: 1 hour).
- `watchtower-auto-retry-delay`: how long (in seconds) the client will wait before auto-retrying a failed tower (default: 8 hours).
- `proxy`: Set a socks v5 proxy IP address and port. Notice this is necessary if you want to connect to a tower through Tor! (default: no proxy).
- `always-use-proxy`: Use the proxy always (default: false).
Notice `proxy` and `always-use-proxy` are general CLN options that are honored by the plugin, so if set the plugin will use Tor to communicate with the tower.
# Getting started
## Registering with a tower
Once the plugin is loaded in your node, the first step is to register your node with an active tower. You can do so by running:
```
lightning-cli registertower tower_id [host, port]
```
Where `tower_id` represents the target tower public key. As a convenience, `tower_id` may be of the form `tower_id@host` or `id@host:port`. In this case, the host and port parameters must be omitted. Port defaults to `9814` and can be changed in the config file.
### Example
```
lightning-cli registertower 02bd2b759dd8a4fcef0f7d9692c105da8400d5da7942ee039e869fbfb8738ffde4
```
If the tower is online, you should get back a response similar to this:
```
{
"user_id": "032fd79e4052531955cf3782b09b495a75919317573ba2fb4dca199652595ced2a",
"available_slots": 10000,
"subscription_expiry": 4712
}
```
Where `available_slots` is the amount of free slots the user has available in the tower, `user_id` is the user's public key and `subscription_expiry` is the block height when the subscription expires. Generally speaking, a slot fits an appointment, so in this example the user can send **10000** appointments in roughly **one month**.
Notice that, ideally, the client and the tower have to agree on the **subscription details** (`available_slots` and `subscription_expiry`). Currently, those depend only on the tower, since it is offering the service for free. However, in the current state, hitting `registertower` again will add another `10000` slots and reset the time to `current_height + roughtly_one_mont_in_blocks`.
## Sending data to the tower
Once your node is registered with at least one tower it will start sending appointments to the tower for every commitment transaction update on any of your channels. In the current version of the plugin, everything is sent to every registered tower (**full replication**). There is nothing to be done here, under normal conditions, the plugin takes care of it.
## Checking the state of the towers
To find out more information about registered towers, you can use `list_towers` and `gettowerinfo`:
```
lightning-cli listtowers
```
```
{
"02bd2b759dd8a4fcef0f7d9692c105da8400d5da7942ee039e869fbfb8738ffde4": {
"net_addr": "http://localhost:9814",
"available_slots": 9996,
"subscription_expiry": 4712,
"status": "reachable",
"pending_appointments": [],
"invalid_appointments": []
}
}
```
The overview contains the `id` and network address of the tower (`netaddr`), as well as the current `status` and two list of appointments: **pending** and **invalid**.
The tower has 5 different states:
- `reachable`: the tower is reachable at the given network address.
- `temporarily unreachable`: the tower is temporarily unreachable, meaning that one of the last requests sent to it has failed.
- `unreachable`: the tower has been unreachable for a while.
- `misbehaving`: the tower has sent us incorrect data.
- `subscription error`: the subscription with the tower has expired or run out of slots.
The main difference between `temporarily unreachable` and `unreachable` is the amount of time that has passed since we last received a response. If a tower is temporarily unreachable, a backoff strategy is triggered and all the appointments that cannot be delivered are stored under `pending_appointments`. If the tower comes back online within the retry strategy, every pending appointment is sent through and the tower is flagged back as `reachable`. However, if the backoff strategy ends up giving up, the tower is flagged as `unreachable`.
If the client receives data from a tower that is not properly signed, the tower is flagged as `misbehaving` and it is abandoned, meaning that no more appointments are sent to it. This state should never be reached by honest towers.
A `subscription error` means that the subscription needs to be renewed (hit `registertower` again).
Regarding `pending_appointments` and `invalid_appointments` they store the data that is pending to be sent to the tower (for unreachable towers) and the appointments that have been rejected by the tower for being invalid, respectively. The latter should never get populated for honest clients.
`gettowerinfo` provides more detailed information about the tower:
**Usage**
```
lightning-cli gettowerinfo tower_id
```
**Call**
```
lightning-cli gettowerinfo 02bd2b759dd8a4fcef0f7d9692c105da8400d5da7942ee039e869fbfb8738ffde4
```
**Return**
```
{
"net_addr": "http://localhost:9814",
"available_slots": 9996,
"subscription_expiry": 4712,
"status": "reachable",
"appointments": {
"b851b8ec05f5809b9a710f7d9d24db6c": "rbxrs8ncqgzyrxkw5h95a64tbeyhmx6wopdtqndktkko3mq8q3tkczjyk19epd713it8warbpnxgk8py6utq87dt16f3qk6ehkjw5c7q",
"10c6f7787fc33d6298fa89fc41f6a0eb": "dhrtt91bbswmmu41nu4quszt7bsxzpfyx84ycfc1yjt73rs8eqpqg3fwqq8q9tff8aqorohueo3bcgqrww1ocef38hdfuhna44ikjife",
"52dc9bd565bdfe227111927e3964d70b": "d9495n3giiof4rq5aqzh4a6fezftnhofwdi1gb7q5mciyq9besdh4xixczitpgo5dxzdnyzzdy4b9i7hd1zcojdgw833975dn8azfc7x",
"e2824d355f711806d38671c19b91110d": "rbxhpeztw74dspxsr3tk7jdekw7cbkt88kfmda4guf5xkmh1tcmeauqf3s15168y8eo438nbpath58qrxsh9usskzmxk8suf1h19meae"
},
"pending_appointments": {
"062dc0f28ce5b31e6902c87ff1de15ee": {
"encrypted_blob": "e91bf1a1ab097f71976f240fb2d0c036f5b2188f14089dd1960e041b0a4d31a2bcbf9d6bec064a1d81471bdacf1f4d3b7c8d5df280d86a44504a5ee2ebf309adadc4976cc48cef7b94c9a8f17a16f0dcddfd6d0d105621bc519c0f20b46a8335a3a091bf6bfcc813bd4e34e644822bddda81b2a829d8a3b522b4c9b3f4465a6e416ae9ca8c808637cbc51e8d73dfe80cad3a6cc8c5ca018dd8a4cf2edbc02fd5f6cee0aef5ed5411731ef89061272712180c04150652f5bbb1b540ccc72547fe4ca5e92819c3bbb2feeccd7ce8f7b6568dd7f725fefdd64684f63d59e5d719b24a11272c64818b6319c19a261ee9c8a1674eb2e7c7367797893ac8",
"to_self_delay": 42
},
"ad229060698d4bc2b910a30933b1b50a": {
"encrypted_blob": "5881dce52efc18b698adc4f93b4ba275eb73271645b471227680ddb889ab60870972c4d44278dc55da4502021d9af67fd4e40803a2c9a6b4d2fe1d1f89b93373407302b67d12bb6c90b6e72b073f1c6bb3c69d57e635bfd5ff2b9648812364821b30bd95b3e8b3b2a888da8225e3d4d5cd2cd1cf2705d022b908b6b2d71c155ea50c38e2b3fb45a615c7bc1d61607a9240999c1bf174d6153b4ca7d086586614c99a45d7195c589fda8101ee8801e28b7ccad7c2b5fbda38cfe7b5e8ec13c23b8fa3cc3e6791ea9675f312cd59278ea0434538d15600b7fc905cf5a8371fc93d1e834e16d5c6399127b71c8f5c9ebfc11c5c8d3f72ce92e278f163",
"to_self_delay": 42
}
},
"invalid_appointments": {}
}
```
Notice that there are is a new field in this report: `appointments`.
`appointments` contains a collection of `locator:tower_signature` pairs of all the appointments sent and accepted by the tower.
The report may also contain a `misbehaving_proof` field if the tower has misbehaved (this is not the case for this example). The proof would look as follows:
```
"misbehaving_proof": {
"locator": "3ebd6c5a4d5ec18c815ad9fcda9aac75",
"appointment_receipt": {
"user_signature": "d7efykp63dy69jrtc3r65pssbdhp4335etq3jap1zqk135qmrtyhr8ghbdhw8y8f7nsjgmm9eoyhsfj6yugzq1bu657frmwwrudr9gpt",
"start_block": 391,
"signature": "rd41nsmhtjsawhc9pta1p5na7kmsyk48xttjy4bt3tbkbajboyzfq6mpamkjixs1w7qotocwjg3sxnbzg6uduec4cnahhkmctgddjn8w"
},
"recovered_id": "02bd2b759dd8a4fcef0f7d9692c105da8400d5da7942ee039e869fbfb8738ffde4"
}
```
Finally, notice how `pending_appointments` now contains all the data about the pending appointments (**the full appointment**). The same applies to `invalid_appointments`.
## Manually retrying a tower
If a tower has been flagged as **unreachable** (after the default backoff has failed) or there has been a **subscription error**, the tower won't be tried again until the user manually requests so. This can be managed with the `retrytower` command:
**Usage**
```
lightning-cli retrytower tower_id
```
**Call**
```
lightning-cli retrytower 02bd2b759dd8a4fcef0f7d9692c105da8400d5da7942ee039e869fbfb8738ffde4
```
**Return**
```
"Retrying 02bd2b759dd8a4fcef0f7d9692c105da8400d5da7942ee039e869fbfb8738ffde4"
```
Notice that this only works if the tower is **unreachable**. A tower cannot be retried if it is already being retried (**temporarily unreachable**).
## Query data from a tower
Data can be queried from a tower to check, for instance, that the tower is keeping it or that it is correct. This can be done using the `getappointment` command:
**Usage**
```
lightning-cli getappointment tower_id locator
```
**Call**
```
lightning-cli getappointment 02bd2b759dd8a4fcef0f7d9692c105da8400d5da7942ee039e869fbfb8738ffde4 b851b8ec05f5809b9a710f7d9d24db6c
```
**Return**
```
{
"appointment": {
"locator": "b851b8ec05f5809b9a710f7d9d24db6c",
"encrypted_blob": "017044dd0686e89bd3cf69777f1fdcb63d13eafa35e1946a0ac1324247ed793f11e27b3ee599bb1676cc98862c1f07d8e5bd29ed51c94c4ea2721a2b6f205f11cbdb1478da413ced585fe5069c6f438e977d325499bdedb985c055eaff00466209007587f20d09d153b537b0b1b6f5b8151384a1ad9f94dfffd5d5f6c2d484bad7d007976fdcaff173b18dbc4e1e24ca2ae29f8ab7e6933468c179f3857c813441e303b2e9e9b7625b19d8460d368f66cf5a7a2f54139ae0a0c9f0ef0c56183734e5dd51289ecb4f046d97e02895373c97e242c71f910c3ed1fc1b32eda4a3c28c73ad7e5fef624094fadb0753c03f8c9a4189a427e721f3ddfc0a",
"to_self_delay": 42
},
"status": "being_watched"
}
```