Skip to content

Commit 140367e

Browse files
sekulicdaltafan
andauthored
Add admin port (#725)
* option to run admin rpcs on separate port * Fix localhost * Use port 7071 as default admin port & Add --macaroon flag to arkd cli --------- Co-authored-by: altafan <18440657+altafan@users.noreply.github.com>
1 parent 4268011 commit 140367e

File tree

16 files changed

+272
-144
lines changed

16 files changed

+272
-144
lines changed

README.md

Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -57,37 +57,38 @@ In this documentation, you'll learn how to install and use `arkd`, a Bitcoin ser
5757

5858
The `arkd` server can be configured using environment variables.
5959

60-
| Environment Variable | Description | Default |
61-
|---------------------|-------------|--------|
62-
| `ARKD_DATADIR` | Directory to store data | App data directory |
63-
| `ARKD_PORT` | Port to listen on | `7070` |
64-
| `ARKD_LOG_LEVEL` | Logging level (0-6, where 6 is trace) | `4` (info) |
65-
| `ARKD_ROUND_INTERVAL` | Interval between rounds in seconds | `30` |
66-
| `ARKD_DB_TYPE` | Database type (postgres, sqlite, badger) | `postgres` |
67-
| `ARKD_PG_DB_URL` | Postgres connection url if `ARKD_DB_TYPE` is set to `postgres` | - |
68-
| `ARKD_EVENT_DB_TYPE` | Event database type (postgres, badger) | `postgres` |
69-
| `ARKD_PG_EVENT_DB_URL` | Event database url if `ARKD_EVENT_DB_TYPE` is set to `postgres` | - |
70-
| `ARKD_TX_BUILDER_TYPE` | Transaction builder type (covenantless) | `covenantless` |
71-
| `ARKD_LIVE_STORE_TYPE` | Cache service type (redis, inmemory) | `redis` |
72-
| `ARKD_REDIS_URL` | Redis db connection url if `ARKD_LIVE_STORE_TYPE` is set to `redis` | - |
73-
| `ARKD_REDIS_NUM_OF_RETRIES` | Maximum number of retries for Redis write operations in case of conflicts | - |
74-
| `ARKD_VTXO_TREE_EXPIRY` | VTXO tree expiry in seconds | `604672` (7 days) |
75-
| `ARKD_UNILATERAL_EXIT_DELAY` | Unilateral exit delay in seconds | `86400` (24 hours) |
76-
| `ARKD_BOARDING_EXIT_DELAY` | Boarding exit delay in seconds | `7776000` (3 months) |
77-
| `ARKD_ESPLORA_URL` | Esplora API URL | `https://blockstream.info/api` |
78-
| `ARKD_WALLET_ADDR` | The arkd wallet address to connect to in the form `host:port` | - |
79-
| `ARKD_SIGNER_ADDR` | The signer address to connect to in the form `host:port` | value of `ARKD_WALLET_ADDR` |
80-
| `ARKD_NO_MACAROONS` | Disable macaroon authentication | `false` |
81-
| `ARKD_NO_TLS` | Disable TLS | `true` |
82-
| `ARKD_UNLOCKER_TYPE` | Wallet unlocker type (env, file) to enable auto-unlock | - |
83-
| `ARKD_UNLOCKER_FILE_PATH` | Path to unlocker file | - |
84-
| `ARKD_UNLOCKER_PASSWORD` | Wallet unlocker password | - |
85-
| `ARKD_ROUND_MAX_PARTICIPANTS_COUNT` | Maximum number of participants per round | `128` |
86-
| `ARKD_ROUND_MIN_PARTICIPANTS_COUNT` | Minimum number of participants per round | `1` |
87-
| `ARKD_UTXO_MAX_AMOUNT` | The maximum allowed amount for boarding or collaborative exit | `-1` (unset) |
88-
| `ARKD_UTXO_MIN_AMOUNT` | The minimum allowed amount for boarding or collaborative exit | `-1` (dust) |
89-
| `ARKD_VTXO_MAX_AMOUNT` | The maximum allowed amount for vtxos | `-1` (unset) |
90-
| `ARKD_VTXO_MIN_AMOUNT` | The minimum allowed amount for vtxos | `-1` (dust) |
60+
| Environment Variable | Description | Default |
61+
|-------------------------------------|---------------------------------------------------------------------------|-------------------------------|
62+
| `ARKD_DATADIR` | Directory to store data | App data directory |
63+
| `ARKD_PORT` | Port (public) to listen on | `7070` |
64+
| `ARKD_ADMIN_PORT` | Admin port (private) to listen on, fallback to service port if 0 | `7071` |
65+
| `ARKD_LOG_LEVEL` | Logging level (0-6, where 6 is trace) | `4` (info) |
66+
| `ARKD_ROUND_INTERVAL` | Interval between rounds in seconds | `30` |
67+
| `ARKD_DB_TYPE` | Database type (postgres, sqlite, badger) | `postgres` |
68+
| `ARKD_PG_DB_URL` | Postgres connection url if `ARKD_DB_TYPE` is set to `postgres` | - |
69+
| `ARKD_EVENT_DB_TYPE` | Event database type (postgres, badger) | `postgres` |
70+
| `ARKD_PG_EVENT_DB_URL` | Event database url if `ARKD_EVENT_DB_TYPE` is set to `postgres` | - |
71+
| `ARKD_TX_BUILDER_TYPE` | Transaction builder type (covenantless) | `covenantless` |
72+
| `ARKD_LIVE_STORE_TYPE` | Cache service type (redis, inmemory) | `redis` |
73+
| `ARKD_REDIS_URL` | Redis db connection url if `ARKD_LIVE_STORE_TYPE` is set to `redis` | - |
74+
| `ARKD_REDIS_NUM_OF_RETRIES` | Maximum number of retries for Redis write operations in case of conflicts | - |
75+
| `ARKD_VTXO_TREE_EXPIRY` | VTXO tree expiry in seconds | `604672` (7 days) |
76+
| `ARKD_UNILATERAL_EXIT_DELAY` | Unilateral exit delay in seconds | `86400` (24 hours) |
77+
| `ARKD_BOARDING_EXIT_DELAY` | Boarding exit delay in seconds | `7776000` (3 months) |
78+
| `ARKD_ESPLORA_URL` | Esplora API URL | `https://blockstream.info/api` |
79+
| `ARKD_WALLET_ADDR` | The arkd wallet address to connect to in the form `host:port` | - |
80+
| `ARKD_SIGNER_ADDR` | The signer address to connect to in the form `host:port` | value of `ARKD_WALLET_ADDR` |
81+
| `ARKD_NO_MACAROONS` | Disable macaroon authentication | `false` |
82+
| `ARKD_NO_TLS` | Disable TLS | `true` |
83+
| `ARKD_UNLOCKER_TYPE` | Wallet unlocker type (env, file) to enable auto-unlock | - |
84+
| `ARKD_UNLOCKER_FILE_PATH` | Path to unlocker file | - |
85+
| `ARKD_UNLOCKER_PASSWORD` | Wallet unlocker password | - |
86+
| `ARKD_ROUND_MAX_PARTICIPANTS_COUNT` | Maximum number of participants per round | `128` |
87+
| `ARKD_ROUND_MIN_PARTICIPANTS_COUNT` | Minimum number of participants per round | `1` |
88+
| `ARKD_UTXO_MAX_AMOUNT` | The maximum allowed amount for boarding or collaborative exit | `-1` (unset) |
89+
| `ARKD_UTXO_MIN_AMOUNT` | The minimum allowed amount for boarding or collaborative exit | `-1` (dust) |
90+
| `ARKD_VTXO_MAX_AMOUNT` | The maximum allowed amount for vtxos | `-1` (unset) |
91+
| `ARKD_VTXO_MIN_AMOUNT` | The minimum allowed amount for vtxos | `-1` (dust) |
9192

9293
## Provisioning
9394

cmd/arkd/commands.go

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -149,13 +149,13 @@ var timeout = time.Minute
149149

150150
func walletStatusAction(ctx *cli.Context) error {
151151
baseURL := ctx.String(urlFlagName)
152-
_, tlsCertPath, err := getCredentialPaths(ctx)
152+
_, tlsConfig, err := getCredentials(ctx)
153153
if err != nil {
154154
return err
155155
}
156156

157157
url := fmt.Sprintf("%s/v1/admin/wallet/status", baseURL)
158-
status, err := getStatus(url, tlsCertPath)
158+
status, err := getStatus(url, tlsConfig)
159159
if err != nil {
160160
return err
161161
}
@@ -166,7 +166,7 @@ func walletStatusAction(ctx *cli.Context) error {
166166

167167
func walletCreateOrRestoreAction(ctx *cli.Context) error {
168168
baseURL := ctx.String(urlFlagName)
169-
_, tlsCertPath, err := getCredentialPaths(ctx)
169+
_, tlsConfig, err := getCredentials(ctx)
170170
if err != nil {
171171
return err
172172
}
@@ -181,7 +181,7 @@ func walletCreateOrRestoreAction(ctx *cli.Context) error {
181181
`{"seed": "%s", "password": "%s", "gap_limit": %d}`,
182182
mnemonic, password, gapLimit,
183183
)
184-
if _, err := post[struct{}](url, body, "", "", tlsCertPath); err != nil {
184+
if _, err := post[struct{}](url, body, "", "", tlsConfig); err != nil {
185185
return err
186186
}
187187

@@ -190,7 +190,7 @@ func walletCreateOrRestoreAction(ctx *cli.Context) error {
190190
}
191191

192192
url := fmt.Sprintf("%s/v1/admin/wallet/seed", baseURL)
193-
seed, err := get[string](url, "seed", "", tlsCertPath)
193+
seed, err := get[string](url, "seed", "", tlsConfig)
194194
if err != nil {
195195
return err
196196
}
@@ -199,7 +199,7 @@ func walletCreateOrRestoreAction(ctx *cli.Context) error {
199199
body := fmt.Sprintf(
200200
`{"seed": "%s", "password": "%s"}`, seed, password,
201201
)
202-
if _, err := post[struct{}](url, body, "", "", tlsCertPath); err != nil {
202+
if _, err := post[struct{}](url, body, "", "", tlsConfig); err != nil {
203203
return err
204204
}
205205

@@ -215,7 +215,7 @@ func walletDropWtxmgrAction(ctx *cli.Context) error {
215215

216216
func walletUnlockAction(ctx *cli.Context) error {
217217
baseURL := ctx.String(urlFlagName)
218-
_, tlsCertPath, err := getCredentialPaths(ctx)
218+
_, tlsConfig, err := getCredentials(ctx)
219219
if err != nil {
220220
return err
221221
}
@@ -224,7 +224,7 @@ func walletUnlockAction(ctx *cli.Context) error {
224224
url := fmt.Sprintf("%s/v1/admin/wallet/unlock", baseURL)
225225
body := fmt.Sprintf(`{"password": "%s"}`, password)
226226

227-
if _, err := post[struct{}](url, body, "", "", tlsCertPath); err != nil {
227+
if _, err := post[struct{}](url, body, "", "", tlsConfig); err != nil {
228228
return err
229229
}
230230

@@ -234,13 +234,13 @@ func walletUnlockAction(ctx *cli.Context) error {
234234

235235
func walletAddressAction(ctx *cli.Context) error {
236236
baseURL := ctx.String(urlFlagName)
237-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
237+
macaroon, tlsConfig, err := getCredentials(ctx)
238238
if err != nil {
239239
return err
240240
}
241241

242242
url := fmt.Sprintf("%s/v1/admin/wallet/address", baseURL)
243-
addr, err := get[string](url, "address", macaroon, tlsCertPath)
243+
addr, err := get[string](url, "address", macaroon, tlsConfig)
244244
if err != nil {
245245
return err
246246
}
@@ -251,13 +251,13 @@ func walletAddressAction(ctx *cli.Context) error {
251251

252252
func walletBalanceAction(ctx *cli.Context) error {
253253
baseURL := ctx.String(urlFlagName)
254-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
254+
macaroon, tlsConfig, err := getCredentials(ctx)
255255
if err != nil {
256256
return err
257257
}
258258

259259
url := fmt.Sprintf("%s/v1/admin/wallet/balance", baseURL)
260-
balance, err := getBalance(url, macaroon, tlsCertPath)
260+
balance, err := getBalance(url, macaroon, tlsConfig)
261261
if err != nil {
262262
return err
263263
}
@@ -270,7 +270,7 @@ func walletWithdrawAction(ctx *cli.Context) error {
270270
baseURL := ctx.String(urlFlagName)
271271
amount := ctx.Float64(amountFlagName)
272272
address := ctx.String(addressFlagName)
273-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
273+
macaroon, tlsConfig, err := getCredentials(ctx)
274274
if err != nil {
275275
return err
276276
}
@@ -279,7 +279,7 @@ func walletWithdrawAction(ctx *cli.Context) error {
279279
amountInSats := uint64(amount * ONE_BTC)
280280
body := fmt.Sprintf(`{"address": "%s", "amount": %d}`, address, amountInSats)
281281

282-
txid, err := post[string](url, body, "txid", macaroon, tlsCertPath)
282+
txid, err := post[string](url, body, "txid", macaroon, tlsConfig)
283283
if err != nil {
284284
return err
285285
}
@@ -299,7 +299,7 @@ func signerLoadAction(ctx *cli.Context) error {
299299
if signerKey != "" && signerUrl != "" {
300300
return fmt.Errorf("private key and url are mutually esclusive, only one must be provided")
301301
}
302-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
302+
macaroon, tlsConfig, err := getCredentials(ctx)
303303
if err != nil {
304304
return err
305305
}
@@ -310,7 +310,7 @@ func signerLoadAction(ctx *cli.Context) error {
310310
body = fmt.Sprintf(`{"signerPrivateKey": "%s"}`, signerKey)
311311
}
312312

313-
if _, err := post[struct{}](url, body, "", macaroon, tlsCertPath); err != nil {
313+
if _, err := post[struct{}](url, body, "", macaroon, tlsConfig); err != nil {
314314
return err
315315
}
316316

@@ -331,15 +331,15 @@ func createNoteAction(ctx *cli.Context) error {
331331
baseURL := ctx.String(urlFlagName)
332332
amount := ctx.Uint(amountFlagName)
333333
quantity := ctx.Uint(quantityFlagName)
334-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
334+
macaroon, tlsConfig, err := getCredentials(ctx)
335335
if err != nil {
336336
return err
337337
}
338338

339339
url := fmt.Sprintf("%s/v1/admin/note", baseURL)
340340
body := fmt.Sprintf(`{"amount": %d, "quantity": %d}`, amount, quantity)
341341

342-
notes, err := post[[]string](url, body, "notes", macaroon, tlsCertPath)
342+
notes, err := post[[]string](url, body, "notes", macaroon, tlsConfig)
343343
if err != nil {
344344
return err
345345
}
@@ -353,7 +353,7 @@ func createNoteAction(ctx *cli.Context) error {
353353

354354
func listIntentsAction(ctx *cli.Context) error {
355355
baseURL := ctx.String(urlFlagName)
356-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
356+
macaroon, tlsConfig, err := getCredentials(ctx)
357357
if err != nil {
358358
return err
359359
}
@@ -368,7 +368,7 @@ func listIntentsAction(ctx *cli.Context) error {
368368
q.Set("intent_ids", strings.Join(requestIds, ","))
369369
u.RawQuery = q.Encode()
370370
}
371-
response, err := get[[]map[string]any](u.String(), "intents", macaroon, tlsCertPath)
371+
response, err := get[[]map[string]any](u.String(), "intents", macaroon, tlsConfig)
372372
if err != nil {
373373
return err
374374
}
@@ -383,7 +383,7 @@ func listIntentsAction(ctx *cli.Context) error {
383383

384384
func deleteIntentsAction(ctx *cli.Context) error {
385385
baseURL := ctx.String(urlFlagName)
386-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
386+
macaroon, tlsConfig, err := getCredentials(ctx)
387387
if err != nil {
388388
return err
389389
}
@@ -397,7 +397,7 @@ func deleteIntentsAction(ctx *cli.Context) error {
397397
url := fmt.Sprintf("%s/v1/admin/intents/delete", baseURL)
398398
body := fmt.Sprintf(`{"intent_ids": %s}`, intentIdsJSON)
399399

400-
if _, err := post[struct{}](url, body, "", macaroon, tlsCertPath); err != nil {
400+
if _, err := post[struct{}](url, body, "", macaroon, tlsConfig); err != nil {
401401
return err
402402
}
403403

@@ -407,15 +407,15 @@ func deleteIntentsAction(ctx *cli.Context) error {
407407

408408
func clearIntentsAction(ctx *cli.Context) error {
409409
baseURL := ctx.String(urlFlagName)
410-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
410+
macaroon, tlsConfig, err := getCredentials(ctx)
411411
if err != nil {
412412
return err
413413
}
414414

415415
url := fmt.Sprintf("%s/v1/admin/intents/delete", baseURL)
416416
body := `{"intent_ids": []}`
417417

418-
if _, err := post[struct{}](url, body, "", macaroon, tlsCertPath); err != nil {
418+
if _, err := post[struct{}](url, body, "", macaroon, tlsConfig); err != nil {
419419
return err
420420
}
421421

@@ -425,14 +425,14 @@ func clearIntentsAction(ctx *cli.Context) error {
425425

426426
func scheduledSweepAction(ctx *cli.Context) error {
427427
baseURL := ctx.String(urlFlagName)
428-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
428+
macaroon, tlsConfig, err := getCredentials(ctx)
429429
if err != nil {
430430
return err
431431
}
432432

433433
url := fmt.Sprintf("%s/v1/admin/sweeps", baseURL)
434434

435-
resp, err := get[[]map[string]any](url, "sweeps", macaroon, tlsCertPath)
435+
resp, err := get[[]map[string]any](url, "sweeps", macaroon, tlsConfig)
436436
if err != nil {
437437
return err
438438
}
@@ -448,14 +448,14 @@ func scheduledSweepAction(ctx *cli.Context) error {
448448
func roundInfoAction(ctx *cli.Context) error {
449449
baseURL := ctx.String(urlFlagName)
450450
roundId := ctx.String(roundIdFlagName)
451-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
451+
macaroon, tlsConfig, err := getCredentials(ctx)
452452
if err != nil {
453453
return err
454454
}
455455

456456
url := fmt.Sprintf("%s/v1/admin/round/%s", baseURL, roundId)
457457

458-
resp, err := getRoundInfo(url, macaroon, tlsCertPath)
458+
resp, err := getRoundInfo(url, macaroon, tlsConfig)
459459
if err != nil {
460460
return err
461461
}
@@ -472,7 +472,7 @@ func roundsInTimeRangeAction(ctx *cli.Context) error {
472472
baseURL := ctx.String(urlFlagName)
473473
beforeDate := ctx.String(beforeDateFlagName)
474474
afterDate := ctx.String(afterDateFlagName)
475-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
475+
macaroon, tlsConfig, err := getCredentials(ctx)
476476
if err != nil {
477477
return err
478478
}
@@ -497,7 +497,7 @@ func roundsInTimeRangeAction(ctx *cli.Context) error {
497497
}
498498
}
499499

500-
roundIds, err := get[map[string]string](url, "rounds", macaroon, tlsCertPath)
500+
roundIds, err := get[map[string]string](url, "rounds", macaroon, tlsConfig)
501501
if err != nil {
502502
return err
503503
}
@@ -512,14 +512,14 @@ func roundsInTimeRangeAction(ctx *cli.Context) error {
512512

513513
func getMarketHourAction(ctx *cli.Context) error {
514514
baseURL := ctx.String(urlFlagName)
515-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
515+
macaroon, tlsConfig, err := getCredentials(ctx)
516516
if err != nil {
517517
return err
518518
}
519519

520520
url := fmt.Sprintf("%s/v1/admin/marketHour", baseURL)
521521

522-
resp, err := get[map[string]string](url, "config", macaroon, tlsCertPath)
522+
resp, err := get[map[string]string](url, "config", macaroon, tlsConfig)
523523
if err != nil {
524524
return err
525525
}
@@ -570,7 +570,7 @@ func updateMarketHourAction(ctx *cli.Context) error {
570570
return fmt.Errorf("--start-date and --end-date must be set together")
571571
}
572572

573-
macaroon, tlsCertPath, err := getCredentialPaths(ctx)
573+
macaroon, tlsConfig, err := getCredentials(ctx)
574574
if err != nil {
575575
return err
576576
}
@@ -600,7 +600,7 @@ func updateMarketHourAction(ctx *cli.Context) error {
600600
if err != nil {
601601
return fmt.Errorf("failed to encode request body: %s", err)
602602
}
603-
if _, err := post[any](url, string(body), "", macaroon, tlsCertPath); err != nil {
603+
if _, err := post[any](url, string(body), "", macaroon, tlsConfig); err != nil {
604604
return err
605605
}
606606

cmd/arkd/flags.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
const (
1313
urlFlagName = "url"
1414
datadirFlagName = "datadir"
15+
macaroonFlagName = "macaroon"
1516
passwordFlagName = "password"
1617
dbPathFlagName = "datadir"
1718
mnemonicFlagName = "mnemonic"
@@ -38,13 +39,17 @@ var (
3839
urlFlag = &cli.StringFlag{
3940
Name: urlFlagName,
4041
Usage: "the url where to reach ark server",
41-
Value: fmt.Sprintf("http://localhost:%d", config.DefaultPort),
42+
Value: fmt.Sprintf("http://127.0.0.1:%d", config.DefaultAdminPort),
4243
}
4344
datadirFlag = &cli.StringFlag{
4445
Name: datadirFlagName,
4546
Usage: "arkd datadir from where to source TLS cert and macaroon if needed",
4647
Value: arklib.AppDataDir("arkd", false),
4748
}
49+
macaroonFlag = &cli.StringFlag{
50+
Name: macaroonFlagName,
51+
Usage: "macaroon in hex format used for authenticated requests",
52+
}
4853
dbPathFlag = &cli.StringFlag{
4954
Name: dbPathFlagName,
5055
Usage: "path to the wallet database",

0 commit comments

Comments
 (0)