fedimint_gateway_server/
config.rs

1use std::net::SocketAddr;
2use std::path::PathBuf;
3use std::str::FromStr;
4
5use bitcoin::Network;
6use clap::{ArgGroup, Parser};
7use fedimint_core::envs::{FM_IROH_DNS_ENV, FM_IROH_RELAY_ENV};
8use fedimint_core::util::SafeUrl;
9use fedimint_gateway_common::{LightningMode, V1_API_ENDPOINT};
10use fedimint_lnv2_common::gateway_api::PaymentFee;
11
12use super::envs;
13use crate::envs::{
14    FM_BITCOIND_PASSWORD_ENV, FM_BITCOIND_URL_ENV, FM_BITCOIND_USERNAME_ENV, FM_ESPLORA_URL_ENV,
15};
16
17#[derive(Debug, Clone, Copy, clap::ValueEnum)]
18pub enum DatabaseBackend {
19    /// Use RocksDB database backend
20    #[value(name = "rocksdb")]
21    RocksDb,
22    /// Use CursedRedb database backend (hybrid memory/redb)
23    #[value(name = "cursed-redb")]
24    CursedRedb,
25}
26
27/// Command line parameters for starting the gateway. `mode`, `data_dir`,
28/// `listen`, and `api_addr` are all required.
29#[derive(Parser)]
30#[command(version)]
31#[command(
32    group(
33        ArgGroup::new("bitcoind_password_auth")
34           .args(["bitcoind_password"])
35           .multiple(false)
36    ),
37    group(
38        ArgGroup::new("bitcoind_auth")
39            .args(["bitcoind_url"])
40            .requires("bitcoind_password_auth")
41            .requires_all(["bitcoind_username", "bitcoind_url"])
42    ),
43    group(
44        ArgGroup::new("bitcoin_rpc")
45            .required(true)
46            .multiple(true)
47            .args(["bitcoind_url", "esplora_url"])
48    )
49)]
50pub struct GatewayOpts {
51    #[clap(subcommand)]
52    pub mode: LightningMode,
53
54    /// Path to folder containing gateway config and data files
55    #[arg(long = "data-dir", env = envs::FM_GATEWAY_DATA_DIR_ENV)]
56    pub data_dir: PathBuf,
57
58    /// Gateway webserver listen address
59    #[arg(long = "listen", env = envs::FM_GATEWAY_LISTEN_ADDR_ENV)]
60    listen: SocketAddr,
61
62    /// Public URL from which the webserver API is reachable
63    #[arg(long = "api-addr", env = envs::FM_GATEWAY_API_ADDR_ENV)]
64    api_addr: SafeUrl,
65
66    /// Gateway webserver authentication bcrypt password hash
67    #[arg(long = "bcrypt-password-hash", env = envs::FM_GATEWAY_BCRYPT_PASSWORD_HASH_ENV)]
68    bcrypt_password_hash: String,
69
70    /// Bitcoin network this gateway will be running on
71    #[arg(long = "network", env = envs::FM_GATEWAY_NETWORK_ENV)]
72    network: Network,
73
74    /// Number of route hints to return in invoices
75    #[arg(
76        long = "num-route-hints",
77        env = envs::FM_NUMBER_OF_ROUTE_HINTS_ENV,
78        default_value_t = super::DEFAULT_NUM_ROUTE_HINTS
79    )]
80    num_route_hints: u32,
81
82    /// Database backend to use.
83    #[arg(long, env = envs::FM_DB_BACKEND_ENV, value_enum, default_value = "rocksdb")]
84    pub db_backend: DatabaseBackend,
85
86    /// The username to use when connecting to bitcoind
87    #[arg(long, env = FM_BITCOIND_USERNAME_ENV)]
88    pub bitcoind_username: Option<String>,
89
90    /// The password to use when connecting to bitcoind
91    #[arg(long, env = FM_BITCOIND_PASSWORD_ENV)]
92    pub bitcoind_password: Option<String>,
93
94    /// Bitcoind RPC URL, e.g. <http://127.0.0.1:8332>
95    /// This should not include authentication parameters, they should be
96    /// included in `FM_BITCOIND_USERNAME` and `FM_BITCOIND_PASSWORD`
97    #[arg(long, env = FM_BITCOIND_URL_ENV)]
98    pub bitcoind_url: Option<SafeUrl>,
99
100    /// Esplora HTTP base URL, e.g. <https://mempool.space/api>
101    #[arg(long, env = FM_ESPLORA_URL_ENV)]
102    pub esplora_url: Option<SafeUrl>,
103
104    /// The default routing fees that are applied to new federations
105    #[arg(long = "default-routing-fees", env = envs::FM_DEFAULT_ROUTING_FEES_ENV, default_value_t = PaymentFee::TRANSACTION_FEE_DEFAULT)]
106    default_routing_fees: PaymentFee,
107
108    /// The default transaction fees that are applied to new federations
109    #[arg(long = "default-transaction-fees", env = envs::FM_DEFAULT_TRANSACTION_FEES_ENV, default_value_t = PaymentFee::TRANSACTION_FEE_DEFAULT)]
110    default_transaction_fees: PaymentFee,
111
112    /// Gateway iroh listen address
113    #[arg(long = "iroh-listen", env = envs::FM_GATEWAY_IROH_LISTEN_ADDR_ENV)]
114    iroh_listen: SocketAddr,
115
116    /// Optional URL of the Iroh DNS server
117    #[arg(long, env = FM_IROH_DNS_ENV)]
118    iroh_dns: Option<SafeUrl>,
119
120    /// Optional URLs of the Iroh relays to use for registering
121    #[arg(long, env = FM_IROH_RELAY_ENV)]
122    iroh_relays: Vec<SafeUrl>,
123}
124
125impl GatewayOpts {
126    /// Converts the command line parameters into a helper struct the Gateway
127    /// uses to store runtime parameters.
128    pub fn to_gateway_parameters(&self) -> anyhow::Result<GatewayParameters> {
129        let versioned_api = self.api_addr.join(V1_API_ENDPOINT).map_err(|e| {
130            anyhow::anyhow!(
131                "Failed to version gateway API address: {api_addr:?}, error: {e:?}",
132                api_addr = self.api_addr,
133            )
134        })?;
135
136        let bcrypt_password_hash = bcrypt::HashParts::from_str(&self.bcrypt_password_hash)?;
137
138        Ok(GatewayParameters {
139            listen: self.listen,
140            versioned_api,
141            bcrypt_password_hash,
142            network: self.network,
143            num_route_hints: self.num_route_hints,
144            default_routing_fees: self.default_routing_fees,
145            default_transaction_fees: self.default_transaction_fees,
146            iroh_listen: self.iroh_listen,
147            iroh_dns: self.iroh_dns.clone(),
148            iroh_relays: self.iroh_relays.clone(),
149        })
150    }
151}
152
153/// `GatewayParameters` is a helper struct that can be derived from
154/// `GatewayOpts` that holds the CLI or environment variables that are specified
155/// by the user.
156///
157/// If `GatewayConfiguration is set in the database, that takes precedence and
158/// the optional parameters will have no affect.
159#[derive(Debug)]
160pub struct GatewayParameters {
161    pub listen: SocketAddr,
162    pub versioned_api: SafeUrl,
163    pub bcrypt_password_hash: bcrypt::HashParts,
164    pub network: Network,
165    pub num_route_hints: u32,
166    pub default_routing_fees: PaymentFee,
167    pub default_transaction_fees: PaymentFee,
168    pub iroh_listen: SocketAddr,
169    pub iroh_dns: Option<SafeUrl>,
170    pub iroh_relays: Vec<SafeUrl>,
171}