-
-
Notifications
You must be signed in to change notification settings - Fork 37
/
Copy pathopts.rs
291 lines (247 loc) · 9.38 KB
/
opts.rs
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
// LNP Node: node running lightning network protocol and generalized lightning
// channels.
// Written in 2020-2022 by
// Dr. Maxim Orlovsky <[email protected]>
//
// To the extent possible under law, the author(s) have dedicated all
// copyright and related and neighboring rights to this software to
// the public domain worldwide. This software is distributed without
// any warranty.
//
// You should have received a copy of the MIT License along with this software.
// If not, see <https://opensource.org/licenses/MIT>.
use std::net::IpAddr;
use std::str::FromStr;
use internet2::addr::{NodeId, PartialNodeAddr, ServiceAddr};
use lightning_invoice::Invoice;
use lnp::addr::LnpAddr;
use lnp::p2p::bolt::{ChannelId, ChannelType};
use lnp_rpc::LNP_NODE_RPC_ENDPOINT;
/// Command-line tool for working with LNP node
#[derive(Parser, Clone, PartialEq, Eq, Debug)]
#[clap(name = "lnp-cli", bin_name = "lnp-cli", author, version)]
pub struct Opts {
/// ZMQ socket for connecting daemon RPC interface.
///
/// Socket can be either TCP address in form of `<ipv4 | ipv6>:<port>` – or a path
/// to an IPC file.
///
/// Defaults to `127.0.0.1:62962`.
#[clap(
short = 'R',
long = "rpc",
global = true,
default_value = LNP_NODE_RPC_ENDPOINT,
env = "LNP_NODE_RPC_ENDPOINT"
)]
pub connect: ServiceAddr,
/// Set verbosity level.
///
/// Can be used multiple times to increase verbosity.
#[clap(short, long, global = true, parse(from_occurrences))]
pub verbose: u8,
/// Command to execute
#[clap(subcommand)]
pub command: Command,
}
/// Command-line commands:
#[derive(Subcommand, Clone, PartialEq, Eq, Debug)]
pub enum Command {
/// Bind to a socket and start listening for incoming LN peer connections
Listen {
/// Use BOLT lightning network protocol.
#[clap(long, conflicts_with = "bifrost")]
bolt: bool,
/// Use Bifrost lightning network protocol.
#[clap(long, required_unless_present = "bolt")]
bifrost: bool,
/// IPv4 or IPv6 address to bind to
#[clap(short, long = "ip", default_value = "0.0.0.0")]
ip_addr: IpAddr,
/// Port to use; defaults to the native LN port.
#[clap(short, long)]
port: Option<u16>,
},
/// Connect to the remote lightning network peer
Connect {
/// Address of the remote node, in
/// '<public_key>@<ipv4>|<ipv6>|<onionv2>|<onionv3>[:<port>]' format
peer: LnpAddr,
},
/// Ping remote peer (must be already connected)
Ping {
/// Use BOLT lightning network protocol.
#[clap(long, conflicts_with = "bifrost")]
bolt: bool,
/// Use Bifrost lightning network protocol.
#[clap(long, required_unless_present = "bolt")]
bifrost: bool,
/// Public key (id) of the remote node
peer: NodeId,
},
/// General information about the running node
Info {
/// Use BOLT lightning network protocol.
#[clap(long, conflicts_with = "bifrost")]
bolt: bool,
/// Use Bifrost lightning network protocol.
#[clap(long, required_unless_present = "bolt")]
bifrost: bool,
/// Remote peer address or temporary/permanent/short channel id. If
/// absent, returns information about the node itself
subject: Option<String>,
},
/// Lists all funds available for channel creation with the list of assets
/// and provides information about funding points (bitcoin address or UTXO
/// for RGB assets)
Funds,
/// Lists existing peer connections
Peers,
/// Lists existing channels
Channels,
/// Opens a new channel with a remote peer, which must be already
/// connected.
Open {
/// Address of the remote node, in
/// '<public_key>@<ipv4>|<ipv6>|<onionv2>|<onionv3>[:<port>]' format
peer: PartialNodeAddr,
/// Amount of satoshis to allocate to the channel (the actual
/// allocation will happen later using `fund` command after the
/// channel acceptance)
funding_sat: u64,
/// Amount of millisatoshis to pay to the remote peer at channel opening
#[clap(long = "pay")]
push_msat: Option<u64>,
// The following are the customization of the channel parameters which should override node
// settings
/// Sets fee rate for the channel transacitons.
///
/// If used, overrides default node settings.
///
/// Initial fee rate in satoshi per 1000-weight (i.e. 1/4 the more normally-used 'satoshi
/// per 1000 vbytes') that this side will pay for commitment and HTLC transactions, as
/// described in BOLT #3 (this can be adjusted later with an `fee` command).
#[clap(long)]
fee_rate: Option<u32>,
/// Make channel public and route payments.
///
/// If used, overrides default node settings.
///
/// Should the channel be announced to the lightning network. Required for the node to earn
/// routing fees. Setting this flag results in the channel and node becoming
/// public.
#[clap(long)]
announce_channel: Option<bool>,
/// Channel type as defined in BOLT-2.
///
/// If used, overrides default node settings.
///
/// Possible values:
///
/// - basic
///
/// - static_remotekey
///
/// - anchored
///
/// - anchored_zero_fee
#[clap(long)]
channel_type: Option<ChannelType>,
/// The threshold below which outputs on transactions broadcast by sender will be omitted.
///
/// If used, overrides default node settings.
#[clap(long)]
dust_limit: Option<u64>,
/// The number of blocks which the counterparty will have to wait to claim on-chain funds
/// if they broadcast a commitment transaction
///
/// If used, overrides default node settings.
#[clap(long)]
to_self_delay: Option<u16>,
/// The maximum number of the received HTLCs.
///
/// If used, overrides default node settings.
#[clap(long)]
htlc_max_count: Option<u16>,
/// Indicates the smallest value of an HTLC this node will accept, in milli-satoshi.
///
/// If used, overrides default node settings.
#[clap(long)]
htlc_min_value: Option<u64>,
/// The maximum inbound HTLC value in flight towards this node, in milli-satoshi
///
/// If used, overrides default node settings.
#[clap(long)]
htlc_max_total_value: Option<u64>,
/// The minimum value unencumbered by HTLCs for the counterparty to keep in
/// the channel, in satoshis.
///
/// If used, overrides default node settings.
#[clap(long)]
channel_reserve: Option<u64>,
},
/// Create an invoice
Invoice {
/// Asset amount to invoice, in atomic unit (satoshis or smallest asset
/// unit type)
amount: u64,
/// Asset ticker in which the invoice should be issued
#[clap(default_value = "btc")]
asset: String,
},
/// Pay the invoice
Pay {
/// Invoice bech32 string
invoice: Invoice,
/// Channel from which the payment should happen
channel: ChannelId,
/// Amount of milli-satoshis to pay. Required for invoices lacking
/// amount. Overrides amount provided by the invoice.
amount_msat: Option<u64>,
},
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display, Error, From)]
#[display(doc_comments)]
pub enum AmountOfAssetParseError {
/// The provided value can't be parsed as a pair of asset name/ticker and
/// asset amount; use <asset>:<amount> or '<amount> <asset>' form and do
/// not forget about quotation marks in the second case
NeedsValuePair,
/// The provided amount can't be interpreted; please use unsigned integer
#[from(std::num::ParseIntError)]
InvalidAmount,
}
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Display)]
#[display("{amount} {asset}", alt = "{asset}:{amount}")]
pub struct AmountOfAsset {
/// Asset ticker
asset: String,
/// Amount of the asset in atomic units
amount: u64,
}
impl FromStr for AmountOfAsset {
type Err = AmountOfAssetParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (asset, amount);
if s.contains(':') {
let mut split = s.split(':');
asset = split.next().ok_or(AmountOfAssetParseError::NeedsValuePair)?;
amount = split.next().ok_or(AmountOfAssetParseError::NeedsValuePair)?;
if split.count() > 0 {
return Err(AmountOfAssetParseError::NeedsValuePair);
}
} else if s.contains(' ') {
let mut split = s.split(' ');
amount = split.next().ok_or(AmountOfAssetParseError::NeedsValuePair)?;
asset = split.next().ok_or(AmountOfAssetParseError::NeedsValuePair)?;
if split.count() > 0 {
return Err(AmountOfAssetParseError::NeedsValuePair);
}
} else {
return Err(AmountOfAssetParseError::NeedsValuePair);
}
let amount = u64::from_str(amount)?;
let asset = asset.to_owned();
Ok(AmountOfAsset { asset, amount })
}
}