/*
____ __ __ ____ _ _ _____ ___ _____ ____ _ _
( _ \( )( )(_ _)( \( )( _ )___ / __)( _ )(_ _)( \( )
)(_) ))(__)( _)(_ ) ( )(_)((___)( (__ )(_)( _)(_ ) (
(____/(______)(____)(_)\_)(_____) \___)(_____)(____)(_)\_)
Official code for Arduino boards (and relatives) version 4.3
Duino-Coin Team & Community 2019-2024 © MIT Licensed
https://duinocoin.com
https://github.com/revoxhere/duino-coin
If you don't know where to start, visit official website and navigate to
the Getting Started page. Have fun mining!
*/
/* For microcontrollers with low memory change that to -Os in all files,
for default settings use -O0. -O may be a good tradeoff between both */
#pragma GCC optimize ("-Ofast")
/* For microcontrollers with custom LED pins, adjust the line below */
#ifndef LED_BUILTIN
#define LED_BUILTIN 13
#endif
#define SEP_TOKEN ","
#define END_TOKEN "\n"
/* For 8-bit microcontrollers we should use 16 bit variables since the
difficulty is low, for all the other cases should be 32 bits. */
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
typedef uint32_t uintDiff;
#else
typedef uint32_t uintDiff;
#endif
// Arduino identifier library - https://github.com/ricaun
#include "uniqueID.h"
#include "duco_hash.h"
String get_DUCOID() {
String ID = "DUCOID";
char buff[4];
for (size_t i = 0; i < 8; i++) {
sprintf(buff, "%02X", (uint8_t)UniqueID8[i]);
ID += buff;
}
return ID;
}
String DUCOID = "";
void setup() {
// Prepare built-in led pin as output
pinMode(LED_BUILTIN, OUTPUT);
DUCOID = get_DUCOID();
// Open serial port
Serial.begin(115200);
Serial.setTimeout(10000);
while (!Serial)
; // For Arduino Leonardo or any board with the ATmega32U4
Serial.flush();
}
void lowercase_hex_to_bytes(char const * hexDigest, uint8_t * rawDigest) {
for (uint8_t i = 0, j = 0; j < SHA1_HASH_LEN; i += 2, j += 1) {
uint8_t x = hexDigest[i];
uint8_t b = x >> 6;
uint8_t r = ((x & 0xf) | (b << 3)) + b;
x = hexDigest[i + 1];
b = x >> 6;
rawDigest[j] = (r << 4) | (((x & 0xf) | (b << 3)) + b);
}
}
// DUCO-S1A hasher
uintDiff ducos1a(char const * prevBlockHash, char const * targetBlockHash, uintDiff difficulty) {
#if defined(ARDUINO_ARCH_AVR) || defined(ARDUINO_ARCH_MEGAAVR)
// If the difficulty is too high for AVR architecture then return 0
if (difficulty > 655) return 0;
#endif
uint8_t target[SHA1_HASH_LEN];
lowercase_hex_to_bytes(targetBlockHash, target);
uintDiff const maxNonce = difficulty * 100 + 1;
return ducos1a_mine(prevBlockHash, target, maxNonce);
}
uintDiff ducos1a_mine(char const * prevBlockHash, uint8_t const * target, uintDiff maxNonce) {
static duco_hash_state_t hash;
duco_hash_init(&hash, prevBlockHash);
char nonceStr[10 + 1];
for (uintDiff nonce = 0; nonce < maxNonce; nonce++) {
ultoa(nonce, nonceStr, 10);
uint8_t const * hash_bytes = duco_hash_try_nonce(&hash, nonceStr);
if (memcmp(hash_bytes, target, SHA1_HASH_LEN) == 0) {
return nonce;
}
}
return 0;
}
void loop() {
// Wait for serial data
if (Serial.available() <= 0) {
return;
}
// Reserve 1 extra byte for comma separator (and later zero)
char lastBlockHash[40 + 1];
char newBlockHash[40 + 1];
// Read last block hash
if (Serial.readBytesUntil(',', lastBlockHash, 41) != 40) {
return;
}
lastBlockHash[40] = 0;
// Read expected hash
if (Serial.readBytesUntil(',', newBlockHash, 41) != 40) {
return;
}
newBlockHash[40] = 0;
// Read difficulty
uintDiff difficulty = strtoul(Serial.readStringUntil(',').c_str(), NULL, 10);
// Clearing the receive buffer reading one job.
while (Serial.available()) Serial.read();
// Turn off the built-in led
#if defined(ARDUINO_ARCH_AVR)
PORTB = PORTB | B00100000;
#else
digitalWrite(LED_BUILTIN, LOW);
#endif
// Start time measurement
uint32_t startTime = micros();
// Call DUCO-S1A hasher
uintDiff ducos1result = ducos1a(lastBlockHash, newBlockHash, difficulty);
// Calculate elapsed time
uint32_t elapsedTime = micros() - startTime;
// Turn on the built-in led
#if defined(ARDUINO_ARCH_AVR)
PORTB = PORTB & B11011111;
#else
digitalWrite(LED_BUILTIN, HIGH);
#endif
// Clearing the receive buffer before sending the result.
while (Serial.available()) Serial.read();
// Send result back to the program with share time
Serial.print(String(ducos1result, 2)
+ SEP_TOKEN
+ String(elapsedTime, 2)
+ SEP_TOKEN
+ String(DUCOID)
+ END_TOKEN);
}