-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.cpp
128 lines (100 loc) · 3.64 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
#include <Arduino.h>
#include "mbedtls/md.h"
#define THREADS 4
#define SHARE_DIFF 20000
int shares = 0;
// Print sha256 in little endian
void printHash(unsigned char* string) {
Serial.print("Hash: ");
for(int i=31; i>=0; i--){
char str[3];
sprintf(str, "%02x", (int)string[i]);
Serial.print(str);
}
Serial.println();
}
// check if first 9 bytes are zero
bool checkHash(unsigned char* string) {
bool valid = true;
for(uint8_t i=31; i>22; i--) {
if(string[i] != 0)
valid = false;
}
return valid;
}
void runWorker(void *name) {
Serial.printf("\nRunning %s on core %d\n", (char *)name, xPortGetCoreID());
// Header of Bitcoin block nr. 563333
byte payload[] = {
0x0, 0x0, 0x0, 0x20, // version
0xa2, 0x17, 0x62, 0x4e, 0xf7, 0x72, 0x1b, 0x95, 0x4c, 0x7d, 0x93, 0x75, 0xaa, 0x85, 0xc1, 0x34, 0xe5, 0xb7, 0x66, 0xd2, 0x26, 0xa, 0x2c, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, // prev hash
0xa5, 0x12, 0x42, 0x48, 0xfa, 0x62, 0xcb, 0xef, 0x22, 0xc1, 0x26, 0x8c, 0xc0, 0x24, 0x86, 0xec, 0xfb, 0x5, 0xc2, 0x6d, 0x45, 0xba, 0x42, 0xff, 0x7e, 0x9b, 0x34, 0x6c, 0x0, 0xdf, 0x60, 0xaf, // merkle root
0x5d, 0x80, 0x68, 0x5c, // time (2019-02-16)
0x88, 0x6f, 0x2e, 0x17, // difficulty bits
0x94, 0x4b, 0x40, 0x19 // nonce
};
const size_t payloadLength = 80;
uint32_t targetNonce = 423644052; // 0x19404b94
byte interResult[32]; // 256 bit
byte shaResult[32]; // 256 bit
mbedtls_md_context_t ctx;
mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
mbedtls_md_init(&ctx);
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(md_type), 0);
uint32_t nonce = targetNonce-SHARE_DIFF;
uint32_t startT = micros();
while(true) {
payload[76] = (nonce >> 0) & 0xFF;
payload[77] = (nonce >> 8) & 0xFF;
payload[78] = (nonce >> 16) & 0xFF;
payload[79] = (nonce >> 24) & 0xFF;
mbedtls_md_starts(&ctx);
mbedtls_md_update(&ctx, payload, payloadLength);
mbedtls_md_finish(&ctx, interResult);
mbedtls_md_starts(&ctx);
mbedtls_md_update(&ctx, interResult, 32);
mbedtls_md_finish(&ctx, shaResult);
if(checkHash(shaResult)) {
// Comment this in if you want to run only a single time
// break;
nonce = targetNonce-SHARE_DIFF;
Serial.printf("%s on core %d: ", (char *)name, xPortGetCoreID());
Serial.printf("Share completed with nonce: %d | 0x%x\n", nonce, nonce);
shares++;
// vTaskDelay(1);
}
nonce++;
}
uint32_t duration = micros() - startT;
mbedtls_md_free(&ctx);
Serial.println(checkHash(shaResult)? "Valid Block found!" : "no valid block...");
printHash(shaResult);
Serial.printf("With nonce: %d | 0x%x\n", nonce, nonce);
Serial.printf("In %d rounds, %f ms\n", SHARE_DIFF, duration/1000.0);
Serial.printf("Hash Rate: %f kH/s", (1000.0/duration)*SHARE_DIFF);
}
void runMonitor(void *name) {
unsigned long start = millis();
while (1) {
unsigned long elapsed = millis()-start;
Serial.printf(">>> Completed %d share(s), %d hashes, avg. hashrate %.3f KH/s\n",
shares, shares*SHARE_DIFF, (1.0*shares*SHARE_DIFF)/elapsed);
delay(5000);
}
}
void setup(){
Serial.begin(9600);
delay(3000);
// Idle task that would reset WDT never runs, because core 0 gets fully utilized
disableCore0WDT();
for (size_t i = 0; i < THREADS; i++) {
char *name = (char*) malloc(32);
sprintf(name, "Worker[%d]", i);
// Start mining tasks
BaseType_t res = xTaskCreate(runWorker, name, 30000, (void*)name, 1, NULL);
Serial.printf("Starting %s %s!\n", name, res == pdPASS? "successful":"failed");
}
// Higher prio monitor task
xTaskCreate(runMonitor, "Monitor", 5000, NULL, 4, NULL);
}
void loop(){}