@@ -740,33 +740,29 @@ void miner_task_core1(void *param) {
740740}
741741
742742#elif defined(CONFIG_IDF_TARGET_ESP32S3)
743- #include < sha/sha_dma.h> // For esp_sha_acquire/release_hardware
744- // ESP32-S3: Optimized pipelined assembly mining with MIDSTATE CACHING (v2)
745- // Key optimizations:
746- // 1. Hardware midstate computed ONCE per job (not per nonce!)
747- // 2. Block 2 template prepared once, only nonce changes
748- // 3. Double-hash padding leverages zeros from block 2
743+ // ESP32-S3: software-midstate dual-core mining.
744+ // The S3 SHA accelerator cannot resume from an externally-written midstate
745+ // (SHA_H write + SHA_CONTINUE is ignored), so the hardware "midstate restore"
746+ // hot loop produced wrong hashes and zero valid shares (issues #28, #10, #5).
747+ // Both cores now run the correct BitsyMiner software double-SHA256 over split
748+ // nonce ranges. The unused sha256_pipelined_s3*/sha256_s3 helpers are retained
749+ // for reference but no longer on the mining hot path.
749750
750751void miner_task_core1 (void *param) {
751752 block_header_t hb;
752- block_header_t hbVerify; // BitsyMiner pattern: keep UNSWAPPED copy for verification
753753 sha256_hash_t ctx;
754- sha256_hash_t sw_midstate; // SOFTWARE midstate for verification
755- uint32_t hw_midstate[8 ]; // HARDWARE midstate for mining (NEW!)
754+ sha256_hash_t sw_midstate; // SOFTWARE midstate (BitsyMiner path)
756755 char jobId[MAX_JOB_ID_LEN ];
757756 uint32_t minerId = 1 ;
758757
759- Serial.printf (" [MINER1] Started on core %d (S3 Optimized ASM v2 + Midstate Cache , priority %d)\n " ,
758+ Serial.printf (" [MINER1] Started on core %d (S3 SOFTWARE-MIDSTATE, nonce-hi , priority %d)\n " ,
760759 xPortGetCoreID (), uxTaskPriorityGet (NULL ));
761760
762- // Initialize S3 pipelined SHA hardware
763- sha256_pipelined_s3_init ();
764-
765761 // Wait for first job
766762 while (!s_miningActive) {
767763 vTaskDelay (100 / portTICK_PERIOD_MS);
768764 }
769- Serial.println (" [MINER1] Got first job, starting S3 optimized assembly mining (v2 with midstate )" );
765+ Serial.println (" [MINER1] Got first job, starting S3 software-midstate mining (nonce-hi )" );
770766
771767 while (true ) {
772768 if (!s_miningActive) {
@@ -779,112 +775,42 @@ void miner_task_core1(void *param) {
779775 // Copy job data
780776 xSemaphoreTake (s_jobMutex, portMAX_DELAY);
781777 memcpy (&hb, &s_pendingBlock, sizeof (block_header_t ));
782- memcpy (&hbVerify, &s_pendingBlock, sizeof (block_header_t )); // Keep UNSWAPPED for verification!
783778 strncpy (jobId, s_currentJobId, MAX_JOB_ID_LEN );
784779 xSemaphoreGive (s_jobMutex);
785780
786- // BitsyMiner pattern: Compute SOFTWARE midstate on UNSWAPPED header (for verification)
787- miner_sha256_midstate (&sw_midstate, &hbVerify);
788-
789- // ========================================
790- // BYTESWAP32 all 20 words of header for hardware SHA
791- // ========================================
792- uint32_t header_swapped[20 ];
793- uint32_t *header_words = (uint32_t *)&hb;
794- for (int i = 0 ; i < 20 ; i++) {
795- header_swapped[i] = __builtin_bswap32 (header_words[i]);
796- }
797-
798- // ========================================
799- // OPTIMIZATION v3: Compute hardware midstate ONCE per job!
800- // Also initialize persistent zeros in SHA_TEXT
801- // ========================================
802- esp_sha_acquire_hardware ();
803- sha256_s3_compute_midstate (header_swapped, hw_midstate);
804- sha256_s3_init_zeros (); // Set persistent zeros for block 2 padding
805-
806- // Prepare block 2 template (words 16-18: last 4 bytes merkle, timestamp, nbits)
807- // Word 19 (nonce) will be set per iteration
808- uint32_t block2_template[3 ];
809- block2_template[0 ] = header_swapped[16 ]; // merkle_root tail (swapped)
810- block2_template[1 ] = header_swapped[17 ]; // timestamp (swapped)
811- block2_template[2 ] = header_swapped[18 ]; // nbits (swapped)
812-
813- // Nonce in big-endian format for hardware SHA
814- uint32_t nonce_swapped = __builtin_bswap32 (s_startNonce[minerId]);
781+ // The ESP32-S3 SHA peripheral cannot resume hashing from an externally
782+ // written midstate: writing the SHA_H registers and issuing SHA_CONTINUE is
783+ // ignored by the engine, so the old pipelined-assembly hot loop computed the
784+ // wrong first-SHA digest. Every "candidate" then failed the software
785+ // re-verification and the device submitted ZERO shares while still reporting
786+ // a high (but fake) hashrate. See issues #28, #10, #5.
787+ //
788+ // Fix: mine in software using the BitsyMiner midstate path, exactly like
789+ // Core 0. Correct and pool-valid; throughput is roughly half the old fake
790+ // rate but the shares are real. (A correct HW path would have to re-hash
791+ // block 1 every nonce -- no midstate caching -- a possible future optimization.)
792+ miner_sha256_midstate (&sw_midstate, &hb);
815793
816- #ifdef DEBUG_MINING
817- Serial.printf (" [S3-V3] Midstate cached, zeros persistent, starting batched-copy loop\n " );
818- static uint32_t s3_call_count = 0 ;
819- uint64_t hashes_before = s_stats.hashes ;
820- #endif
794+ // Core 1 scans the upper half of the nonce range; Core 0 takes the lower half.
795+ hb.nonce = s_startNonce[minerId];
821796
797+ uint32_t yieldCounter = 0 ;
822798 while (s_miningActive) {
823- // Run ULTRA-OPTIMIZED pipelined assembly mining loop (v3)
824- // - Midstate restore (same as v2)
825- // - Batched register loads for SHA_H copy (pipeline memory)
826- // - Persistent zeros (skip writing 10 zeros per iteration)
827- #ifdef DEBUG_MINING
828- s3_call_count++;
829- #endif
830-
831- bool candidate = sha256_pipelined_mine_s3_v3 (
832- hw_midstate,
833- block2_template,
834- &nonce_swapped,
835- &s_stats.hashes ,
836- &s_miningActive
837- );
838-
839- #ifdef DEBUG_MINING
840- if ((s3_call_count & 0x7FFFF ) == 0 ) { // Every ~512K calls
841- uint64_t hashes_now = s_stats.hashes ;
842- Serial.printf (" [S3-V3] calls=%u, hashes=%llu\n " , s3_call_count, hashes_now);
843- }
844- #endif
845-
846- if (!s_miningActive) break ;
847-
848- if (candidate) {
849- // BitsyMiner pattern: The assembly incremented nonce BEFORE exiting
850- uint32_t candidate_nonce_swapped = nonce_swapped - 1 ;
851- uint32_t candidate_nonce_native = __builtin_bswap32 (candidate_nonce_swapped);
852-
853- // Debug logging for S3 share validation investigation (Issue #5)
854- #if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(DEBUG_SHARE_VALIDATION)
855- Serial.printf (" [S3-DBG] Candidate found! nonce_swapped=%08x native=%08x\n " ,
856- candidate_nonce_swapped, candidate_nonce_native);
857- #endif
858-
859- // BitsyMiner CRITICAL: Verify with SOFTWARE SHA on UNSWAPPED header
860- hbVerify.nonce = candidate_nonce_native;
861- bool swVerified = miner_sha256_header (&sw_midstate, &ctx, &hbVerify);
862-
863- // Debug logging for S3 share validation investigation (Issue #5)
864- #if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(DEBUG_SHARE_VALIDATION)
865- Serial.printf (" [S3-DBG] SW verify=%s hash[28-31]=%02x%02x%02x%02x\n " ,
866- swVerified ? " PASS" : " FAIL" ,
867- ctx.bytes [28 ], ctx.bytes [29 ], ctx.bytes [30 ], ctx.bytes [31 ]);
868- #endif
869-
870- if (swVerified) {
871- hashCheck (jobId, &ctx, hbVerify.timestamp , candidate_nonce_native);
872- }
799+ // Pure software double-SHA256 from the cached midstate (no HW contention)
800+ if (miner_sha256_header (&sw_midstate, &ctx, &hb)) {
801+ hashCheck (jobId, &ctx, hb.timestamp , hb.nonce );
873802 }
803+ hb.nonce ++;
804+ s_stats.hashes ++;
805+ s_core1Hashes++;
874806
875- // Yield periodically to prevent WDT
876- // The ASM function returns every ~65k hashes (on partial match),
877- // so we yield every 16 iterations (approx 1M hashes)
878- static uint32_t loop_iter = 0 ;
879- if (++loop_iter >= 16 ) {
880- loop_iter = 0 ;
881- esp_sha_release_hardware ();
807+ // Yield periodically so WiFi/Stratum/monitor tasks run (prevents WDT)
808+ if (++yieldCounter >= CORE_0_YIELD_COUNT ) {
809+ yieldCounter = 0 ;
882810 vTaskDelay (1 );
883- esp_sha_acquire_hardware ();
884811 }
885812 }
886813
887- esp_sha_release_hardware ();
888814 s_core1Mining = false ;
889815 vTaskDelay (20 / portTICK_PERIOD_MS);
890816 }
0 commit comments