Skip to content

Commit

Permalink
Merge branch 'development' into ho_sender_receiver_protocol
Browse files Browse the repository at this point in the history
  • Loading branch information
SWvheerden authored Nov 13, 2023
2 parents 361f0ea + 4870c49 commit 3b6c0b7
Show file tree
Hide file tree
Showing 61 changed files with 702 additions and 238 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/base_node_binaries.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
"cross": false,
"target_cpu": "x86-64",
"target_bins": "--bin minotari_node --bin minotari_console_wallet --bin minotari_merge_mining_proxy --bin minotari_miner",
"features": "safe"
"features": "libtor, safe"
},
{
"name": "macos-arm64",
Expand All @@ -38,7 +38,7 @@
"cross": false,
"target_cpu": "generic",
"target_bins": "--bin minotari_node --bin minotari_console_wallet --bin minotari_merge_mining_proxy --bin minotari_miner",
"features": "safe",
"features": "libtor, safe",
"build_enabled": false
},
{
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/base_node_binaries.yml
Original file line number Diff line number Diff line change
Expand Up @@ -204,14 +204,14 @@ jobs:
if [ "${{ matrix.builds.cross }}" != "true" ]; then
cargo build --release \
--target ${{ matrix.builds.target }} \
--features ${{ matrix.builds.features }} \
--features "${{ matrix.builds.features }}" \
${{ matrix.builds.target_bins }} \
${{ matrix.builds.flags }} --locked
else
cargo install cross
cross build --release \
--target ${{ matrix.builds.target }} \
--features ${{ matrix.builds.features }} \
--features "${{ matrix.builds.features }}" \
${{ matrix.builds.target_bins }} \
${{ matrix.builds.flags }} --locked
fi
Expand Down
1 change: 1 addition & 0 deletions Cargo.lock

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

55 changes: 50 additions & 5 deletions applications/minotari_app_grpc/src/authentication/basic_auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -363,19 +363,33 @@ mod tests {
//
#[test]
fn it_compares_user_names_in_constant_time() {
// Enable flag `do_performance_testing` to run performance tests; for regular CI runs, this flag should be
// `false` otherwise the test will fail.
// Notes:
// - The `assert!(!do_performance_testing);` at the end of the test will cause a panic on CI if the flag is
// enabled, if it is enabled it will allow results to be printed when running in release mode.
// - For CI (flag disabled), we are only interested if the functional test pass, thus 1 iteration completed
// successfully.
let do_performance_testing = false;

#[allow(clippy::cast_possible_truncation)]
fn round_to_6_decimals(num: f64) -> f64 {
((num * 100000.0) as u128) as f64 / 100000.0
}

const ITERATIONS: usize = 100;
const ITERATIONS: usize = 250;
let mut variances = Vec::with_capacity(ITERATIONS);
let mut short = Vec::with_capacity(ITERATIONS);
let mut long = Vec::with_capacity(ITERATIONS);
let mut actual = Vec::with_capacity(ITERATIONS);
// This value should be chosen to comply with:
// - Small enough to ensure a single iteration does not take too long.
// - Large enough to enable proper time measurement; executing the function that many times should be
// measurable, thus > micro seconds in this case.
const COUNTS: usize = 2500;
let username_actual = "admin";
let hashed_password = create_salted_hashed_password(b"secret").unwrap();
let mut test_runs = 0;
for i in 1..=ITERATIONS {
let credentials =
BasicAuthCredentials::new(username_actual.to_string(), hashed_password.to_string().into()).unwrap();
Expand Down Expand Up @@ -425,6 +439,11 @@ mod tests {
long.push(time_taken_2);
actual.push(time_taken_3);

test_runs += 1;
if !do_performance_testing {
break;
}

// The use of sleep between iterations helps ensure that the tests are run under different conditions,
// simulating real-world scenarios.
if i < ITERATIONS {
Expand All @@ -438,12 +457,15 @@ mod tests {
let avg_long = round_to_6_decimals(long.iter().sum::<u128>() as f64 / long.len() as f64 / COUNTS as f64);
let avg_actual =
round_to_6_decimals(actual.iter().sum::<u128>() as f64 / actual.len() as f64 / COUNTS as f64);
println!("Test runs: {}", test_runs);
println!("Minimum variance: {} %", min_variance);
println!("Average variance: {} %", avg_variance);
println!("Average short username time: {} microseconds", avg_short);
println!("Average long username time: {} microseconds", avg_long);
println!("Average actual username time: {} microseconds", avg_actual);
assert!(*min_variance < 10.0);

// This is to make sure we do not run performance tests on CI.
assert!(!do_performance_testing);
}

// This unit test asserts that the minimum variance is less than 10% (chosen to be robust for running the unit
Expand Down Expand Up @@ -491,19 +513,34 @@ mod tests {
//
#[test]
fn it_compares_credentials_in_constant_time() {
// Enable flag `do_performance_testing` to run performance tests; for regular CI runs, this flag should be
// `false` otherwise the test will fail.
// Notes:
// - The `assert!(!do_performance_testing);` at the end of the test will cause a panic on CI if the flag is
// enabled, if it is enabled it will allow results to be printed when running in release mode.
// - For CI (flag disabled), we are only interested if the functional test pass, thus 1 iteration completed
// successfully.
// - Running this specific test in debug mode is ~100x slower when compared to release mode.
let do_performance_testing = false;

#[allow(clippy::cast_possible_truncation)]
fn round_to_6_decimals(num: f64) -> f64 {
((num * 100000.0) as u128) as f64 / 100000.0
}

const ITERATIONS: usize = 10;
const ITERATIONS: usize = 250;
let mut variances = Vec::with_capacity(ITERATIONS);
let mut short = Vec::with_capacity(ITERATIONS);
let mut long = Vec::with_capacity(ITERATIONS);
let mut actual = Vec::with_capacity(ITERATIONS);
const COUNTS: usize = 20;
// This value should be chosen to comply with:
// - Small enough to ensure a single iteration does not take too long.
// - Large enough to enable proper time measurement; executing the function that many times should be
// measurable, thus > milli seconds in this case.
const COUNTS: usize = 10;
let username_actual = "admin";
let hashed_password = create_salted_hashed_password(b"secret").unwrap();
let mut test_runs = 0;
for i in 1..=ITERATIONS {
let credentials =
BasicAuthCredentials::new(username_actual.to_string(), hashed_password.to_string().into()).unwrap();
Expand Down Expand Up @@ -551,6 +588,11 @@ mod tests {
long.push(time_taken_2);
actual.push(time_taken_3);

test_runs += 1;
if !do_performance_testing {
break;
}

// The use of sleep between iterations helps ensure that the tests are run under different conditions,
// simulating real-world scenarios.
if i < ITERATIONS {
Expand All @@ -564,12 +606,15 @@ mod tests {
let avg_long = round_to_6_decimals(long.iter().sum::<u128>() as f64 / long.len() as f64 / COUNTS as f64);
let avg_actual =
round_to_6_decimals(actual.iter().sum::<u128>() as f64 / actual.len() as f64 / COUNTS as f64);
println!("Test runs: {}", test_runs);
println!("Minimum variance: {} %", min_variance);
println!("Average variance: {} %", avg_variance);
println!("Average short username time: {} microseconds", avg_short);
println!("Average long username time: {} microseconds", avg_long);
println!("Average actual username time: {} microseconds", avg_actual);
assert!(*min_variance < 10.0);

// This is to make sure we do not run performance tests on CI.
assert!(!do_performance_testing);
}
}

Expand Down
5 changes: 3 additions & 2 deletions applications/minotari_merge_mining_proxy/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,9 @@ tari_comms = { path = "../../comms/core" }
tari_core = { path = "../../base_layer/core", default-features = false, features = ["transactions"] }
minotari_app_utilities = { path = "../minotari_app_utilities" }
tari_utilities = { version = "0.6" }
minotari_node_grpc_client = {path="../../clients/rust/base_node_grpc_client" }
minotari_wallet_grpc_client = {path="../../clients/rust/wallet_grpc_client" }
minotari_node_grpc_client = { path = "../../clients/rust/base_node_grpc_client" }
minotari_wallet_grpc_client = { path = "../../clients/rust/wallet_grpc_client" }
minotari_app_grpc = { path = "../minotari_app_grpc" }

anyhow = "1.0.53"
crossterm = { version = "0.25.0" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,13 @@
use std::{cmp, sync::Arc};

use log::*;
use minotari_node_grpc_client::{grpc, BaseNodeGrpcClient};
use minotari_wallet_grpc_client::WalletGrpcClient;
use minotari_app_grpc::{
authentication::ClientAuthenticationInterceptor,
tari_rpc::{base_node_client::BaseNodeClient, wallet_client::WalletClient},
};
use minotari_node_grpc_client::grpc;
use tari_core::proof_of_work::{monero_rx, monero_rx::FixedByteArray, Difficulty};
use tonic::{codegen::InterceptedService, transport::Channel};

use crate::{
block_template_data::{BlockTemplateData, BlockTemplateDataBuilder},
Expand All @@ -41,14 +45,14 @@ const LOG_TARGET: &str = "minotari_mm_proxy::proxy::block_template_protocol";
/// Structure holding grpc connections.
pub struct BlockTemplateProtocol<'a> {
config: Arc<MergeMiningProxyConfig>,
base_node_client: &'a mut BaseNodeGrpcClient<tonic::transport::Channel>,
wallet_client: &'a mut WalletGrpcClient<tonic::transport::Channel>,
base_node_client: &'a mut BaseNodeClient<InterceptedService<Channel, ClientAuthenticationInterceptor>>,
wallet_client: &'a mut WalletClient<InterceptedService<Channel, ClientAuthenticationInterceptor>>,
}

impl<'a> BlockTemplateProtocol<'a> {
pub fn new(
base_node_client: &'a mut BaseNodeGrpcClient<tonic::transport::Channel>,
wallet_client: &'a mut WalletGrpcClient<tonic::transport::Channel>,
base_node_client: &'a mut BaseNodeClient<InterceptedService<Channel, ClientAuthenticationInterceptor>>,
wallet_client: &'a mut WalletClient<InterceptedService<Channel, ClientAuthenticationInterceptor>>,
config: Arc<MergeMiningProxyConfig>,
) -> Self {
Self {
Expand Down
3 changes: 3 additions & 0 deletions applications/minotari_merge_mining_proxy/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ pub struct MergeMiningProxyConfig {
pub monerod_use_auth: bool,
/// The Minotari base node's GRPC address
pub base_node_grpc_address: Option<Multiaddr>,
/// GRPC authentication for base node
pub base_node_grpc_authentication: GrpcAuthentication,
/// The Minotari wallet's GRPC address
pub console_wallet_grpc_address: Option<Multiaddr>,
/// GRPC authentication for console wallet
Expand Down Expand Up @@ -80,6 +82,7 @@ impl Default for MergeMiningProxyConfig {
monerod_password: String::new(),
monerod_use_auth: false,
base_node_grpc_address: None,
base_node_grpc_authentication: GrpcAuthentication::default(),
console_wallet_grpc_address: None,
console_wallet_grpc_authentication: GrpcAuthentication::default(),
listener_address: "/ip4/127.0.0.1/tcp/18081".parse().unwrap(),
Expand Down
13 changes: 7 additions & 6 deletions applications/minotari_merge_mining_proxy/src/proxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ use bytes::Bytes;
use hyper::{header::HeaderValue, service::Service, Body, Method, Request, Response, StatusCode, Uri};
use json::json;
use jsonrpc::error::StandardError;
use minotari_node_grpc_client::{grpc, BaseNodeGrpcClient};
use minotari_wallet_grpc_client::WalletGrpcClient;
use minotari_node_grpc_client::{grpc, grpc::base_node_client::BaseNodeClient};
use minotari_wallet_grpc_client::{grpc::wallet_client::WalletClient, ClientAuthenticationInterceptor};
use reqwest::{ResponseBuilderExt, Url};
use serde_json as json;
use tari_core::proof_of_work::{
Expand All @@ -50,6 +50,7 @@ use tari_core::proof_of_work::{
randomx_factory::RandomXFactory,
};
use tari_utilities::hex::Hex;
use tonic::{codegen::InterceptedService, transport::Channel};
use tracing::{debug, error, info, instrument, trace, warn};

use crate::{
Expand All @@ -75,8 +76,8 @@ impl MergeMiningProxyService {
pub fn new(
config: MergeMiningProxyConfig,
http_client: reqwest::Client,
base_node_client: BaseNodeGrpcClient<tonic::transport::Channel>,
wallet_client: WalletGrpcClient<tonic::transport::Channel>,
base_node_client: BaseNodeClient<InterceptedService<Channel, ClientAuthenticationInterceptor>>,
wallet_client: WalletClient<InterceptedService<Channel, ClientAuthenticationInterceptor>>,
block_templates: BlockTemplateRepository,
randomx_factory: RandomXFactory,
) -> Self {
Expand Down Expand Up @@ -157,8 +158,8 @@ struct InnerService {
config: Arc<MergeMiningProxyConfig>,
block_templates: BlockTemplateRepository,
http_client: reqwest::Client,
base_node_client: BaseNodeGrpcClient<tonic::transport::Channel>,
wallet_client: WalletGrpcClient<tonic::transport::Channel>,
base_node_client: BaseNodeClient<InterceptedService<Channel, ClientAuthenticationInterceptor>>,
wallet_client: WalletClient<InterceptedService<Channel, ClientAuthenticationInterceptor>>,
initial_sync_achieved: Arc<AtomicBool>,
current_monerod_server: Arc<RwLock<Option<String>>>,
last_assigned_monerod_server: Arc<RwLock<Option<String>>>,
Expand Down
76 changes: 54 additions & 22 deletions applications/minotari_merge_mining_proxy/src/run_merge_miner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,13 @@
// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
// USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

use std::convert::Infallible;
use std::{convert::Infallible, str::FromStr};

use futures::future;
use hyper::{service::make_service_fn, Server};
use log::*;
use minotari_node_grpc_client::BaseNodeGrpcClient;
use minotari_wallet_grpc_client::WalletGrpcClient;
use minotari_node_grpc_client::grpc::base_node_client::BaseNodeClient;
use minotari_wallet_grpc_client::{grpc::wallet_client::WalletClient, ClientAuthenticationInterceptor};
use tari_common::{
configuration::bootstrap::{grpc_default_port, ApplicationType},
load_configuration,
Expand All @@ -35,6 +35,10 @@ use tari_common::{
use tari_comms::utils::multiaddr::multiaddr_to_socketaddr;
use tari_core::proof_of_work::randomx_factory::RandomXFactory;
use tokio::time::Duration;
use tonic::{
codegen::InterceptedService,
transport::{Channel, Endpoint},
};

use crate::{
block_template_data::BlockTemplateRepository,
Expand All @@ -59,25 +63,9 @@ pub async fn start_merge_miner(cli: Cli) -> Result<(), anyhow::Error> {
.build()
.map_err(MmProxyError::ReqwestError)?;

let base_node = multiaddr_to_socketaddr(
config
.base_node_grpc_address
.as_ref()
.expect("No base node address provided"),
)?;
info!(target: LOG_TARGET, "Connecting to base node at {}", base_node);
println!("Connecting to base node at {}", base_node);
let base_node_client = BaseNodeGrpcClient::connect(format!("http://{}", base_node)).await?;
let wallet_addr = multiaddr_to_socketaddr(
config
.console_wallet_grpc_address
.as_ref()
.expect("No waller address provided"),
)?;
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 base_node_client = connect_base_node(&config).await?;
let wallet_client = connect_wallet(&config).await?;

let listen_addr = multiaddr_to_socketaddr(&config.listener_address)?;
let randomx_factory = RandomXFactory::new(config.max_randomx_vms);
let randomx_service = MergeMiningProxyService::new(
Expand Down Expand Up @@ -110,6 +98,50 @@ pub async fn start_merge_miner(cli: Cli) -> Result<(), anyhow::Error> {
}
}

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

Ok(wallet_conn)
}

async fn connect_base_node(
config: &MergeMiningProxyConfig,
) -> Result<BaseNodeClient<InterceptedService<Channel, ClientAuthenticationInterceptor>>, MmProxyError> {
let base_node_addr = format!(
"http://{}",
multiaddr_to_socketaddr(
&config
.base_node_grpc_address
.clone()
.expect("Base node grpc address not found")
)?
);
info!(target: LOG_TARGET, "👛 Connecting to base node at {}", base_node_addr);
let channel = Endpoint::from_str(&base_node_addr)?.connect().await?;
let node_conn = BaseNodeClient::with_interceptor(
channel,
ClientAuthenticationInterceptor::create(&config.base_node_grpc_authentication)?,
);

Ok(node_conn)
}

fn setup_grpc_config(config: &mut MergeMiningProxyConfig) {
if config.base_node_grpc_address.is_none() {
config.base_node_grpc_address = Some(
Expand Down
Loading

0 comments on commit 3b6c0b7

Please sign in to comment.