Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(clients): add base node and wallet client crates #4722

Merged
merged 2 commits into from
Sep 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 24 additions & 5 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ members = [
"base_layer/wallet",
"base_layer/wallet_ffi",
"base_layer/tari_mining_helper_ffi",
"clients/rust/base_node_grpc_client",
"clients/rust/wallet_grpc_client",
"comms/core",
"comms/dht",
"comms/rpc_macros",
Expand Down
24 changes: 18 additions & 6 deletions applications/tari_app_grpc/src/authentication/basic_auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use std::{borrow::Cow, string::FromUtf8Error};

use argon2::{password_hash::Encoding, Argon2, PasswordHash, PasswordVerifier};
use tari_utilities::SafePassword;
use tonic::metadata::{errors::InvalidMetadataValue, Ascii, MetadataValue};
use zeroize::{Zeroize, Zeroizing};

/// Implements [RFC 2617](https://www.ietf.org/rfc/rfc2617.txt#:~:text=The%20%22basic%22%20authentication%20scheme%20is,other%20realms%20on%20that%20server.)
Expand Down Expand Up @@ -89,7 +90,7 @@ impl BasicAuthCredentials {
Ok(())
}

pub fn generate_header(username: &str, password: &[u8]) -> Result<String, BasicAuthError> {
pub fn generate_header(username: &str, password: &[u8]) -> Result<MetadataValue<Ascii>, BasicAuthError> {
let password_str = String::from_utf8_lossy(password);
let token_str = Zeroizing::new(format!("{}:{}", username, password_str));
let mut token = base64::encode(token_str);
Expand All @@ -99,12 +100,13 @@ impl BasicAuthCredentials {
Cow::Borrowed(_) => {},
Cow::Owned(mut owned) => owned.zeroize(),
}
let header = header.parse()?;
Ok(header)
}
}

/// Authorization Header Error
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
#[derive(Debug, thiserror::Error)]
pub enum BasicAuthError {
#[error("Invalid username")]
InvalidUsername,
Expand All @@ -118,6 +120,8 @@ pub enum BasicAuthError {
InvalidUtf8Value(#[from] FromUtf8Error),
#[error("Invalid password: {0}")]
InvalidPassword(#[from] argon2::password_hash::Error),
#[error("Invalid header value: {0}")]
InvalidMetadataValue(#[from] InvalidMetadataValue),
}

#[cfg(test)]
Expand All @@ -137,9 +141,17 @@ mod tests {
#[test]
fn it_rejects_header_without_basic_scheme() {
let err = BasicAuthCredentials::from_header(" YWRtaW46c2VjcmV0").unwrap_err();
assert_eq!(err, BasicAuthError::InvalidScheme("".to_string()));
if let BasicAuthError::InvalidScheme(s) = err {
assert_eq!(s, "");
} else {
panic!("Unexpected error: {:?}", err);
};
let err = BasicAuthCredentials::from_header("Cookie YWRtaW46c2VjcmV0").unwrap_err();
assert_eq!(err, BasicAuthError::InvalidScheme("Cookie".to_string()));
if let BasicAuthError::InvalidScheme(s) = err {
assert_eq!(s, "Cookie");
} else {
panic!("Unexpected error: {:?}", err);
};
}
}

Expand All @@ -162,7 +174,7 @@ mod tests {

let credentials = BasicAuthCredentials::new("bruteforce".to_string(), "secret".to_string().into());
let err = credentials.validate("admin", b"secret").unwrap_err();
assert_eq!(err, BasicAuthError::InvalidUsername);
assert!(matches!(err, BasicAuthError::InvalidUsername));
}
}

Expand All @@ -172,7 +184,7 @@ mod tests {
#[test]
fn it_generates_a_valid_header() {
let header = BasicAuthCredentials::generate_header("admin", b"secret").unwrap();
let cred = BasicAuthCredentials::from_header(&header).unwrap();
let cred = BasicAuthCredentials::from_header(header.to_str().unwrap()).unwrap();
assert_eq!(cred.user_name, "admin");
assert_eq!(cred.password.reveal(), &b"secret"[..]);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,9 @@ impl ClientAuthenticationInterceptor {
pub fn create(auth: &GrpcAuthentication) -> Result<Self, BasicAuthError> {
let authorization_header = match auth {
GrpcAuthentication::None => None,
GrpcAuthentication::Basic { username, password } => Some(
BasicAuthCredentials::generate_header(username, password.reveal())?
.parse()
.unwrap(),
),
GrpcAuthentication::Basic { username, password } => {
Some(BasicAuthCredentials::generate_header(username, password.reveal())?)
},
};
Ok(Self { authorization_header })
}
Expand Down
4 changes: 2 additions & 2 deletions applications/tari_merge_mining_proxy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ edition = "2018"
default = []

[dependencies]
tari_app_grpc = { path = "../tari_app_grpc" }
tari_common = { path = "../../common" }
tari_common_types = { path = "../../base_layer/common_types" }
tari_comms = { path = "../../comms/core" }
tari_core = { path = "../../base_layer/core", default-features = false, features = ["transactions"] }
tari_app_utilities = { path = "../tari_app_utilities" }
tari_crypto = { git = "https://github.com/tari-project/tari-crypto.git", tag = "v0.15.5" }
tari_utilities = { git = "https://github.com/tari-project/tari_utilities.git", tag = "v0.4.5" }
tari_base_node_grpc_client = {path="../../clients/rust/base_node_grpc_client" }
tari_wallet_grpc_client = {path="../../clients/rust/wallet_grpc_client" }

anyhow = "1.0.53"
crossterm = { version = "0.17" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use std::{collections::HashMap, sync::Arc};
#[cfg(not(test))]
use chrono::Duration;
use chrono::{self, DateTime, Utc};
use tari_app_grpc::tari_rpc as grpc;
use tari_base_node_grpc_client::grpc;
use tari_core::proof_of_work::monero_rx::FixedByteArray;
use tokio::sync::RwLock;
use tracing::trace;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@
use std::cmp;

use log::*;
use tari_app_grpc::{authentication::ClientAuthenticationInterceptor, tari_rpc as grpc};
use tari_base_node_grpc_client::{grpc, BaseNodeGrpcClient};
use tari_core::proof_of_work::{monero_rx, monero_rx::FixedByteArray, Difficulty};
use tari_wallet_grpc_client::WalletGrpcClient;

use crate::{
block_template_data::{BlockTemplateData, BlockTemplateDataBuilder},
Expand All @@ -38,18 +39,14 @@ const LOG_TARGET: &str = "tari_mm_proxy::proxy::block_template_protocol";

/// Structure holding grpc connections.
pub struct BlockTemplateProtocol<'a> {
base_node_client: &'a mut grpc::base_node_client::BaseNodeClient<tonic::transport::Channel>,
wallet_client: &'a mut grpc::wallet_client::WalletClient<
tonic::codegen::InterceptedService<tonic::transport::Channel, ClientAuthenticationInterceptor>,
>,
base_node_client: &'a mut BaseNodeGrpcClient<tonic::transport::Channel>,
wallet_client: &'a mut WalletGrpcClient<tonic::transport::Channel>,
}

impl<'a> BlockTemplateProtocol<'a> {
pub fn new(
base_node_client: &'a mut grpc::base_node_client::BaseNodeClient<tonic::transport::Channel>,
wallet_client: &'a mut grpc::wallet_client::WalletClient<
tonic::codegen::InterceptedService<tonic::transport::Channel, ClientAuthenticationInterceptor>,
>,
base_node_client: &'a mut BaseNodeGrpcClient<tonic::transport::Channel>,
wallet_client: &'a mut WalletGrpcClient<tonic::transport::Channel>,
) -> Self {
Self {
base_node_client,
Expand Down Expand Up @@ -160,7 +157,7 @@ impl BlockTemplateProtocol<'_> {
let tip = self
.base_node_client
.clone()
.get_tip_info(tari_app_grpc::tari_rpc::Empty {})
.get_tip_info(grpc::Empty {})
.await?
.into_inner();
let tip_height = tip.metadata.as_ref().map(|m| m.height_of_longest_chain).unwrap_or(0);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@

use std::convert::{TryFrom, TryInto};

use tari_app_grpc::tari_rpc as grpc;
use tari_base_node_grpc_client::grpc;
use tari_core::{
blocks::NewBlockTemplate,
transactions::transaction_components::{TransactionKernel, TransactionOutput},
Expand Down
2 changes: 1 addition & 1 deletion applications/tari_merge_mining_proxy/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@

use serde::{Deserialize, Serialize};
use tari_common::{configuration::StringList, SubConfigPath};
use tari_common_types::grpc_authentication::GrpcAuthentication;
use tari_comms::multiaddr::Multiaddr;
use tari_wallet_grpc_client::GrpcAuthentication;

#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
Expand Down
3 changes: 2 additions & 1 deletion applications/tari_merge_mining_proxy/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,10 @@ use std::io;

use hex::FromHexError;
use hyper::header::InvalidHeaderValue;
use tari_app_grpc::authentication::BasicAuthError;
// use tari_app_grpc::authentication::BasicAuthError;
use tari_common::{ConfigError, ConfigurationError};
use tari_core::{proof_of_work::monero_rx::MergeMineError, transactions::CoinbaseBuildError};
use tari_wallet_grpc_client::BasicAuthError;
use thiserror::Error;
use tonic::{codegen::http::uri::InvalidUri, transport};

Expand Down
37 changes: 8 additions & 29 deletions applications/tari_merge_mining_proxy/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ mod test;
use std::{
convert::Infallible,
io::{stdout, Write},
str::FromStr,
};

use clap::Parser;
Expand All @@ -43,16 +42,13 @@ use futures::future;
use hyper::{service::make_service_fn, Server};
use log::*;
use proxy::MergeMiningProxyService;
use tari_app_grpc::{authentication::ClientAuthenticationInterceptor, tari_rpc as grpc};
use tari_app_utilities::consts;
use tari_base_node_grpc_client::BaseNodeGrpcClient;
use tari_common::{initialize_logging, load_configuration, DefaultConfigLoader};
use tari_comms::utils::multiaddr::multiaddr_to_socketaddr;
use tari_core::proof_of_work::randomx_factory::RandomXFactory;
use tari_wallet_grpc_client::WalletGrpcClient;
use tokio::time::Duration;
use tonic::{
codegen::InterceptedService,
transport::{Channel, Endpoint},
};

use crate::{
block_template_data::BlockTemplateRepository,
Expand All @@ -62,24 +58,6 @@ use crate::{
};
const LOG_TARGET: &str = "tari_mm_proxy::proxy";

pub(crate) type WalletGrpcClient =
grpc::wallet_client::WalletClient<InterceptedService<Channel, ClientAuthenticationInterceptor>>;

async fn connect_wallet_with_authenticator(config: &MergeMiningProxyConfig) -> Result<WalletGrpcClient, MmProxyError> {
let wallet_addr = format!(
"http://{}",
multiaddr_to_socketaddr(&config.console_wallet_grpc_address)?
);
info!(target: LOG_TARGET, "👛 Connecting to wallet at {}", wallet_addr);
let channel = Endpoint::from_str(&wallet_addr)?.connect().await?;
let wallet_conn = grpc::wallet_client::WalletClient::with_interceptor(
channel,
ClientAuthenticationInterceptor::create(&config.console_wallet_grpc_authentication)?,
);

Ok(wallet_conn)
}

#[tokio::main]
async fn main() -> Result<(), anyhow::Error> {
let terminal_title = format!("Tari Merge Mining Proxy - Version {}", consts::APP_VERSION);
Expand Down Expand Up @@ -109,11 +87,12 @@ async fn main() -> Result<(), anyhow::Error> {
let base_node = multiaddr_to_socketaddr(&config.base_node_grpc_address)?;
info!(target: LOG_TARGET, "Connecting to base node at {}", base_node);
println!("Connecting to base node at {}", base_node);
let base_node_client = grpc::base_node_client::BaseNodeClient::connect(format!("http://{}", base_node)).await?;
let wallet = multiaddr_to_socketaddr(&config.console_wallet_grpc_address)?;
info!(target: LOG_TARGET, "Connecting to wallet at {}", wallet);
println!("Connecting to wallet at {}", wallet);
let wallet_client = connect_wallet_with_authenticator(&config).await?;
let base_node_client = BaseNodeGrpcClient::connect(format!("http://{}", base_node)).await?;
let wallet_addr = multiaddr_to_socketaddr(&config.console_wallet_grpc_address)?;
info!(target: LOG_TARGET, "Connecting to wallet at {}", wallet_addr);
let wallet_addr = format!("http://{}", wallet_addr);
let wallet_client =
WalletGrpcClient::connect_with_auth(&wallet_addr, &config.console_wallet_grpc_authentication).await?;
let listen_addr = multiaddr_to_socketaddr(&config.listener_address)?;
let randomx_factory = RandomXFactory::new(config.max_randomx_vms);
let xmrig_service = MergeMiningProxyService::new(
Expand Down
Loading