Рабочее имя проекта. Финальное название не выбрано — кандидаты см. в конце файла.
Минимальный, но настоящий соло-майнер биткоина: подключается к публичному соло-пулу, реализует протокол Stratum V1 с нуля, перебирает SHA-256 в чистом Python и отправляет шары. Без зависимостей.
Цель проекта — разобраться, как работает Bitcoin mining изнутри: protocol, block header, merkle tree, target, double-SHA-256. Это не способ заработать (см. раздел «Реалистичные ожидания»), а образовательный код, который можно пощупать руками и развивать дальше.
- TCP-клиент к
solo.ckpool.org:3333через стандартнуюsocket - JSON-RPC поверх Stratum V1
-
mining.subscribe— получениеextranonce1иextranonce2_size -
mining.authorize— аутентификация под BTC-адресом - Обработка
mining.set_difficulty(динамическая сложность пула) - Обработка
mining.notify(получение свежей работы) - Сборка coinbase-транзакции (
coinb1 + extranonce1 + extranonce2 + coinb2) - Вычисление merkle root через ветки от пула
- Корректная сборка 80-байтного block header (с правильным word-swap для prevhash)
- Цикл перебора
nonce0…2³² с double-SHA-256 - Сравнение хеша с pool target → отправка
mining.submitпри попадании - Фоновая нить чтения сообщений от пула, защита
current_jobчерезLock - Прерывание цикла при получении свежей работы (clean job)
- Печать хешрейта раз в 5 секунд
Уровень 0 — стабилизация: завершён.
- Reconnect с экспоненциальным backoff (1→2→4→…→60с)
- Обработка
mining.set_extranonce - Корректное завершение по Ctrl+C (общий
stop_event,client.close(),join) -
loggingвместоprintсо стандартными уровнями - 15 юнит-тестов на криптографические функции (
unittest) -
src/-layout, пакетhope_hash,pyproject.toml(hatchling) - CI matrix Python 3.11/3.12/3.13 × ubuntu/windows/macos
- Конфиг через CLI/YAML — перенесено в Уровень 1
Уровень 1 — производительность и наблюдаемость: завершён.
- Multiprocessing: N воркеров (default
cpu_count - 1), флаг--workers - EMA-хешрейт (alpha=0.3, окно 5с)
- SQLite-журнал шаров и сессий (
storage.py, флаг--db) - Prometheus-метрики на
/metrics(metrics.py, флаг--metrics-port) - Telegram-уведомления (через stdlib urllib, env-конфиг)
- TUI на
rich/curses— отложено (зависимости либо ограниченная Win-поддержка) - Команды Telegram-бота (
/stats,/restart) — отложено
Уровень 1.5 — глубокий аудит и UX (v0.3.0):
- Mid-state SHA-256 (
hashlib.sha256().copy()после первых 64 байт) — ≈×1.5–2 хешрейт -
mining.suggest_difficulty+ CLI флаг--suggest-diff(vardiff) - Demo-режим:
--demo [--demo-diff]— offline-майнинг без подключения к пулу - Pre-flight валидация BTC-адреса (bech32/bech32m/Base58Check, mainnet only)
- Prometheus метрики
hopehash_shares_accepted_total/_rejected_total - Запись шара в SQLite фиксируется только после подтверждения пула (
on_share_resultколбэк) -
mining.authorizeответ верифицируется (раньше отказ авторизации игнорировался) -
time.perf_counter()вместоtime.time()для всех относительных интервалов -
except queue.Emptyвместо bareexcept Exceptionв горячих циклах
Не сделано / известные ограничения:
- Нет UI — только консоль через
loggingи/metricsчерез HTTP. - Только Stratum V1, без Stratum V2.
- C/Rust/SIMD/GPU — Уровни 2–3, ещё впереди.
.
├── README.md ← этот файл
├── ROADMAP.md ← план развития, расставленный по сложности
├── CHANGELOG.md ← история версий (Keep a Changelog)
├── CLAUDE.md ← правила для AI-ассистента
├── LICENSE ← MIT
├── pyproject.toml ← метаданные + hatchling backend
├── Makefile ← short-cuts: install / test / run / lint
├── .github/workflows/ci.yml ← matrix Python 3.11–3.13 × ubuntu/windows/macos
├── src/hope_hash/
│ ├── __init__.py ← публичный API + __version__
│ ├── __main__.py ← `python -m hope_hash`
│ ├── cli.py ← argparse, точка входа, инициализация observers
│ ├── miner.py ← mine() оркестратор + supervisor_loop
│ ├── parallel.py ← multiprocessing воркеры nonce-loop
│ ├── stratum.py ← StratumClient (TCP + JSON-RPC)
│ ├── block.py ← double_sha256, swap_words, target, merkle
│ ├── address.py ← валидация BTC-адресов (bech32/bech32m/Base58Check)
│ ├── demo.py ← offline-майнинг (--demo)
│ ├── bench.py ← бенчмарк хешрейта (--benchmark)
│ ├── storage.py ← SQLite журнал шаров и сессий
│ ├── metrics.py ← Prometheus экспортёр (http.server)
│ ├── notifier.py ← Telegram через urllib
│ ├── _logging.py ← настройка logger("hope_hash")
│ └── py.typed ← PEP 561 marker
└── tests/
├── conftest.py ← общие фикстуры (заготовка)
├── test_block.py ← 22 теста на чистые функции + mid-state
├── test_storage.py ← 11 тестов на SQLite журнал
├── test_metrics.py ← 16 тестов на Prometheus экспортёр
├── test_notifier.py ← 16 тестов на Telegram (через mock)
├── test_address.py ← 18 тестов на валидацию BTC-адреса
├── test_stratum.py ← 15 тестов на Stratum-протокол (FakeSocket)
└── test_bench.py ← 3 теста на бенчмарк-режим
Никаких runtime-зависимостей, нужен только Python ≥3.11.
# Установка один раз (editable):
python -m pip install -e .
# Запуск любым из способов:
hope-hash <BTC_адрес> [имя_воркера]
python -m hope_hash <BTC_адрес> [имя_воркера]Пример:
hope-hash bc1q5n2x4pvxhq8sxc7ck3uxq8sxc7ck3uxqzfm2py mylaptopРасширенные опции:
hope-hash <BTC_адрес> mylaptop \
--workers 8 \ # число процессов (default: cpu_count - 1)
--db ./shares.db \ # путь к SQLite (default: hope_hash.db)
--metrics-port 9090 \ # Prometheus /metrics (0 — отключить)
--suggest-diff 0.001 # vardiff: запросить у пула низкую сложностьDemo-режим (без подключения к пулу):
hope-hash --demo # синтетический заголовок, низкая сложность
hope-hash --demo --demo-diff 0.0001 # ещё ниже — найдёт быстрее
hope-hash --demo --workers 4 # сколько процессов перебирают nonceDemo не нуждается в BTC-адресе и не делает никаких сетевых вызовов — удобно для smoke-теста на машине, где нужно убедиться, что multiprocessing-воркеры стартуют корректно.
Бенчмарк-режим:
hope-hash --benchmark # 10 секунд на cpu_count-1 воркерах
hope-hash --benchmark --bench-duration 30 # длиннее = точнее число
hope-hash --benchmark --workers 1 # baseline для одного ядраМеряет pure-Python хешрейт без сети и без шар. Полезно как точка отсчёта перед C/Rust/SIMD-оптимизациями (см. ROADMAP уровни 2–3): без числа «до» сравнивать числа «после» бессмысленно. Пример вывода на Intel i7-12700H, 4 воркера, 5 секунд:
[bench] platform: Windows-10-10.0.26200-SP0
[bench] python: 3.11.9 (cpython)
[bench] cpu: 16 logical cores (Intel Family 6 Model 151)
[bench] workers: 4, duration: 5.0s
[bench] t= 1.0s hashes= 2,654,208 rate=2.64 MH/s
[bench] t= 2.0s hashes= 5,914,624 rate=2.93 MH/s
[bench] t= 3.0s hashes= 9,093,120 rate=3.01 MH/s
[bench] === result ===
[bench] total hashes: 11,436,032
[bench] wall time: 5.01s
[bench] hashrate: 2.28 MH/s
[bench] per-worker: 570.23 KH/s (workers: 4)
Валидация BTC-адреса срабатывает локально перед подключением к пулу. Принимаются только mainnet-адреса:
bc1q...(P2WPKH, P2WSH) — bech32, BIP-173bc1p...(Taproot) — bech32m, BIP-3501...(P2PKH),3...(P2SH) — Base58Check
Неверная контрольная сумма, смешанный регистр, testnet-префикс — отвергаются с конкретным сообщением, без сетевого round-trip.
Telegram-уведомления (опционально): задать env vars и просто запустить:
export HOPE_HASH_TELEGRAM_TOKEN=123456:abcdef-your-bot-token
export HOPE_HASH_TELEGRAM_CHAT_ID=123456789
hope-hash <BTC_адрес>Тесты:
python -m unittest discover -s tests -v # 101 тестPrometheus-метрики, экспортируемые на /metrics:
| Метрика | Тип | Описание |
|---|---|---|
hopehash_hashrate_hps |
gauge | EMA-хешрейт в H/s |
hopehash_pool_difficulty |
gauge | текущая сложность от пула |
hopehash_workers |
gauge | число активных воркеров |
hopehash_uptime_seconds |
gauge | время работы майнера |
hopehash_shares_total |
counter | всего отправленных шаров |
hopehash_shares_accepted_total |
counter | подтверждённых пулом |
hopehash_shares_rejected_total |
counter | отклонённых пулом |
BTC-адрес нужен валидный mainnet-адрес (1..., 3..., bc1q..., bc1p...). Можно завести в любом некастодиальном кошельке — например, Sparrow, Electrum, Wasabi. Имя воркера — произвольная строка.
Что увидишь:
[net] подключён к solo.ckpool.org:3333
[stratum] subscribed: extranonce1=ab12cd34, en2_size=4
[stratum] authorize отправлен для воркера bc1q....mylaptop
[stratum] новая сложность: 1.0
[stratum] новая работа job_id=4f2 clean=true
[stats] хешрейт ≈ 87 KH/s | pool diff = 1.0
[stratum] *** ШАР ПРИНЯТ *** (id=3)
...
*** ШАР ПРИНЯТ *** означает, что ты честно работаешь и пул это видит — это не заработок. Реальная награда наступит только при НАЙДЕН ШАР с хешем ниже сетевого target (не пулового), что соответствует найденному блоку.
┌───────────────────────────────────────────┐
│ solo.ckpool.org:3333 │
└─────────────────┬─────────────────────────┘
│ TCP + JSON line-delimited
│
┌─────────────────▼─────────────────────────┐
│ StratumClient (main thread) │
│ • subscribe / authorize │
│ • держит current_job под Lock │
└──────┬──────────────────────────┬─────────┘
│ │
│ читает входящие │ держит работу
▼ ▼
┌─────────────┐ ┌─────────────────┐
│ reader_loop │ │ mine() loop │
│ (thread) │ │ (main thread) │
│ │ │ │
│ обновляет │ │ 1. coinbase │
│ current_job │ │ 2. merkle root │
│ при notify │ │ 3. header base │
└─────────────┘ │ 4. nonce++ │
│ 5. SHA256d │
│ 6. compare │
│ vs target │
│ 7. submit ─────┼──> через client
└─────────────────┘
Один процесс, две нити: одна крутит хеши, вторая слушает пул. Свежий mining.notify обновляет current_job под локом, цикл хеширования каждые ~16k итераций проверяет, не сменился ли job_id — если да, выходит и берёт свежую работу.
| Метрика | Значение |
|---|---|
| Хешрейт (Python, 1 поток) | 50–200 KH/s |
| Хешрейт всей сети Bitcoin | ~700 EH/s = 7×10²⁰ H/s |
| Доля от сети | ~10⁻¹⁵ |
| Блоков в день | ~144 |
| Ожидание блока соло | ~10¹³ дней |
| Награда при удаче | 3.125 BTC (~$200k) |
Это лотерея с космически низкими шансами. Соло-майнинг на CPU имеет смысл только как:
- Учебный проект (понять протокол на пальцах).
- Лотерейный билет (формально шанс не ноль).
- База для оптимизации (можно сравнивать с C/CUDA-версиями).
Случаи, когда подобные мини-майнеры находили блок за всю историю — единичные, и каждый раз это был громкий новостной повод.
Финальное имя проекта не выбрано. Шорт-лист, на котором остановились:
Серьёзные:
- pyrite — пирит, «золото дураков», + отсылка к Python (py-)
- Sisyphus — Сизиф, вечно катит хеш в гору
Самоироничные:
- CopiumMiner —
copium(мем-вещество, чтобы примириться с реальностью) - statisticallynever — про реальный шанс
- HopeHash — короткое и грустное
Технические:
- PicoMiner / NanoNonce — про размер
- bitfly — битовая муха
Перед выбором проверить:
- занятость на GitHub:
https://github.com/<name> - занятость на PyPI:
pip show <name> - свободный домен:
<name>.dev/<name>.io
См. ROADMAP.md — план развития, разбитый на лёгкое / среднее / сложное и сгруппированный по фичам.