mirror of
https://github.com/Cyrix126/gupaxx.git
synced 2024-11-16 15:27:46 +00:00
refactor: turn algorithm.rs structure into a struct with implementations
This commit is contained in:
parent
b34839a793
commit
efc156149b
2 changed files with 349 additions and 371 deletions
|
@ -4,7 +4,6 @@ use std::{
|
|||
};
|
||||
|
||||
use log::{debug, info, warn};
|
||||
use readable::num::Float;
|
||||
use reqwest::Client;
|
||||
use tokio::time::sleep;
|
||||
|
||||
|
@ -24,288 +23,6 @@ use crate::{
|
|||
|
||||
use super::{priv_stats::RuntimeDonationLevel, PubXvbApi, SamplesAverageHour};
|
||||
|
||||
pub(crate) fn calcul_donated_time(
|
||||
lhr: f32,
|
||||
gui_api_p2pool: &Arc<Mutex<PubP2poolApi>>,
|
||||
gui_api_xvb: &Arc<Mutex<PubXvbApi>>,
|
||||
state_p2pool: &crate::disk::state::P2pool,
|
||||
) -> u32 {
|
||||
let p2pool_ehr = lock!(gui_api_p2pool).sidechain_ehr;
|
||||
// what if ehr stay still for the next ten minutes ? mHR will augment every ten minutes because it thinks that oHR is decreasing.
|
||||
//
|
||||
let avg_hr = calc_last_hour_avg_hash_rate(&lock!(gui_api_xvb).p2pool_sent_last_hour_samples);
|
||||
let mut p2pool_ohr = p2pool_ehr - avg_hr;
|
||||
if p2pool_ohr < 0.0 {
|
||||
p2pool_ohr = 0.0;
|
||||
}
|
||||
info!("XvB Process | p2pool sidechain HR - last hour average HR = estimated outside HR\n{p2pool_ehr} - {avg_hr} = {p2pool_ohr}");
|
||||
let mut min_hr = minimum_hashrate_share(
|
||||
lock!(gui_api_p2pool).p2pool_difficulty_u64,
|
||||
state_p2pool.mini,
|
||||
p2pool_ohr,
|
||||
);
|
||||
if min_hr.is_sign_negative() {
|
||||
info!("XvB Process | if minimum HR is negative, it is 0.");
|
||||
min_hr = 0.0;
|
||||
}
|
||||
info!("Xvb Process | hr {}, min_hr: {} ", lhr, min_hr);
|
||||
// numbers are divided by a thousands to print kH/s and not H/s
|
||||
let msg_lhr = format!(
|
||||
"{} kH/s local HR from Xmrig",
|
||||
Float::from_3((lhr / 1000.0).into())
|
||||
);
|
||||
let msg_mhr = format!(
|
||||
"{} kH/s minimum required local HR to keep a share in PPLNS window",
|
||||
Float::from_3((min_hr / 1000.0).into())
|
||||
);
|
||||
let msg_ehr = format!(
|
||||
"{} kH/s estimated sent the last hour for your address on p2pool, including this instance",
|
||||
Float::from_3((p2pool_ehr / 1000.0).into())
|
||||
);
|
||||
output_console(gui_api_xvb, &msg_lhr);
|
||||
output_console(gui_api_xvb, &msg_mhr);
|
||||
output_console(gui_api_xvb, &msg_ehr);
|
||||
|
||||
let xvb_chr = lock!(gui_api_xvb).stats_priv.donor_1hr_avg * 1000.0;
|
||||
info!("current HR on XvB (last hour): {xvb_chr}");
|
||||
let shr = calc_last_hour_avg_hash_rate(&lock!(gui_api_xvb).xvb_sent_last_hour_samples);
|
||||
|
||||
// calculate how much time can be spared
|
||||
let mode = lock!(gui_api_xvb).stats_priv.runtime_mode.clone();
|
||||
|
||||
let default_spared_time = time_that_could_be_spared(lhr, min_hr);
|
||||
let mut spared_time = match mode {
|
||||
RuntimeMode::Auto => {
|
||||
info!("RuntimeMode::Auto - calculating spared_time");
|
||||
// calculate how much time needed to be spared to be in most round type minimum HR + buffer
|
||||
minimum_time_for_highest_accessible_round(default_spared_time, lhr, xvb_chr, shr)
|
||||
}
|
||||
RuntimeMode::Hero => {
|
||||
info!("RuntimeMode::Hero - calculating spared_time lhr:{lhr} min_hr:{min_hr}");
|
||||
output_console(gui_api_xvb, "Hero mode is enabled for this decision");
|
||||
default_spared_time
|
||||
}
|
||||
RuntimeMode::ManualXvb => {
|
||||
let donate_hr = lock!(gui_api_xvb).stats_priv.runtime_manual_amount;
|
||||
info!("RuntimeMode::ManualXvb - lhr:{lhr} donate_hr:{donate_hr}");
|
||||
|
||||
XVB_TIME_ALGO * (donate_hr as u32) / (lhr as u32)
|
||||
}
|
||||
RuntimeMode::ManualP2pool => {
|
||||
let keep_hr = lock!(gui_api_xvb).stats_priv.runtime_manual_amount;
|
||||
info!("RuntimeMode::ManualXvb - lhr:{lhr} keep_hr:{keep_hr}");
|
||||
|
||||
XVB_TIME_ALGO - (XVB_TIME_ALGO * (keep_hr as u32) / (lhr as u32))
|
||||
}
|
||||
RuntimeMode::ManualDonationLevel => {
|
||||
let donation_level = lock!(gui_api_xvb)
|
||||
.stats_priv
|
||||
.runtime_manual_donation_level
|
||||
.clone();
|
||||
info!("RuntimeMode::ManualDonationLevel");
|
||||
|
||||
minimum_time_for_manual_round(donation_level, default_spared_time, lhr, xvb_chr, shr)
|
||||
}
|
||||
};
|
||||
|
||||
info!("Final spared_time is {spared_time}");
|
||||
if spared_time > XVB_TIME_ALGO {
|
||||
spared_time = XVB_TIME_ALGO;
|
||||
}
|
||||
|
||||
spared_time
|
||||
}
|
||||
fn minimum_hashrate_share(difficulty: u64, mini: bool, ohr: f32) -> f32 {
|
||||
let pws = if mini {
|
||||
BLOCK_PPLNS_WINDOW_MINI
|
||||
} else {
|
||||
BLOCK_PPLNS_WINDOW_MAIN
|
||||
};
|
||||
let minimum_hr = ((difficulty / (pws * SECOND_PER_BLOCK_P2POOL)) as f32 * XVB_BUFFER) - ohr;
|
||||
info!("XvB Process | (difficulty / (window pplns blocks * seconds per p2pool block) * BUFFER) - outside HR = minimum HR to keep a share\n({difficulty} / ({pws} * {SECOND_PER_BLOCK_P2POOL}) * {XVB_BUFFER}) - {ohr} = {minimum_hr}");
|
||||
minimum_hr
|
||||
}
|
||||
fn time_that_could_be_spared(hr: f32, min_hr: f32) -> u32 {
|
||||
// percent of time minimum
|
||||
let minimum_time_required_on_p2pool = XVB_TIME_ALGO as f32 / (hr / min_hr);
|
||||
info!("XvB Process | Time of algo / local hashrate / minimum hashrate = minimum time required on p2pool\n{XVB_TIME_ALGO} / ({hr} / {min_hr}) = {minimum_time_required_on_p2pool}");
|
||||
let spared_time = XVB_TIME_ALGO as f32 - minimum_time_required_on_p2pool;
|
||||
info!("XvB Process | Time of algo - minimum time required on p2pool = time that can be spared.\n{XVB_TIME_ALGO} - {minimum_time_required_on_p2pool} = {spared_time}");
|
||||
// if less than 6 seconds, XMRig could hardly have the time to mine anything.
|
||||
if spared_time >= 6.0 {
|
||||
return spared_time as u32;
|
||||
}
|
||||
info!(
|
||||
"XvB Process | sparted time is equal or less than 6 seconds, so everything goes to p2pool."
|
||||
);
|
||||
0
|
||||
}
|
||||
|
||||
// spared time, local hr, current 1h average hr already mining on XvB, 1h average local HR sent on XvB.
|
||||
fn minimum_time_for_highest_accessible_round(st: u32, lhr: f32, chr: f32, shr: f32) -> u32 {
|
||||
// we remove one second that could possibly be sent, because if the time needed is a float, it will be rounded up.
|
||||
// this subtraction can not fail because mnimum spared time is >= 6.
|
||||
let hr_for_xvb = ((st - 1) as f32 / XVB_TIME_ALGO as f32) * lhr;
|
||||
info!(
|
||||
"hr for xvb is: ({st} / {}) * {lhr} = {hr_for_xvb}H/s",
|
||||
XVB_TIME_ALGO
|
||||
);
|
||||
let ohr = chr - shr;
|
||||
info!("ohr is: {chr} - {shr} = {ohr}H/s");
|
||||
let min_mega = XVB_ROUND_DONOR_MEGA_MIN_HR as f32 - ohr;
|
||||
info!(
|
||||
"minimum required HR for mega round is: {} - {ohr} = {min_mega}H/s",
|
||||
XVB_ROUND_DONOR_MEGA_MIN_HR
|
||||
);
|
||||
let min_whale = XVB_ROUND_DONOR_WHALE_MIN_HR as f32 - ohr;
|
||||
info!(
|
||||
"minimum required HR for whale round is: {} - {ohr} = {min_whale}H/s",
|
||||
XVB_ROUND_DONOR_WHALE_MIN_HR
|
||||
);
|
||||
let min_donorvip = XVB_ROUND_DONOR_VIP_MIN_HR as f32 - ohr;
|
||||
info!(
|
||||
"minimum required HR for donor vip round is: {} - {ohr} = {min_donorvip}H/s",
|
||||
XVB_ROUND_DONOR_VIP_MIN_HR
|
||||
);
|
||||
let min_donor = XVB_ROUND_DONOR_MIN_HR as f32 - ohr;
|
||||
info!(
|
||||
"minimum required HR for donor round is: {} - {ohr} = {min_donor}H/s",
|
||||
XVB_ROUND_DONOR_MIN_HR
|
||||
);
|
||||
let min = match hr_for_xvb {
|
||||
x if x > min_mega => {
|
||||
info!("trying to get Mega round");
|
||||
info!(
|
||||
"minimum second to send = ((({x} - ({x} - {min_mega})) / {lhr}) * {}) ",
|
||||
XVB_TIME_ALGO
|
||||
);
|
||||
min_mega
|
||||
}
|
||||
x if x > min_whale => {
|
||||
info!("trying to get Whale round");
|
||||
info!(
|
||||
"minimum second to send = ((({x} - ({x} - {min_whale})) / {lhr}) * {}) ",
|
||||
XVB_TIME_ALGO
|
||||
);
|
||||
min_whale
|
||||
}
|
||||
x if x > min_donorvip => {
|
||||
info!("trying to get Vip Donor round");
|
||||
info!(
|
||||
"minimum second to send = ((({x} - ({x} - {min_donorvip})) / {lhr}) * {}) ",
|
||||
XVB_TIME_ALGO
|
||||
);
|
||||
min_donorvip
|
||||
}
|
||||
x if x > min_donor => {
|
||||
info!("trying to get Donor round");
|
||||
info!(
|
||||
"minimum second to send = ((({x} - ({x} - {min_donor})) / {lhr}) * {}) ",
|
||||
XVB_TIME_ALGO
|
||||
);
|
||||
min_donor
|
||||
}
|
||||
_ => return 0,
|
||||
};
|
||||
|
||||
(((hr_for_xvb - (hr_for_xvb - min)) / lhr) * XVB_TIME_ALGO as f32).ceil() as u32
|
||||
}
|
||||
|
||||
fn minimum_time_for_manual_round(
|
||||
level: RuntimeDonationLevel,
|
||||
st: u32,
|
||||
lhr: f32,
|
||||
chr: f32,
|
||||
shr: f32,
|
||||
) -> u32 {
|
||||
let hr_for_xvb = ((st - 1) as f32 / XVB_TIME_ALGO as f32) * lhr;
|
||||
info!(
|
||||
"hr for xvb is: ({st} / {}) * {lhr} = {hr_for_xvb}H/s",
|
||||
XVB_TIME_ALGO
|
||||
);
|
||||
let ohr = chr - shr;
|
||||
|
||||
let min = match level {
|
||||
RuntimeDonationLevel::Donor => {
|
||||
info!("RuntimeDonationLevel::Donor");
|
||||
XVB_ROUND_DONOR_MIN_HR as f32 - ohr
|
||||
}
|
||||
RuntimeDonationLevel::DonorVIP => {
|
||||
info!("RuntimeDonationLevel::DonorVIP");
|
||||
XVB_ROUND_DONOR_VIP_MIN_HR as f32 - ohr
|
||||
}
|
||||
RuntimeDonationLevel::DonorWhale => {
|
||||
info!("RuntimeDonationLevel::DonorWhale");
|
||||
XVB_ROUND_DONOR_WHALE_MIN_HR as f32 - ohr
|
||||
}
|
||||
RuntimeDonationLevel::DonorMega => {
|
||||
info!("RuntimeDonationLevel::DonorMega");
|
||||
XVB_ROUND_DONOR_MEGA_MIN_HR as f32 - ohr
|
||||
}
|
||||
};
|
||||
|
||||
(((hr_for_xvb - (hr_for_xvb - min)) / lhr) * XVB_TIME_ALGO as f32).ceil() as u32
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
async fn sleep_then_update_node_xmrig(
|
||||
spared_time: u32,
|
||||
client: &Client,
|
||||
api_uri: &str,
|
||||
token_xmrig: &str,
|
||||
address: &str,
|
||||
gui_api_xvb: &Arc<Mutex<PubXvbApi>>,
|
||||
gui_api_xmrig: &Arc<Mutex<PubXmrigApi>>,
|
||||
rig: &str,
|
||||
) {
|
||||
let node = lock!(gui_api_xvb).stats_priv.node;
|
||||
debug!(
|
||||
"Xvb Process | algo sleep for {} while mining on P2pool",
|
||||
XVB_TIME_ALGO - spared_time
|
||||
);
|
||||
sleep(Duration::from_secs((XVB_TIME_ALGO - spared_time).into())).await;
|
||||
// only update xmrig config if it is actually mining.
|
||||
if spared_time > 0 {
|
||||
debug!("Xvb Process | request xmrig to mine on XvB");
|
||||
if lock!(gui_api_xvb).current_node.is_none()
|
||||
|| lock!(gui_api_xvb)
|
||||
.current_node
|
||||
.as_ref()
|
||||
.is_some_and(|n| n == &XvbNode::P2pool)
|
||||
{
|
||||
if let Err(err) = PrivXmrigApi::update_xmrig_config(
|
||||
client,
|
||||
api_uri,
|
||||
token_xmrig,
|
||||
&node,
|
||||
address,
|
||||
gui_api_xmrig,
|
||||
rig,
|
||||
)
|
||||
.await
|
||||
{
|
||||
// show to console error about updating xmrig config
|
||||
warn!("Xvb Process | Failed request HTTP API Xmrig");
|
||||
output_console(
|
||||
gui_api_xvb,
|
||||
&format!(
|
||||
"Failure to update xmrig config with HTTP API.\nError: {}",
|
||||
err
|
||||
),
|
||||
);
|
||||
} else {
|
||||
debug!("Xvb Process | mining on XvB pool");
|
||||
}
|
||||
}
|
||||
// will not quit the process until it is really done.
|
||||
// xvb process watch this algo handle to see if process is finished or not.
|
||||
sleep(Duration::from_secs(spared_time.into())).await;
|
||||
}
|
||||
}
|
||||
// push new value into samples before executing this calcul
|
||||
fn calc_last_hour_avg_hash_rate(samples: &SamplesAverageHour) -> f32 {
|
||||
samples.0.iter().sum::<f32>() / samples.0.len() as f32
|
||||
}
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) async fn algorithm(
|
||||
client: &Client,
|
||||
|
@ -318,24 +35,63 @@ pub(crate) async fn algorithm(
|
|||
time_donated: &Arc<Mutex<u32>>,
|
||||
rig: &str,
|
||||
) {
|
||||
debug!("Xvb Process | Algorithm is started");
|
||||
output_console(
|
||||
let mut algorithm = Algorithm::new(
|
||||
client,
|
||||
gui_api_xvb,
|
||||
"Algorithm of distribution HR started for the next ten minutes.",
|
||||
gui_api_xmrig,
|
||||
gui_api_p2pool,
|
||||
token_xmrig,
|
||||
state_p2pool,
|
||||
share,
|
||||
time_donated,
|
||||
rig,
|
||||
);
|
||||
// the time that takes the algorithm do decide the next ten minutes could means less p2pool mining. It is solved by the buffer and spawning requests.
|
||||
let address = &state_p2pool.address;
|
||||
// request XMrig to mine on P2pool
|
||||
// if share is in PW,
|
||||
if share > 0 {
|
||||
debug!("Xvb Process | Algorithm share is in current window");
|
||||
// calcul minimum HR
|
||||
algorithm.run().await;
|
||||
}
|
||||
|
||||
output_console(
|
||||
gui_api_xvb,
|
||||
"At least one share is in current PPLNS window.",
|
||||
);
|
||||
struct Algorithm<'a> {
|
||||
client: &'a Client,
|
||||
gui_api_xvb: &'a Arc<Mutex<PubXvbApi>>,
|
||||
gui_api_xmrig: &'a Arc<Mutex<PubXmrigApi>>,
|
||||
gui_api_p2pool: &'a Arc<Mutex<PubP2poolApi>>,
|
||||
token_xmrig: &'a str,
|
||||
state_p2pool: &'a crate::disk::state::P2pool,
|
||||
time_donated: &'a Arc<Mutex<u32>>,
|
||||
rig: &'a str,
|
||||
stats: Stats,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct Stats {
|
||||
share: u32,
|
||||
hashrate_xmrig: f32,
|
||||
target_donation_hashrate: f32,
|
||||
xvb_24h_avg: f32,
|
||||
xvb_1h_avg: f32,
|
||||
address: String,
|
||||
runtime_mode: RuntimeMode,
|
||||
runtime_donation_level: RuntimeDonationLevel,
|
||||
runtime_amount: f64,
|
||||
p2pool_total_hashrate: f32,
|
||||
avg_last_hour_hashrate: f32,
|
||||
p2pool_external_hashrate: f32,
|
||||
share_min_hashrate: f32,
|
||||
spareable_hashrate: f32,
|
||||
spared_time: u32,
|
||||
}
|
||||
|
||||
impl<'a> Algorithm<'a> {
|
||||
fn new(
|
||||
client: &'a Client,
|
||||
gui_api_xvb: &'a Arc<Mutex<PubXvbApi>>,
|
||||
gui_api_xmrig: &'a Arc<Mutex<PubXmrigApi>>,
|
||||
gui_api_p2pool: &'a Arc<Mutex<PubP2poolApi>>,
|
||||
token_xmrig: &'a str,
|
||||
state_p2pool: &'a crate::disk::state::P2pool,
|
||||
share: u32,
|
||||
time_donated: &'a Arc<Mutex<u32>>,
|
||||
rig: &'a str,
|
||||
) -> Self {
|
||||
let hashrate_xmrig = {
|
||||
if lock!(gui_api_xmrig).hashrate_raw_15m > 0.0 {
|
||||
lock!(gui_api_xmrig).hashrate_raw_15m
|
||||
|
@ -346,87 +102,116 @@ pub(crate) async fn algorithm(
|
|||
}
|
||||
};
|
||||
|
||||
*lock!(time_donated) =
|
||||
calcul_donated_time(hashrate_xmrig, gui_api_p2pool, gui_api_xvb, state_p2pool);
|
||||
let time_donated = *lock!(time_donated);
|
||||
debug!("Xvb Process | Donated time {} ", time_donated);
|
||||
output_console(
|
||||
gui_api_xvb,
|
||||
&format!(
|
||||
"Mining on P2pool node for {} seconds then on XvB for {} seconds.",
|
||||
XVB_TIME_ALGO - time_donated,
|
||||
time_donated
|
||||
),
|
||||
);
|
||||
let address = state_p2pool.address.clone();
|
||||
|
||||
// p2pool need to be mined if donated time is not equal to xvb_time_algo
|
||||
if time_donated != XVB_TIME_ALGO && lock!(gui_api_xvb).current_node != Some(XvbNode::P2pool)
|
||||
{
|
||||
debug!("Xvb Process | request xmrig to mine on p2pool");
|
||||
if let Err(err) = PrivXmrigApi::update_xmrig_config(
|
||||
client,
|
||||
XMRIG_CONFIG_URI,
|
||||
token_xmrig,
|
||||
&XvbNode::P2pool,
|
||||
address,
|
||||
gui_api_xmrig,
|
||||
rig,
|
||||
)
|
||||
.await
|
||||
{
|
||||
warn!("Xvb Process | Failed request HTTP API Xmrig");
|
||||
output_console(
|
||||
gui_api_xvb,
|
||||
&format!(
|
||||
"Failure to update xmrig config with HTTP API.\nError: {}",
|
||||
err
|
||||
),
|
||||
);
|
||||
}
|
||||
let xvb_24h_avg = lock!(gui_api_xvb).stats_priv.donor_24hr_avg;
|
||||
let xvb_1h_avg = lock!(gui_api_xvb).stats_priv.donor_1hr_avg;
|
||||
|
||||
let runtime_mode = lock!(gui_api_xvb).stats_priv.runtime_mode.clone();
|
||||
let runtime_donation_level = lock!(gui_api_xvb)
|
||||
.stats_priv
|
||||
.runtime_manual_donation_level
|
||||
.clone();
|
||||
let runtime_amount = lock!(gui_api_xvb).stats_priv.runtime_manual_amount.clone();
|
||||
|
||||
let p2pool_total_hashrate = lock!(gui_api_p2pool).sidechain_ehr;
|
||||
|
||||
let avg_last_hour_hashrate =
|
||||
Self::calc_last_hour_avg_hash_rate(&lock!(gui_api_xvb).p2pool_sent_last_hour_samples);
|
||||
let mut p2pool_external_hashrate = p2pool_total_hashrate - avg_last_hour_hashrate;
|
||||
if p2pool_external_hashrate < 0.0 {
|
||||
p2pool_external_hashrate = 0.0;
|
||||
}
|
||||
|
||||
// sleep 10m less spared time then request XMrig to mine on XvB
|
||||
sleep_then_update_node_xmrig(
|
||||
time_donated,
|
||||
client,
|
||||
XMRIG_CONFIG_URI,
|
||||
token_xmrig,
|
||||
let mut share_min_hashrate = Self::minimum_hashrate_share(
|
||||
lock!(gui_api_p2pool).p2pool_difficulty_u64,
|
||||
state_p2pool.mini,
|
||||
p2pool_external_hashrate,
|
||||
);
|
||||
if share_min_hashrate.is_sign_negative() {
|
||||
info!("XvB Process | if minimum HR is negative, it is 0.");
|
||||
share_min_hashrate = 0.0;
|
||||
}
|
||||
|
||||
let spareable_hashrate = hashrate_xmrig - share_min_hashrate;
|
||||
|
||||
// TODO consider printing algorithm stats instead of spreadout print statements
|
||||
let stats = Stats {
|
||||
share,
|
||||
hashrate_xmrig,
|
||||
xvb_24h_avg,
|
||||
xvb_1h_avg,
|
||||
address,
|
||||
target_donation_hashrate: f32::default(),
|
||||
runtime_mode,
|
||||
runtime_donation_level,
|
||||
runtime_amount,
|
||||
p2pool_total_hashrate,
|
||||
avg_last_hour_hashrate,
|
||||
p2pool_external_hashrate,
|
||||
share_min_hashrate,
|
||||
spareable_hashrate,
|
||||
spared_time: u32::default(),
|
||||
};
|
||||
|
||||
let mut new_instace = Self {
|
||||
client,
|
||||
gui_api_xvb,
|
||||
gui_api_xmrig,
|
||||
"",
|
||||
)
|
||||
.await;
|
||||
lock!(gui_api_xvb)
|
||||
.p2pool_sent_last_hour_samples
|
||||
.0
|
||||
.push_back(
|
||||
hashrate_xmrig
|
||||
* ((XVB_TIME_ALGO as f32 - time_donated as f32) / XVB_TIME_ALGO as f32),
|
||||
);
|
||||
lock!(gui_api_xvb)
|
||||
.xvb_sent_last_hour_samples
|
||||
.0
|
||||
.push_back(hashrate_xmrig * (time_donated as f32 / XVB_TIME_ALGO as f32));
|
||||
} else {
|
||||
// no share, so we mine on p2pool. We update xmrig only if it was still mining on XvB.
|
||||
if lock!(gui_api_xvb).current_node != Some(XvbNode::P2pool) {
|
||||
gui_api_p2pool,
|
||||
token_xmrig,
|
||||
state_p2pool,
|
||||
time_donated,
|
||||
rig,
|
||||
stats,
|
||||
};
|
||||
|
||||
new_instace.stats.target_donation_hashrate = new_instace.get_target_donation_hashrate();
|
||||
new_instace.stats.spared_time = ((new_instace.stats.target_donation_hashrate as u32)
|
||||
/ (new_instace.stats.hashrate_xmrig as u32))
|
||||
* XVB_TIME_ALGO;
|
||||
|
||||
info!("XvB Process | Starting Algorithm - Algorithm State:",);
|
||||
info!("{:#?}", new_instace.stats);
|
||||
|
||||
new_instace
|
||||
}
|
||||
|
||||
fn is_share_fulfilled(&self) -> bool {
|
||||
self.stats.share > 0
|
||||
}
|
||||
|
||||
fn is_xvb_24h_fulfilled(&self) -> bool {
|
||||
self.stats.xvb_24h_avg > self.stats.target_donation_hashrate
|
||||
}
|
||||
|
||||
fn xvb_1h_fulfilled(&self) -> bool {
|
||||
self.stats.xvb_1h_avg > self.stats.target_donation_hashrate
|
||||
}
|
||||
|
||||
async fn fulfill_xvb_1h(&self) {
|
||||
self.mine_p2pool().await;
|
||||
self.sleep_then_update_node_xmrig().await;
|
||||
}
|
||||
|
||||
async fn mine_p2pool(&self) {
|
||||
if lock!(self.gui_api_xvb).current_node != Some(XvbNode::P2pool) {
|
||||
info!("Xvb Process | request xmrig to mine on p2pool");
|
||||
|
||||
if let Err(err) = PrivXmrigApi::update_xmrig_config(
|
||||
client,
|
||||
self.client,
|
||||
XMRIG_CONFIG_URI,
|
||||
token_xmrig,
|
||||
self.token_xmrig,
|
||||
&XvbNode::P2pool,
|
||||
address,
|
||||
gui_api_xmrig,
|
||||
rig,
|
||||
&self.stats.address,
|
||||
self.gui_api_xmrig,
|
||||
self.rig,
|
||||
)
|
||||
.await
|
||||
{
|
||||
warn!("Xvb Process | Failed request HTTP API Xmrig");
|
||||
output_console(
|
||||
gui_api_xvb,
|
||||
self.gui_api_xvb,
|
||||
&format!(
|
||||
"Failure to update xmrig config with HTTP API.\nError: {}",
|
||||
err
|
||||
|
@ -434,19 +219,198 @@ pub(crate) async fn algorithm(
|
|||
);
|
||||
}
|
||||
}
|
||||
output_console(gui_api_xvb, "No share in the current PPLNS Window !");
|
||||
output_console(gui_api_xvb, "Mining on P2pool for the next ten minutes.");
|
||||
output_console(self.gui_api_xvb, "No share in the current PPLNS Window !");
|
||||
output_console(
|
||||
self.gui_api_xvb,
|
||||
"Mining on P2pool for the next ten minutes.",
|
||||
);
|
||||
sleep(Duration::from_secs(XVB_TIME_ALGO.into())).await;
|
||||
lock!(gui_api_xvb)
|
||||
lock!(self.gui_api_xvb)
|
||||
.p2pool_sent_last_hour_samples
|
||||
.0
|
||||
.push_back(lock!(gui_api_xmrig).hashrate_raw_15m);
|
||||
lock!(gui_api_xvb)
|
||||
.push_back(lock!(self.gui_api_xmrig).hashrate_raw_15m);
|
||||
lock!(self.gui_api_xvb)
|
||||
.xvb_sent_last_hour_samples
|
||||
.0
|
||||
.push_back(0.0);
|
||||
}
|
||||
// algorithm has run, so do not retry but run normally
|
||||
// put a space to mark the difference with the next run.
|
||||
output_console_without_time(gui_api_xvb, "");
|
||||
|
||||
async fn mine_xvb(&self) {
|
||||
let node = lock!(self.gui_api_xvb).stats_priv.node;
|
||||
|
||||
debug!("Xvb Process | request xmrig to mine on XvB");
|
||||
if lock!(self.gui_api_xvb).current_node.is_none()
|
||||
|| lock!(self.gui_api_xvb)
|
||||
.current_node
|
||||
.as_ref()
|
||||
.is_some_and(|n| n == &XvbNode::P2pool)
|
||||
{
|
||||
if let Err(err) = PrivXmrigApi::update_xmrig_config(
|
||||
self.client,
|
||||
XMRIG_CONFIG_URI,
|
||||
self.token_xmrig,
|
||||
&node,
|
||||
&self.stats.address,
|
||||
self.gui_api_xmrig,
|
||||
self.rig,
|
||||
)
|
||||
.await
|
||||
{
|
||||
// show to console error about updating xmrig config
|
||||
warn!("Xvb Process | Failed request HTTP API Xmrig");
|
||||
output_console(
|
||||
self.gui_api_xvb,
|
||||
&format!(
|
||||
"Failure to update xmrig config with HTTP API.\nError: {}",
|
||||
err
|
||||
),
|
||||
);
|
||||
} else {
|
||||
debug!("Xvb Process | mining on XvB pool");
|
||||
}
|
||||
}
|
||||
sleep(Duration::from_secs(XVB_TIME_ALGO.into())).await;
|
||||
|
||||
lock!(self.gui_api_xvb)
|
||||
.p2pool_sent_last_hour_samples
|
||||
.0
|
||||
.push_back(lock!(self.gui_api_xmrig).hashrate_raw_15m);
|
||||
lock!(self.gui_api_xvb)
|
||||
.xvb_sent_last_hour_samples
|
||||
.0
|
||||
.push_back(0.0);
|
||||
}
|
||||
|
||||
async fn sleep_then_update_node_xmrig(&self) {
|
||||
let node = lock!(self.gui_api_xvb).stats_priv.node;
|
||||
debug!(
|
||||
"Xvb Process | algo sleep for {} while mining on P2pool",
|
||||
XVB_TIME_ALGO - self.stats.spared_time
|
||||
);
|
||||
sleep(Duration::from_secs(
|
||||
(XVB_TIME_ALGO - self.stats.spared_time).into(),
|
||||
))
|
||||
.await;
|
||||
|
||||
// only update xmrig config if it is actually mining.
|
||||
debug!("Xvb Process | request xmrig to mine on XvB");
|
||||
if lock!(self.gui_api_xvb).current_node.is_none()
|
||||
|| lock!(self.gui_api_xvb)
|
||||
.current_node
|
||||
.as_ref()
|
||||
.is_some_and(|n| n == &XvbNode::P2pool)
|
||||
{
|
||||
if let Err(err) = PrivXmrigApi::update_xmrig_config(
|
||||
self.client,
|
||||
XMRIG_CONFIG_URI,
|
||||
self.token_xmrig,
|
||||
&node,
|
||||
&self.stats.address,
|
||||
self.gui_api_xmrig,
|
||||
self.rig,
|
||||
)
|
||||
.await
|
||||
{
|
||||
// show to console error about updating xmrig config
|
||||
warn!("Xvb Process | Failed request HTTP API Xmrig");
|
||||
output_console(
|
||||
self.gui_api_xvb,
|
||||
&format!(
|
||||
"Failure to update xmrig config with HTTP API.\nError: {}",
|
||||
err
|
||||
),
|
||||
);
|
||||
} else {
|
||||
debug!("Xvb Process | mining on XvB pool");
|
||||
}
|
||||
}
|
||||
// will not quit the process until it is really done.
|
||||
// xvb process watch this algo handle to see if process is finished or not.
|
||||
sleep(Duration::from_secs(self.stats.spared_time.into())).await;
|
||||
}
|
||||
|
||||
fn get_target_donation_hashrate(&self) -> f32 {
|
||||
match self.stats.runtime_mode {
|
||||
RuntimeMode::Auto => self.get_auto_mode_target_donation_hashrate(),
|
||||
RuntimeMode::Hero => self.get_hero_mode_target_donation_hashrate(),
|
||||
RuntimeMode::ManualXvb => self.stats.runtime_amount as f32,
|
||||
RuntimeMode::ManualP2pool => {
|
||||
(XVB_TIME_ALGO as f32) - (self.stats.runtime_amount as f32)
|
||||
}
|
||||
RuntimeMode::ManualDonationLevel => self.stats.runtime_donation_level.get_hashrate(),
|
||||
}
|
||||
}
|
||||
|
||||
fn get_auto_mode_target_donation_hashrate(&self) -> f32 {
|
||||
// TODO fix wrong target hashrate being selected
|
||||
// TODO consider using xvb_24h_avg for calculations
|
||||
// TODO consider using dynamic buffer size buffer gets smaller as gupaxx runs for longer to provide more stability
|
||||
|
||||
let donation_level = match self.stats.spareable_hashrate {
|
||||
x if x > (XVB_ROUND_DONOR_MIN_HR as f32) => Some(RuntimeDonationLevel::Donor),
|
||||
x if x > (XVB_ROUND_DONOR_VIP_MIN_HR as f32) => Some(RuntimeDonationLevel::DonorVIP),
|
||||
x if x > (XVB_ROUND_DONOR_WHALE_MIN_HR as f32) => {
|
||||
Some(RuntimeDonationLevel::DonorWhale)
|
||||
}
|
||||
x if x > (XVB_ROUND_DONOR_MEGA_MIN_HR as f32) => Some(RuntimeDonationLevel::DonorMega),
|
||||
_ => None,
|
||||
};
|
||||
|
||||
if let Some(level) = donation_level {
|
||||
level.get_hashrate()
|
||||
} else {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
|
||||
fn get_hero_mode_target_donation_hashrate(&self) -> f32 {
|
||||
// TODO improve selection method
|
||||
// TODO consider using a large buffer size
|
||||
// TODO consider manually setting the share count to aim for on hero mode
|
||||
|
||||
self.stats.spareable_hashrate
|
||||
}
|
||||
|
||||
// push new value into samples before executing this calcul
|
||||
fn calc_last_hour_avg_hash_rate(samples: &SamplesAverageHour) -> f32 {
|
||||
samples.0.iter().sum::<f32>() / samples.0.len() as f32
|
||||
}
|
||||
|
||||
fn minimum_hashrate_share(difficulty: u64, mini: bool, p2pool_external_hashrate: f32) -> f32 {
|
||||
let pws = if mini {
|
||||
BLOCK_PPLNS_WINDOW_MINI
|
||||
} else {
|
||||
BLOCK_PPLNS_WINDOW_MAIN
|
||||
};
|
||||
let minimum_hr = ((difficulty / (pws * SECOND_PER_BLOCK_P2POOL)) as f32 * XVB_BUFFER)
|
||||
- p2pool_external_hashrate;
|
||||
info!("XvB Process | (difficulty / (window pplns blocks * seconds per p2pool block) * BUFFER) - outside HR = minimum HR to keep a share\n({difficulty} / ({pws} * {SECOND_PER_BLOCK_P2POOL}) * {XVB_BUFFER}) - {p2pool_external_hashrate} = {minimum_hr}");
|
||||
minimum_hr
|
||||
}
|
||||
|
||||
async fn run(&mut self) {
|
||||
// TODO add console output for each step
|
||||
|
||||
if self.is_share_fulfilled() && self.is_xvb_24h_fulfilled() {
|
||||
output_console(
|
||||
self.gui_api_xvb,
|
||||
"There is a share in p2pool and 24H avg XvB is achieved.",
|
||||
);
|
||||
output_console(self.gui_api_xvb, "Calculating donation time for XvB...");
|
||||
|
||||
self.fulfill_xvb_1h().await
|
||||
} else if self.is_share_fulfilled() {
|
||||
output_console(self.gui_api_xvb, "24H avg XvB target not achieved.");
|
||||
output_console(self.gui_api_xvb, "Sending all hashrate to XvB");
|
||||
|
||||
self.mine_xvb().await
|
||||
} else {
|
||||
output_console(self.gui_api_xvb, "There are no shares in p2pool");
|
||||
output_console(self.gui_api_xvb, "Sending all hashrate to p2pool");
|
||||
|
||||
self.mine_p2pool().await
|
||||
}
|
||||
|
||||
output_console(self.gui_api_xvb, "")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,13 +9,16 @@ use reqwest::{Client, StatusCode};
|
|||
use serde::Deserialize;
|
||||
use tokio::time::sleep;
|
||||
|
||||
use crate::disk::state::XvbMode;
|
||||
use crate::{
|
||||
disk::state::ManualDonationLevel,
|
||||
helper::{xvb::output_console, Process, ProcessState},
|
||||
macros::lock,
|
||||
XVB_URL,
|
||||
};
|
||||
use crate::{
|
||||
disk::state::XvbMode, XVB_ROUND_DONOR_MEGA_MIN_HR, XVB_ROUND_DONOR_MIN_HR,
|
||||
XVB_ROUND_DONOR_VIP_MIN_HR, XVB_ROUND_DONOR_WHALE_MIN_HR,
|
||||
};
|
||||
|
||||
use super::{nodes::XvbNode, rounds::XvbRound, PubXvbApi};
|
||||
|
||||
|
@ -38,6 +41,17 @@ pub enum RuntimeDonationLevel {
|
|||
DonorMega,
|
||||
}
|
||||
|
||||
impl RuntimeDonationLevel {
|
||||
pub fn get_hashrate(&self) -> f32 {
|
||||
match &self {
|
||||
Self::Donor => XVB_ROUND_DONOR_MIN_HR as f32,
|
||||
Self::DonorVIP => XVB_ROUND_DONOR_VIP_MIN_HR as f32,
|
||||
Self::DonorWhale => XVB_ROUND_DONOR_WHALE_MIN_HR as f32,
|
||||
Self::DonorMega => XVB_ROUND_DONOR_MEGA_MIN_HR as f32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Deserialize)]
|
||||
pub struct XvbPrivStats {
|
||||
pub fails: u8,
|
||||
|
|
Loading…
Reference in a new issue