Skip to content
This repository was archived by the owner on Apr 3, 2023. It is now read-only.

Commit 808c4ec

Browse files
author
bhat
committed
Improve memory usage.
1 parent 5cc05d4 commit 808c4ec

File tree

4 files changed

+75
-46
lines changed

4 files changed

+75
-46
lines changed

Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ sha-1 = { version = "0.9", features = ["asm"] }
1313
data-encoding = "2.3"
1414
rand = "0.8"
1515
parity-wordlist = "1"
16+
hex = "0.4"
1617

1718
tokio = { version = "1.9", features = ["full"] }
1819
futures = "0.3"

src/hasher.rs

Lines changed: 66 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,81 +1,104 @@
1-
use sha1::{Digest, Sha1};
2-
31
use std::collections::HashMap;
42
use std::sync::Arc;
53

6-
use tokio::sync::{Mutex, RwLock};
4+
use tokio::sync::Mutex;
5+
6+
use hex::FromHex;
7+
use sha1::{Digest, Sha1};
78

8-
fn sha1_digest(input: &str) -> String {
9-
let mut hasher = Sha1::new();
10-
sha1::Digest::update(&mut hasher, input.as_bytes());
9+
type BlockHash = [u8; 20];
1110

12-
let h = hasher.finalize();
13-
format!("{:x}", h)
11+
fn to_block_hash(s: &str) -> BlockHash {
12+
<BlockHash>::from_hex(s).unwrap_or_else(|_| panic!("{} is not hex string.", s))
1413
}
1514

1615
#[derive(Clone)]
1716
pub struct Sha1Hasher {
18-
hashmap: Arc<RwLock<HashMap<String, Vec<String>>>>,
19-
stack: Arc<Mutex<Vec<String>>>,
17+
hashmap: Arc<Mutex<HashMap<BlockHash, Vec<BlockHash>>>>,
18+
stack: Arc<Mutex<Vec<BlockHash>>>,
2019
}
2120

2221
impl Sha1Hasher {
23-
const HASHMAP_LIMIT: usize = 100;
22+
const HASHMAP_LIMIT: usize = 10;
2423

2524
pub fn new() -> Self {
2625
Self {
27-
hashmap: Arc::new(RwLock::new(HashMap::new())),
28-
stack: Arc::new(Mutex::new(Vec::new())),
26+
hashmap: Arc::new(Mutex::new(HashMap::with_capacity(Self::HASHMAP_LIMIT * 2))),
27+
stack: Arc::new(Mutex::new(Vec::with_capacity(Self::HASHMAP_LIMIT * 2))),
2928
}
3029
}
3130

32-
pub async fn get_hash(&self, last_block_hash: String, expected_hash: String, diff: u32) -> u32 {
33-
{
34-
let hashmap = self.hashmap.read().await;
35-
if let Some(hashes) = hashmap.get(&last_block_hash) {
36-
if hashes.len() < diff as usize {
37-
log::warn!("Diff changed, recalculating.");
38-
} else {
39-
// Optimized for lower difficulty, uses AVX.
40-
for (duco_numeric_result, hash) in hashes.iter().enumerate() {
41-
if hash == &expected_hash {
42-
return duco_numeric_result as u32;
43-
}
44-
}
31+
pub async fn get_hash(&self, last_block_hash: &str, expected_hash: &str, diff: u32) -> u32 {
32+
let last_block_hash = to_block_hash(last_block_hash);
33+
let expected_hash = to_block_hash(expected_hash);
34+
35+
let mut hashmap = self.hashmap.lock().await;
36+
if let Some(hashes) = hashmap.get_mut(&last_block_hash) {
37+
// Optimized for lower difficulty, uses AVX.
38+
for (duco_numeric_result, hash) in hashes.iter().enumerate() {
39+
if hash == &expected_hash {
40+
return duco_numeric_result as u32;
4541
}
4642
}
47-
} // Unlock hashmap
4843

49-
let hashes = self.precompute(last_block_hash, diff).await;
44+
let current_progress = hashes.len() as u32;
45+
if current_progress < diff {
46+
log::info!("Continuing calculation.");
5047

51-
for (duco_numeric_result, hash) in hashes.iter().enumerate() {
52-
if hash == &expected_hash {
53-
return duco_numeric_result as u32;
48+
for duco_numeric_result in current_progress..diff {
49+
let hash = self.hash_next_block(&last_block_hash, duco_numeric_result);
50+
hashes.push(hash);
51+
52+
if hash == expected_hash {
53+
return duco_numeric_result as u32;
54+
}
55+
}
5456
}
5557
}
5658

57-
return 0;
58-
}
59-
60-
async fn precompute(&self, last_block_hash: String, diff: u32) -> Vec<String> {
61-
let mut hashmap = self.hashmap.write().await;
6259
let mut stack = self.stack.lock().await;
6360

64-
if hashmap.len() > Self::HASHMAP_LIMIT {
61+
if hashmap.len() > Self::HASHMAP_LIMIT * 2 {
62+
log::warn!("Too many hashes stored. Freeing.");
63+
6564
for _ in 0..(hashmap.len() - Self::HASHMAP_LIMIT) {
6665
let k = stack.remove(0);
6766
hashmap.remove(&k);
6867
}
6968
}
7069

71-
let hashes: Vec<String> = (0..diff)
72-
.map(|duco_numeric_result| format!("{}{}", last_block_hash, duco_numeric_result))
73-
.map(|h| sha1_digest(h.as_str()))
74-
.collect();
70+
let mut hashes: Vec<BlockHash> = Vec::with_capacity(diff as usize);
71+
for duco_numeric_result in 0..diff {
72+
let hash = self.hash_next_block(&last_block_hash, duco_numeric_result);
73+
hashes.push(hash);
74+
75+
if hash == expected_hash {
76+
hashmap.insert(last_block_hash, hashes);
77+
stack.push(last_block_hash);
78+
79+
return duco_numeric_result;
80+
}
81+
}
7582

76-
hashmap.insert(last_block_hash.clone(), hashes.clone());
83+
hashmap.insert(last_block_hash, hashes);
7784
stack.push(last_block_hash);
7885

79-
hashes
86+
0
87+
}
88+
89+
fn hash_next_block(&self, last_block_hash: &BlockHash, duco_numeric_result: u32) -> BlockHash {
90+
let mut hasher = Sha1::new();
91+
92+
let mut encode_slice: [u8; 40] = [0; 40];
93+
hex::encode_to_slice(&last_block_hash, &mut encode_slice).unwrap();
94+
95+
sha1::Digest::update(&mut hasher, &encode_slice);
96+
sha1::Digest::update(&mut hasher, duco_numeric_result.to_string().as_bytes());
97+
let h = hasher.finalize();
98+
99+
let mut hash: [u8; 20] = [0; 20];
100+
hash.copy_from_slice(&h);
101+
102+
hash
80103
}
81104
}

src/main.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,9 +161,7 @@ async fn start_miner(device: Device, pool: String, hasher: Sha1Hasher) -> Result
161161

162162
let start = SystemTime::now();
163163

164-
let duco_numeric_result = hasher
165-
.get_hash(last_block_hash.to_string(), expected_hash.to_string(), diff)
166-
.await;
164+
let duco_numeric_result = hasher.get_hash(last_block_hash, expected_hash, diff).await;
167165

168166
let end = SystemTime::now();
169167
let duration = end.duration_since(start).unwrap().as_micros();

0 commit comments

Comments
 (0)