Prerequisites:
- 04-bitcoin-script
Типы транзакций Bitcoin
Зачем это нужно в блокчейне
За 15 лет Bitcoin прошел путь от простых P2PKH-транзакций до Taproot, где все выходы выглядят одинаково независимо от сложности условий траты. Каждый шаг решал конкретную проблему:
- P2SH — сложные скрипты (мультиподпись)
- SegWit — масштабирование и fix malleability
- Taproot — приватность и гибкость
Понимание эволюции типов транзакций — это понимание того, как Bitcoin решает фундаментальные проблемы масштабируемости, приватности и программируемости без хард-форков.
P2PKH (Pay-to-Public-Key-Hash)
Оригинальный тип транзакций Bitcoin, используется с 2009 года.
scriptPubKey:
OP_DUP OP_HASH160 <pubKeyHash> OP_EQUALVERIFY OP_CHECKSIG
scriptSig:
<sig> <pubKey>
Характеристики:
- Адреса начинаются с
1(Base58Check) - Подробный разбор выполнения скрипта — в предыдущем уроке (BTC-04)
- Размер типичной транзакции (1-in, 2-out): ~226 bytes
- Подпись и публичный ключ находятся внутри scriptSig (часть txid)
Проблема malleability: Поскольку подпись входит в данные, которые хешируются для txid, третья сторона может незначительно изменить формат подписи (не меняя её валидность) и изменить txid транзакции до её подтверждения. Это делает невозможными зависимые цепочки неподтвержденных транзакций.
P2SH (Pay-to-Script-Hash)
BIP 16 (2012). Революционная идея: вместо полного скрипта в выходе, записываем только хеш скрипта.
scriptPubKey:
OP_HASH160 <scriptHash> OP_EQUAL
scriptSig:
<sig1> <sig2> ... <redeemScript>
Ключевое преимущество: Сложность скрипта переносится на сторону получателя. Отправитель видит только короткий хеш, независимо от того, насколько сложный скрипт стоит за ним.
Пример: 2-of-3 мультиподпись
redeemScript: OP_2 <pubKey1> <pubKey2> <pubKey3> OP_3 OP_CHECKMULTISIG
scriptPubKey: OP_HASH160 hash160(redeemScript) OP_EQUAL
- Адреса начинаются с
3(Base58Check) - Отправитель платит на короткий адрес
3..., не зная структуры мультиподписи - При трате получатель раскрывает полный redeemScript
SegWit v0: P2WPKH и P2WSH
BIP 141 (Segregated Witness, 2017). Фундаментальное обновление Bitcoin.
Что такое Segregated Witness
Segregated = отделенный. Witness = свидетельство (подпись).
SegWit перемещает подписи из основного тела транзакции в отдельное поле witness. Это решает:
- Transaction malleability — witness данные НЕ входят в txid
- Масштабирование — witness данные получают скидку на комиссию
- Безопасные цепочки транзакций — Lightning Network стал возможен
P2WPKH (Pay-to-Witness-Public-Key-Hash)
scriptPubKey: OP_0 <20-byte-hash>
witness: <sig> <pubKey>
- Адреса:
bc1q...(bech32) - scriptSig ПУСТ (всё в witness)
- Размер: ~143.5 vB (~37% экономии vs P2PKH)
P2WSH (Pay-to-Witness-Script-Hash)
scriptPubKey: OP_0 <32-byte-hash>
witness: <sig1> <sig2> ... <witnessScript>
- Адреса:
bc1q...(bech32, длиннее чем P2WPKH) - SegWit-версия P2SH для сложных скриптов
Формат SegWit-транзакции
Ключевое отличие SegWit — новые поля в формате транзакции. Нажимайте на поля, чтобы увидеть описание:
Сравнение форматов
Legacy: [version][inputs][outputs][locktime]
SegWit: [version][marker=0x00][flag=0x01][inputs][outputs][witness][locktime]
Marker byte (0x00) выглядит как “0 входов” для старых нод, поэтому они пропускают транзакцию. Новые ноды распознают 0x00 + 0x01 как SegWit-маркер и парсят witness данные.
Расчет веса транзакции
SegWit ввел новую метрику — weight units (WU) вместо простого подсчета байт. Пройдите все шаги расчета:
Формула
weight = non_witness_bytes * 4 + witness_bytes * 1
vB (virtual bytes) = weight / 4
Почему именно так?
- Legacy-транзакции: все байты “стоят” 4 WU -> vB = raw bytes (обратная совместимость)
- SegWit: witness данные “стоят” 1 WU -> скидка 75% на подписи
- Комиссия считается в sat/vB, поэтому SegWit дешевле
Примеры размеров (1 вход, 2 выхода)
| Тип | Bytes | WU | vB | Экономия |
|---|---|---|---|---|
| P2PKH | ~226 | ~904 | ~226 | — |
| P2WPKH | ~141 | ~574 | ~143.5 | ~37% |
| P2TR | ~154 | ~616 | ~154 | ~32% |
Эволюция типов транзакций
Сравнение всех пяти типов Bitcoin-транзакций:
Taproot (P2TR) — BIP 341/342
Активирован в ноябре 2021 года. Taproot объединяет преимущества всех предыдущих типов и добавляет приватность.
Tweaked Public Key
Центральная идея Taproot — tweaked public key:
Q = P + t * G
где:
- P — внутренний публичный ключ (internal key)
- t =
tagged_hash("TapTweak", P || script_root)— tweak - G — генератор кривой secp256k1
- Q — tweaked key (записывается в scriptPubKey)
scriptPubKey:
OP_1 <32-byte tweaked pubKey Q>
Два пути траты
Key path (основной):
- Подпись одной Schnorr-подписью:
<schnorr_sig> - Подпись создается tweaked приватным ключом
d + t - Со стороны наблюдателя выглядит как обычная одиночная подпись
- Это самый частый и самый дешевый способ траты
Script path (альтернативный):
- Раскрытие скрипта через Merkle proof:
<script> <control_block> - Control block содержит: внутренний ключ P + Merkle proof до script_root
- Позволяет создать дерево из множества скриптов (MAST — Merkelized Abstract Syntax Trees)
Приватность Taproot
Ключевое преимущество: Все P2TR-выходы выглядят одинаково — OP_1 <32 bytes>. Наблюдатель не может отличить:
- Простой перевод одному получателю
- 2-of-3 мультиподпись
- Lightning Network commitment transaction
- Timelock-скрипт
Это значительное улучшение приватности по сравнению с P2SH, где тип скрипта раскрывается при трате.
Связь с CRYPTO-12: В уроке о подписях Шнорра мы изучили, как Schnorr signatures позволяют агрегацию ключей (MuSig2). Taproot использует эту возможность: несколько участников могут объединить свои ключи в один tweaked key и подписать одной подписью.
- Адреса:
bc1p...(bech32m) - Размер key path spend: ~154 vB
Математический уровень: Taproot Tweaking
Доказательство того, что key path spending работает:
Tweaked key: Q = P + t*G
Подпись создается tweaked приватным ключом:
d_tweaked = d + t (где d -- приватный ключ для P)
Проверка:
d_tweaked * G = (d + t) * G = d*G + t*G = P + t*G = Q
Schnorr verification: verify(Q, sig) = true
Почему нельзя подделать:
- Чтобы вычислить
t, нуженscript_root(Merkle root дерева скриптов) - Если script_root публичен, то tweak
tдетерминирован - Если скрипты секретны, наблюдатель не знает
tи не может отличить Q от “обычного” публичного ключа
Код на Python
P2WPKH транзакция (python-bitcoinlib)
from bitcoin import SelectParams
from bitcoin.core import (b2x, lx, COIN, COutPoint, CTxOut, CTxIn,
CTxInWitness, CTxWitness, CScriptWitness,
CMutableTransaction, Hash160)
from bitcoin.core.script import (CScript, OP_0, SignatureHash,
SIGHASH_ALL, SIGVERSION_WITNESS_V0)
from bitcoin.wallet import P2WPKHBitcoinAddress
SelectParams('regtest')
# Создаем P2WPKH scriptPubKey
pubkey_hash = bytes(20) # Hash160 публичного ключа
script_pubkey = CScript([OP_0, pubkey_hash])
print("P2WPKH scriptPubKey:", b2x(script_pubkey))
# Вывод: 0014 + 20 нулевых байт
# OP_0 (0x00) + push 20 bytes (0x14) + hash
P2TR с bitcoin-utils (концептуальный пример)
# Для Taproot используйте bitcoin-utils==0.7.3
# python-bitcoinlib НЕ поддерживает P2TR
from bitcoinutils.setup import setup
from bitcoinutils.keys import PrivateKey
setup('regtest')
# Генерация ключа
priv = PrivateKey()
pub = priv.get_public_key()
# Получение P2TR адреса (tweaked key)
taproot_address = pub.get_taproot_address()
print(f"P2TR адрес: {taproot_address.to_string()}")
# Вывод: bcrt1p... (bech32m для regtest)
Примечание:
python-bitcoinlibне поддерживает Taproot (P2TR). Для работы с Taproot в Python используйте библиотекуbitcoin-utils==0.7.3. Подробнее — в Jupyter notebook.
Практика
Откройте Jupyter notebook 11-bitcoin-script.ipynb для практики:
- Создание скриптов для всех типов транзакций
- Расчет weight units и virtual bytes
- Сравнение размеров P2PKH, P2WPKH и P2TR
- Taproot-примеры с bitcoin-utils
Для работы с bitcoin-cli на regtest откройте lab-02-script.sh:
- Создание адресов P2PKH, P2SH, P2WPKH, P2TR
- Отправка на разные типы адресов и сравнение транзакций
- Декодирование scriptPubKey для каждого типа
- Исследование descriptor wallets
Итоги
| Тип | Эпоха | Ключевое улучшение | Адрес |
|---|---|---|---|
| P2PKH | 2009 | Оригинальный тип | 1... |
| P2SH | 2012 | Сложные скрипты | 3... |
| P2WPKH | 2017 | -37% комиссия, fix malleability | bc1q... |
| P2WSH | 2017 | Сложные скрипты + SegWit | bc1q... |
| P2TR | 2021 | Приватность, Schnorr, MAST | bc1p... |
Следующий урок: Майнинг и Proof-of-Work — как Bitcoin обеспечивает консенсус без центрального сервера.
Finished the lesson?
Mark it as complete to track your progress