Pretty Damn Quick Miner
High-performance open-source Bitcoin mining firmware for ESP32
Features • Flasher • Manager • Hardware • Installation • Docker • Roadmap • Contributing
PDQminer is a fully open-source Bitcoin mining ecosystem for ESP32 microcontrollers, consisting of:
- PDQminer Firmware - Maximum hashrate mining firmware (~1081 KH/s with HW SHA256 NOP pipeline)
- PDQFlasher - Cross-platform firmware flashing tool with auto-detection
- PDQManager - Fleet management application for monitoring multiple miners
Goal: Exceed 1000 KH/s on ESP32-D0 hardware while remaining 100% transparent, secure, and community-driven. Currently at 1081 KH/s — surpassing NMMiner's claimed 1095 KH/s on identical hardware.
| Aspect | NerdMiner | NMMiner | PDQminer |
|---|---|---|---|
| Open Source | ✅ Yes | ❌ Closed | ✅ 100% Open |
| Hashrate (ESP32-D0) | ~350 KH/s | ~1095 KH/s | ~1081 KH/s |
| Configuration | Captive Portal | Captive Portal | Captive Portal |
| Fleet Management | ❌ No | ❌ No | ✅ PDQManager |
| Auto-Flash Tool | ❌ No | ✅ Yes | ✅ PDQFlasher |
| Security Focused | Basic | Unknown | ✅ PBKDF2 + Rate Limiting |
-
Maximum Hashrate SHA256d Engine
- ESP32 hardware SHA256 acceleration (~945 KH/s on HW peripheral)
- NOP-timed pipeline — calibrated NOP delays replace BUSY polling (35% faster)
- Overlapped register writes (fill next block during SHA computation)
- START→CONTINUE operation chaining (zero-gap atomic transition)
- Noinline cold path — hash candidate check isolated to reduce hot loop register pressure
- Inline l16ui hash pre-filter — 16-bit load rejects 99.998% of candidates in 1 cycle
- Reduced double-hash overlap (only block0[8:15] via
HwShaFillBlock0Upper) - Software midstate precomputation (first 64 bytes cached)
- Nonce-only block updates (16 bytes per hash)
- Fully unrolled SHA256 rounds (SW path, no loop overhead)
- Early hash rejection (check MSB first)
- Boot-time hardware correctness test + mining loop verification
-
Dual-Task Architecture (HW + SW)
- Core 0: Hardware SHA256 engine (~945 KH/s) - 7/8 of nonce space
- Core 1: Software SHA256 engine (~40 KH/s) - 1/8 of nonce space
- Combined throughput: ~1081 KH/s
- Zero contention design - no mutex in hash loop
-
Stratum V1 Protocol
- Pool mining with automatic reconnection
- Share submission and difficulty tracking
- Pool failover with backup pool support
-
Minimalistic Display Mode
- 5-second update interval (configurable)
- Text-only stats (hashrate, shares, uptime)
- Zero GPU acceleration needed
- Maximum CPU cycles for mining
-
Captive Portal Configuration
- WiFi SSID/Password
- Primary and backup pool settings
- BTC wallet address and worker name
- Timezone and display preferences
- Settings stored encrypted in NVS
Cross-platform firmware flashing tool with GUI and CLI:
-
Auto Board Detection
- ESP32-D0, ESP32-S3, ESP32-C3 identification
- Display controller detection (ILI9341/ST7789)
- Automatic firmware selection
-
One-Click Flashing
- Built-in esptool integration
- Progress bar and status updates
- Verify after flash option
-
Cross-Platform
- Windows, macOS, Linux support
- GUI (DearPyGUI) and CLI modes
- No additional drivers required
Fleet management application for monitoring multiple miners:
-
mDNS Discovery
- Automatic miner discovery on local network
- Real-time device status updates
- No manual IP configuration
-
Fleet Monitoring
- Combined hashrate dashboard
- Per-device statistics
- Historical performance graphs
-
Remote Configuration
- Pool settings management
- Firmware update coordination
- Device restart/reset controls
-
Secure Communication
- Per-device password authentication
- Token-based API sessions
- Rate limiting on auth endpoints
| Board | Display | Driver | Build Target | Status |
|---|---|---|---|---|
| ESP32-2432S028R | 2.8" TFT | ILI9341 | cyd_ili9341 |
In Development |
| ESP32-2432S028R | 2.8" TFT | ST7789 | cyd_st7789 |
In Development |
| Board | Display | Status |
|---|---|---|
| ESP32-2432S028C | 2.8" TFT (Capacitive) | Planned |
| ESP32-2432S024 | 2.4" TFT | Planned |
| ESP32-3248S035 | 3.5" TFT | Planned |
| ESP32-WROOM-32 | Various | Planned |
| LILYGO T-Display S3 | 1.9" AMOLED | Planned |
Note: The ESP32-2432S028R (CYD - Cheap Yellow Display) exists in two variants with different display drivers. PDQFlasher auto-detects your variant.
- Download PDQFlasher from Releases
- Connect your ESP32 board via USB
- Run PDQFlasher and click "Flash"
esptool.py --chip esp32 --port /dev/ttyUSB0 \
--baud 921600 write_flash \
0x1000 bootloader.bin \
0x8000 partitions.bin \
0x10000 pdqminer.bin- Power on the device - display shows "PDQminer Setup"
- Connect to WiFi network:
PDQminer-XXXX(password:pdqminer123) - Browser opens automatically (or navigate to
192.168.4.1) - Configure:
- WiFi network credentials
- Primary pool:
pool.nerdminers.org:3333(recommended) - Backup pool:
public-pool.io:3333(optional) - BTC wallet address
- Worker name (optional)
- Click "Save & Reboot"
- Device connects to WiFi and starts mining
- PlatformIO (recommended)
- or ESP-IDF v5.x
- Python 3.10+ (for tools)
git clone https://github.com/zacdreyer/PDQminer.git
cd PDQminer
# Build for CYD with ILI9341 display
pio run -e cyd_ili9341
# Build for CYD with ST7789 display
pio run -e cyd_st7789
# Upload to connected board
pio run -e cyd_ili9341 -t upload
# Run tests
pio test -e nativecd tools/pdqflasher
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
# Flash connected device
pdqflash flash --binary build/pdqminer.bin
# Detect connected board
pdqflash detect
# See all options
pdqflash flash --helpSee PDQFlasher User Guide for full documentation.
cd tools/pdqmanager
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
# Start web dashboard (opens browser automatically)
pdqmanager
# Quick scan without web server
pdqmanager scan
# Export fleet data
pdqmanager export --format json --output fleet.jsonSee PDQManager User Guide for full documentation.
PDQminer can run on Docker, macOS, or Linux using the software SHA256 path (~46 KH/s per thread). This is useful for development, testing, and protocol validation without ESP32 hardware.
# Create .env with your wallet
cat > .env << 'EOF'
PDQ_WALLET=bc1q_YOUR_BITCOIN_ADDRESS
PDQ_WORKER=docker01
PDQ_THREADS=2
EOF
# Build and run
docker compose up --build
# Run in background
docker compose up --build -d
docker compose logs -f
# Stop
docker compose down# Install tools (if needed)
xcode-select --install
# Build with clang (no cmake required)
cd platform/linux && mkdir -p build
cc -std=c11 -O2 -Wall -Wextra -Wno-unused-parameter -Wno-missing-field-initializers \
-DPDQ_HEADLESS=1 -DPDQ_LINUX=1 -D_GNU_SOURCE \
-I../../src \
main.c linux_hal.c linux_config.c linux_wifi.c linux_display.c linux_mining.c \
../../src/core/sha256_engine.c \
../../src/stratum/stratum_client.c \
../../src/api/device_api.c \
-lpthread -o build/pdqminer
# Run
./build/pdqminer --wallet bc1q_YOUR_ADDRESS --threads 2sudo apt-get install build-essential cmake # Debian/Ubuntu
cd platform/linux && mkdir -p build && cd build
cmake -DCMAKE_BUILD_TYPE=Release ..
make -j$(nproc)
./pdqminer --wallet bc1q_YOUR_ADDRESS --threads 2Full guide: See Docker & Native Build Guide for CLI reference, environment variables, config files, multi-instance setups, architecture details, and troubleshooting.
| Component | Core | Hashrate | Cycles/Nonce |
|---|---|---|---|
| HW SHA256 Engine | Core 0 | ~1040 KH/s | ~264 |
| SW SHA256 Engine | Core 1 | ~40 KH/s | — |
| Combined | Both | ~1081 KH/s | — |
Hardware: ESP32-D0WD-V3 (rev3.1), Dual-Core Xtensa LX6 @ 240 MHz
| Milestone | Hashrate | Optimization |
|---|---|---|
| SW-only baseline | 58 KH/s | Dual-core, midstate, unrolled rounds |
| HW SHA256 engine | 472 KH/s | ESP32 SHA peripheral acceleration |
| Overlap optimization | 627 KH/s | Register writes overlapped with SHA computation |
| START→CONTINUE chaining | ~700 KH/s | Zero-gap atomic operation chaining |
| NOP pipeline + cold path | 949 KH/s | NOP-timed pipeline, noinline cold path, register caching |
| NOP fine-tuning | ~985 KH/s | Binary search NOP calibration (54/42/12/13/9/1 = 130 NOPs) |
| APB bus fix + minimal display | ~1081 KH/s | Stripped APB-contending TFT, terminal-only stats |
| Property | Value |
|---|---|
| SHA_TEXT_BASE | 0x3FF03000 |
| START latency | 627 CPU cycles |
| CONTINUE latency | 627 CPU cycles |
| LOAD latency | 562 CPU cycles |
| Midstate restore | Not possible (no SHA_H_BASE on ESP32-D0) |
| Overlap writes during START | Safe (engine latches on trigger) |
| Overlap writes during CONTINUE | Unsafe (corrupts result) |
- NOP-Timed Pipeline: Calibrated NOP delays replace BUSY register polling (~264 cycles/nonce vs 413)
- Noinline Cold Path: Hash candidate check isolated to reduce hot loop register pressure (64-byte stack frame, 1 spill)
- Inline l16ui Hash Pre-filter: 16-bit load instruction rejects 99.998% of hash candidates in 1 cycle
- Hardware SHA256 Acceleration: ESP32's SHA peripheral handles double-SHA256
- Overlapped Register Writes: Fill next SHA block while current block is being hashed
- START→CONTINUE Chaining: Zero-gap atomic operation chaining (undocumented ESP32 behavior)
- Midstate Caching: First SHA256 block computed once per job (SW path)
- Nonce-Only Updates: Only 4 bytes change per hash attempt
- Loop Unrolling: 64 SHA256 rounds fully unrolled (SW path)
- Early Rejection: Check hash MSB before full comparison
- Zero Allocation: No malloc/free in mining loop
- GCC Optimization Split: -Os for SW mining code, -O2 for HW mining code
- JSON Input Validation: Extranonce2 clamping, coinbase length validation, recv buffer guards
- Security Hardening: strtol integer parsing, socket invalidation on failure, CORS restriction
- Project architecture and documentation
- Software Design Document (SDD)
- Test-Driven Development Guide (TDD)
- Coding standards with security/memory best practices
- PDQManager specification
- PDQFlasher specification
- Project scaffolding and build system
- SHA256 engine with midstate optimization
- Dual-core mining task implementation
- Hardware abstraction layer (HAL)
- Benchmark firmware
- Stratum V1 client implementation
- WiFi manager and captive portal
- NVS configuration storage
- Phase B code review - Round 1 (security, accuracy, optimization)
- Phase B code review - Round 2 (comprehensive review, 9 issues fixed)
- Phase B code review - Round 3 (critical share submission fix, 4 issues fixed)
- Phase B code review - Round 4 (100% confidence review, 5 critical bugs fixed)
- SHA256 optimization pass 1 (W pre-computation, early rejection)
- Code review - Round 5 (100% confidence verification)
- Display driver (ILI9341/ST7789) with TFT_eSPI
- Code review - Round 6 (display driver verification)
- Code review - Round 12 (security audit: 6 bugs + 2 security issues fixed)
- Performance benchmarking framework
- SHA256 hot path profiling and optimization pass 1
- SHA256 optimization pass 2 (W2 pre-computation, loop reduction)
- Code review - Round 7 (critical W2_SIG0_8 bug fix)
- Memory usage analysis and optimization
- Hardware testing and performance validation (58 KH/s SW baseline)
- ESP32 hardware SHA256 integration (472 KH/s)
- Overlapped register write optimization (627 KH/s)
- Hardware diagnostic: midstate caching impossible on ESP32-D0
- IRAM testing (no benefit for HW path, reverted)
- START→CONTINUE operation chaining (~700 KH/s)
- NOP-timed pipeline optimization (949 KH/s)
- Noinline cold path extraction (register pressure optimization)
- NOP binary search calibration (NOP_57=54, NOP_50=42, NOP_15=12, NOP_13=13, NOP_9=9, NOP_8=1)
- Boot-time HW correctness test + mining loop verification test
- First pool-accepted share on public-pool.io
- Security review (6 bugs + 2 security issues fixed)
- Pool configuration update (pool.nerdminers.org primary, public-pool.io backup)
- APB bus contention fix + minimal terminal display (1081 KH/s)
- Comprehensive security hardening (30+ issues fixed across all platforms)
- Xtensa inline assembly exploration (target ≥1100 KH/s)
- PDQFlasher CLI implementation (37 tests passing)
- PDQFlasher auto-detection (port, board, chip)
- PDQManager backend (Flask + REST API)
- PDQManager frontend (web UI dashboard)
- mDNS discovery implementation
- PDQManager device authentication + config management
- Code review + 7 bug fixes (verify_firmware, XSS, thread safety, CSV)
- Comprehensive user guide documentation
- Docker & native (Linux/macOS) build
- GitHub Actions CI/CD pipelines
- CI/CD lint + format + test verification (65 Python tests passing)
- Beta testing program
- Documentation finalization
- v1.0.0 release
- Additional board support
PDQminer/
├── src/ # Firmware source code
│ ├── core/ # SHA256 engine, mining tasks
│ ├── stratum/ # Pool communication
│ ├── network/ # WiFi management
│ ├── display/ # Display drivers
│ └── hal/ # Hardware abstraction
├── platform/ # Native platform builds
│ └── linux/ # Docker, Linux & macOS build
│ ├── main.c # CLI entry point (replaces Arduino setup/loop)
│ ├── linux_mining.c # pthread-based mining threads
│ ├── linux_config.c # JSON file config (replaces NVS)
│ ├── linux_hal.c # POSIX HAL (temp, heap, chip ID)
│ ├── linux_wifi.c # Host networking stub
│ ├── linux_display.c # Headless display stubs
│ ├── CMakeLists.txt # CMake build configuration
│ └── README.md # Docker & Native Build Guide
├── test/ # Unit & integration tests
│ ├── unit/ # Isolated unit tests
│ ├── integration/ # Component integration tests
│ ├── benchmark/ # Performance benchmarks
│ └── mocks/ # Mock implementations
├── tools/ # PC tools
│ ├── pdqflasher/ # Firmware flashing tool
│ └── pdqmanager/ # Fleet management tool
├── boards/ # Board configurations
├── docs/ # Documentation
│ ├── sdd.md # Software Design Document
│ ├── tdd.md # Test-Driven Development Guide
│ ├── coding-standards.md # Coding standards
│ └── agents/ # AI agent documentation
├── .github/workflows/ # CI/CD pipelines
│ ├── ci.yml # Test & lint on push/PR
│ └── release.yml # Build & release on tags
├── Dockerfile # Multi-stage Docker build
├── docker-compose.yml # Docker Compose configuration
├── platformio.ini # ESP32 build configuration
└── README.md # This file
PDQminer is designed with security as a priority:
- Password Storage: PBKDF2-SHA256 with 100,000 iterations and random salt
- API Authentication: Token-based with 5-minute expiry
- Rate Limiting: 5 attempts per 5 minutes on auth endpoints
- Input Validation: All external input validated and sanitized
- Buffer Safety: No strcpy/sprintf, all buffers bounds-checked
- Memory Safety: Sensitive data zeroed after use
- Safe Integer Parsing: strtol() used throughout (no atoi on untrusted data)
- Socket Safety: Automatic disconnect on send failure prevents stale socket use
- CORS Restriction: PDQManager API restricted to localhost origins
- IP Validation: Device client validates IP addresses to prevent SSRF
- Allocation Safety: std::nothrow with null checks on heap allocation
See Security Considerations for details.
Contributions are welcome! Please read our contributing guidelines before submitting PRs.
- Fork the repository
- Create a feature branch:
git checkout -b feature/amazing-optimization - Follow the coding standards
- Write tests for new functionality
- Ensure all tests pass:
pio test -e native - Submit a pull request
<type>(<scope>): <subject>
<body>
<footer>
Types: feat, fix, perf, refactor, docs, test, chore
Example:
perf(sha256): optimize midstate computation
- Precompute first 64 bytes of message schedule
- Reduce per-nonce computation by 50%
- Measured improvement: 340 KH/s → 680 KH/s
Closes #42
- NerdMiner - Inspiration and reference implementation
- public-pool.io - Low difficulty pool for small miners
- ESP-IDF and PlatformIO communities
GNU General Public License v3.0 - see LICENSE for details.
Solo mining with an ESP32 is extremely unlikely to find a Bitcoin block. This project is for educational purposes and entertainment. The odds of finding a block with 1000 KH/s are approximately 1 in 10^18 per year.
⚡ Mine Bitcoin. Open Source. Pretty Damn Quick. ⚡
