Skip to content
Learning Platform
Intermediate
30 minutes
Proof of History PoH SHA-256 VDF Криптографические часы

Prerequisites:

  • 05-solana/01-solana-architecture

Proof of History

Зачем это блокчейну?

Главная проблема распределенных систем — время. Когда два события происходят на разных узлах, как определить, какое было раньше? В Ethereum валидаторы обмениваются сообщениями для согласования порядка — это требует нескольких раундов коммуникации и стоит времени.

Solana решает эту проблему иначе: вместо того чтобы спрашивать остальных, который сейчас час, она создает криптографические часы — верифицируемое доказательство того, что время прошло.

Ключевое заблуждение: PoH — это НЕ механизм консенсуса. Это часы. Консенсус в Solana обеспечивает Tower BFT (следующий урок). PoH лишь дает валидаторам общую шкалу времени.

# Проблема: как доказать, что событие A произошло ДО события B?

# Ethereum:
# 1. Валидатор A: "Я видел tx_A в 14:00:01"
# 2. Валидатор B: "Я видел tx_B в 14:00:02"
# 3. Проблема: кто врет? Нужен консенсус о времени -> несколько раундов сообщений

# Solana (PoH):
# 1. hash_1000 = SHA-256(hash_999)
# 2. hash_1001 = SHA-256(hash_1000 || tx_A)  <- tx_A вмешана в хеш
# 3. hash_1002 = SHA-256(hash_1001)
# 4. hash_1003 = SHA-256(hash_1002 || tx_B)  <- tx_B вмешана позже
# Доказательство: tx_A определенно РАНЬШЕ tx_B (1001 < 1003)
# Никаких переговоров не нужно -- порядок криптографически доказан!

Интуитивное объяснение: аналогия с газетой

Представьте, что вам нужно доказать, что документ существовал до определенной даты. Классический трюк: сфотографируйтесь с сегодняшней газетой. Дата на газете доказывает, что фото не могло быть сделано раньше.

PoH работает так же, но вместо газеты — цепочка хешей:

  • Каждый хеш = “газета” с уникальной датой
  • Вычислить следующий хеш можно только имея предыдущий
  • Событие, вмешанное в хеш N, доказуемо произошло после N-1 и до N+1

Цепочка хешей: пошагово

PoH — это последовательная цепочка SHA-256 хешей. Каждый хеш вычисляется из предыдущего, создавая верифицируемую шкалу времени.

Proof of History: цепочка хешей
H(0)
1999900298f0023e
Шаг 1 из 6Начальное состояние. Seed-значение хешируется для создания H(0). Это первый элемент цепочки PoH.

Алгоритмический уровень

import hashlib

def sha256(data: bytes) -> bytes:
    return hashlib.sha256(data).digest()

class ProofOfHistory:
    def __init__(self, seed: bytes):
        self.current_hash = sha256(seed)
        self.counter = 0
        self.history = [(0, self.current_hash.hex(), None)]

    def tick(self):
        """Один тик часов -- чистый хеш без события"""
        self.current_hash = sha256(self.current_hash)
        self.counter += 1
        self.history.append((self.counter, self.current_hash.hex(), None))

    def record_event(self, event_data: bytes):
        """Записать событие в цепочку -- вмешать в хеш"""
        combined = self.current_hash + event_data
        self.current_hash = sha256(combined)
        self.counter += 1
        self.history.append((self.counter, self.current_hash.hex(), event_data))

    def verify(self, start_hash: bytes, entries: list) -> bool:
        """Верификация: воспроизвести цепочку и проверить хеши"""
        h = start_hash
        for entry in entries:
            if entry.event_data:
                h = sha256(h + entry.event_data)
            else:
                h = sha256(h)
            if h != entry.hash:
                return False
        return True

# Демонстрация:
poh = ProofOfHistory(b"solana-genesis")
poh.tick()                                        # H(1) = SHA-256(H(0))
poh.tick()                                        # H(2) = SHA-256(H(1))
poh.record_event(b"Transfer 5 SOL")               # H(3) = SHA-256(H(2) || event)
poh.tick()                                        # H(4) = SHA-256(H(3))
poh.record_event(b"Create Account")                # H(5) = SHA-256(H(4) || event)

for counter, hash_hex, event in poh.history:
    event_str = event.decode() if event else "-"
    print(f"  H({counter}): {hash_hex[:16]}... event={event_str}")

Формальное определение

PoH — это верифицируемая функция задержки (VDF) на основе SHA-256:

Определение: Последовательность хешей (h_0, h_1, ..., h_N) где:

h_0 = SHA-256(seed)
h_i = SHA-256(h_{i-1})                     -- тик (чистый хеш)
h_i = SHA-256(h_{i-1} || event_data)       -- запись события

Свойства:
1. Последовательность: h_i вычислим ТОЛЬКО из h_{i-1}
   (нельзя вычислить h_N, не вычислив все предыдущие)

2. Верифицируемость: любой может проверить цепочку,
   повторив вычисления (и это можно делать параллельно!)

3. Временная метка: позиция события в цепочке однозначно
   определяет его порядок относительно других событий

Генерация vs верификация: ключевая асимметрия

Самое важное свойство PoH — это асимметрия между генерацией и верификацией:

  • Генерация: последовательная, один CPU, O(N) времени
  • Верификация: параллельная, K ядер, O(N/K) времени
PoH: генерация vs верификация
Генерация (последовательная)
1 ядро, N операций, O(N)
CPU
Core 1
H(0)
H(1)
H(2)
H(3)
H(4)
H(5)
H(6)
H(7)
Верификация (параллельная)
4 ядра, N/4 операций каждое, O(N/cores)
Core 1
проверяет
H(0)
H(2)
Core 2
проверяет
H(2)
H(4)
Core 3
проверяет
H(4)
H(6)
Core 4
проверяет
H(6)
H(8)
Ключевое свойствоЭта асимметрия делает PoH полезным: один лидер генерирует доказательство (последовательно, медленно), а все валидаторы верифицируют его быстро (параллельно, во много раз быстрее).

Почему верификация параллельна?

# Генерация (последовательная -- нельзя распараллелить):
h[0] = SHA-256(seed)
h[1] = SHA-256(h[0])   # нужен h[0]
h[2] = SHA-256(h[1])   # нужен h[1]
h[3] = SHA-256(h[2])   # нужен h[2]
...
# Каждый шаг зависит от предыдущего!

# Верификация (параллельная):
# У верификатора уже есть ВСЯ цепочка: h[0], h[1], ..., h[N]
# Он знает входы и выходы каждого шага

# Core 1 проверяет: SHA-256(h[0]) == h[1]? SHA-256(h[1]) == h[2]? ...
# Core 2 проверяет: SHA-256(h[100]) == h[101]? SHA-256(h[101]) == h[102]? ...
# Core 3 проверяет: SHA-256(h[200]) == h[201]? ...
# Core 4 проверяет: SHA-256(h[300]) == h[301]? ...

# 4 ядра => 4x быстрее! GPU с 4000 ядрами => ...

# Аналогия: написать книгу нужно последовательно (слово за словом),
# но проверить орфографию могут 10 корректоров параллельно,
# каждый проверяет свою главу

Математический уровень

Теорема (асимметрия PoH):
  Пусть f = SHA-256 (прообраз-стойкая хеш-функция)
  Генерация цепочки длины N: T_gen = N * t_hash (последовательно)
  Верификация цепочки длины N на K ядрах: T_ver = (N/K) * t_hash

  Ускорение: T_gen / T_ver = K

  Это работает потому, что:
  - Генерация: h_i зависит от h_{i-1} (цепная зависимость)
  - Верификация: проверка h_i = f(h_{i-1}) не зависит от
    проверки h_j = f(h_{j-1}) для j != i (при известных h)

PoH в контексте Solana

Как лидер использует PoH

В каждый момент один валидатор является лидером (мы разберем расписание лидеров в SOL-03). Лидер непрерывно генерирует PoH-хеши:

# Упрощенный цикл лидера:
while is_leader(current_slot):
    # 1. Генерировать тики (доказательство времени)
    poh.tick()

    # 2. Если есть транзакции -- вмешать их в цепочку
    if pending_transactions:
        tx = pending_transactions.pop()
        poh.record_event(tx.serialize())
        # Теперь tx имеет криптографическую временную метку

    # 3. После набора тиков -- сформировать entry
    if poh.counter % ticks_per_entry == 0:
        entry = create_entry(poh.current_hash, poh.counter, transactions)
        broadcast_via_turbine(entry)

# Скорость: ~400,000 хешей/секунду на одном ядре
# Это дает ~400,000 "тиков" часов в секунду

PoH vs другие подходы к времени

ПодходКак работаетПреимуществаНедостатки
NTP (Network Time Protocol)Синхронизация часов через сетьПростотаНе криптографический, можно обмануть
Ethereum (slot time)Фиксированные 12-секундные слотыПредсказуемостьНет доказательства между слотами
Bitcoin (timestamps)Таймстемп в заголовке блокаПростотаНеточный (допустимое отклонение ~2 часа)
PoH (Solana)Криптографическая цепочка хешейВерифицируемый, точный, параллельная верификацияОдин ядро на генерацию, CPU-интенсивный

Ограничения PoH

PoH — мощный инструмент, но у него есть ограничения:

  1. Не заменяет консенсус. PoH доказывает порядок, но не то, что порядок “правильный”. Для этого нужен Tower BFT.
  2. Зависит от скорости CPU. Если у атакующего CPU в 2x быстрее, он может генерировать PoH-цепочку в 2x быстрее. Однако SHA-256 — это хорошо изученная функция, и разница в скорости между процессорами невелика.
  3. Один поток. PoH генерируется на одном ядре CPU. Это создает потенциальное узкое место, хотя на практике скорость SHA-256 достаточна.

Alpenglow: что придет после PoH?

Alpenglow — планируемый протокол, который заменит PoH + Tower BFT новым механизмом с целевой финальностью ~100-150ms. Важно: программы, аккаунты и Anchor-разработка не затрагиваются — меняется только консенсусный слой.

Связь с криптографией

Криптографическая основаПрименение в PoHУроки
SHA-256Основа цепочки хешейCRYPTO-05, CRYPTO-06
Прообраз-стойкостьНельзя вычислить h_{i-1} из h_i — гарантия последовательностиCRYPTO-05
VDF (Verifiable Delay Function)PoH — это VDF с параллельной верификацией
# Связь PoH с хеш-функциями из модуля 1:
# PoH эксплуатирует ТРИ свойства SHA-256:

# 1. Прообраз-стойкость: нельзя найти x из H(x)
#    => нельзя "перескочить" шаги в цепочке

# 2. Лавинный эффект: малое изменение входа -> кардинальное изменение выхода
#    => вмешанное событие полностью меняет все последующие хеши

# 3. Детерминизм: один вход -> один выход
#    => верификация дает тот же результат, что и генерация

Практика

# Упражнение: реализуйте мини-PoH и измерьте производительность

import hashlib
import time

def mini_poh(seed: bytes, n_hashes: int) -> list:
    """Генерация мини-PoH цепочки"""
    chain = [hashlib.sha256(seed).digest()]
    for _ in range(n_hashes):
        chain.append(hashlib.sha256(chain[-1]).digest())
    return chain

def verify_poh(chain: list) -> bool:
    """Верификация PoH цепочки"""
    for i in range(1, len(chain)):
        if hashlib.sha256(chain[i-1]).digest() != chain[i]:
            return False
    return True

# Замер:
start = time.time()
chain = mini_poh(b"test-seed", 100_000)
gen_time = time.time() - start

start = time.time()
assert verify_poh(chain)
ver_time = time.time() - start

print(f"Generation: {gen_time:.3f}s (100K hashes)")
print(f"Verification: {ver_time:.3f}s (sequential)")
print(f"With 4 cores: ~{ver_time/4:.3f}s (parallel)")

Что дальше?

В следующем уроке мы разберем Tower BFT — механизм консенсуса Solana, который использует PoH как часы. Вы увидите, как голоса валидаторов формируют “башню” с экспоненциально растущим lockout, и почему это обеспечивает быструю финализацию.

Finished the lesson?

Mark it as complete to track your progress