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

Add tproxy initializer for Integration Tests #1254

Merged
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
3 changes: 3 additions & 0 deletions roles/Cargo.lock

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

3 changes: 3 additions & 0 deletions roles/tests-integration/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ roles_logic_sv2 = { path = "../../protocols/v2/roles-logic-sv2" }
tar = "0.4.41"
tokio = { version="1.36.0",features = ["full","tracing"] }
tracing = "0.1.40"
translator_sv2 = { path = "../translator" }
rand = "0.8.4"
stratum-common = { path = "../../common" }

[lib]
path = "tests/common/mod.rs"
88 changes: 87 additions & 1 deletion roles/tests-integration/tests/common/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ use flate2::read::GzDecoder;
use key_utils::{Secp256k1PublicKey, Secp256k1SecretKey};
use once_cell::sync::Lazy;
use pool_sv2::PoolSv2;
use rand::{thread_rng, Rng};
use sniffer::Sniffer;
use std::{
collections::HashSet,
convert::TryFrom,
convert::{TryFrom, TryInto},
env,
fs::{create_dir_all, File},
io::{BufReader, Read},
Expand Down Expand Up @@ -380,3 +381,88 @@ pub async fn start_jds(tp_address: SocketAddr) -> SocketAddr {
tokio::time::sleep(std::time::Duration::from_secs(2)).await;
listen_jd_address
}

pub async fn start_sv2_translator(upstream: SocketAddr) -> SocketAddr {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's try to keep starter APIs consistent, as highlighted in #1234

I'm not opinionated towards any specific approach

I just feel it's important to be careful in fragmenting patterns because that will eventually result in a poor UX for SRI contributors writing tests while working on this like e.g.: #1229 (which will likely happen sooner, rather than later)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the approach here is mostly what we want. No need for the end user to call get_available_address but the role itself does that and returns it

let upstream_address = upstream.ip().to_string();
let upstream_port = upstream.port();
let upstream_authority_pubkey = Secp256k1PublicKey::try_from(
"9auqWEzQDVyd2oe1JVGFLMLHZtCo2FFqZwtKA5gd9xbuEu7PH72".to_string(),
)
.expect("failed");
let listening_address = get_available_address();
let listening_port = listening_address.port();
let hashrate = measure_hashrate(3) as f32 / 100.0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why divide by 100?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is done just part of the testing, I think this will change also until we figure out the best numbers here and in measure_hashrate

let min_individual_miner_hashrate = hashrate;
let shares_per_minute = 60.0;
let channel_diff_update_interval = 60;
let channel_nominal_hashrate = hashrate;
let downstream_difficulty_config =
translator_sv2::proxy_config::DownstreamDifficultyConfig::new(
min_individual_miner_hashrate,
shares_per_minute,
0,
0,
);
let upstream_difficulty_config = translator_sv2::proxy_config::UpstreamDifficultyConfig::new(
channel_diff_update_interval,
channel_nominal_hashrate,
0,
false,
);
let upstream_conf = translator_sv2::proxy_config::UpstreamConfig::new(
upstream_address,
upstream_port,
upstream_authority_pubkey,
upstream_difficulty_config,
);
let downstream_conf = translator_sv2::proxy_config::DownstreamConfig::new(
listening_address.ip().to_string(),
listening_port,
downstream_difficulty_config,
);

let config =
translator_sv2::proxy_config::ProxyConfig::new(upstream_conf, downstream_conf, 2, 2, 8);
let translator_v2 = translator_sv2::TranslatorSv2::new(config);
tokio::spawn(async move {
translator_v2.start().await;
});
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
listening_address
}

fn measure_hashrate(duration_secs: u64) -> f64 {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

interesting approach of dynamically measuring local CPU hashrate

this strategy will save us A LOT of headache and it's quite a game changer in comparison to the static nature of MG tests

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Credit to @GitGab19

use stratum_common::bitcoin::hashes::{sha256d, Hash, HashEngine};

let mut share = {
let mut rng = thread_rng();
let mut arr = [0u8; 80];
rng.fill(&mut arr[..]);
arr
};
let start_time = std::time::Instant::now();
let mut hashes: u64 = 0;
let duration = std::time::Duration::from_secs(duration_secs);
Comment on lines +437 to +445
Copy link
Collaborator

@plebhash plebhash Nov 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm fine with this approach but it seems a bit convoluted and confusing to read/understand

I'm not convinced we really need to replicate the bitcoin protocol so closely if all we want is to know the capacity of the system to calculate sha256d (attention to the d, it's 2x sha256)

why not simply hash some simple input?

if you REALLY want to closely replicate what happens on bitcoin mining, I would suggest leveraging rust-bitcoin

you can initialize a Header struct and then call header.block_hash() to "mine" it.

that's how both mining-device and sv1-mining-device do it


let hash = |share: &mut [u8; 80]| {
let nonce: [u8; 8] = share[0..8].try_into().unwrap();
let mut nonce = u64::from_le_bytes(nonce);
nonce += 1;
share[0..8].copy_from_slice(&nonce.to_le_bytes());
let mut engine = sha256d::Hash::engine();
engine.input(share);
sha256d::Hash::from_engine(engine).into_inner();
};

loop {
if start_time.elapsed() >= duration {
break;
}
hash(&mut share);
hashes += 1;
}

let elapsed_secs = start_time.elapsed().as_secs_f64();

hashes as f64 / elapsed_secs
}
Loading