Хеш-цепочка: почему историю нельзя переписать

Связь «каждый блок хранит хеш предыдущего» превращает цепочку в карточный домик: тронешь одну карту — посыплется всё после неё.

«Подделать один блок легко. Подделать блок так, чтобы сошлась вся цепь после него — вот где начинается настоящая защита.»

Пришло время собрать главную идею блокчейна своими руками. Мы возьмём несколько блоков и свяжем их в хеш-цепочку. Правило простое: в каждый блок записываем хеш предыдущего. Первый блок (его называют генезис-блоком) ссылаться не на что, поэтому в его поле prev_hash ставят нули.

Как ломается подделка

Допустим, злоумышленник хочет изменить транзакцию в блоке номер 2. Он меняет данные — и хеш блока 2 меняется. Но блок 3 хранит старый хеш блока 2. Ссылка не сходится, и любой узел сразу видит подделку. Чтобы скрыть следы, придётся пересчитать блок 3, потом блок 4, и так до самого конца цепи — а сеть тем временем уже ушла вперёд.

Как работает под капотом

   Хеш-цепочка блоков

   [ Блок 1 ]      [ Блок 2 ]      [ Блок 3 ]
   prev: 0000      prev: H1   -->  prev: H2
   data: ...       data: ...       data: ...
   hash: H1   -->  hash: H2   -->  hash: H3

   Меняем data в Блоке 2  =>  H2 меняется
   => ссылка 'prev: H2' в Блоке 3 ломается!

Соберём настоящую мини-цепочку из трёх блоков и убедимся, что подмена данных рвёт связь.

Попробуй сам ▶ Запусти код прямо здесь — он работает в браузере:

import hashlib

def h(prev, data):
    return hashlib.sha256((prev + data).encode()).hexdigest()

# Строим цепь: каждый блок хранит хеш предыдущего
b1 = {'data': 'genesis',       'prev': '0' * 8}
b1['hash'] = h(b1['prev'], b1['data'])

b2 = {'data': 'Аня -> Боря 5', 'prev': b1['hash']}
b2['hash'] = h(b2['prev'], b2['data'])

b3 = {'data': 'Боря -> Вася 2', 'prev': b2['hash']}
b3['hash'] = h(b3['prev'], b3['data'])

chain = [b1, b2, b3]
for i, b in enumerate(chain):
    print(i, b['data'][:14].ljust(14), 'hash:', b['hash'][:12])

# Атака: меняем данные во 2-м блоке
print('\n--- подделка во 2-м блоке ---')
chain[1]['data'] = 'Аня -> Боря 500'
new2 = h(chain[1]['prev'], chain[1]['data'])
print('новый хеш блока 2:', new2[:12])
print('а блок 3 ждёт prev =', chain[2]['prev'][:12])
print('совпадает?', new2 == chain[2]['prev'])

Ответ — нет. Хеш блока 2 изменился, а блок 3 всё ещё ссылается на старый. Связь порвана, подделка видна невооружённым глазом.

Частые заблуждения

  • «Можно подменить один блок незаметно». Нельзя: придётся пересчитать все блоки после него, и сеть это заметит.
  • «Цепочка защищает данные сама по себе». Защищает связь, но добавлять блоки в публичный блокчейн мешает ещё и консенсус (следующий раздел) — без него подделать было бы проще.
  • «Генезис-блок ссылается на банк или сервер». Нет, у первого блока поле prev — это просто нули, ему не на что ссылаться.

Важно понимать (риски)

Хеш-цепочка сама по себе не делает блокчейн неприступным. В нашем примере любой мог бы пересчитать все блоки за миллисекунды. На реальных сетях пересчёт защищён дорогой работой (proof-of-work) или экономическими ставками (proof-of-stake) — об этом следующий раздел. Без этого «груза» хеш-цепочка остаётся лишь умной структурой данных, но не крепостью.

Разбор: что увидел бы узел при подделке

Давай мысленно встанем на место честного узла, которому злоумышленник прислал подделанную цепочку. Узел не верит на слово — он пересчитывает хеши сам. Он берёт первый блок, считает его хеш и сверяет с тем, что записано в поле prev_hash второго блока. Дальше — то же со вторым и третьим. Если хоть на одном стыке хеши не сходятся, узел понимает: цепочку трогали, и отвергает её целиком.

Именно поэтому злоумышленнику недостаточно поправить один блок. Чтобы подделка прошла проверку, ему пришлось бы пересчитать испорченный блок и аккуратно переписать prev_hash во всех последующих блоках, восстановив всю цепочку хешей. В нашем учебном примере это секундное дело. Но в реальной сети каждый блок ещё и «запечатан» дорогой работой майнеров или ставками валидаторов — и вот тогда пересчёт сразу всех блоков становится практически неподъёмным. Хеш-цепочка делает подделку заметной, а консенсус делает её дорогой. Вместе они и дают неизменяемость.

Итоги

  • Каждый блок хранит хеш предыдущего — это и есть «цепь».
  • Изменение одного блока ломает ссылки во всех последующих.
  • Первый блок (генезис) ни на что не ссылается.
  • Сама цепочка — это структура; неприступной её делает консенсус.
Проверьте себя
1. Что произойдёт, если изменить данные в середине хеш-цепочки?
AНичего, остальные блоки не затронуты
BСломаются ссылки во всех последующих блоках
CИзменится только первый блок
DЦепочка станет короче
2. На что ссылается генезис-блок?
AНа банковский сервер
BНа последний блок цепи
CНи на что — его поле prev заполнено нулями
DНа корень Меркла