Доказательство работы и майнинг
Майнинг звучит загадочно, но в основе — простая головоломка: подобрать число так, чтобы хеш блока начинался с нескольких нулей. Сейчас сами «помайним».
Зачем вообще что-то «майнить»
В блокчейне без банка нужен способ решить, кто добавит следующий блок, и сделать подделку дорогой. Доказательство работы (proof-of-work) требует потратить вычислительные усилия: найти решение трудно, а проверить — легко. Это как судоку: решать долго, проверить мгновенно.
Головоломка с нулями
Хеш данных выглядит случайно. Майнер добавляет к блоку число nonce и хеширует снова и снова, перебирая nonce, пока хеш не начнётся, скажем, с трёх нулей. Угадать заранее нельзя — только перебор.
import hashlib
def block_hash(data, nonce):
return hashlib.sha256(f"{data}|{nonce}".encode()).hexdigest()
data = "Блок №7: Аня -> Боре 5 монет"
# Покажем, как хеш скачет при разных nonce
for nonce in range(5):
print(f"nonce={nonce}: {block_hash(data, nonce)}")
print("Хеш непредсказуем — нельзя угадать нужный nonce, только перебирать")
Майнинг-демо: ищем хеш с нулями
Сложность задаётся числом ведущих нулей. Чем больше нулей — тем дольше поиск.
import hashlib, time
def mine(data, difficulty):
target = "0" * difficulty
nonce = 0
start = time.time()
while True:
h = hashlib.sha256(f"{data}|{nonce}".encode()).hexdigest()
if h.startswith(target):
elapsed = time.time() - start
return nonce, h, elapsed
nonce += 1
data = "Блок №7: Аня -> Боре 5 монет"
for difficulty in (1, 2, 3, 4):
nonce, h, t = mine(data, difficulty)
print(f"{difficulty} нуля: nonce={nonce:<7} hash={h[:16]}... за {t:.3f} сек")
Видно, как с каждым нулём поиск резко удлиняется. В сети Bitcoin нулей нужно гораздо больше, и над задачей трудятся миллионы устройств.
Проверить — мгновенно
import hashlib
data = "Блок №7: Аня -> Боре 5 монет"
nonce = 0
while True:
h = hashlib.sha256(f"{data}|{nonce}".encode()).hexdigest()
if h.startswith("000"):
break
nonce += 1
print("Майнер нашёл nonce:", nonce)
# Любой проверяет ОДНИМ хешем:
check = hashlib.sha256(f"{data}|{nonce}".encode()).hexdigest()
print("Проверка хеша:", check[:16], "...")
print("Начинается с 000?", check.startswith("000"))
Зачем это нужно
Чтобы переписать старый блок, жулику пришлось бы заново «прорешать» головоломки для него и всех последующих блоков, обгоняя при этом всю остальную сеть. Это требует колоссальных ресурсов — поэтому подделка экономически бессмысленна. Так proof-of-work защищает блокчейн. Главный минус — огромный расход энергии, из-за чего появились другие подходы (например, proof-of-stake).
Вывод:
Proof-of-work — головоломка: перебором nonce найти хеш блока с нужным числом ведущих нулей. Решать трудно (нужно много вычислений), проверять — один хеш. Это делает подделку прошлого слишком дорогой, но тратит много энергии.