A high-performance NIP-13 Proof of Work miner that leverages optimized SHA256 primitives inspired by hashcat's implementation. This standalone tool provides efficient mining for Nostr events without external dependencies.
Now includes a parallelized version that provides 3-4x performance improvement by utilizing all CPU cores!
- Optimized SHA256: Uses hashcat-inspired SHA256 implementation with SIMD optimizations
- Zero Dependencies: Standalone C implementation - no external libraries required
- Parallel Mining: Multi-threaded version provides 3-4x performance improvement
- Fast Performance: ~1-2 MH/s (single) or ~4-8 MH/s (parallel) on modern CPUs
- Full NIP-13 Compliance: Proper nonce tag injection and leading zero bit counting
- Cross-Platform: Works on macOS, Linux, and other Unix-like systems
- Multiple Difficulty Levels: Supports 1-32 bit difficulty targets
- Realistic Benchmarking: Unique timestamps prevent skewed benchmark results
# Build both versions (single-threaded + parallel)
make all
# Build only parallel version
make nip13_parallel
# Build only single-threaded version
make nip13_miner# Test single-threaded miner
make test
# Test parallel miner (much faster!)
make test-parallelSingle-threaded:
./nip13_miner your_event.json 20 100Parallel (3-4x faster):
./nip13_parallel your_event.json 20 100
# Or specify thread count
./nip13_parallel your_event.json 20 100 8Arguments:
your_event.json- Nostr event JSON file20- Difficulty target (leading zero bits)100- Maximum attempts in millions8- Number of threads (parallel version only, optional)
Apple M1 (single-threaded):
- Difficulty 8: ~0.7 MH/s (found in milliseconds)
- Difficulty 16: ~1.1 MH/s (found in ~70ms)
- Difficulty 20: ~1-2 MH/s (typically 10-60 seconds)
14-core system comparison:
Single-threaded: 0.68 MH/s, 189 solutions/sec
Parallel: 2.76 MH/s, 602 solutions/sec
Improvement: 4.0x MH/s, 3.2x solutions/sec
Threading Performance:
- 1 thread: 0.68 MH/s baseline
- 4 threads: 2.14 MH/s (3.1x improvement)
- 8 threads: 2.83 MH/s (4.2x improvement)
- 14 threads: 2.76 MH/s (4.0x improvement)
Performance scales well with CPU optimization flags (-march=native -mtune=native) and available cores.
The miner follows NIP-13 specification:
- Nonce Injection: Adds
["nonce", "12345"]tag to event - Hash Calculation: SHA256 of serialized event JSON
- Difficulty Check: Counts leading zero bits in hash
- Valid Proof: Hash has β₯ target leading zero bits
Input Event:
{
"id": "",
"pubkey": "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245",
"created_at": 1673347337,
"kind": 1,
"tags": [],
"content": "Testing NIP-13 proof of work",
"sig": ""
}Output with Nonce:
{
"id": "",
"pubkey": "32e1827635450ebb3c5a7d12c1f8e7b2b514439ac10a67eef3d9fd9c5c68e245",
"created_at": 1673347337,
"kind": 1,
"tags": [["nonce", "73062"]],
"content": "Testing NIP-13 proof of work",
"sig": ""
}make -f Makefile.standalonemake -f Makefile.standalone CFLAGS="-Wall -Wextra -O0 -g -std=c99"make -f Makefile.standalone CFLAGS="-Wall -Wextra -O3 -std=c99 -march=native -mtune=native -flto"Single-threaded:
./nip13_miner event.json 16Mines with difficulty 16, up to 100M attempts.
Parallel (3-4x faster):
./nip13_parallel event.json 16
# Or specify thread count
./nip13_parallel event.json 16 100 8The parallel miner includes realistic benchmarking with unique timestamps:
# Find 5 solutions at difficulty 16 and measure solutions/sec
./nip13_parallel event.json 16 benchmark 5
# Find 10 solutions at difficulty 18 with 8 threads
./nip13_parallel event.json 18 benchmark 10 8
# Quick performance test (3 solutions at difficulty 12)
./nip13_parallel event.json 12 benchmark 3The parallel miner automatically increments the event timestamp for each solution found, ensuring:
- Unique search spaces: Each solution search uses a different event hash
- Realistic performance: No skewing from finding identical nonces repeatedly
- True capability measurement: Benchmarks reflect actual mining performance
# OLD behavior: Would find same nonces (714996, 714996, 714996...)
# NEW behavior: Finds different nonces (714996, 42318, 987321...)# Legacy benchmark mode (single-threaded)
./nip13_miner event.json 16 benchmark 5
# High difficulty
./nip13_miner event.json 24 500
# Quick test
./nip13_miner event.json 8 5Benchmark mode provides:
- Solutions per second measurement
- Hash rate in MH/s
- Real-time performance tracking
- Average attempts per solution
- Total time and attempt statistics
Single-threaded:
./nip13_miner <event.json> [difficulty] [max_attempts|benchmark N]
Parallel:
./nip13_parallel <event.json> [difficulty] [max_attempts|benchmark N] [threads]
Arguments:
event.json- Nostr event JSON file to minedifficulty- Target difficulty in bits (default: 16)max_attempts- Maximum attempts in millions (default: 100)benchmark N- Find N solutions and measure solutions/secthreads- Number of threads (parallel only, default: CPU cores)
# Install both miners system-wide
make install
# This installs:
# /usr/local/bin/nip13_miner (single-threaded)
# /usr/local/bin/nip13_parallel (parallel)# Single-threaded benchmarks
make benchmark
# Parallel benchmarks (much faster!)
make benchmark-parallel
# Compare both versions
./parallel_demo.sh# Test different thread counts
./nip13_parallel event.json 16 benchmark 5 1 # 1 thread
./nip13_parallel event.json 16 benchmark 5 4 # 4 threads
./nip13_parallel event.json 16 benchmark 5 8 # 8 threads
./nip13_parallel event.json 16 benchmark 5 # All cores
# Thread scaling demo
./thread_scaling_demo.shmake cleanThe miner uses several optimizations from hashcat:
- Optimized SHA256 Constants: Pre-computed K values
- Efficient Bit Rotation: Hardware-optimized ROTR operations
- Loop Unrolling: Reduced branching in SHA256 rounds
- Native CPU Instructions:
-march=nativeenables SIMD - Fast Memory Access: Aligned data structures
Expected Performance:
- Low-end CPU: 0.5-1.0 MH/s
- Mid-range CPU: 1.0-2.0 MH/s
- High-end CPU: 2.0-5.0 MH/s
The implementation includes:
- Standard SHA256 constants and initialization vectors
- Optimized message scheduling with s0/s1 functions
- Efficient CH/MAJ/S0/S1 bit operations
- Proper padding and length encoding
- JSON Parsing: Simple string manipulation for nonce injection
- Hash Calculation: Direct SHA256 of modified JSON string
- Leading Zero Count: Bit-level analysis of hash output
- Nonce Management: 64-bit nonce space with overflow handling
The parallel implementation uses a simple but effective approach:
- Thread Pool: Creates one thread per CPU core (configurable)
- Work Distribution: Divides the nonce search space equally among threads
- Early Termination: When any thread finds a solution, all threads stop
- Thread Safety: Uses mutex synchronization for solution detection
Thread 0: searches nonces 0 to N/cores
Thread 1: searches nonces N/cores to 2*N/cores
Thread 2: searches nonces 2*N/cores to 3*N/cores
...
Thread n: searches remaining nonces
When a thread finds a valid proof-of-work, it:
- Sets a global flag to stop other threads
- Records the solution nonce
- All threads exit gracefully
The parallel miner includes timestamp incrementing for accurate benchmarks:
// Increments event timestamp by 1 second for each solution
char* increment_timestamp_in_json(const char* json_str, int increment_seconds)This ensures each solution search uses a unique event hash, preventing skewed results from finding identical solutions repeatedly.
But you're really here for:
export GEO=9q; echo '{"content":"pow pow powerbot, pow pow powerbot, powerbot! pow 21!"}' | nak event -k 20000 --tag g=$GEO --tag n=powbot | ./nip13_miner 21 | nak event $(./geohash_relay_finder -q $GEO relays.csv)
This miner demonstrates how to effectively leverage existing cryptographic libraries (like hashcat) for specialized applications. The standalone design makes it easy to understand and modify.
Key Design Principles:
- Zero Dependencies: Pure C implementation
- High Performance: Optimized algorithms from hashcat
- NIP-13 Compliant: Full specification adherence
- Cross-Platform: Standard C99 compatibility
This project extracts and adapts SHA256 primitives from hashcat for NIP-13 mining. The hashcat project is licensed under the MIT License.
- hashcat team: For the optimized SHA256 implementation
- Nostr community: For the NIP-13 specification
- Bitcoin developers: For SHA256 security research
Built with β€οΈ for the Nostr ecosystem