diff --git a/bin/0x10000_firmware.bin b/bin/0x10000_firmware.bin index 4ef1677..3851d7e 100644 Binary files a/bin/0x10000_firmware.bin and b/bin/0x10000_firmware.bin differ diff --git a/platformio.ini b/platformio.ini index bb5126d..0b0cec5 100644 --- a/platformio.ini +++ b/platformio.ini @@ -31,8 +31,8 @@ board_build.partitions = huge_app.csv build_flags = -D LV_LVGL_H_INCLUDE_SIMPLE -D BOARD_HAS_PSRAM - ;-D ARDUINO_USB_MODE=1 - ;-D ARDUINO_USB_CDC_ON_BOOT=1 + -D ARDUINO_USB_MODE=1 + -D ARDUINO_USB_CDC_ON_BOOT=1 ;-D DEBUG_MINING=1 lib_deps = https://github.com/takkaO/OpenFontRender diff --git a/src/NerdMinerV2.ino.cpp b/src/NerdMinerV2.ino.cpp index 09cb85b..f6c2750 100644 --- a/src/NerdMinerV2.ino.cpp +++ b/src/NerdMinerV2.ino.cpp @@ -40,6 +40,7 @@ void setup() // Idle task that would reset WDT never runs, because core 0 gets fully utilized disableCore0WDT(); + disableCore1WDT(); /******** INIT NERDMINER ************/ Serial.println("NerdMiner v2 starting......"); @@ -117,6 +118,9 @@ void loop() { oldStatus = newStatus; } - checkRemoveConfiguration(); + checkResetConfigButton(); + + //Run miner on main core when there is time --Currently on test + runMiner(); } \ No newline at end of file diff --git a/src/mining.cpp b/src/mining.cpp index e409801..1fa30ac 100644 --- a/src/mining.cpp +++ b/src/mining.cpp @@ -6,6 +6,7 @@ #include "media/Free_Fonts.h" #include "media/images.h" #include "mbedtls/md.h" +#include "mbedtls/sha256.h" #include "OpenFontRender.h" #include "mining.h" @@ -18,6 +19,7 @@ unsigned long Mhashes = 0; int halfshares; // increase if blockhash has 16 bits of zeroes int shares; // increase if blockhash has 32 bits of zeroes int valids; // increased if blockhash <= target +bool enableGlobalHash = false; // Variables to hold data from custom textboxes extern char poolString[80]; @@ -27,42 +29,7 @@ extern char btcString[80]; extern OpenFontRender render; extern TFT_eSprite background; -bool checkHalfShare(unsigned char* hash) { - //bool valid = true; - for(uint8_t i=31; i>31-2; i--) { - if(hash[i] != 0) { - return false; - } - } - #ifdef DEBUG_MINING - if (valid) { - Serial.print("\thalf share : "); - for (size_t i = 0; i < 32; i++) - Serial.printf("%02x ", hash[i]); - Serial.println(); - } - #endif - return true; -} -bool checkShare(unsigned char* hash) { - bool valid = true; - for(uint8_t i=31; i>31-4; i--) { - if(hash[i] != 0) { - valid = false; - break; - } - } - #ifdef DEBUG_MINING - if (valid) { - Serial.print("\tshare : "); - for (size_t i = 0; i < 32; i++) - Serial.printf("%02x ", hash[i]); - Serial.println(); - } - #endif - return valid; -} bool checkValid(unsigned char* hash, unsigned char* target) { bool valid = true; @@ -111,17 +78,25 @@ int to_byte_array(const char *in, size_t in_size, uint8_t *out) { return count; } } + +bool verifyPayload (String line){ + String inData=line; + if(inData.length() == 0) return false; + inData.trim(); + if(inData.isEmpty()) return false; + return true; +} + void runWorker(void *name) { // TEST: https://bitcoin.stackexchange.com/questions/22929/full-example-data-for-scrypt-stratum-client Serial.println(""); Serial.printf("\n[WORKER] Started. Running %s on core %d\n", (char *)name, xPortGetCoreID()); - ;Serial.printf("### [Total Heap / Free heap]: %d / %d \n", ESP.getHeapSize(), ESP.getFreeHeap()); + Serial.printf("### [Total Heap / Free heap]: %d / %d \n", ESP.getHeapSize(), ESP.getFreeHeap()); String ADDRESS = String(btcString); - mbedtls_md_context_t ctx; // connect to pool WiFiClient client; bool continueSecuence = false; @@ -146,6 +121,7 @@ void runWorker(void *name) { Serial.print(" Sending : "); Serial.println(payload); client.print(payload.c_str()); line = client.readStringUntil('\n'); + if(!verifyPayload(line)) return; Serial.print(" Receiving: "); Serial.println(line); deserializeJson(doc, line); int error = doc["error"]; @@ -174,6 +150,7 @@ void runWorker(void *name) { Serial.print(" Sending : "); Serial.println(payload); client.print(payload.c_str()); line = client.readStringUntil('\n'); + if(!verifyPayload(line)) return; Serial.print(" Receiving: "); Serial.println(line); Serial.print(" Receiving: "); Serial.println(client.readStringUntil('\n')); Serial.print(" Receiving: "); Serial.println(client.readStringUntil('\n')); @@ -275,20 +252,20 @@ void runWorker(void *name) { Serial.println("---"); #endif - 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); - + mbedtls_sha256_context ctx; + mbedtls_sha256_init(&ctx); + byte interResult[32]; // 256 bit byte shaResult[32]; // 256 bit - mbedtls_md_starts(&ctx); - mbedtls_md_update(&ctx, bytearray, str_len); - mbedtls_md_finish(&ctx, interResult); + mbedtls_sha256_starts_ret(&ctx,0); + mbedtls_sha256_update_ret(&ctx, bytearray, str_len); + mbedtls_sha256_finish_ret(&ctx, interResult); - mbedtls_md_starts(&ctx); - mbedtls_md_update(&ctx, interResult, 32); - mbedtls_md_finish(&ctx, shaResult); + mbedtls_sha256_starts_ret(&ctx,0); + mbedtls_sha256_update_ret(&ctx, interResult, 32); + mbedtls_sha256_finish_ret(&ctx, shaResult); + mbedtls_sha256_free(&ctx); #ifdef DEBUG_MINING Serial.print(" coinbase double sha: "); @@ -323,13 +300,16 @@ void runWorker(void *name) { Serial.println(""); #endif - mbedtls_md_starts(&ctx); - mbedtls_md_update(&ctx, merkle_concatenated, 64); - mbedtls_md_finish(&ctx, interResult); + mbedtls_sha256_context ctx; + mbedtls_sha256_init(&ctx); + mbedtls_sha256_starts_ret(&ctx,0); + mbedtls_sha256_update_ret(&ctx, merkle_concatenated, 64); + mbedtls_sha256_finish_ret(&ctx, interResult); - mbedtls_md_starts(&ctx); - mbedtls_md_update(&ctx, interResult, 32); - mbedtls_md_finish(&ctx, merkle_result); + mbedtls_sha256_starts_ret(&ctx,0); + mbedtls_sha256_update_ret(&ctx, interResult, 32); + mbedtls_sha256_finish_ret(&ctx, merkle_result); + mbedtls_sha256_free(&ctx); #ifdef DEBUG_MINING Serial.print(" merkle sha : "); @@ -419,66 +399,91 @@ void runWorker(void *name) { Serial.println(""); #endif + mbedtls_sha256_context midstate[32]; + unsigned char hash[32]; + + //Calcular midstate + mbedtls_sha256_init(midstate); + mbedtls_sha256_starts_ret(midstate, 0); + mbedtls_sha256_update_ret(midstate, bytearray_blockheader, 64); + // search a valid nonce + enableGlobalHash = true; uint32_t nonce = 0; uint32_t startT = micros(); - bytearray_blockheader[79] = 0; //We only mine until 1MHashes this will allways be zero + unsigned char *header64 = bytearray_blockheader + 64; Serial.println(">>> STARTING TO HASH NONCES"); while(true) { - bytearray_blockheader[76] = (nonce >> 0) & 0xFF; - bytearray_blockheader[77] = (nonce >> 8) & 0xFF; - bytearray_blockheader[78] = (nonce >> 16) & 0xFF; - bytearray_blockheader[79] = (nonce >> 24) & 0xFF; + memcpy(bytearray_blockheader + 77, &nonce, 3); // double sha - mbedtls_md_starts(&ctx); - mbedtls_md_update(&ctx, bytearray_blockheader, 80); - mbedtls_md_finish(&ctx, interResult); + // Sin midstate + /*mbedtls_sha256_starts_ret(&ctx,0); + mbedtls_sha256_update_ret(&ctx, bytearray_blockheader, 80); + mbedtls_sha256_finish_ret(&ctx, interResult); - mbedtls_md_starts(&ctx); - mbedtls_md_update(&ctx, interResult, 32); - mbedtls_md_finish(&ctx, shaResult); + mbedtls_sha256_starts_ret(&ctx,0); + mbedtls_sha256_update_ret(&ctx, interResult, 32); + mbedtls_sha256_finish_ret(&ctx, shaResult); + for (size_t i = 0; i < 32; i++) + Serial.printf("%02x", shaResult[i]); + Serial.println("");*/ - // check if half share - if(checkHalfShare(shaResult)) { - halfshares++; - // check if share - if(checkShare(shaResult)) { - shares++; - // check if valid header - if(checkValid(shaResult, bytearray_target)) { - //Serial.printf("%s on core %d: ", (char *)name, xPortGetCoreID()); - Serial.printf("[WORKER] %s CONGRATULATIONS! Valid completed with nonce: %d | 0x%x\n", (char *)name, nonce, nonce); - valids++; - Serial.printf("[WORKER] %s Submiting work valid!\n", (char *)name); - while (!client.connected()) { - client.connect(poolString, portNumber); - vTaskDelay(1000 / portTICK_PERIOD_MS); - } - // STEP 3: Submit mining job - payload = "{\"params\": [\"" + ADDRESS + "\", \"" + job_id + "\", \"" + extranonce2 + "\", \"" + ntime + "\", \"" + String(nonce, HEX) + "\"], \"id\": "+ String(id++) +", \"method\": \"mining.submit\"}"; - Serial.print(" Sending : "); Serial.println(payload); - client.print(payload.c_str()); - line = client.readStringUntil('\n'); - Serial.print(" Receiving: "); Serial.println(line); - client.stop(); - // exit - nonce = MAX_NONCE; - break; - } - } - } + //Con midstate + // Primer SHA-256 + mbedtls_sha256_clone(&ctx, midstate); //Clonamos el contexto anterior para continuar el SHA desde allí + mbedtls_sha256_update_ret(&ctx, header64, 16); + mbedtls_sha256_finish_ret(&ctx, hash); - nonce++; - hashes++; + // Segundo SHA-256 + mbedtls_sha256_starts_ret(&ctx, 0); + mbedtls_sha256_update_ret(&ctx, hash, 32); + mbedtls_sha256_finish_ret(&ctx, hash); + /*for (size_t i = 0; i < 32; i++) + Serial.printf("%02x", hash[i]); + Serial.println(""); */ - if(hashes++>1000000) { Mhashes++; hashes=0;} - // exit - if (nonce >= MAX_NONCE) { - break; - } + hashes++; + if (nonce++> MAX_NONCE) break; //exit + + // check if 16bit share + if(hash[31]!=0) continue; + if(hash[30]!=0) continue; + halfshares++; + // check if 32bit share + if(hash[29]!=0) continue; + if(hash[28]!=0) continue; + shares++; + + // check if valid header + if(checkValid(hash, bytearray_target)){ + //Serial.printf("%s on core %d: ", (char *)name, xPortGetCoreID()); + Serial.printf("[WORKER] %s CONGRATULATIONS! Valid completed with nonce: %d | 0x%x\n", (char *)name, nonce, nonce); + valids++; + Serial.printf("[WORKER] %s Submiting work valid!\n", (char *)name); + while (!client.connected()) { + client.connect(poolString, portNumber); + vTaskDelay(1000 / portTICK_PERIOD_MS); + } + // STEP 3: Submit mining job + payload = "{\"params\": [\"" + ADDRESS + "\", \"" + job_id + "\", \"" + extranonce2 + "\", \"" + ntime + "\", \"" + String(nonce, HEX) + "\"], \"id\": "+ String(id++) +", \"method\": \"mining.submit\"}"; + Serial.print(" Sending : "); Serial.println(payload); + client.print(payload.c_str()); + line = client.readStringUntil('\n'); + Serial.print(" Receiving: "); Serial.println(line); + client.stop(); + // exit + nonce = MAX_NONCE; + break; + } } // exit if found a valid result or nonce > MAX_NONCE + mbedtls_sha256_free(&ctx); + mbedtls_sha256_free(midstate); + enableGlobalHash = false; + + if(hashes>=MAX_NONCE) { Mhashes=Mhashes+MAX_NONCE/1000000; hashes=hashes-MAX_NONCE;} + if (nonce == MAX_NONCE) { Serial.printf("[WORKER] %s SUBMITING WORK... MAX Nonce reached > MAX_NONCE\n", (char *)name); // STEP 3: Submit mining job @@ -495,12 +500,51 @@ void runWorker(void *name) { } uint32_t duration = micros() - startT; } - mbedtls_md_free(&ctx); + } //////////////////THREAD CALLS/////////////////// +//Testeamos hashrate final usando hilo principal +//this is currently on test + +void runMiner(void){ + uint32_t nonce=0; + unsigned char bytearray_blockheader[80]; + + if(!enableGlobalHash) return; + + mbedtls_sha256_context midstate[32], ctx; + unsigned char hash[32]; + + //Calcular midstate + mbedtls_sha256_init(midstate); + mbedtls_sha256_starts_ret(midstate, 0); + mbedtls_sha256_update_ret(midstate, bytearray_blockheader, 64); + + //Iteraciones + unsigned char *header64 = bytearray_blockheader + 64; + + for(nonce = 0; nonce < 10000; nonce++){ + memcpy(bytearray_blockheader + 77, &nonce, 3); + mbedtls_sha256_clone(&ctx, midstate); //Clonamos el contexto anterior para continuar el SHA desde allí + mbedtls_sha256_update_ret(&ctx, header64, 16); + mbedtls_sha256_finish_ret(&ctx, hash); + + // Segundo SHA-256 + mbedtls_sha256_starts_ret(&ctx, 0); + mbedtls_sha256_update_ret(&ctx, hash, 32); + mbedtls_sha256_finish_ret(&ctx, hash); + + hashes++; + } + + mbedtls_sha256_free(&ctx); + mbedtls_sha256_free(midstate); + +} + void runMonitor(void *name){ Serial.println("[MONITOR] started"); diff --git a/src/mining.h b/src/mining.h index c9cfa61..eadc0b6 100644 --- a/src/mining.h +++ b/src/mining.h @@ -1,7 +1,7 @@ // Mining #define THREADS 1 -#define MAX_NONCE 1000000 +#define MAX_NONCE 3000000 // #define MAX_NONCE 1.215.752.192 // Pool @@ -11,3 +11,4 @@ void runMonitor(void *name); void runWorker(void *name); +void runMiner(void); \ No newline at end of file diff --git a/src/wManager.cpp b/src/wManager.cpp index d0465cd..aa8d993 100644 --- a/src/wManager.cpp +++ b/src/wManager.cpp @@ -141,8 +141,12 @@ void init_WifiManager() Serial.begin(115200); //Serial.setTxTimeoutMs(10); //Init config pin - // pinMode(TRIGGER_PIN, INPUT); - + pinMode(PIN_BUTTON_2, INPUT); + + //Init pin 15 to eneble 5V external power (LilyGo bug) + pinMode(PIN_ENABLE5V, OUTPUT); + digitalWrite(PIN_ENABLE5V, HIGH); + // Change to true when testing to force configuration every time we run bool forceConfig = false; @@ -170,7 +174,7 @@ void init_WifiManager() //Advanced settings wm.setConfigPortalBlocking(false); //Hacemos que el portal no bloquee el firmware - wm.setConnectTimeout(30); // how long to try to connect for before continuing + wm.setConnectTimeout(50); // how long to try to connect for before continuing //wm.setConfigPortalTimeout(30); // auto close configportal after n seconds // wm.setCaptivePortalEnable(false); // disable captive portal redirection // wm.setAPClientCheck(true); // avoid timeout if client connected to softap @@ -267,10 +271,10 @@ void init_WifiManager() } } -void checkResetConfigButton(){ +/*void checkResetConfigButton(){ // Leer el estado del botón - int buttonState = digitalRead(PIN_BUTTON_1); + int buttonState = digitalRead(PIN_BUTTON_0); unsigned int last_time = (millis() - lastButtonPress); Serial.printf("button pressed %i - %u\n", buttonReset, last_time); @@ -286,24 +290,26 @@ void checkResetConfigButton(){ buttonPressed = true; } -} +}*/ -void checkRemoveConfiguration() { - if(!buttonPressed){ - return; - } - - buttonPressed = false; +void checkResetConfigButton() { // check for button press - Serial.printf("[CONFIG] Button reset pressed %i\n", buttonReset); - Serial.println("[CONFIG] Erasing pool config"); - Serial.println("[CONFIG] Deleting existing configuration"); - SPIFFS.remove(JSON_CONFIG_FILE); //Borramos fichero - Serial.println("[CONFIG] Erasing wifi config"); - wm.resetSettings(); - Serial.println("[CONFIG] Restarting"); - delay(1000); - ESP.restart(); + if ( digitalRead(PIN_BUTTON_2) == LOW ) { + // poor mans debounce/press-hold, code not ideal for production + delay(50); + if( digitalRead(PIN_BUTTON_2) == LOW ){ + Serial.println("Button Pressed"); + // still holding button for 3000 ms, reset settings, code not ideaa for production + delay(3000); // reset delay hold + if( digitalRead(PIN_BUTTON_2) == LOW ){ + Serial.println("Button Held"); + Serial.println("Erasing Config, restarting"); + wm.resetSettings(); + SPIFFS.remove(JSON_CONFIG_FILE); //Borramos fichero + ESP.restart(); + } + } + } } diff --git a/src/wManager.h b/src/wManager.h index 6eafb9c..1cb725a 100644 --- a/src/wManager.h +++ b/src/wManager.h @@ -1,6 +1,7 @@ //Botón configuración -#define PIN_BUTTON_1 0 -#define PIN_BUTTON_2 14 +#define PIN_BUTTON_1 0 +#define PIN_BUTTON_2 14 +#define PIN_ENABLE5V 15 void init_WifiManager(); void wifiManagerProcess();