Skip to content
Open
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
3 changes: 2 additions & 1 deletion .github/workflows/checks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ jobs:
uses: actions/checkout@v3

- name: Set up Rust toolchain
uses: dtolnay/rust-toolchain@stable
uses: dtolnay/rust-toolchain@master
with:
toolchain: "1.87.0"
components: rustfmt, clippy

- name: Run cargo fmt
Expand Down
21 changes: 11 additions & 10 deletions src/ingress/sv1_ingress.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use std::{net::{IpAddr, SocketAddr}, sync::Arc};
use std::{
net::{IpAddr, SocketAddr},
sync::Arc,
};

use crate::{
config::Configuration,
Expand Down Expand Up @@ -96,14 +99,12 @@ impl Downstream {
if Configuration::sv1_ingress_log() {
info!("Sending msg to upstream: {}", message);
}
if ! is_subscribed {
if message.contains("mining.subscribe") {
is_subscribed = true;
if message.contains("LUXminer") {
firmware.safe_lock(|f| *f = Firmware::Luxor).unwrap();
} else {
firmware.safe_lock(|f| *f = Firmware::Other).unwrap();
}
if !is_subscribed && message.contains("mining.subscribe") {
is_subscribed = true;
if message.contains("LUXminer") {
firmware.safe_lock(|f| *f = Firmware::Luxor).unwrap();
} else {
firmware.safe_lock(|f| *f = Firmware::Other).unwrap();
}
}
if send.send(message).await.is_err() {
Expand Down Expand Up @@ -158,7 +159,7 @@ impl Downstream {
}
}

#[derive(Debug,Clone,Copy)]
#[derive(Debug, Clone, Copy)]
enum Firmware {
Luxor,
Other,
Expand Down
54 changes: 50 additions & 4 deletions src/translator/downstream/diff_management.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,18 +299,40 @@ fn diff_to_sv1_message(diff: f64) -> ProxyResult<'static, (json_rpc::Message, [u
Ok((message, target))
}

/// Takes a number (`f32`) and rounds it up to the next multiple of its current power of 10.
/// For example, 15.0 becomes 20.0, and 1500.0 becomes 2000.0.
///
/// Returns 0.001 for non-positive inputs (`x <= 0.0`).
/// For positive inputs, it:
/// 1. Identifies the nearest power of 10 (e.g., 10, 100, 1000).
/// 2. Divides the input by this power of 10.
/// 3. Rounds up to the next integer.
/// 4. Multiplies by the power of 10 to get the result.
///
///
/// # Arguments
///
/// * `x` - A 32-bit floating-point number (`f32`).
///
/// # Returns
///
/// * `f32` - The nearest power of 10 greater than or equal to `x`, or `0.001` if `x <= 0.0`.
pub fn nearest_power_of_10(x: f32) -> f32 {
if x <= 0.0 {
return 0.001;
}
let exponent = x.log10().round() as i32;
10f32.powi(exponent)
let log = x.log10();
let base = 10f32.powi(log.floor() as i32);
let scaled = (x / base).ceil();
scaled * base
}

#[cfg(test)]
mod test {
use super::super::super::upstream::diff_management::UpstreamDifficultyConfig;
use crate::translator::downstream::{downstream::DownstreamDifficultyConfig, Downstream};
use crate::translator::downstream::{
diff_management::nearest_power_of_10, downstream::DownstreamDifficultyConfig, Downstream,
};
use binary_sv2::U256;
use pid::Pid;
use rand::{thread_rng, Rng};
Expand All @@ -321,8 +343,20 @@ mod test {
sync::Arc,
time::{Duration, Instant},
};
use sv1_api::{
server_to_client::Notify,
utils::{HexU32Be, MerkleNode, PrevHash},
};
use tokio::sync::mpsc::channel;

#[test]
fn test_nearest_power_of_10() {
assert_eq!(nearest_power_of_10(450.0), 500.0);
assert_eq!(nearest_power_of_10(0.034), 0.04);
assert_eq!(nearest_power_of_10(0.0), 0.001);
assert_eq!(nearest_power_of_10(147.0), 200.0);
}

#[test]
#[ignore] // TODO
fn test_diff_management() {
Expand Down Expand Up @@ -440,6 +474,18 @@ mod test {
};
let (tx_sv1_submit, _rx_sv1_submit) = tokio::sync::mpsc::channel(10);
let (tx_outgoing, _rx_outgoing) = channel(10);
let random_str = rand::thread_rng().gen::<[u8; 32]>().to_vec();
let first_job = Notify {
job_id: "ciao".to_string(),
prev_hash: PrevHash::try_from("0".repeat(64).as_str()).unwrap(),
coin_base1: "ffff".try_into().unwrap(),
coin_base2: "ffff".try_into().unwrap(),
merkle_branch: vec![MerkleNode::try_from(random_str).unwrap()],
version: HexU32Be(5667),
bits: HexU32Be(5678),
time: HexU32Be(5609),
clean_jobs: true,
};
let mut downstream = Downstream::new(
1,
vec![],
Expand All @@ -448,11 +494,11 @@ mod test {
None,
tx_sv1_submit,
tx_outgoing,
false,
0,
downstream_conf.clone(),
Arc::new(Mutex::new(upstream_config)),
crate::api::stats::StatsSender::new(),
first_job,
);
downstream.difficulty_mgmt.estimated_downstream_hash_rate = start_hashrate as f32;

Expand Down
9 changes: 5 additions & 4 deletions src/translator/downstream/downstream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,6 +354,7 @@ impl Downstream {
difficulty_mgmt: DownstreamDifficultyConfig,
upstream_difficulty_config: Arc<Mutex<UpstreamDifficultyConfig>>,
stats_sender: StatsSender,
first_job: Notify<'static>,
) -> Self {
Downstream {
connection_id,
Expand All @@ -367,7 +368,7 @@ impl Downstream {
difficulty_mgmt,
upstream_difficulty_config,
last_call_to_update_hr: 0,
first_job: Notify,
first_job,
stats_sender,
recent_jobs: RecentJobs::new(),
}
Expand Down Expand Up @@ -494,19 +495,19 @@ impl IsServer<'static> for Downstream {
"Share for Job {} and difficulty {} is accepted",
request.job_id, met_difficulty
);
return true;
true
} else {
error!("Share rejected: Invalid share");
self.stats_sender.update_rejected_shares(self.connection_id);
return false;
false
}
} else {
error!(
"Share rejected: can not find job with id {}",
request.job_id
);
self.stats_sender.update_rejected_shares(self.connection_id);
return false;
false
}
}
Ok(false) => {
Expand Down
4 changes: 1 addition & 3 deletions src/translator/downstream/notify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,7 @@ pub async fn start_notify(
}
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
}
if let Err(e) =
start_update(task_manager, downstream.clone(), connection_id).await
{
if let Err(e) = start_update(task_manager, downstream.clone(), connection_id).await {
warn!("Translator impossible to start update task: {e}");
} else if authorized_in_time {
// Get the mask after initialization since is set by configure message
Expand Down