Skip to main content

server_rpc/
lib.rs

1//!
2//!
3//! # Note on protocol version
4//!
5//! Whenever anything changes related to the interactions between client and
6//! server, including protocol encoding versions, gRPC data fields, expected
7//! behavior etc, that is not automatically backwards compatible, the protocol
8//! version is bumped.
9//!
10//! Both the server and the client can be implemented so as to support multiple
11//! different protocol versions. This gives maximum flexibility to implement
12//! compatibility for both sides.
13//!
14//! The server advertises the protocol versions it supports and the client picks
15//! one and sets it in the header of each subsequent request.
16//!
17//! However, the server will only check the protocol version in cases where
18//! behavior can be different for different versions. This gives outdated or
19//! exotic clients an extra level of flexibility, as calls that have not
20//! changed since the latest supported protocol version might still work.
21//!
22//! This makes the server maximally flexible and puts all the responsibility
23//! on the client. Our own client implementation bails out if it cannot speak
24//! any of the supported protocol versions the server supports.
25//!
26//! ## Protocol version changelog
27//!
28//! * `1`: initial version
29//! * `2`: fixed the offboard sighash for multi-input offboards
30//! * `3`: checkpoint the lightning-receive claim so the watchman can't
31//!   force-exit a freshly claimed VTXO
32//! * `4`: ppm fees round up to a satoshi instead of down; ppm expiry fees
33//!   are calculated on the exact total across all VTXOs
34
35#[cfg(all(any(target_os = "android", target_os = "ios"), feature = "tls-native-roots"))]
36compile_error!("feature `tls-native-roots` can't be used on Android or iOS, use `tls-webpki-roots` instead");
37
38pub extern crate tonic;
39
40// Generated gRPC method lookup from proto files (server-only)
41#[cfg(feature = "server")]
42include!(concat!(env!("OUT_DIR"), "/grpc_methods.rs"));
43
44mod convert;
45pub use crate::convert::{ConvertError, TryFromBytes};
46
47mod error;
48pub use crate::error::StatusExt;
49
50pub mod pver;
51
52pub mod client;
53/// Terms of service may apply, check your server's `ArkInfo.tos_link`.
54pub mod protos {
55	pub mod core {
56		tonic::include_proto!("core");
57	}
58	pub use self::core::*;
59	pub mod bark_server {
60		tonic::include_proto!("bark_server");
61	}
62	pub use self::bark_server::*;
63	pub mod intman {
64		tonic::include_proto!("intman");
65	}
66	pub mod mailbox_server {
67		tonic::include_proto!("mailbox_server");
68	}
69}
70
71pub use client::ServerConnection;
72pub use crate::protos::bark_server::ark_service_client::ArkServiceClient;
73
74pub mod admin {
75	pub use crate::protos::bark_server::wallet_admin_service_client::WalletAdminServiceClient;
76	pub use crate::protos::bark_server::round_admin_service_client::RoundAdminServiceClient;
77	pub use crate::protos::bark_server::lightning_admin_service_client::LightningAdminServiceClient;
78	pub use crate::protos::bark_server::sweep_admin_service_client::SweepAdminServiceClient;
79	pub use crate::protos::bark_server::ban_admin_service_client::BanAdminServiceClient;
80	pub use crate::protos::bark_server::blocklist_admin_service_client::BlocklistAdminServiceClient;
81	pub use crate::protos::bark_server::nursery_admin_service_client::NurseryAdminServiceClient;
82}
83
84#[cfg(feature = "intman")]
85pub mod intman {
86	pub use crate::protos::intman::integration_service_client::IntegrationServiceClient;
87}
88
89#[cfg(feature = "server")]
90pub mod server {
91	pub use crate::protos::bark_server::ark_service_server::{ArkService, ArkServiceServer};
92	pub use crate::protos::bark_server::wallet_admin_service_server::{WalletAdminService, WalletAdminServiceServer};
93	pub use crate::protos::bark_server::round_admin_service_server::{RoundAdminService, RoundAdminServiceServer};
94	pub use crate::protos::bark_server::lightning_admin_service_server::{LightningAdminService, LightningAdminServiceServer};
95	pub use crate::protos::bark_server::sweep_admin_service_server::{SweepAdminService, SweepAdminServiceServer};
96	pub use crate::protos::bark_server::ban_admin_service_server::{BanAdminService, BanAdminServiceServer};
97	pub use crate::protos::bark_server::blocklist_admin_service_server::{BlocklistAdminService, BlocklistAdminServiceServer};
98	pub use crate::protos::bark_server::nursery_admin_service_server::{NurseryAdminService, NurseryAdminServiceServer};
99	pub use crate::protos::intman::integration_service_server::{IntegrationService, IntegrationServiceServer};
100	pub use crate::protos::mailbox_server::mailbox_service_server::{MailboxService, MailboxServiceServer};
101}
102
103pub mod mailbox {
104	pub use crate::protos::mailbox_server::mailbox_service_client::MailboxServiceClient;
105}
106
107
108use std::borrow::BorrowMut;
109use std::str::FromStr;
110use std::time::Duration;
111
112use bitcoin::{Address, Amount, OutPoint};
113use bitcoin::address::NetworkUnchecked;
114
115
116/// The minimum protocol version supported by the client.
117///
118/// For info on protocol versions, see [server_rpc](crate) module documentation.
119pub const MIN_PROTOCOL_VERSION: u64 = pver::PROTOCOL_VERSION_PPM_FEE_TOTAL;
120
121/// The maximum protocol version supported by the client.
122///
123/// For info on protocol versions, see [server_rpc](crate) module documentation.
124pub const MAX_PROTOCOL_VERSION: u64 = pver::PROTOCOL_VERSION_HASHLOCK_CLAUSES;
125
126/// The bark client version sent in HandshakeRequest. Exposed so
127/// alternate callers (e.g. integration tests) send the same string a
128/// real client would.
129pub const BARK_CRATE_VERSION: &str = env!("CARGO_PKG_VERSION");
130
131/// The string used in the gRPC HTTP header for the protocol version.
132pub const PROTOCOL_VERSION_HEADER: &str = "pver";
133
134/// The maximum number of recovery IDs that the server accepts per request.
135pub const MAX_NB_MAILBOX_RECOVERY_IDS: usize = 20;
136
137/// The number of child keys the server derives from a client xpub and looks
138/// up in one batch when recovering VTXOs by xpub.
139pub const RECOVERY_XPUB_CHUNK_SIZE: u32 = 10_000;
140
141/// The maximum number of vtxo IDs that the server accepts per forfeit nonces request.
142pub const MAX_NB_FORFEIT_NONCE_IDS: usize = 1000;
143
144/// The maximum number of vtxo IDs that the server accepts per by-ids request.
145pub const MAX_NB_VTXO_IDS: usize = 1000;
146
147/// The maximum number of vtxos that the server accepts per register request.
148pub const MAX_NB_REGISTER_VTXOS: usize = 1000;
149
150/// The maximum number of vtxos that the server accepts per arkoor mailbox
151/// post. Generous for a single payment's outputs to one recipient; clients
152/// sending more should split into multiple posts.
153pub const MAX_NB_MAILBOX_ARKOOR_VTXOS: usize = 100;
154
155/// The maximum number of inputs of a board funding tx
156pub const MAX_NB_BOARD_FUNDING_INPUTS: usize = 100;
157
158
159#[derive(Debug, Clone)]
160pub struct WalletStatus {
161	pub address: Address<NetworkUnchecked>,
162	pub total_balance: Amount,
163	pub trusted_balance: Amount,
164	pub untrusted_balance: Amount,
165	pub confirmed_utxos: Vec<OutPoint>,
166	pub unconfirmed_utxos: Vec<OutPoint>,
167}
168
169/// Extension trait on [tonic::Request].
170pub trait RequestExt<T>: BorrowMut<tonic::Request<T>> {
171	/// Check for the protocol version header.
172	///
173	/// Returns None in case of missing header.
174	fn try_pver(&self) -> Result<Option<u64>, tonic::Status> {
175		self.borrow().metadata().get(PROTOCOL_VERSION_HEADER).map(|v| {
176			v.to_str().ok().and_then(|s| u64::from_str(s).ok())
177				.ok_or_else(|| tonic::Status::invalid_argument("invalid protocol version header"))
178		}).transpose()
179	}
180
181	/// Check for the protocol version header.
182	///
183	/// Returns error in case of missing header.
184	fn pver(&self) -> Result<u64, tonic::Status> {
185		self.try_pver()?.ok_or_else(|| tonic::Status::invalid_argument("missing pver header"))
186	}
187
188	/// Set the protocol version header.
189	fn set_pver(&mut self, pver: u64) {
190		self.borrow_mut().metadata_mut().insert(PROTOCOL_VERSION_HEADER, pver.into());
191	}
192
193	/// Sets a request timeout only if no timeout has already been set
194	fn set_default_timeout(&mut self, timeout: Duration) {
195		const GRPC_TIMEOUT_HEADER: &str = "grpc-timeout";
196
197		let slf = self.borrow_mut();
198		if slf.metadata().get(GRPC_TIMEOUT_HEADER).is_none () {
199			slf.set_timeout(timeout);
200		}
201	}
202}
203impl<T> RequestExt<T> for tonic::Request<T> {}