mirror of
https://github.com/talaia-labs/rust-teos.git
synced 2026-08-13 12:33:22 +02:00
Merge pull request #249 from sr-gi/2024-01-authcookie
Adds rpccookie to bitcoind auth methods
This commit is contained in:
commit
997f77f695
4 changed files with 88 additions and 17 deletions
|
|
@ -18,6 +18,7 @@ use bitcoin::base64;
|
|||
use bitcoin::hash_types::{BlockHash, Txid};
|
||||
use bitcoin::hashes::hex::ToHex;
|
||||
use bitcoin::{Block, Transaction};
|
||||
use bitcoincore_rpc::Auth;
|
||||
use lightning::util::ser::Writeable;
|
||||
use lightning_block_sync::http::{HttpEndpoint, JsonResponse};
|
||||
use lightning_block_sync::rpc::RpcClient;
|
||||
|
|
@ -32,9 +33,9 @@ pub struct BitcoindClient<'a> {
|
|||
/// The port to connect to.
|
||||
port: u16,
|
||||
/// The RPC user `bitcoind` is configured with.
|
||||
rpc_user: &'a str,
|
||||
rpc_user: String,
|
||||
/// The RPC password for the given user.
|
||||
rpc_password: &'a str,
|
||||
rpc_password: String,
|
||||
}
|
||||
|
||||
impl BlockSource for &BitcoindClient<'_> {
|
||||
|
|
@ -74,12 +75,33 @@ impl<'a> BitcoindClient<'a> {
|
|||
pub async fn new(
|
||||
host: &'a str,
|
||||
port: u16,
|
||||
rpc_user: &'a str,
|
||||
rpc_password: &'a str,
|
||||
auth: Auth,
|
||||
teos_network: &'a str,
|
||||
) -> std::io::Result<BitcoindClient<'a>> {
|
||||
let http_endpoint = HttpEndpoint::for_host(host.to_owned()).with_port(port);
|
||||
let rpc_credentials = base64::encode(&format!("{rpc_user}:{rpc_password}"));
|
||||
let (rpc_user, rpc_password) = {
|
||||
let (user, pass) = auth.get_user_pass().map_err(|e| {
|
||||
Error::new(
|
||||
ErrorKind::InvalidInput,
|
||||
format!("Cannot read cookie file. {}", e),
|
||||
)
|
||||
})?;
|
||||
if user.is_none() {
|
||||
Err(Error::new(
|
||||
ErrorKind::InvalidInput,
|
||||
"Empty btc_rpc_user parsed from rpc_cookie".to_string(),
|
||||
))
|
||||
} else if pass.is_none() {
|
||||
Err(Error::new(
|
||||
ErrorKind::InvalidInput,
|
||||
"Empty btc_rpc_password parsed from rpc_cookie",
|
||||
))
|
||||
} else {
|
||||
Ok((user.unwrap(), pass.unwrap()))
|
||||
}
|
||||
}?;
|
||||
|
||||
let rpc_credentials = base64::encode(&format!("{}:{}", rpc_user, rpc_password));
|
||||
let bitcoind_rpc_client = RpcClient::new(&rpc_credentials, http_endpoint)?;
|
||||
|
||||
let client = Self {
|
||||
|
|
|
|||
|
|
@ -12,8 +12,10 @@ rpc_port = 8814
|
|||
# bitcoind
|
||||
btc_network = "mainnet"
|
||||
btc_rpc_user = "CSW"
|
||||
## Notice only user+password **OR** cookie is allowed as rpc auth, any other combination would be rejected
|
||||
btc_rpc_password = "NotSatoshi"
|
||||
btc_rpc_connect = "localhost"
|
||||
btc_rpc_cookie = "~/.bitcoin/.cookie"
|
||||
btc_rpc_port = 8332
|
||||
|
||||
# Flags
|
||||
|
|
|
|||
|
|
@ -41,6 +41,14 @@ impl std::fmt::Display for ConfigError {
|
|||
|
||||
impl std::error::Error for ConfigError {}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub enum AuthMethod {
|
||||
UserPass,
|
||||
CookieFile,
|
||||
Multiple,
|
||||
Invalid,
|
||||
}
|
||||
|
||||
/// Holds all the command line options.
|
||||
#[derive(StructOpt, Debug, Clone)]
|
||||
#[structopt(rename_all = "lowercase")]
|
||||
|
|
@ -66,14 +74,18 @@ pub struct Opt {
|
|||
#[structopt(long)]
|
||||
pub btc_network: Option<String>,
|
||||
|
||||
/// bitcoind rpcuser [default: user]
|
||||
/// bitcoind rpcuser
|
||||
#[structopt(long)]
|
||||
pub btc_rpc_user: Option<String>,
|
||||
|
||||
/// bitcoind rpcpassword [default: passwd]
|
||||
/// bitcoind rpcpassword
|
||||
#[structopt(long)]
|
||||
pub btc_rpc_password: Option<String>,
|
||||
|
||||
/// bitcoind rpccookie
|
||||
#[structopt(long)]
|
||||
pub btc_rpc_cookie: Option<String>,
|
||||
|
||||
/// bitcoind rpcconnect [default: localhost]
|
||||
#[structopt(long)]
|
||||
pub btc_rpc_connect: Option<String>,
|
||||
|
|
@ -136,6 +148,7 @@ pub struct Config {
|
|||
// Bitcoind
|
||||
pub btc_network: String,
|
||||
pub btc_rpc_user: String,
|
||||
pub btc_rpc_cookie: String,
|
||||
pub btc_rpc_password: String,
|
||||
pub btc_rpc_connect: String,
|
||||
pub btc_rpc_port: u16,
|
||||
|
|
@ -164,6 +177,24 @@ pub struct Config {
|
|||
}
|
||||
|
||||
impl Config {
|
||||
/// The only combinations of valid authentication methods are:
|
||||
/// - User **AND** password
|
||||
/// - **OR** Cookie file
|
||||
//
|
||||
/// Any other combination will be rejected
|
||||
pub fn get_auth_method(&self) -> AuthMethod {
|
||||
match (
|
||||
self.btc_rpc_user.is_empty(),
|
||||
self.btc_rpc_password.is_empty(),
|
||||
self.btc_rpc_cookie.is_empty(),
|
||||
) {
|
||||
(false, false, true) => AuthMethod::UserPass,
|
||||
(true, true, false) => AuthMethod::CookieFile,
|
||||
(true, true, true) => AuthMethod::Invalid,
|
||||
_ => AuthMethod::Multiple,
|
||||
}
|
||||
}
|
||||
|
||||
/// Patches the configuration options with the command line options.
|
||||
pub fn patch_with_options(&mut self, options: Opt) {
|
||||
if options.api_bind.is_some() {
|
||||
|
|
@ -187,6 +218,9 @@ impl Config {
|
|||
if options.btc_rpc_password.is_some() {
|
||||
self.btc_rpc_password = options.btc_rpc_password.unwrap();
|
||||
}
|
||||
if options.btc_rpc_cookie.is_some() {
|
||||
self.btc_rpc_cookie = options.btc_rpc_cookie.unwrap();
|
||||
}
|
||||
if options.btc_rpc_connect.is_some() {
|
||||
self.btc_rpc_connect = options.btc_rpc_connect.unwrap();
|
||||
}
|
||||
|
|
@ -216,11 +250,14 @@ impl Config {
|
|||
/// This will also assign the default `btc_rpc_port` depending on the network if it has not
|
||||
/// been overwritten at this point.
|
||||
pub fn verify(&mut self) -> Result<(), ConfigError> {
|
||||
if self.btc_rpc_user == String::new() {
|
||||
return Err(ConfigError("btc_rpc_user must be set".to_owned()));
|
||||
}
|
||||
if self.btc_rpc_password == String::new() {
|
||||
return Err(ConfigError("btc_rpc_password must be set".to_owned()));
|
||||
let auth_method = self.get_auth_method();
|
||||
if auth_method == AuthMethod::Invalid {
|
||||
return Err(ConfigError("No valid bitcoind auth provided. Set either both btc_rpc_user/btc_rpc_password or btc_rpc_cookie".to_owned()));
|
||||
} else if auth_method == AuthMethod::Multiple {
|
||||
return Err(ConfigError(
|
||||
"Multiple bitcoind auth provided. Pick a single one (either btc_rpc_user/btc_rpc_password or btc_rpc_cookie)"
|
||||
.to_owned(),
|
||||
));
|
||||
}
|
||||
|
||||
// Normalize the network option to the ones used by bitcoind.
|
||||
|
|
@ -291,6 +328,7 @@ impl Default for Config {
|
|||
btc_network: "mainnet".into(),
|
||||
btc_rpc_user: String::new(),
|
||||
btc_rpc_password: String::new(),
|
||||
btc_rpc_cookie: String::new(),
|
||||
btc_rpc_connect: "localhost".into(),
|
||||
btc_rpc_port: 0,
|
||||
|
||||
|
|
@ -326,6 +364,7 @@ mod tests {
|
|||
btc_network: None,
|
||||
btc_rpc_user: None,
|
||||
btc_rpc_password: None,
|
||||
btc_rpc_cookie: None,
|
||||
btc_rpc_connect: None,
|
||||
btc_rpc_port: None,
|
||||
data_dir: String::from("~/.teos"),
|
||||
|
|
@ -363,7 +402,7 @@ mod tests {
|
|||
// required to be updated by the user.
|
||||
let mut config = Config::default();
|
||||
assert!(
|
||||
matches!(config.verify(), Err(ConfigError(e)) if e.contains("btc_rpc_user must be set"))
|
||||
matches!(config.verify(), Err(ConfigError(e)) if e.contains("No valid bitcoind auth provided"))
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ use teos::api::{http, tor::TorAPI};
|
|||
use teos::bitcoin_cli::BitcoindClient;
|
||||
use teos::carrier::Carrier;
|
||||
use teos::chain_monitor::ChainMonitor;
|
||||
use teos::config::{self, Config, Opt};
|
||||
use teos::config::{self, AuthMethod, Config, Opt};
|
||||
use teos::dbm::DBM;
|
||||
use teos::gatekeeper::Gatekeeper;
|
||||
use teos::protos as msgs;
|
||||
|
|
@ -142,12 +142,20 @@ async fn main() {
|
|||
};
|
||||
log::info!("tower_id: {tower_pk}");
|
||||
|
||||
let btc_rpc_auth = match conf.get_auth_method() {
|
||||
AuthMethod::CookieFile => {
|
||||
Auth::CookieFile(config::data_dir_absolute_path(conf.btc_rpc_cookie))
|
||||
}
|
||||
AuthMethod::UserPass => Auth::UserPass(conf.btc_rpc_user, conf.btc_rpc_password),
|
||||
// Notice an invalid conf would have failed on `Config::verify()`
|
||||
_ => unreachable!("A verified conf will only have one of these two auth methods"),
|
||||
};
|
||||
|
||||
// Initialize our bitcoind client
|
||||
let (bitcoin_cli, bitcoind_reachable) = match BitcoindClient::new(
|
||||
&conf.btc_rpc_connect,
|
||||
conf.btc_rpc_port,
|
||||
&conf.btc_rpc_user,
|
||||
&conf.btc_rpc_password,
|
||||
btc_rpc_auth.clone(),
|
||||
&conf.btc_network,
|
||||
)
|
||||
.await
|
||||
|
|
@ -176,7 +184,7 @@ async fn main() {
|
|||
let rpc = Arc::new(
|
||||
Client::new(
|
||||
&format!("{schema}{}:{}", conf.btc_rpc_connect, conf.btc_rpc_port),
|
||||
Auth::UserPass(conf.btc_rpc_user.clone(), conf.btc_rpc_password.clone()),
|
||||
btc_rpc_auth,
|
||||
)
|
||||
.unwrap(),
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue