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

Commit c284e49

Browse files
author
bhat
committed
First commit.
0 parents  commit c284e49

File tree

8 files changed

+1286
-0
lines changed

8 files changed

+1286
-0
lines changed

Cargo.lock

Lines changed: 838 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: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
[package]
2+
name = "duino-miner"
3+
version = "0.1.0"
4+
edition = "2018"
5+
6+
[dependencies]
7+
serde = { version = "1.0", features = ["derive"] }
8+
serde_yaml = "0.8"
9+
10+
sha-1 = "0.9"
11+
data-encoding = "2.3"
12+
rand = "0.8"
13+
parity-wordlist = "1"
14+
15+
tokio = { version = "1.9", features = ["full"] }
16+
futures = "0.3"
17+
18+
clap = "3.0.0-beta.2"
19+
thiserror = "1.0"
20+
21+
[profile.release]
22+
opt-level = 'z'
23+
lto = true
24+
codegen-units = 1
25+
panic = 'abort'

README.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# duino-miner
2+
3+
A multiplexed CPU miner for Duinocoin (duino-coin),
4+
*if you know what I am talking about*.
5+
6+
This high-performance miner is implemented in asynchronous Rust, from scratch.
7+
This makes it several times faster than the official miner,
8+
and highly efficient even on non-conventional mining hardwares
9+
such as a Raspberry Pi. (Again, if you know what I am talking about.)
10+
11+
To build this project, execute
12+
13+
```sh
14+
cargo build --release
15+
```
16+
17+
To generate a config file for the miner, execute
18+
19+
```sh
20+
duino-miner generate -u my_username --device-type=AVR --firmware="Official AVR Miner v2.6" --device-name-prefix "avr-" --target-rate 182
21+
```
22+
23+
To run the miner from your config file, execute
24+
25+
```sh
26+
duino-miner run
27+
```

src/bin/register.rs

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
use duino_miner::error::MinerError;
2+
3+
use tokio::net::TcpStream;
4+
5+
use rand::{thread_rng, Rng};
6+
use rand::distributions::Alphanumeric;
7+
8+
use clap::{AppSettings, Clap};
9+
use tokio::io::{AsyncReadExt, AsyncWriteExt};
10+
11+
12+
#[derive(Clap)]
13+
#[clap(version = "0.0", author = "Black H. <[email protected]>")]
14+
#[clap(setting = AppSettings::ColoredHelp)]
15+
struct Opts {
16+
#[clap(short, long, default_value = "51.15.127.80")]
17+
host: String,
18+
#[clap(short, long, default_value = "2811")]
19+
port: u16,
20+
}
21+
22+
#[tokio::main]
23+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
24+
let opts: Opts = Opts::parse();
25+
26+
let mut username = parity_wordlist::random_phrase(2);
27+
username.retain(|c| !c.is_whitespace());
28+
let password: String = thread_rng()
29+
.sample_iter(&Alphanumeric)
30+
.take(16)
31+
.map(char::from)
32+
.collect();
33+
34+
let mut stream = TcpStream::connect(
35+
format!("{}:{}", opts.host, opts.port)).await.map_err(|_| MinerError::Connection)?;
36+
37+
println!("Connected to pool {}:{}", opts.host, opts.port);
38+
39+
let mut cmd_in: [u8; 200] = [0; 200];
40+
41+
let n = stream.read(&mut cmd_in).await.map_err(|_| MinerError::RecvCommand)?;
42+
println!("version: {}", std::str::from_utf8(&cmd_in[..n])?);
43+
44+
let cmd_job = format!("REGI,{},{},{}@gmail.com\n", username, password, username);
45+
stream.write(cmd_job.as_bytes()).await.map_err(|_| MinerError::SendCommand)?;
46+
let n = stream.read(&mut cmd_in).await.map_err(|_| MinerError::RecvCommand)?;
47+
let reg_status = std::str::from_utf8(&cmd_in[..n]).map_err(|_| MinerError::InvalidUTF8)?;
48+
49+
if reg_status != "OK" {
50+
println!("register failed: {}", reg_status);
51+
} else {
52+
println!("registered {} with {}", username, password);
53+
}
54+
55+
Ok(())
56+
}

src/bin/transfer.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
use duino_miner::error::MinerError;
2+
3+
use serde::{Serialize, Deserialize};
4+
5+
use tokio::net::TcpStream;
6+
use tokio::io::{AsyncReadExt, AsyncWriteExt};
7+
8+
use clap::{AppSettings, Clap};
9+
10+
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
11+
struct Config {
12+
host: String,
13+
port: u16,
14+
15+
main_account: String,
16+
accounts: Vec<Account>,
17+
}
18+
19+
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
20+
struct Account {
21+
username: String,
22+
password: String,
23+
}
24+
25+
#[derive(Clap)]
26+
#[clap(version = "0.0", author = "Black H. <[email protected]>")]
27+
#[clap(setting = AppSettings::ColoredHelp)]
28+
struct Opts {
29+
#[clap(short, long, default_value = "transfer.yaml")]
30+
config_file: String,
31+
#[clap(short)]
32+
force: bool,
33+
}
34+
35+
#[tokio::main]
36+
async fn main() -> Result<(), Box<dyn std::error::Error>> {
37+
let opts: Opts = Opts::parse();
38+
39+
let c_serial = tokio::fs::read_to_string(opts.config_file).await?;
40+
let c: Config = serde_yaml::from_str(c_serial.as_str())?;
41+
42+
for account in c.accounts {
43+
if account.username == c.main_account {
44+
continue;
45+
}
46+
47+
let mut stream = TcpStream::connect(
48+
format!("{}:{}", c.host, c.port)).await.map_err(|_| MinerError::Connection)?;
49+
50+
println!("Connected to pool {}:{}", c.host, c.port);
51+
52+
let mut cmd_in: [u8; 200] = [0; 200];
53+
54+
let n = stream.read(&mut cmd_in).await.map_err(|_| MinerError::RecvCommand)?;
55+
println!("version: {}", std::str::from_utf8(&cmd_in[..n])?);
56+
57+
let cmd_job = format!("LOGI,{},{}\n", account.username, account.password);
58+
stream.write(cmd_job.as_bytes()).await.map_err(|_| MinerError::SendCommand)?;
59+
let n = stream.read(&mut cmd_in).await.map_err(|_| MinerError::RecvCommand)?;
60+
let login_status = std::str::from_utf8(&cmd_in[..n]).map_err(|_| MinerError::InvalidUTF8)?;
61+
62+
if login_status != "OK" {
63+
println!("{} login failed", account.username);
64+
continue;
65+
}
66+
67+
stream.write("BALA".as_bytes()).await.map_err(|_| MinerError::SendCommand)?;
68+
let n = stream.read(&mut cmd_in).await.map_err(|_| MinerError::RecvCommand)?;
69+
let balance: f32 = std::str::from_utf8(&cmd_in[..n]).map_err(|_| MinerError::InvalidUTF8)?.parse()?;
70+
println!("account {} has balance {}", account.username, balance);
71+
72+
let balance = balance as u32;
73+
74+
if balance > 100 || opts.force {
75+
let cmd_job = format!("SEND,-,{},{}\n", c.main_account, balance);
76+
stream.write(cmd_job.as_bytes()).await.map_err(|_| MinerError::SendCommand)?;
77+
let n = stream.read(&mut cmd_in).await.map_err(|_| MinerError::RecvCommand)?;
78+
let transfer_status = std::str::from_utf8(&cmd_in[..n]).map_err(|_| MinerError::InvalidUTF8)?;
79+
80+
println!("transfer of {} coins to {} exited with status {}", balance, c.main_account, transfer_status);
81+
}
82+
}
83+
84+
Ok(())
85+
}

src/error.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
#[derive(thiserror::Error, Debug)]
2+
pub enum MinerError {
3+
#[error("Could not establish a connection")]
4+
Connection,
5+
#[error("Could not send command")]
6+
SendCommand,
7+
#[error("Could not receive command")]
8+
RecvCommand,
9+
#[error("Received invalid UTF-8")]
10+
InvalidUTF8,
11+
#[error("Received malformed job: `{0}`")]
12+
MalformedJob(String),
13+
#[error("unknown error")]
14+
Unknown,
15+
}

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub mod error;

0 commit comments

Comments
 (0)