Цепочка блоков: как хеши делают историю неизменяемой
Слово «блокчейн» звучит сложно, но в основе лежит одна простая идея: связать блоки данных хешами так, чтобы подделать прошлое стало невозможно незаметно.
Напоминание про хеш
Хеш (SHA-256) — это «отпечаток» данных: фиксированная строка, которая полностью меняется при малейшем изменении входа. По хешу нельзя восстановить данные, но можно проверить, что данные не трогали.
import hashlib
def h(s):
return hashlib.sha256(s.encode()).hexdigest()
print("hash('Аня шлёт 5'):", h("Аня шлёт 5")[:24], "...")
print("hash('Аня шлёт 6'):", h("Аня шлёт 6")[:24], "...")
print("Одна цифра — совершенно другой хеш!")
Идея цепочки
Каждый блок хранит свои данные и хеш предыдущего блока. Получается цепь: блок 2 ссылается на блок 1, блок 3 — на блок 2 и так далее. Если кто-то изменит старый блок, его хеш поменяется, и ссылка в следующем блоке перестанет совпадать — подделка сразу видна.
Собираем мини-блокчейн
import hashlib
def block_hash(index, data, prev_hash):
body = f"{index}|{data}|{prev_hash}"
return hashlib.sha256(body.encode()).hexdigest()
# Строим цепочку из 3 блоков
chain = []
prev = "0" * 64 # генезис-блок ссылается в никуда
for i, data in enumerate(["Аня -> Боре: 5", "Боря -> Вите: 2", "Витя -> Ане: 1"]):
hsh = block_hash(i, data, prev)
chain.append({"index": i, "data": data, "prev": prev, "hash": hsh})
prev = hsh
for b in chain:
print(f"Блок {b['index']}: {b['data']}")
print(f" prev: {b['prev'][:16]}...")
print(f" hash: {b['hash'][:16]}...")
Проверка целостности
Теперь попробуем подделать средний блок и увидим, как цепь «рвётся»:
import hashlib
def block_hash(index, data, prev_hash):
return hashlib.sha256(f"{index}|{data}|{prev_hash}".encode()).hexdigest()
def build(datas):
chain, prev = [], "0" * 64
for i, d in enumerate(datas):
hsh = block_hash(i, d, prev)
chain.append({"index": i, "data": d, "prev": prev, "hash": hsh})
prev = hsh
return chain
def is_valid(chain):
for i in range(1, len(chain)):
recomputed = block_hash(chain[i]["index"], chain[i]["data"], chain[i]["prev"])
if chain[i]["hash"] != recomputed:
return False, i
if chain[i]["prev"] != chain[i-1]["hash"]:
return False, i
return True, None
chain = build(["Аня -> Боре: 5", "Боря -> Вите: 2", "Витя -> Ане: 1"])
print("Цепочка цела?", is_valid(chain))
# Жулик меняет сумму во 2-м блоке
chain[1]["data"] = "Боря -> Вите: 9999"
ok, where = is_valid(chain)
print("После подделки цела?", ok, "| сломалось на блоке", where)
Почему это важно
Изменить один старый блок недостаточно — придётся пересчитать хеши всех последующих блоков. А в реальной сети тысячи компьютеров хранят копию цепочки и сверяют её. Подделать прошлое незаметно становится практически невозможно. Именно так хеши дают блокчейну неизменяемость.
Вывод:
Каждый блок хранит хеш предыдущего, образуя цепь. Изменение любого старого блока меняет его хеш и рвёт связь со следующим — подделка сразу заметна. Так SHA-256 делает историю блокчейна неизменяемой.